Xyce  6.1
N_ANP_NOISE.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-NOISE04-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 //-----------------------------------------------------------------------------
27 // Filename : $RCSfile: N_ANP_NOISE.C,v $
28 // Purpose : NOISE analysis functions.
29 // Special Notes :
30 // Creator : Eric Keiter
31 // Creation Date : 12/8/2014
32 //
33 // Revision Information:
34 // ---------------------
35 // Revision Number: $Revision: 1.27.2.2 $
36 // Revision Date : $Date: 2015/04/06 22:45:57 $
37 // Current Owner : $Author: erkeite $
38 //-----------------------------------------------------------------------------
39 
40 #include <Xyce_config.h>
41 
42 #include <iomanip>
43 
44 #include <fstream>
45 
46 #include <N_ANP_NOISE.h>
47 #include <N_ANP_NoiseData.h>
48 
49 #include <N_ANP_AnalysisManager.h>
50 #include <N_ANP_OutputMgrAdapter.h>
51 #include <N_ERH_Message.h>
52 #include <N_ERH_ErrorMgr.h>
53 #include <N_IO_CmdParse.h>
54 #include <N_IO_PkgOptionsMgr.h>
55 #include <N_LAS_BlockMatrix.h>
56 #include <N_LAS_BlockSystemHelpers.h>
57 #include <N_LAS_BlockVector.h>
58 #include <N_LAS_Builder.h>
59 #include <N_LAS_Matrix.h>
60 #include <N_LAS_MultiVector.h>
61 #include <N_LAS_System.h>
62 #include <N_LOA_Loader.h>
63 #include <N_NLS_Manager.h>
64 
65 #include <N_TIA_DataStore.h>
67 #include <N_TIA_StepErrorControl.h>
69 
70 #include <N_UTL_Diagnostic.h>
71 #include <N_UTL_FeatureTest.h>
72 #include <N_UTL_LogStream.h>
73 #include <N_UTL_Math.h>
74 #include <N_UTL_Timer.h>
75 #include <N_PDS_Comm.h>
76 #include <N_PDS_MPI.h>
77 #include <N_PDS_Manager.h>
78 #include <N_PDS_Serial.h>
79 
80 #include <N_PDS_ParMap.h>
81 
82 #include <N_TOP_Topology.h>
83 
84 #include <Epetra_SerialComm.h>
85 #include <Epetra_Map.h>
86 #include <Epetra_BlockMap.h>
87 #include <Epetra_CrsMatrix.h>
88 #include <Epetra_CrsGraph.h>
89 #include <Epetra_MultiVector.h>
90 #include <Epetra_Vector.h>
91 #include <Epetra_Export.h>
92 #include <Epetra_LinearProblem.h>
93 #include <Amesos.h>
94 
95 #include<N_UTL_ExtendedString.h>
96 #include<N_UTL_ExpressionData.h>
97 #include<N_NLS_ReturnCodes.h>
98 
99 #include <Teuchos_RCP.hpp>
100 using Teuchos::RCP;
101 using Teuchos::rcp;
102 
103 // putting these here for now (from spice3's noisedefs.h file)
104 #define N_MINLOG 1E-38 /* the smallest number we can take the log of */
105 #define N_MINGAIN 1E-20 // the smallest input-output gain we can tolerate
106  // (to calculate input-referred noise we divide
107  // the output noise by the gain)
108 
109 #define N_INTFTHRESH 1E-10 // the largest slope (of a log-log noise spectral
110  // density vs. freq plot) at which the noise
111  // spectum is still considered flat. (no need for
112  // log curve fitting)
113 #define N_INTUSELOG 1E-10 // decides which expression to use for the integral of
114  // x**k. If k is -1, then we must use a 'ln' form.
115  // Otherwise, we use a 'power' form. This
116  // parameter is the region around (k=) -1 for which
117  // use the 'ln' form.
118 
119 namespace Xyce {
120 namespace Analysis {
121 
122 //-----------------------------------------------------------------------------
123 // Function : AnalysisManager::setTimeIntegratorOptions
124 // Purpose :
125 // Special Notes : These are from '.options timeint'
126 // Scope : public
127 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
128 // Creation Date : 04/18/02
129 //-----------------------------------------------------------------------------
131  const Util::OptionBlock & option_block)
132 {
133  for (Util::ParamList::const_iterator it = option_block.begin(),
134  end = option_block.end(); it != end; ++it)
135  {
136  const Util::Param &param = *it;
137 
138  if (param.uTag() == "DEBUGLEVEL" )
139  {
140  IO::setTimeIntegratorDebugLevel(analysisManager_.getCommandLine(), param.getImmutableValue<int>());
141  }
142  else if (nonlinearManager_.setReturnCodeOption(param))
143  {
144  ;
145  }
146  else if (tiaParams_.setTimeIntegratorOption(param))
147  {
148  ;
149  }
150  else if (setDCOPOption(param))
151  {
152  ;
153  }
154  else
155  {
156  Report::UserError() << param.uTag()
157  << " is not a recognized time integration option";
158  }
159  }
160 
161  return true;
162 }
163 
164 //-----------------------------------------------------------------------------
165 // Function : NOISE::NOISE
166 // Purpose : constructor
167 // Special Notes :
168 // Scope : public
169 // Creator : Eric Keiter
170 // Creation Date : 12/8/2014
171 //-----------------------------------------------------------------------------
173  AnalysisManager & analysis_manager,
174  N_LAS_System & linear_system,
175  Nonlinear::Manager & nonlinear_manager,
176  Topo::Topology & topology)
177  : AnalysisBase(analysis_manager, "NOISE"),
178  StepEventListener(&analysis_manager),
179  analysisManager_(analysis_manager),
180  loader_(analysis_manager.getLoader()),
181  linearSystem_(linear_system),
182  nonlinearManager_(nonlinear_manager),
183  topology_(topology),
184  outputManagerAdapter_(analysis_manager.getOutputManagerAdapter()),
185  bVecRealPtr(linearSystem_.builder().createVector()),
186  bVecImagPtr(linearSystem_.builder().createVector()),
187  bNoiseVecRealPtr(linearSystem_.builder().createVector()),
188  bNoiseVecImagPtr(linearSystem_.builder().createVector()),
189  hackOutputCalledBefore_(false),
190  useAdjoint_(true),
191  outputNodeSingle_(true),
192  outputNode1_(""),
193  outputNode2_(""),
194  specifiedSource_(""),
195  ACMatrix_(0),
196  B_(0),
197  X_(0),
198  saved_AC_X_(0),
199  blockSolver_(0),
200  blockProblem_(0),
201  noiseLoopSize_(0),
202  type_("DEC"),
203  stepFlag_(false),
204  np_(10.0),
205  fStart_(1.0),
206  fStop_(1.0),
207  stepMult_(0.0),
208  fstep_(0.0),
209  pts_per_summary_(0),
210  pts_per_summary_Given(false),
211  delFreq_(0.0),
212  lastFreq_(0.0),
213  currentFreq_(0.0),
214  lnFreq_(0.0),
215  lnLastFreq_(0.0),
216  delLnFreq_(0.0),
217  GainSqInv_(0.0),
218  lnGainInv_(0.0),
219  totalOutputNoise_(0.0),
220  totalInputNoise_(0.0),
221  totalOutputNoiseDens_(0.0),
222  totalInputNoiseDens_(0.0)
223 {
224  bVecRealPtr->putScalar(0.0);
225  bVecImagPtr->putScalar(0.0);
226  bNoiseVecRealPtr->putScalar(0.0);
227  bNoiseVecImagPtr->putScalar(0.0);
228 }
229 
230 //-----------------------------------------------------------------------------
231 // Function : NOISE::~NOISE()
232 // Purpose : destructor
233 // Special Notes :
234 // Scope : public
235 // Creator : Eric Keiter
236 // Creation Date : 12/8/2014
237 //-----------------------------------------------------------------------------
239 {
240  delete bVecRealPtr;
241  delete bVecImagPtr;
242  delete bNoiseVecRealPtr;
243  delete bNoiseVecImagPtr;
244  delete ACMatrix_;
245  delete B_;
246  delete X_;
247  delete saved_AC_X_;
248  delete blockSolver_;
249  delete blockProblem_;
250 
251  int size = noiseDataVec_.size();
252  for (int i=0;i<size;++i)
253  {
254  delete (noiseDataVec_[i]);
255  }
256  noiseDataVec_.clear();
257 }
258 
259 //-----------------------------------------------------------------------------
260 // Function : NOISE::notify
261 // Purpose :
262 // Special Notes :
263 // Scope : public
264 // Creator :
265 // Creation Date :
266 //-----------------------------------------------------------------------------
267 void NOISE::notify(const StepEvent &event)
268 {
269  if (event.state_ == StepEvent::STEP_STARTED)
270  {
272 
273  stepFlag_ = true;
275 
276  bVecRealPtr->putScalar(0.0);
277  bVecImagPtr->putScalar(0.0);
278  bNoiseVecRealPtr->putScalar(0.0);
279  bNoiseVecImagPtr->putScalar(0.0);
280  }
281 }
282 
283 //-----------------------------------------------------------------------------
284 // Function : NOISE::setAnalysisParams
285 // Purpose :
286 // Special Notes : These are from the .NOISE statement.
287 // Scope : public
288 // Creator : Eric Keiter, SNL
289 // Creation Date : 12/8/2014
290 //-----------------------------------------------------------------------------
291 bool NOISE::setAnalysisParams(const Util::OptionBlock & paramsBlock)
292 {
293  for (Util::ParamList::const_iterator it = paramsBlock.begin(),
294  end = paramsBlock.end(); it != end; ++it)
295  {
296  if ((*it).uTag() == "V")
297  {
298  if ((*it).getImmutableValue<double>()==1.0)
299  {
300  outputNodeSingle_ = true;
301  Util::ParamList::const_iterator itNode = it;
302  itNode++;
303  outputNode1_ = (*itNode).uTag();
304  }
305  else if ((*it).getImmutableValue<double>()==2.0)
306  {
307  outputNodeSingle_ = false;
308  Util::ParamList::const_iterator itNode = it;
309  itNode++;
310  outputNode1_ = (*itNode).uTag();
311  itNode++;
312  outputNode2_ = (*itNode).uTag();
313  }
314  }
315  else if ((*it).uTag() == "SOURCE")
316  {
317  specifiedSource_ = (*it).stringValue();
318  }
319  else if ((*it).uTag() == "TYPE")
320  {
321  type_ = (*it).stringValue();
322  }
323  else if ((*it).uTag() == "NP")
324  {
325  np_ = (*it).getImmutableValue<double>();
326  }
327  else if ((*it).uTag() == "FSTART")
328  {
329  fStart_ = (*it).getImmutableValue<double>();
330  }
331  else if ((*it).uTag() == "FSTOP")
332  {
333  fStop_ = (*it).getImmutableValue<double>();
334  }
335  else if ((*it).uTag() == "PTS_PER_SUMMARY")
336  {
337  pts_per_summary_ = (*it).getImmutableValue<int>();
338  }
339  }
340 
341  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
342  {
343  dout() << section_divider << std::endl
344  << "NOISE simulation parameters"
345  << std::endl;
346 
347  if (outputNodeSingle_)
348  {
349  dout() << "Output Node: V(" << outputNode1_ << ")" <<std::endl;
350  }
351  else
352  {
353  dout() << "Output Node: V(" << outputNode1_ << ","<<outputNode2_<<")" <<std::endl;
354  }
355 
356  dout() << "specified source = " << specifiedSource_ << std::endl
357  << "number of points = " << np_ << std::endl
358  << "starting frequency = " << fStart_ << std::endl
359  << "stop frequency = " << fStop_ << std::endl
360  << "pts_per_summary = " << pts_per_summary_
361  << std::endl;
362  }
363 
364  return true;
365 }
366 
367 //-----------------------------------------------------------------------------
368 // Function : NOISE::getDCOPFlag()
369 // Purpose :
370 // Special Notes :
371 // Scope : public
372 // Creator : Eric Keiter, SNL
373 // Creation Date : 12/8/2014
374 //-----------------------------------------------------------------------------
375 bool NOISE::getDCOPFlag() const
376 {
378 }
379 
380 //-----------------------------------------------------------------------------
381 // Function : NOISE::run()
382 // Purpose :
383 // Special Notes :
384 // Scope : public
385 // Creator : Eric Keiter, SNL
386 // Creation Date : 12/8/2014
387 //-----------------------------------------------------------------------------
389 {
390  return doInit() && doLoopProcess() && doFinish();
391 }
392 
393 //-----------------------------------------------------------------------------
394 // Function : NOISE::init()
395 // Purpose :
396 // Special Notes :
397 // Scope : public
398 // Creator : Eric Keiter, SNL
399 // Creation Date : 12/8/2014
400 //-----------------------------------------------------------------------------
402 {
403  bool bsuccess = true;
404 
406 
407  // Get set to do the operating point.
410 
411  stepNumber = 0;
414 
415  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
417 
418  // set initial guess, if there is one to be set.
419  // this setInitialGuess call is to up an initial guess in the
420  // devices that have them (usually PDE devices). This is different than
421  // the "intializeProblem" call, which sets IC's. (initial conditions are
422  // different than initial guesses.
424 
425  // If available, set initial solution (.IC, .NODESET, etc).
430 
431  // Set a constant history for operating point calculation
435 
436  // solving for DC op
443 
445  {
446  Report::UserError() << "Solving for DC operating point failed! Cannot continue NOISE analysis";
447  return false;
448  }
449 
450  // only output DC op if the .op was specified in the netlist
451  // or if this NOISE analysis is called from a .step loop
453  {
455  stepNumber,
461  objectiveVec_,
464  }
465 
466  // This for saving the data from the DC op. different from the above where we are
467  // concerned with generating normal output.
469 
471 
472 #if 0
473  Xyce::dout() << "bVecReal:" <<std::endl;
474  bVecRealPtr->printPetraObject(Xyce::dout());
475  Xyce::dout() << "bVecImag:" <<std::endl;
476  bVecImagPtr->printPetraObject(Xyce::dout());
477 #endif
478 
479  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
481 
483 
484  return bsuccess;
485 }
486 
487 //-----------------------------------------------------------------------------
488 // Function : NOISE::loopProcess()
489 // Purpose : Conduct the stepping loop.
490 // Special Notes :
491 // Scope : public
492 // Creator : Eric Keiter, SNL
493 // Creation Date : 12/8/2014
494 //-----------------------------------------------------------------------------
496 {
497  analysisManager_.getDataStore()->daeQVectorPtr->putScalar(0.0);
498  analysisManager_.getDataStore()->daeFVectorPtr->putScalar(0.0);
499 
504 
515  );
516 
541 
548 
551 
552  if (DEBUG_TIME && isActive(Diag::TIME_PARAMETERS))
553  {
554  Xyce::dout() << "dQdxMatrixPtr:" << std::endl;
555  analysisManager_.getDataStore()->dQdxMatrixPtr->printPetraObject( Xyce::dout() );
556 
557  Xyce::dout() << "dFdxMatrixPtr:" << std::endl;
558  analysisManager_.getDataStore()->dFdxMatrixPtr->printPetraObject( Xyce::dout() );
559 
560  Xyce::dout() << std::endl;
561  }
562 
564 
565  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
567 
568  int numNoiseDevices = loader_.getNumNoiseDevices();
569  noiseDataVec_.resize(numNoiseDevices);
570  for (int i=0;i<numNoiseDevices;++i)
571  {
572  noiseDataVec_[i] = new NoiseData();
573  }
574 
576 
577  // clear out the integral arrays
578  for (int i=0;i<numNoiseDevices;++i)
579  {
580  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
581  for (int j=0;j<numNoiseThisDevice;++j)
582  {
583  noiseDataVec_[i]->inputNoiseTotal[j] = 0.0;
584  noiseDataVec_[i]->outputNoiseTotal[j] = 0.0;
585  }
586  }
587 
588  // loop over all the specified frequencies, do an AC solve and a NOISE solve at each.
589  if (useAdjoint_)
590  {
592  }
593 
594  N_PDS_Manager &pds_manager = *analysisManager_.getPDSManager();
595  N_PDS_Comm & comm = *(pds_manager.getPDSComm());
596  int myPID = comm.procID();
597 
598  ///////////////////////////////////////////////////////////////////////////
599  // frequency loop
600  for (int currentStep = 0; currentStep < noiseLoopSize_; ++currentStep)
601  {
602  // solve the AC system, to get up-to-date currents and voltages
603  updateCurrentFreq_(currentStep);
604 
606 
607  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
609 
610  bool stepAttemptStatus;
611  {
612  Stats::StatTop _nonlinearStat("Nonlinear Solve");
613  Stats::TimeBlock _nonlinearTimer(_nonlinearStat);
614 
615  stepAttemptStatus = solveACLinearSystem_();
616  }
617 
618 #if 0
619  Xyce::dout()<<"AC X vector:"<<std::endl;
620  X_->printPetraObject(Xyce::dout());
621 #endif
622 
623  // save a copy of X_ (the AC solution, already computed), for output purposes, etc.
624  delete saved_AC_X_;
625  saved_AC_X_ = new N_LAS_BlockVector (*X_);
626 
627  // Compute AC gain.
628  N_LAS_Vector & Xreal = X_->block( 0 );
629  N_LAS_Vector & Ximag = X_->block( 1 );
630 
631  double v1r = 0.0;
632  double v1i = 0.0;
633  double v2r = 0.0;
634  double v2i = 0.0;
635 
636  //comm.barrier();
637  int root=-1;
638  if (outputVarGIDs_.size()>0)
639  {
640  if (outputVarGIDs_[0] > -1)
641  {
642  v1r = Xreal.getElementByGlobalIndex(outputVarGIDs_[0]);
643  v1i = Ximag.getElementByGlobalIndex(outputVarGIDs_[0]);
644  root = myPID;
645  }
646  Xyce::Parallel::AllReduce(comm.comm(), MPI_MAX, &root, 1);
647  comm.bcast( &v1r, 1, root );
648  comm.bcast( &v1i, 1, root );
649  }
650 
651  root=-1;
652  if (outputVarGIDs_.size()>1)
653  {
654  if (outputVarGIDs_[1] > -1)
655  {
656  v2r = Xreal.getElementByGlobalIndex(outputVarGIDs_[1]);
657  v2i = Ximag.getElementByGlobalIndex(outputVarGIDs_[1]);
658  root = myPID;
659  }
660  Xyce::Parallel::AllReduce(comm.comm(), MPI_MAX, &root, 1);
661  comm.bcast( &v2r, 1, root );
662  comm.bcast( &v2i, 1, root );
663  }
664  //comm.barrier();
665 
666  double realVal = v1r-v2r;
667  double imagVal = v1i-v2i;
668  GainSqInv_ = 1.0 / std::max(((realVal*realVal) + (imagVal*imagVal)),N_MINGAIN);
669  lnGainInv_ = std::log(GainSqInv_);
670 
671 #if 0
672  std::cout
673  //<< "\tPosNodeID = " << outputVarGIDs_[0]
674  << "\tv1r = "<< v1r << "\tv2r = " << v2r
675  << "\tv1i = "<< v1i << "\tv2i = " << v2i
676  << "\trealVal = "<< realVal << "\timagVal = " << imagVal
677  << "\tGainSqInv_ = "<< GainSqInv_ << "\tlnGainInv_ = " << lnGainInv_ << std::endl;
678 #endif
679 
680 
681  // save previous (last) lnNoise densities
682  for (int i=0;i<noiseDataVec_.size();++i)
683  {
684  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
685  for (int j=0;j<numNoiseThisDevice;++j)
686  {
687  noiseDataVec_[i]->lastLnNoiseDens[j] = noiseDataVec_[i]->lnNoiseDens[j];
688  }
689  }
690 
691  // do NOISE analysis for this frequency.
692  if (useAdjoint_)
693  {
696  }
697  else// only here as diagnostic, not implemented yet.
698  {
700  }
701 
702  // perform total noise integrals
703  if (currentStep != 0)
704  {
705  for (int i=0;i<noiseDataVec_.size();++i)
706  {
707  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
708  for (int j=0;j<numNoiseThisDevice;++j)
709  {
710  double noizDens = noiseDataVec_[i]->outputNoiseDens[j];
711  double lnDens = noiseDataVec_[i]->lnNoiseDens[j];
712  double lnlastDens = noiseDataVec_[i]->lastLnNoiseDens[j];
713 
714  double tempOutNoise = noiseIntegral( noizDens, lnDens, lnlastDens,
716 
717  double tempInNoise = noiseIntegral(
718  noizDens * GainSqInv_,
719  lnDens + lnGainInv_,
720  lnlastDens + lnGainInv_,
722 
723 
724  noiseDataVec_[i]->outputNoiseTotal[j] += tempOutNoise;
725  noiseDataVec_[i]->inputNoiseTotal[j] += tempInNoise;
726 
727 #if 0
728  std::cout
729  << "\t" << tempOutNoise
730  << "\t" << noiseDataVec_[i]->outputNoiseTotal[j]
731  << "\t" << tempInNoise
732  << "\t" << noiseDataVec_[i]->inputNoiseTotal[j] << std::endl;
733 #endif
734 
735  totalOutputNoise_+=tempOutNoise;
736  totalInputNoise_+=tempInNoise;
737  }
738  }
739  }
740 
741  // process success/failure
742  if (stepAttemptStatus)
743  {
744  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
747  }
748  else // stepAttemptStatus (ie do this if the step FAILED)
749  {
750  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
753  }
754  }
755 
756  //Report::safeBarrier(comm.comm());
757  Xyce::Parallel::AllReduce(comm.comm(), MPI_SUM, &totalOutputNoise_, 1);
758  Xyce::Parallel::AllReduce(comm.comm(), MPI_SUM, &totalInputNoise_, 1);
759 
760  // Outputs to the screen:
761  Xyce::lout() << "Total Output Noise = " << totalOutputNoise_ <<std::endl;
762  Xyce::lout() << "Total Input Noise = " << totalInputNoise_ <<std::endl;
763 
764  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish
766 
767  return true;
768 }
769 
770 //-----------------------------------------------------------------------------
771 // Function : NOISE::createACLinearSystem_()
772 // Purpose :
773 // Special Notes :
774 // Scope : public
775 // Creator : Eric Keiter, SNL
776 // Creation Date : 12/8/2014
777 //-----------------------------------------------------------------------------
779 {
780  bool bsuccess = true;
781 
782  N_PDS_Manager &pds_manager = *analysisManager_.getPDSManager();
783 
784  RCP<N_PDS_ParMap> baseMap = rcp(pds_manager.getParallelMap( Parallel::SOLUTION ), false);
785  Epetra_CrsGraph &baseFullGraph = *pds_manager.getMatrixGraph(Parallel::JACOBIAN);
786 
787  int numBlocks = 2;
788 
789  RCP<N_PDS_ParMap> blockMap = Linear::createBlockParMap(numBlocks, *baseMap);
790 
791  // Create a block vector
792  delete B_;
793  B_ = new N_LAS_BlockVector(numBlocks, blockMap, baseMap);
794 
795  // -----------------------------------------------------
796  // Now test block graphs.
797  // -----------------------------------------------------
798 
799  std::vector<std::vector<int> > blockPattern(2);
800  blockPattern[0].resize(2);
801  blockPattern[0][0] = 0; blockPattern[0][1] = 1;
802  blockPattern[1].resize(2);
803  blockPattern[1][0] = 0; blockPattern[1][1] = 1;
804 
805  int offset = Linear::generateOffset( *baseMap );
806 
807  RCP<Epetra_CrsGraph> blockGraph = Linear::createBlockGraph( offset, blockPattern, *blockMap, baseFullGraph);
808 
809  delete ACMatrix_;
810  ACMatrix_ = new N_LAS_BlockMatrix( numBlocks, offset, blockPattern, *blockGraph, baseFullGraph);
811 
812  // First diagonal block
813  ACMatrix_->put( 0.0 ); // Zero out whole matrix
814  ACMatrix_->block( 0, 0 ).add(*G_);
815 
816  // Second diagonal block
817  ACMatrix_->block( 1, 1 ).add(*G_);
818 
819  B_->putScalar( 0.0 );
820  B_->block( 0 ).addVec( 1.0, *bVecRealPtr);
821  B_->block( 1 ).addVec( 1.0, *bVecImagPtr);
822 
823 #if 0
824  Xyce::dout()<<"original AC B vector:"<<std::endl;
825  B_->printPetraObject(Xyce::dout());
826 #endif
827 
828  Amesos amesosFactory;
829 
830  delete X_;
831  X_ = new N_LAS_BlockVector (numBlocks, blockMap, baseMap);
832  X_->putScalar( 0.0 );
833 
834  delete saved_AC_X_;
835  saved_AC_X_ = new N_LAS_BlockVector (numBlocks, blockMap, baseMap);
836  saved_AC_X_->putScalar( 0.0 );
837 
838  delete blockProblem_;
839  blockProblem_ = new Epetra_LinearProblem(&ACMatrix_->epetraObj(), &X_->epetraObj(), &B_->epetraObj() );
840 
841  delete blockSolver_;
842  blockSolver_ = amesosFactory.Create( "Klu", *blockProblem_ );
843 
844  // Need to reindex the linear system because of the noncontiguous block map.
845  Teuchos::ParameterList params;
846  params.set( "Reindex", true );
847  blockSolver_->SetParameters( params );
848 
849 #if 0
850  // Call symbolic factorization without syncronizing the values, since they are not necessary here.
851  int linearStatus = blockSolver_->SymbolicFactorization();
852  if (linearStatus != 0)
853  {
854  Xyce::dout() << "Amesos symbolic factorization exited with error: " << linearStatus;
855  bsuccess = false;
856  }
857 #endif
858 
859  return bsuccess;
860 }
861 
862 //-----------------------------------------------------------------------------
863 // Function : NOISE::resetACLinearSystem_
864 // Purpose :
865 // Special Notes :
866 // Scope : public
867 // Creator : Eric Keiter, SNL
868 // Creation Date : 12/8/2014
869 //-----------------------------------------------------------------------------
871 {
872  double omega = 2.0 * M_PI * currentFreq_;
873 
874  ACMatrix_->block( 0, 1).put( 0.0);
875  ACMatrix_->block( 0, 1).add(*C_);
876  ACMatrix_->block( 0, 1).scale(-omega);
877 
878  ACMatrix_->block(1, 0).put( 0.0);
879  ACMatrix_->block(1, 0).add(*C_);
880  ACMatrix_->block(1, 0).scale(omega);
881 
882  // Copy the values loaded into the blocks into the global matrix for the solve.
883  ACMatrix_->assembleGlobalMatrix();
884 
885  ACMatrix_->setUseTranspose (false);
886  blockSolver_->SetUseTranspose(false);
887 
888  // restore the AC RHS
889  B_->putScalar( 0.0 );
890  B_->block( 0 ).addVec( 1.0, *bVecRealPtr);
891  B_->block( 1 ).addVec( 1.0, *bVecImagPtr);
892 
893  // clear out X_
894  X_->putScalar( 0.0 );
895 
896 #if 0
897  Xyce::dout()<<"G matrix:"<<std::endl;
898  G_->printPetraObject(Xyce::dout());
899 
900  Xyce::dout()<<"C matrix:"<<std::endl;
901  C_->printPetraObject(Xyce::dout());
902 
903  Xyce::dout()<<"AC matrix:"<<std::endl;
904  ACMatrix_->printPetraObject(Xyce::dout());
905 
906  Xyce::dout()<<"AC B vector:"<<std::endl;
907  B_->printPetraObject(Xyce::dout());
908 #endif
909 
910  return true;
911 }
912 
913 //-----------------------------------------------------------------------------
914 // Function : NOISE::solveACLinearSystem_()
915 // Purpose :
916 // Special Notes :
917 // Scope : public
918 // Creator : Eric Keiter, SNL
919 // Creation Date : 12/8/2014
920 //-----------------------------------------------------------------------------
922 {
923  bool bsuccess = true;
924  // Solve the block problem
925 
926  int linearStatus = blockSolver_->SymbolicFactorization();
927  if (linearStatus != 0)
928  {
929  Xyce::dout() << "Amesos symbolic factorization exited with error: " << linearStatus;
930  bsuccess = false;
931  }
932 
933  linearStatus = blockSolver_->NumericFactorization();
934  if (linearStatus != 0)
935  {
936  Xyce::dout() << "Amesos numeric factorization exited with error: " << linearStatus;
937  bsuccess = false;
938  }
939 
940  linearStatus = blockSolver_->Solve();
941  if (linearStatus != 0)
942  {
943  Xyce::dout() << "Amesos solve exited with error: " << linearStatus;
944  bsuccess = false;
945  }
946 
947  return bsuccess;
948 }
949 
950 
951 //-----------------------------------------------------------------------------
952 // Function : NOISE::processOutputNodes
953 // Purpose : determines the GIDs for the nodes specified in the first argument
954 // of the .NOISE line.
955 // Special Notes :
956 // Scope : public
957 // Creator : Eric Keiter, SNL
958 // Creation Date : 12/15/2014
959 //-----------------------------------------------------------------------------
961 {
962  // setup the names:
963  outputVarNames_.clear();
964  outputVarNames_.push_back(outputNode1_);
965  if (!outputNodeSingle_)
966  {
967  outputVarNames_.push_back(outputNode2_);
968  }
969  int numOutVars = outputVarNames_.size();
970 
971  // set up the gid's:
972  int found(0);
973  int found2(0);
974  bool foundLocal(false);
975  bool foundLocal2(false);
976 
977  N_PDS_Manager &pds_manager = *analysisManager_.getPDSManager();
978  N_PDS_Comm & comm = *(pds_manager.getPDSComm());
979  int myPID = comm.procID();
980 
981  outputVarGIDs_.resize( numOutVars, -1 );
982  for (int iout = 0; iout < numOutVars; ++iout)
983  {
984  std::vector<int> svGIDList1, dummyList;
985  char type1;
986  foundLocal = topology_.getNodeSVarGIDs(NodeID(outputVarNames_[iout], Xyce::_VNODE),
987  svGIDList1, dummyList, type1);
988 
989  found = static_cast<int>(foundLocal);
990  Xyce::Parallel::AllReduce(comm.comm(), MPI_LOR, &found, 1);
991 
992  foundLocal2 = false;
993  if (!found)// if looking for this as a voltage node failed, try a "device" (i.e. current) node.
994  {
995  foundLocal2 = topology_.getNodeSVarGIDs(NodeID(outputVarNames_[iout], Xyce::_DNODE),
996  svGIDList1, dummyList, type1);
997  }
998  found2 = static_cast<int>(foundLocal2);
999  Xyce::Parallel::AllReduce(comm.comm(), MPI_LOR, &found2, 1);
1000 
1001  if (!found && !found2)
1002  {
1003  Report::UserError() << "Output function variable " << outputVarNames_[iout] << " not found";
1004  }
1005 
1006  if (found || found2)
1007  {
1008  int tmpGID=-1;
1009  if(svGIDList1.size()==1)
1010  {
1011  tmpGID = svGIDList1.front();
1012  }
1013  outputVarGIDs_[iout] = tmpGID;
1014  }
1015  }
1016 }
1017 
1018 //-----------------------------------------------------------------------------
1019 // Function : NOISE::solveDirectNOISE_
1020 // Purpose : Solves for NOISE using the direct method.
1021 // Special Notes : Not practical, implemented only as a test for adjoint.
1022 // Scope : public
1023 // Creator : Eric Keiter, SNL
1024 // Creation Date : 12/15/2014
1025 //-----------------------------------------------------------------------------
1027 {
1028  bool bsuccess = true;
1029  // Solve the block problem
1030 
1031  // get the number of noise sources
1032  // int numSources = loader_.getNumNoiseSources();
1033  // for (int isource=0;isource<numSources;++isources)
1034  // {
1035  // // need different BVector and linear solve set up for each noise source
1036  //
1037  // // substitute the noise Bvector into the linear system object
1038  //
1039  // // solve linear problem for dX/dNoise
1040  //
1041  // // perform matvec to get this dOutput/dNoise for this noise source
1042  // }
1043 
1044 
1045  return bsuccess;
1046 }
1047 
1048 //-----------------------------------------------------------------------------
1049 // Function : NOISE::setupAdjointRHS_
1050 // Purpose : Sets up stuff that only needs to be set up once,
1051 // but is unique to the adjoint solve.
1052 // (i.e. is not used by the direct form)
1053 // Special Notes :
1054 // Scope : public
1055 // Creator : Eric Keiter, SNL
1056 // Creation Date : 12/15/2014
1057 //-----------------------------------------------------------------------------
1059 {
1060  // set up the RHS vector of 1's and 0's vector to represent dOutput/dX.
1061  // If thinking of this as the input to the adjoint circuit problem
1062  // (or adjoint operator) this can also be thought of as current sources to
1063  // the adjoint circuit.
1064  //
1065  // For the adjoint problem
1066  // assume that the phase is zero (as this is essentially the input to the
1067  // adjoint operator) and just set 1's on the real part of the block vector.
1068  // For this purpose re-use the B_ vector from the AC problem.
1069 
1070  // replace RHS in linear system. Assume that the phase is zero, so no
1071  // imaginary contribution.
1072 
1073  N_PDS_Manager &pds_manager = *analysisManager_.getPDSManager();
1074  N_PDS_Comm & comm = *(pds_manager.getPDSComm());
1075  int myPID = comm.procID();
1076 
1077 
1078  bNoiseVecRealPtr->putScalar(0.0);
1079  bNoiseVecImagPtr->putScalar(0.0);
1080 
1081  int numOutVars = outputVarNames_.size();
1082  for (int iout=0;iout<numOutVars;++iout)
1083  {
1084  int tmpGID=outputVarGIDs_[iout];
1085  if (tmpGID > -1)
1086  {
1087  double val=1.0;
1088  if (iout>0) val=-1.0;
1089  bNoiseVecRealPtr->setElementByGlobalIndex( tmpGID, val, 0);
1090  }
1091  }
1092  bNoiseVecRealPtr->fillComplete();
1093 }
1094 
1095 //-----------------------------------------------------------------------------
1096 // Function : NOISE::resetAdjointNOISELinearSystem_
1097 // Purpose :
1098 // Special Notes :
1099 // Scope : public
1100 // Creator : Eric Keiter, SNL
1101 // Creation Date : 12/15/2014
1102 //-----------------------------------------------------------------------------
1104 {
1105  // clear out the X_ vector used by the linear solver.
1106  X_->putScalar(0.0);
1107 
1108 
1109  // setup the B_ vector RHS for the adjoint solve:
1110  B_->putScalar( 0.0 );
1111  B_->block( 0 ).addVec( 1.0, *bNoiseVecRealPtr);
1112  B_->block( 1 ).addVec( 1.0, *bNoiseVecImagPtr);
1113 
1114  //-------------------------------------------
1115  //Xyce::dout()<<"adjoint noise B vector:"<<std::endl;
1116  //B_->printPetraObject(Xyce::dout());
1117  //-------------------------------------------
1118 
1119  // solve transpose (adjoint) system to obtain dOutput/dF. If thinking of this
1120  // as the adjoint circuit problem (or adjoint operator) this can also be
1121  // thought of as the adjoint voltages, or more precisely a transImpedance (gain).
1122 
1123  ACMatrix_->setUseTranspose (true);
1124  blockSolver_->SetUseTranspose(true);
1125 }
1126 
1127 //-----------------------------------------------------------------------------
1128 // Function : NOISE::solveAdjointNOISE_
1129 // Purpose : Solves for NOISE using the adjoint method.
1130 // Special Notes : This is the production solve.
1131 // Scope : public
1132 // Creator : Eric Keiter, SNL
1133 // Creation Date : 12/15/2014
1134 //-----------------------------------------------------------------------------
1136 {
1137  bool bsuccess = true;
1138 
1139  // do the solve of the tranpose system to get dOutput/dF
1140  int linearStatus = blockSolver_->SymbolicFactorization();
1141  if (linearStatus != 0)
1142  {
1143  Xyce::dout() << "Amesos symbolic factorization exited with error: " << linearStatus;
1144  bsuccess = false;
1145  }
1146 
1147  linearStatus = blockSolver_->NumericFactorization();
1148  if (linearStatus != 0)
1149  {
1150  Xyce::dout() << "Amesos numeric factorization exited with error: " << linearStatus;
1151  bsuccess = false;
1152  }
1153 
1154  linearStatus = blockSolver_->Solve();
1155  if (linearStatus != 0)
1156  {
1157  Xyce::dout() << "Amesos solve exited with error: " << linearStatus;
1158  bsuccess = false;
1159  }
1160 
1161 #if 0
1162 //-------------------------------------------
1163  Xyce::dout()<<"transImpedance(gain):"<<std::endl;
1164  X_->printPetraObject(Xyce::dout());
1165 //-------------------------------------------
1166 #endif
1167 
1168  double omega = 2.0 * M_PI * currentFreq_;
1169 
1170  int numNoiseDevices = noiseDataVec_.size();
1171  for (int i=0;i<numNoiseDevices;++i)
1172  {
1173  (noiseDataVec_[i])->omega = omega;
1174  (noiseDataVec_[i])->freq = currentFreq_;
1175  }
1176 
1178 
1179  std::vector< Teuchos::RCP<N_LAS_Vector> > outputVectors;
1180  outputVectors.push_back( rcp(linearSystem_.builder().createVector()) );
1181  outputVectors.push_back( rcp(linearSystem_.builder().createVector()) );
1182 
1183  copyFromBlockVector( *X_, outputVectors );
1184  N_LAS_Vector & Xreal = *(outputVectors[0]);
1185  N_LAS_Vector & Ximag = *(outputVectors[1]);
1186 
1187 #if 0
1188 //-------------------------------------------
1189  Xyce::dout()<<"Xreal:"<<std::endl;
1190  Xreal.printPetraObject(Xyce::dout());
1191  Xyce::dout()<<"Ximag:"<<std::endl;
1192  Ximag.printPetraObject(Xyce::dout());
1193 //-------------------------------------------
1194 #endif
1195 
1196  N_PDS_Manager &pds_manager = *analysisManager_.getPDSManager();
1197  N_PDS_Comm & comm = *(pds_manager.getPDSComm());
1198  int myPID = comm.procID();
1199 
1200  totalOutputNoiseDens_ = 0.0;
1201  totalInputNoiseDens_ = 0.0;
1202  for (int i=0;i<numNoiseDevices;++i)
1203  {
1204  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
1205 
1206  noiseDataVec_[i]->totalNoise = 0.0;
1207  noiseDataVec_[i]->totalOutputNoise = 0.0;
1208  for (int j=0;j<numNoiseThisDevice;++j)
1209  {
1210  int li_Pos = noiseDataVec_[i]->li_Pos[j];
1211  int li_Neg = noiseDataVec_[i]->li_Neg[j];
1212 
1213  double realVal = Xreal[li_Pos] - Xreal[li_Neg];
1214  double imagVal = Ximag[li_Pos] - Ximag[li_Neg];
1215  double gain = (realVal*realVal) + (imagVal*imagVal);
1216 
1217  noiseDataVec_[i]->totalNoise += noiseDataVec_[i]->noiseDens[j];
1218 
1219  noiseDataVec_[i]->outputNoiseDens[j] = gain * noiseDataVec_[i]->noiseDens[j];
1220  noiseDataVec_[i]->lnNoiseDens[j] = std::log(std::max( noiseDataVec_[i]->outputNoiseDens[j],N_MINLOG) );
1221 
1222  noiseDataVec_[i]->inputNoiseDens[j] = noiseDataVec_[i]->outputNoiseDens[j] * GainSqInv_;
1223 
1224  noiseDataVec_[i]->totalOutputNoise += noiseDataVec_[i]->outputNoiseDens[j];
1225  }
1226  noiseDataVec_[i]->totalInputNoise = noiseDataVec_[i]->totalOutputNoise * GainSqInv_;
1227 
1228  totalOutputNoiseDens_ += noiseDataVec_[i]->totalOutputNoise;
1229  }
1230  Xyce::Parallel::AllReduce(comm.comm(), MPI_SUM, &totalOutputNoiseDens_, 1);
1231  totalInputNoiseDens_ += totalOutputNoiseDens_ * GainSqInv_;
1232 
1233  if (comm.isSerial() )
1234  {
1235  // FIX: replace this output call!
1237  }
1238 
1239  return bsuccess;
1240 }
1241 
1242 
1243 //-----------------------------------------------------------------------------
1244 // Function : NOISE::hackTecplotOutput
1245 // Purpose : provides an output function until I setup the output
1246 // manager properly for NOISE.
1247 // Author : Eric Keiter
1248 // Date : 1/5/2015
1249 //-----------------------------------------------------------------------------
1251 {
1252  int numNoiseDevices = noiseDataVec_.size();
1253  std::string fileName = analysisManager_.getNetlistFilename() + "_noise.dat";
1254 
1255  std::ofstream output_stream(fileName.c_str(),
1256  !hackOutputCalledBefore_ ? std::ios_base::out : std::ios_base::app);
1257 
1259  {
1260  // header output
1261  output_stream << "TITLE=\"noise output\"\tVARIABLES=\"frequency\" "<<std::endl;
1262  output_stream << "\t\"Re(V(" << outputNode1_ << "))\""<<std::endl;
1263  output_stream << "\t\"Im(V(" << outputNode1_ << "))\""<<std::endl;
1264 
1265  if(!outputNodeSingle_)
1266  {
1267  output_stream << "\t\"Re(V(" << outputNode2_ << "))\""<<std::endl;
1268  output_stream << "\t\"Im(V(" << outputNode2_ << "))\""<<std::endl;
1269  }
1270  output_stream << "\t\"onoise_spectrum \""<<std::endl;
1271  output_stream << "\t\"inoise_spectrum \""<<std::endl;
1272 
1273  if(pts_per_summary_>0)
1274  {
1275  for (int i=0;i<numNoiseDevices;++i)
1276  {
1277  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
1278  for (int j=0;j<numNoiseThisDevice;++j)
1279  {
1280  std::string namestring = noiseDataVec_[i]->noiseNames[j];
1281  std::transform(namestring.begin(), namestring.end(), namestring.begin(), ::tolower);
1282  output_stream << "\t\"" << namestring << "\"";
1283  }
1284 
1285  // spice doesn't output input noise for individual devices, so exclude.
1286  if (numNoiseThisDevice > 1)
1287  {
1288  std::string totalOutputNoiseName = "onoise_" + noiseDataVec_[i]->deviceName;
1289 
1290  std::transform(totalOutputNoiseName.begin(), totalOutputNoiseName.end(), totalOutputNoiseName.begin(), ::tolower);
1291 
1292  output_stream << "\t\""<<totalOutputNoiseName<<"\"";
1293  }
1294  }
1295  }
1296 
1297  output_stream << std::endl;
1298  output_stream << "ZONE F=POINT"<<std::endl;
1299  hackOutputCalledBefore_ = true;
1300  }
1301 
1302  // data output
1303  output_stream.setf(std::ios::scientific);
1304 
1305  // output the AC solution for the output node(s) (for double checking)
1306  N_LAS_Vector & Xreal = saved_AC_X_->block( 0 );
1307  N_LAS_Vector & Ximag = saved_AC_X_->block( 1 );
1308  double v1r = Xreal.getElementByGlobalIndex(outputVarGIDs_[0]);
1309  double v1i = Ximag.getElementByGlobalIndex(outputVarGIDs_[0]);
1310 
1311  output_stream << currentFreq_ << "\t" << v1r << "\t" << v1i;
1312 
1313  if(!outputNodeSingle_)
1314  {
1315  double v2r = 0.0;
1316  double v2i = 0.0;
1317  v2r = Xreal.getElementByGlobalIndex(outputVarGIDs_[1]);
1318  v2i = Ximag.getElementByGlobalIndex(outputVarGIDs_[1]);
1319  output_stream << "\t" << v2r << "\t" << v2i;
1320  }
1321 
1322  output_stream << "\t" << totalOutputNoiseDens_ << "\t" << totalInputNoiseDens_;
1323 
1324  if(pts_per_summary_>0)
1325  {
1326  for (int i=0;i<numNoiseDevices;++i)
1327  {
1328  int numNoiseThisDevice = noiseDataVec_[i]->numSources;
1329  for (int j=0;j<numNoiseThisDevice;++j)
1330  {
1331  output_stream << "\t" << noiseDataVec_[i]->outputNoiseDens[j];
1332  }
1333 
1334  if (numNoiseThisDevice > 1)
1335  {
1336  output_stream << "\t" << noiseDataVec_[i]->totalOutputNoise;
1337  }
1338  output_stream << std::endl;
1339  }
1340  }
1341  output_stream << std::endl;
1342 }
1343 
1344 //-----------------------------------------------------------------------------
1345 // Function : NOISE::noiseIntegral
1346 // Purpose : based on the spice3 function: Nintegrate.
1347 // This subroutine evaluates the integral of the function
1348 //
1349 // EXPONENT
1350 // NOISE = a * (FREQUENCY)
1351 //
1352 // given two points from the curve. If EXPONENT is relatively close
1353 // to 0, the noise is simply multiplied by the change in frequency.
1354 // If it isn't, a more complicated expression must be used. Note that
1355 // EXPONENT = -1 gives a different equation than EXPONENT <> -1.
1356 // Hence, the reason for the constant 'N_INTUSELOG'.
1357 //
1358 // Special Notes :
1359 // Scope : public
1360 // Creator : Eric Keiter, SNL
1361 // Creation Date : 12/8/2014
1362 //-----------------------------------------------------------------------------
1363 double NOISE::noiseIntegral(double noizDens, double lnNdens, double lnNlstDens,
1364  double delLnFreq, double delFreq, double lnFreq, double lnLastFreq)
1365 {
1366  double exponent;
1367  double a;
1368 
1369  exponent = (lnNdens - lnNlstDens) / delLnFreq;
1370  if ( fabs(exponent) < N_INTFTHRESH )
1371  {
1372  return (noizDens * delFreq);
1373  } else
1374  {
1375  a = std::exp(lnNdens - exponent*lnFreq);
1376  exponent += 1.0;
1377  if (fabs(exponent) < N_INTUSELOG)
1378  {
1379  return (a * (lnFreq - lnLastFreq));
1380  }
1381  else
1382  {
1383  return (a * ((std::exp(exponent * lnFreq) - std::exp(exponent * lnLastFreq)) /
1384  exponent));
1385  }
1386  }
1387 }
1388 
1389 //-----------------------------------------------------------------------------
1390 // Function : NOISE::processSuccessfulStep()
1391 // Purpose :
1392 // Special Notes :
1393 // Scope : public
1394 // Creator : Eric Keiter, SNL
1395 // Creation Date : 12/8/2014
1396 //-----------------------------------------------------------------------------
1398 {
1399  bool bsuccess = true;
1400 
1401  // FIX OUTPUT
1403 
1406 
1407  if ( !firstDoubleDCOPStep() )
1408  {
1409  stepNumber += 1;
1412  }
1413 
1414  // This output call is for device-specific output (like from a PDE device,
1415  // outputting mesh-based tecplot files). It will only work in parallel if on
1416  // a machine where all processors have I/O capability.
1417  loader_.output();
1418 
1419  return bsuccess;
1420 }
1421 
1422 //-----------------------------------------------------------------------------
1423 // Function : NOISE::processFailedStep
1424 // Purpose :
1425 // Special Notes :
1426 // Scope : public
1427 // Creator : Eric Keiter, SNL
1428 // Creation Date : 12/8/2014
1429 //-----------------------------------------------------------------------------
1431 {
1432  bool bsuccess = true;
1433 
1434  stepNumber += 1;
1435  noiseSweepFailures_.push_back(stepNumber);
1438 
1439  return bsuccess;
1440 }
1441 
1442 //-----------------------------------------------------------------------------
1443 // Function : NOISE::finish
1444 // Purpose :
1445 // Special Notes :
1446 // Scope : public
1447 // Creator : Eric Keiter, SNL
1448 // Creation Date : 12/8/2014
1449 //-----------------------------------------------------------------------------
1451 {
1452  bool bsuccess = true;
1453 
1454  if (DEBUG_ANALYSIS)
1455  {
1456  Xyce::dout() << "Calling NOISE::doFinish() outputs!" << std::endl;
1457  }
1458 
1459  // FIX OUTPUT
1461 
1462  if (!(noiseSweepFailures_.empty()))
1463  {
1464  bsuccess = false;
1465  }
1466 
1467  return bsuccess;
1468 }
1469 
1470 
1471 //-----------------------------------------------------------------------------
1472 // Function : NOISE::doHandlePredictor
1473 // Purpose :
1474 // Special Notes :
1475 // Scope : private
1476 // Creator : Eric Keiter, SNL
1477 // Creation Date : 12/8/2014
1478 //-----------------------------------------------------------------------------
1480 {
1484 
1485  // In case this is the upper level of a 2-level sim, tell the
1486  // inner solve to do its prediction:
1488 
1489  return true;
1490 }
1491 
1492 //-----------------------------------------------------------------------------
1493 // Function : NOISE::updateCurrentFreq_(int stepNumber )
1494 // Purpose :
1495 // Special Notes : Used for NOISE analysis classes.
1496 // Scope : public
1497 // Creator : Eric Keiter, SNL.
1498 // Creation Date : 12/8/2014
1499 //-----------------------------------------------------------------------------
1500 bool NOISE::updateCurrentFreq_(int stepNumber)
1501 {
1503  if (type_ == "LIN")
1504  {
1505 
1506  currentFreq_ = fStart_ + static_cast<double>(stepNumber)*fstep_;
1507  }
1508  else if(type_ == "DEC" || type_ == "OCT")
1509  {
1510 
1511  currentFreq_ = fStart_*pow(stepMult_, static_cast<double>(stepNumber) );
1512  }
1513  else
1514  {
1515  Report::DevelFatal().in("NOISE::updateCurrentFreq_")
1516  << "NOISE::updateCurrentFreq_: unsupported STEP type";
1517  }
1518 
1520 
1521  lnFreq_ = std::log(std::max(currentFreq_,N_MINLOG));
1522  lnLastFreq_ = std::log(std::max(lastFreq_,N_MINLOG));
1524 
1525 #if 0
1526  if (isActive(Diag::TIME_PARAMETERS))
1527  {
1528  Xyce::dout() << "currentFreq_ = " << currentFreq_ << std::endl;
1529  Xyce::dout() << "lastFreq_ = " << lastFreq_ << std::endl;
1530  Xyce::dout() << "delFreq_ = " << delFreq_ << std::endl;
1531  }
1532 #endif
1533 
1534  return true;
1535 }
1536 
1537 //-----------------------------------------------------------------------------
1538 // Function : NOISE::setupSweepParam_
1539 // Purpose : Processes sweep parameters.
1540 // Special Notes : Used for NOISE analysis classes.
1541 // Scope : public
1542 // Creator : Eric Keiter, SNL.
1543 // Creation Date : 12/8/2014
1544 //-----------------------------------------------------------------------------
1546 {
1547  double fstart, fstop;
1548  double fcount = 0.0;
1549 
1550  fstart = fStart_;
1551  fstop = fStop_;
1552 
1553  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1554  {
1555  Xyce::dout() << std::endl << std::endl;
1556  Xyce::dout() << section_divider << std::endl;
1557  Xyce::dout() << "NOISE::setupSweepParam_" << std::endl;
1558  }
1559 
1560  if (type_ == "LIN")
1561  {
1562  int np = static_cast<int>(np_);
1563 
1564  if ( np == 1)
1565  fstep_ = 0;
1566  else
1567  fstep_ = (fstop - fstart)/(np_ - 1.0);
1568 
1569  fcount = np_;
1570  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1571  {
1572  Xyce::dout() << "fstep = " << fstep_ << std::endl;
1573  }
1574  }
1575  else if (type_ == "DEC")
1576  {
1577  stepMult_ = std::pow(10.0, 1.0/np_);
1578  fcount = floor(fabs(std::log10(fstart) - std::log10(fstop)) * np_ + 1.0);
1579  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1580  {
1581  Xyce::dout() << "stepMult_ = " << stepMult_ << std::endl;
1582  }
1583  }
1584  else if (type_ == "OCT")
1585  {
1586  stepMult_ = std::pow(2.0, 1.0/np_);
1587 
1588  // changed to remove dependence on "log2" function, which apparently
1589  // doesn't exist in the math libraries of FreeBSD or the mingw
1590  // cross-compilation suite. Log_2(x)=log_e(x)/log_e(2.0)
1591  double ln2 = std::log(2.0);
1592  fcount = floor(fabs(std::log(fstart) - std::log(fstop))/ln2 * np_ + 1.0);
1593  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1594  {
1595  Xyce::dout() << "stepMult_ = " << stepMult_ << std::endl;
1596  }
1597  }
1598  else
1599  {
1600  Report::DevelFatal().in("NOISE::setupSweepParam") << "Unsupported type";
1601  }
1602 
1603  // At this point, pinterval equals the total number of steps
1604  // for the step loop.
1605  return static_cast<int> (fcount);
1606 }
1607 
1608 namespace {
1609 
1610 //-----------------------------------------------------------------------------
1611 // Class : NOISEFactory
1612 // Purpose :
1613 // Special Notes :
1614 // Scope : public
1615 // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
1616 // Creation Date : Thu Jan 29 12:53:02 2015
1617 //-----------------------------------------------------------------------------
1618 ///
1619 /// Factory for parsing NOISE parameters from the netlist and creating NOISE analysis.
1620 ///
1621 class NOISEFactory : public Factory<NOISE>
1622 {
1623 public:
1624  //-----------------------------------------------------------------------------
1625  // Function : NOISEFactory
1626  // Purpose :
1627  // Special Notes :
1628  // Scope : public
1629  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
1630  // Creation Date : Thu Jan 29 12:54:09 2015
1631  //-----------------------------------------------------------------------------
1632  ///
1633  /// Constructs the NOISE analysis factory
1634  ///
1635  /// @invariant Stores the results of parsing, so if more than one of the analysis and
1636  /// associated lines are parsed, the second options simply overwrite the previously parsed
1637  /// values.
1638  ///
1639  /// @invariant The existence of the parameters specified in the constructor cannot
1640  /// change.
1641  ///
1642  /// @param analysis_manager
1643  /// @param linear_system
1644  /// @param nonlinear_manager
1645  /// @param topology
1646  ///
1647  NOISEFactory(
1648  Analysis::AnalysisManager & analysis_manager,
1649  Linear::System & linear_system,
1650  Nonlinear::Manager & nonlinear_manager,
1651  Topo::Topology & topology)
1652  : Factory<NOISE>(),
1653  analysisManager_(analysis_manager),
1654  linearSystem_(linear_system),
1655  nonlinearManager_(nonlinear_manager),
1656  topology_(topology)
1657  {}
1658 
1659  virtual ~NOISEFactory()
1660  {}
1661 
1662  //-----------------------------------------------------------------------------
1663  // Function : create
1664  // Purpose :
1665  // Special Notes :
1666  // Scope : public
1667  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
1668  // Creation Date : Thu Jan 29 12:59:00 2015
1669  //-----------------------------------------------------------------------------
1670  ///
1671  /// Create a new NOISE analysis and applies the analysis and time integrator option blocks.
1672  ///
1673  /// @return new NOISE analysis object
1674  ///
1675  NOISE *create() const
1676  {
1677  analysisManager_.setAnalysisMode(ANP_MODE_NOISE);
1678  NOISE *noise = new NOISE(analysisManager_, linearSystem_, nonlinearManager_, topology_);
1679  noise->setAnalysisParams(noiseAnalysisOptionBlock_);
1680  noise->setTimeIntegratorOptions(timeIntegratorOptionBlock_);
1681 
1682  return noise;
1683  }
1684 
1685  //-----------------------------------------------------------------------------
1686  // Function : setNOISEAnalysisOptionBlock
1687  // Purpose :
1688  // Special Notes :
1689  // Scope : public
1690  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
1691  // Creation Date : Thu Jan 29 13:00:14 2015
1692  //-----------------------------------------------------------------------------
1693  ///
1694  /// Saves the analysis parsed options block in the factory.
1695  ///
1696  /// @invariant Overwrites any previously specified analysis option block.
1697  ///
1698  /// @param option_block parsed option block
1699  ///
1700  void setNOISEAnalysisOptionBlock(const Util::OptionBlock &option_block)
1701  {
1702  noiseAnalysisOptionBlock_ = option_block;
1703  }
1704 
1705  //-----------------------------------------------------------------------------
1706  // Function : setTimeIntegratorOptionBlock
1707  // Purpose :
1708  // Special Notes :
1709  // Scope : public
1710  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
1711  // Creation Date : Thu Jan 29 13:01:27 2015
1712  //-----------------------------------------------------------------------------
1713  ///
1714  /// Saves the time integrator parsed option block.
1715  ///
1716  /// @invariant Overwrites any previously specified time integrator option block.
1717  ///
1718  /// @param option_block parsed option block
1719  ///
1720  void setTimeIntegratorOptionBlock(const Util::OptionBlock &option_block)
1721  {
1722  timeIntegratorOptionBlock_ = option_block;
1723  }
1724 
1725 public:
1726  AnalysisManager & analysisManager_;
1727  Linear::System & linearSystem_;
1728  Nonlinear::Manager & nonlinearManager_;
1729  Topo::Topology & topology_;
1730 
1731 private:
1732  Util::OptionBlock noiseAnalysisOptionBlock_;
1733  Util::OptionBlock timeIntegratorOptionBlock_;
1734 };
1735 
1736 // .options TIMEINT
1737 struct TimeIntegratorOptionsReg : public IO::PkgOptionsReg
1738 {
1739  TimeIntegratorOptionsReg(
1740  NOISEFactory & factory )
1741  : factory_(factory)
1742  {}
1743 
1744  bool operator()(const Util::OptionBlock &option_block)
1745  {
1746  factory_.setTimeIntegratorOptionBlock(option_block);
1747 
1748  return true;
1749  }
1750 
1751  NOISEFactory & factory_;
1752 };
1753 
1754 // .NOISE
1755 struct NOISEAnalysisReg : public IO::PkgOptionsReg
1756 {
1757  NOISEAnalysisReg(
1758  NOISEFactory & factory )
1759  : factory_(factory)
1760  {}
1761 
1762  bool operator()(const Util::OptionBlock &option_block)
1763  {
1764  factory_.setNOISEAnalysisOptionBlock(option_block);
1765 
1766  factory_.analysisManager_.addAnalysis(&factory_);
1767 
1768  return true;
1769  }
1770 
1771  NOISEFactory & factory_;
1772 };
1773 
1774 } // namespace <unnamed>
1775 
1776 //-----------------------------------------------------------------------------
1777 // Function : NOISEFactory::registerFactory
1778 // Purpose :
1779 //-----------------------------------------------------------------------------
1780 bool
1782  const std::string & netlist_filename,
1783  IO::PkgOptionsMgr & options_manager,
1784  AnalysisManager & analysis_manager,
1785  Linear::System & linear_system,
1786  Nonlinear::Manager & nonlinear_manager,
1787  Topo::Topology & topology)
1788 {
1789  NOISEFactory *factory = new NOISEFactory(analysis_manager, linear_system, nonlinear_manager, topology);
1790 
1791  analysis_manager.addAnalysisFactory(factory);
1792 
1793  options_manager.submitRegistration("NOISE", netlist_filename, new NOISEAnalysisReg(*factory));
1794  options_manager.submitRegistration("TIMEINT", netlist_filename, new TimeIntegratorOptionsReg(*factory));
1795 
1796  return true;
1797 }
1798 
1799 } // namespace Analysis
1800 } // namespace Xyce
Util::OptionBlock noiseAnalysisOptionBlock_
Definition: N_ANP_NOISE.C:1732
Linear::Vector * lastSolutionPtr
N_LAS_BlockVector * saved_AC_X_
Definition: N_ANP_NOISE.h:198
Linear::Vector * nextLeadCurrentQPtr
unsigned int successfulStepsTaken_
Number of consecutive successful time-integration steps.
std::vector< double > dOdpVec_
Definition: N_ANP_NOISE.h:209
virtual bool setInitialGuess(Linear::Vector *solVectorPtr)
Definition: N_LOA_Loader.h:231
Nonlinear::Manager & nonlinearManager_
Definition: N_ANP_NOISE.h:143
Linear::Vector * lastLeadDeltaVPtr
Nonlinear::Manager & nonlinearManager_
Definition: N_ANP_NOISE.C:1728
std::vector< double > scaled_dOdpAdjVec_
Definition: N_ANP_NOISE.h:212
bool setTimeIntegratorOption(const Util::Param &param)
TimeIntg::TIAParams tiaParams_
Definition: N_ANP_NOISE.h:146
Linear::System & linearSystem_
Definition: N_ANP_NOISE.C:1727
N_LAS_BlockMatrix * ACMatrix_
Definition: N_ANP_NOISE.h:195
void outputAC(double freq, const Linear::Vector &solnVecRealPtr, const Linear::Vector &solnVecImaginaryPtr)
Pure virtual class to augment a linear system.
#define N_INTUSELOG
Definition: N_ANP_NOISE.C:113
int doubleDCOPStep_
current step in the DCOP loop.
void dcOutput(int dcStepNumber, Linear::Vector &currSolutionPtr, Linear::Vector &stateVecPtr, Linear::Vector &storeVecPtr, Linear::Vector &lead_current_vector, Linear::Vector &junction_voltage_vector, std::vector< double > &objectiveVec_, std::vector< double > &dOdpVec_, std::vector< double > &dOdpAdjVec_, std::vector< double > &scaled_dOdpVec_, std::vector< double > &scaled_dOdpAdjVec_)
virtual bool loadDAEVectors(Linear::Vector *nextSolVectorPtr, Linear::Vector *currSolVectorPtr, Linear::Vector *lastSolVectorPtr, Linear::Vector *nextStaVectorPtr, Linear::Vector *currStaVectorPtr, Linear::Vector *lastStaVectorPtr, Linear::Vector *StaDerivVectorPtr, Linear::Vector *nextStoVectorPtr, Linear::Vector *currStoVectorPtr, Linear::Vector *lastStoVectorPtr, Linear::Vector *stoLeadCurrQVectorPtr, Linear::Vector *nextLeadFVectorPtr, Linear::Vector *currLeadFVectorPtr, Linear::Vector *lastLeadFVectorPtr, Linear::Vector *nextLeadQVectorPtr, Linear::Vector *nextJunctionVVectorPtr, Linear::Vector *currJunctionVVectorPtr, Linear::Vector *lastJunctionVVectorPtr, Linear::Vector *QVectorPtr, Linear::Vector *FVectorPtr, Linear::Vector *BVectorPtr, Linear::Vector *dFdxdVpVectorPtr, Linear::Vector *dQdxdVpVectorPtr)
Definition: N_LOA_Loader.h:121
virtual int getNumNoiseDevices()
Definition: N_LOA_Loader.h:214
unsigned int stepNumber
Time-integration step number counter.
NOISE(AnalysisManager &analysis_manager, Linear::System &linear_system, Nonlinear::Manager &nonlinear_manager, Topo::Topology &topology)
Definition: N_ANP_NOISE.C:172
virtual bool loadBVectorsforAC(Linear::Vector *bVecRealPtr, Linear::Vector *bVecImagPtr)
Definition: N_LOA_Loader.h:202
bool registerNOISEFactory(const std::string &netlist_filename, IO::PkgOptionsMgr &options_manager, AnalysisManager &analysis_manager, Linear::System &linear_system, Nonlinear::Manager &nonlinear_manager, Topo::Topology &topology)
Definition: N_ANP_NOISE.C:1781
Linear::Vector * currStorePtr
Linear::Vector * lastStatePtr
Epetra_LinearProblem * blockProblem_
Definition: N_ANP_NOISE.h:201
void gatherStepStatistics(StatCounts &stats, Nonlinear::NonLinearSolver &nonlinear_solver, int newton_convergence_status)
void createTimeIntegratorMethod(const TimeIntg::TIAParams &tia_params, const unsigned int integration_method)
N_LAS_Matrix * G_
Definition: N_ANP_NOISE.h:194
bool setupInitialConditions(Linear::Vector &solnVec, Linear::Vector &flagVec)
std::vector< double > objectiveVec_
Definition: N_ANP_NOISE.h:208
bool resetAll(const TIAParams &tia_params)
std::string specifiedSource_
Definition: N_ANP_NOISE.h:161
std::vector< int > noiseSweepFailures_
Definition: N_ANP_NOISE.h:164
Util::ListenerAutoSubscribe< StepEvent > StepEventListener
Linear::Vector * nextLeadDeltaVPtr
Linear::Vector * currStatePtr
unsigned int failedStepsAttempted_
Total number of failed time-integration steps.
Parallel::Manager * getPDSManager() const
bool setDCOPOption(const Util::Param &param)
TimeIntg::StepErrorControl & getStepErrorControl()
#define N_MINLOG
Definition: N_ANP_NOISE.C:104
const std::string & getNetlistFilename() const
NonLinearSolver & getNonlinearSolver()
Linear::Vector * daeQVectorPtr
AnalysisManager & analysisManager_
Definition: N_ANP_NOISE.h:140
AnalysisManager & analysisManager_
Definition: N_ANP_NOISE.C:1726
Linear::Vector * lastLeadCurrentPtr
virtual bool startTimeStep()
Definition: N_LOA_Loader.h:304
void setErrorWtVector(const TIAParams &tia_params)
Linear::Vector * daeFVectorPtr
N_LAS_BlockVector * X_
Definition: N_ANP_NOISE.h:197
bool getDCOPFlag() const
Definition: N_ANP_NOISE.C:375
NOISEFactory & factory_
Definition: N_ANP_NOISE.C:1751
Linear::Matrix * dFdxMatrixPtr
virtual bool updateSources()
Definition: N_LOA_Loader.h:243
N_LAS_System & linearSystem_
Definition: N_ANP_NOISE.h:142
Linear::Vector * nextStatePtr
Linear::Vector * dFdxdVpVectorPtr
bool updateCurrentFreq_(int stepNumber)
Definition: N_ANP_NOISE.C:1500
virtual bool loadDAEMatrices(Linear::Vector *tmpSolVectorPtr, Linear::Vector *tmpStaVectorPtr, Linear::Vector *tmpStaDerivVectorPtr, Linear::Vector *tmpStoVectorPtr, Linear::Matrix *tmpdQdxMatrixPtr, Linear::Matrix *tmpdFdxMatrixPtr)
Definition: N_LOA_Loader.h:109
virtual bool updateState(Linear::Vector *nextSolVectorPtr, Linear::Vector *currSolVectorPtr, Linear::Vector *lastSolVectorPtr, Linear::Vector *nextStaVectorPtr, Linear::Vector *currStaVectorPtr, Linear::Vector *lastStaVectorPtr, Linear::Vector *nextStoVectorPtr, Linear::Vector *currStoVectorPtr, Linear::Vector *lastStoVectorPtr)
Definition: N_LOA_Loader.h:188
Linear::Vector * currLeadDeltaVPtr
N_LAS_BlockVector * B_
Definition: N_ANP_NOISE.h:196
N_LAS_Vector * bVecImagPtr
Definition: N_ANP_NOISE.h:150
std::vector< Xyce::Analysis::NoiseData * > noiseDataVec_
Definition: N_ANP_NOISE.h:206
void addAnalysisFactory(Factory< void > *factory)
Loader::Loader & loader_
Definition: N_ANP_NOISE.h:141
virtual void getNoiseSources(std::vector< Xyce::Analysis::NoiseData * > &noiseDataVec)
Definition: N_LOA_Loader.h:222
#define N_INTFTHRESH
Definition: N_ANP_NOISE.C:109
N_LAS_Matrix * C_
Definition: N_ANP_NOISE.h:193
Linear::Vector * nextSolutionPtr
std::vector< double > scaled_dOdpVec_
Definition: N_ANP_NOISE.h:211
#define M_PI
Topo::Topology & topology_
Definition: N_ANP_NOISE.C:1729
void notify(const StepEvent &event)
Definition: N_ANP_NOISE.C:267
virtual bool getDoubleDCOPFlag() const
Definition: N_LOA_Loader.h:255
virtual void setupNoiseSources(std::vector< Xyce::Analysis::NoiseData * > &noiseDataVec)
Definition: N_LOA_Loader.h:219
Linear::Vector * nextStorePtr
bool setTimeIntegratorOptions(const Util::OptionBlock &option_block)
Definition: N_ANP_NOISE.C:130
The analysis factory template defines an interface for analysis type testing and analysis creation...
Definition: N_ANP_Factory.h:65
Amesos_BaseSolver * blockSolver_
Definition: N_ANP_NOISE.h:200
Linear::Vector * dQdxdVpVectorPtr
N_LAS_Vector * bVecRealPtr
Definition: N_ANP_NOISE.h:149
Topo::Topology & topology_
Definition: N_ANP_NOISE.h:144
bool setAnalysisParams(const N_UTL_OptionBlock &paramsBlock)
Definition: N_ANP_NOISE.C:291
std::vector< std::string > outputVarNames_
Definition: N_ANP_NOISE.h:203
Linear::Vector * currLeadCurrentPtr
Linear::Vector * lastStorePtr
void setInputOPFlag(bool initial_conditions_loaded)
TimeIntg::WorkingIntegrationMethod & getWorkingIntegrationMethod()
std::string outputNode2_
Definition: N_ANP_NOISE.h:160
std::string outputNode1_
Definition: N_ANP_NOISE.h:159
const IO::CmdParse & getCommandLine() const
N_LAS_Vector * bNoiseVecImagPtr
Definition: N_ANP_NOISE.h:154
std::vector< int > outputVarGIDs_
Definition: N_ANP_NOISE.h:204
OutputMgrAdapter & outputManagerAdapter_
Definition: N_ANP_NOISE.h:145
Linear::Vector * currSolutionPtr
TimeIntg::DataStore * getDataStore()
void evaluateStepError(const TIAParams &tia_params)
bool doubleDCOPFlag_
true if doing a double-DCOP is possible.
unsigned int baseIntegrationMethod_
Current time-integration method flag.
void resetAdjointNOISELinearSystem_()
Definition: N_ANP_NOISE.C:1103
#define N_MINGAIN
Definition: N_ANP_NOISE.C:105
Linear::Vector * nextStoreLeadCurrQPtr
Util::OptionBlock timeIntegratorOptionBlock_
Definition: N_ANP_NOISE.C:1733
Linear::Vector * nextStateDerivPtr
void outputNoise(double freq, double totalOutputNoiseDens_, double totalInputNoiseDens_, const std::vector< Xyce::Analysis::NoiseData * > &noiseDataVec_)
void outputDCOP(const Linear::Vector &solution)
double noiseIntegral(double noizDens, double lnNdens, double lnNlstDens, double delLnFreq, double delFreq, double lnFreq, double lnLastFreq)
Definition: N_ANP_NOISE.C:1363
Linear::Matrix * dQdxMatrixPtr
Linear::Vector * flagSolutionPtr
std::vector< double > dOdpAdjVec_
Definition: N_ANP_NOISE.h:210
Linear::Vector * daeBVectorPtr
bool setReturnCodeOption(const Util::Param &param)
N_LAS_Vector * bNoiseVecRealPtr
Definition: N_ANP_NOISE.h:153
virtual bool output() const
Definition: N_LOA_Loader.h:260
Linear::Vector * nextLeadCurrentPtr