46 #include <Xyce_config.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>
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>
73 #include <Epetra_CrsMatrix.h>
90 Topo::Topology & topTmp)
100 matrixDiagonalPtr_(0),
102 jacobianMatrixPtr_(0),
103 nextSolVectorPtrPtr_(0),
104 currSolVectorPtrPtr_(0),
105 savedRHSVectorPtr_(0),
106 savedNewtonVectorPtr_(0),
110 gidsSetUpFlag_(false)
130 #ifdef Xyce_PARALLEL_MPI
133 columnMapPtr_ =
new N_PDS_ParMap( &(const_cast<Epetra_Map&>(col_map)),
168 for (
int ivec=0; ivec<vecSize ;++ivec)
213 bool bsuccess =
true;
215 for (Util::ParamList::const_iterator it_tpL = OB.begin();
216 it_tpL != OB.end(); ++ it_tpL)
218 if (it_tpL->uTag() ==
"DEBUGLEVEL")
220 setNonlinearConductanceDebugLevel(it_tpL->getImmutableValue<
int>());
248 const std::map<std::string, double> & inputMap)
250 bool bsuccess =
true;
253 int idSize = inputMap.size();
258 for (
int i=0; i<idSize ;++i)
269 std::map<std::string,double>::const_iterator iterM = inputMap.begin();
270 std::map<std::string,double>::const_iterator endM = inputMap.end ();
272 for (; iterM != endM; ++i, ++iterM)
276 ExtendedString src = iterM->first;
278 std::string sourceName = src;
284 std::vector<int> GIDList, extGIDList;
285 top_.getNodeSVarGIDs(NodeID(sourceName, Xyce::_DNODE), GIDList, extGIDList, type);
287 std::vector<int>::iterator iterI;
288 if (!(GIDList.empty ()))
290 iterI = GIDList.begin();
294 iterI = extGIDList.begin();
300 std::string msg =
"ConductanceExtractor::setupIDs_";
301 msg +=
" The " + sourceName +
" source has the positive node"
302 " owned by another processor. The 2-level solve can't handle that.";
303 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
308 int vnegGID = *iterI;
311 std::string msg =
"ConductanceExtractor::setupIDs_";
312 msg +=
" The " + sourceName +
" source has the negative node"
313 " connected to something other than ground! The 2-level solve can't handle that.";
314 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
320 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
322 Xyce::dout() <<
"current GIDs: " << std::endl;
323 for(
int i1=0; i1 < idSize; ++i1 )
325 Xyce::dout() <<
" currentGIDs_["<<i1<<
"] = " <<
currentGIDs_[i1] <<
", currentLIDs_["<<i1<<
"] = " <<
currentLIDs_[i1] << std::endl;
328 Xyce::dout() <<
"Vsrc pos equation rows: " << std::endl;
329 for(
int i1=0; i1 < idSize; ++i1 )
331 Xyce::dout() <<
" vsrcPosGIDs_["<<i1<<
"] = " <<
vsrcPosGIDs_[i1] <<
", vsrcPosLIDs_["<<i1<<
"] = " <<
vsrcPosLIDs_[i1] << std::endl;
350 bool bsuccess =
true;
364 Linear::Vector * currentVec;
366 for(
int iC_row=0; iC_row < idSize; ++iC_row )
368 #ifdef Xyce_PARALLEL_MPI
374 currentVec->putScalar(0.0);
380 int numEntries = rowLength;
381 std::vector<double> coeffs(rowLength, 0.0);
382 std::vector<int> colIndices(rowLength, -1);
385 (iRow, rowLength, numEntries, &coeffs[0], &colIndices[0]);
387 for (
int ic=0;ic<rowLength;++ic)
391 int gid = colIndices[ic];
395 for (
int icol=0;icol<rowLength;++icol)
397 double val = coeffs[icol];
398 int gid = colIndices[icol];
400 currentVec->setElementByGlobalIndex(gid, val, 0);
403 currentVec->fillComplete();
405 #ifdef Xyce_PARALLEL_MPI
409 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
411 Xyce::dout() <<
"\ndIdx[" << iC_row <<
"]:" << std::endl;
429 const std::map<std::string,double> & inputMap,
430 std::vector<double> & outputVector,
431 std::vector< std::vector<double> > & jacobian)
433 bool bsuccess =
true;
435 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
437 Xyce::dout() << subsection_divider << std::endl;
438 Xyce::dout() <<
"ConductanceExtractor::extract" << std::endl;
439 Xyce::dout() << subsection_divider << std::endl;
442 if (inputMap.empty() ||
443 outputVector.empty() ||
470 outputVector[i] = solnVecPtr->getElementByGlobalIndex(index1);
472 outputVector[i] = 0.0;
475 #ifdef Xyce_PARALLEL_MPI
478 std::vector<double> tmpVector(idSize,0.0);
479 for(
int i = 0; i < idSize; ++i )
481 tmpVector[i] = outputVector[i];
482 outputVector[i] = 0.0;
485 comm.sumAll( &(tmpVector[0]), &(outputVector[0]), idSize );
488 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
491 for (itmp=0;itmp < outputVector.size();++itmp)
493 Xyce::dout() <<
"currentVector["<< itmp <<
"] = " << outputVector[itmp]<<std::endl;
544 double diagInfNorm = 0.0;
552 if (diagInfNorm < 1.0e-30)
554 if (DEBUG_CONDUCTANCE)
555 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_WARNING_0,
556 "\n\tJacobian for inner problem not loaded. Forcing a load.\n");
566 std::map<std::string,double>::const_iterator iterM = inputMap.begin();
567 std::map<std::string,double>::const_iterator endM = inputMap.end ();
569 for (;iV_col<idSize;++iV_col,++iterM)
576 (*dfdvVectorPtr_)[irow] = 1.0;
581 for (;iC_row<idSize;++iC_row)
586 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
588 std::string vsrcName = iterM->first;
590 Xyce::dout() <<
"dIdv = " << dIdv << std::endl;
594 jacobian[iC_row][iV_col] = dIdv;
606 if (VERBOSE_CONDUCTANCE)
627 bool bsuccess =
true;
635 for (
int i=0; i<idSize ;++i)
646 ExtendedString src = isoName;
648 std::string sourceName = src;
654 std::vector<int> GIDList, extGIDList;
655 top_.getNodeSVarGIDs(NodeID(sourceName, Xyce::_DNODE), GIDList, extGIDList, type);
657 if (!(GIDList.empty ()))
659 std::vector<int>::iterator gidIter = GIDList.begin();
660 std::vector<int>::iterator gidExtIter = extGIDList.begin();
663 for (i=0;i<idSize;++i,++gidIter,++gidExtIter)
671 for (i=0;i<idSize;++i,++gidExtIter)
680 std::string msg =
"ConductanceExtractor::setupISO_IDs_";
681 msg +=
" The " + sourceName +
" source has the positive node"
682 " owned by another processor. The 2-level solve can't handle that.";
683 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
692 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
694 Xyce::dout() <<
"current GIDs: " << std::endl;
695 for(
int i1=0; i1 < idSize; ++i1 )
697 Xyce::dout() <<
" currentGIDs_["<<i1<<
"] = " <<
currentGIDs_[i1] << std::endl;
700 Xyce::dout() <<
"Vsrc pos equation rows: " << std::endl;
701 for(
int i1=0; i1 < idSize; ++i1 )
703 Xyce::dout() <<
" vsrcPosGIDs_["<<i1<<
"] = " <<
vsrcPosGIDs_[i1] << std::endl;
729 (
const std::string & isoName, std::vector< std::vector<double> > & jacobian )
731 bool bsuccess =
true;
733 int idSize = jacobian.size();
735 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
737 Xyce::dout() << subsection_divider << std::endl;
738 Xyce::dout() <<
"ConductanceExtractor::extract - iso2" << std::endl;
739 Xyce::dout() << subsection_divider << std::endl;
744 setupISO2_IDs_(isoName);
748 savedRHSVectorPtr_->putScalar(0.0);
749 savedRHSVectorPtr_->addVec(1.0, *(rhsVectorPtr_));
751 savedNewtonVectorPtr_->putScalar(0.0);
752 savedNewtonVectorPtr_->addVec(1.0, *(NewtonVectorPtr_));
755 bool b1 = setup_dIdX_Vectors_(); bsuccess = bsuccess && b1;
760 for (;iV_col<idSize;++iV_col)
763 dfdvVectorPtr_->putScalar(0.0);
764 int irow = currentLIDs_[iV_col];
767 (*dfdvVectorPtr_)[irow] = 1.0;
769 lasSolverPtr_->solve();
772 for (;iC_row<idSize;++iC_row)
775 double dIdv = dIdxPtrVector_[iC_row]->dotProduct(*(dxdvVectorPtr_));
777 if (DEBUG_CONDUCTANCE && isActive(Diag::NONLINEAR_CONDUCTANCE))
779 std::string tmpName =
"unknown";
780 printPetraObjects_ (tmpName);
781 Xyce::dout() <<
"dIdv = " << dIdv << std::endl;
785 jacobian[iC_row][iV_col] = dIdv;
791 rhsVectorPtr_->putScalar(0.0);
792 rhsVectorPtr_->addVec(1.0, *(savedRHSVectorPtr_));
794 NewtonVectorPtr_->putScalar(0.0);
795 NewtonVectorPtr_->addVec(1.0, *(savedNewtonVectorPtr_));
797 if (VERBOSE_CONDUCTANCE)
799 varMap_[
"Var 0"] = 0.0;
800 varMap_[
"Var 1"] = 0.0;
801 printJacobian_ (varMap_,jacobian);
816 (
const std::map<std::string,double> & inputMap,
817 std::vector< std::vector<double> > & jacobian)
819 Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
820 Xyce::dout() <<
"Output Jacobian/Conductance array: \n";
824 int numElectrodes = jacobian.size();
825 std::map<std::string,double>::const_iterator iterM = inputMap.begin();
826 std::map<std::string,double>::const_iterator endM = inputMap.end ();
827 for (iE1 = 0; iE1 < numElectrodes; ++iE1,++iterM)
829 Xyce::dout() <<
"\t"<<iterM->first;
831 Xyce::dout() << std::endl;
832 iterM = inputMap.begin();
833 for (iE1 = 0; iE1 < numElectrodes; ++iE1,++iterM)
835 Xyce::dout() <<
"\t"<<iterM->first;
836 for (iE2 = 0; iE2 < numElectrodes; ++iE2)
838 Xyce::dout() <<
"\t" <<jacobian[iE1][iE2];
840 Xyce::dout() << std::endl;
842 Xyce::dout() << std::endl;
857 Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
858 std::string srcName = varName;
859 Xyce::dout() <<
"Info for input voltage: " << srcName << std::endl;
860 Xyce::dout() <<
"Jacobian:" << std::endl;
864 Xyce::dout() <<
"dxdv:" << std::endl;
867 Xyce::dout() <<
"dfdv:" << std::endl;
Pure virtual class to augment a linear system.
Linear::Vector * rhsVectorPtr_
Linear::Matrix * jacobianMatrixPtr_
Linear::System * lasSysPtr_
Linear::Vector ** nextSolVectorPtrPtr_
Linear::Solver * lasSolverPtr_
Linear::Vector * NewtonVectorPtr_
Linear::Vector ** currSolVectorPtrPtr_
Loader::NonlinearEquationLoader * loaderPtr_