46 #include <Xyce_config.h>
63 #include <N_ERH_ErrorMgr.h>
65 #include <N_LAS_Vector.h>
66 #include <N_LAS_Matrix.h>
67 #include <N_UTL_FeatureTest.h>
68 #include <N_UTL_ExtendedString.h>
93 val_local(mlData1.val_local),
94 Qval_local(mlData1.Qval_local),
95 col_local(mlData1.col_local),
96 row_local(mlData1.row_local),
97 internalFlag(mlData1.internalFlag),
113 : mlData(right.mlData),
117 val_local(right.val_local),
118 Qval_local(right.Qval_local),
119 col_local(right.col_local),
120 row_local(right.row_local),
121 internalFlag(right.internalFlag),
122 solState (right.solState),
123 extData (right.extData),
124 devOptions(right.devOptions),
125 maxCols(right.maxCols)
173 const std::vector<int> & devLIDs = instance.
getDevLIDs();
174 const std::vector<int> & devStateLIDs = instance.
getStaLIDVec();
175 const std::vector< std::vector<int> > & devJacLIDs = instance.
getDevJacLIDs();
176 const std::vector< std::vector<int> > & jacStamp = instance.
jacobianStamp();
180 std::vector< std::vector<double> > & numJacF =
mlData.
numJac;
181 std::vector< std::vector<double> > & saveJacF =
mlData.
saveJac;
182 std::vector< std::vector<double> > & devJacF =
mlData.
devJac;
183 std::vector< std::vector<double> > & diffJacF =
mlData.
diffJac;
184 std::vector< std::vector<double> > & relJacF =
mlData.
relJac;
186 std::vector< std::vector<double> > & numJacQ =
mlData.
numJacQ;
188 std::vector< std::vector<double> > & devJacQ =
mlData.
devJacQ;
190 std::vector< std::vector<double> > & relJacQ =
mlData.
relJacQ;
192 std::vector< std::vector<int> > & statusF =
mlData.
status;
227 int numRows, numCols;
228 numCols = devLIDs.size();
229 numRows = jacStamp.size();
231 int testSize= (numRows>numCols)?numRows:numCols;
232 if (testSize > saveF.size())
238 int numState = devStateLIDs.size();
239 if (numState > saveCurrState.size())
246 if(devJacLIDs.empty())
250 Report::UserWarning() << instance.
getName() <<
" does not have jacLIDs available";
256 if (instance.
getOrigFlag() && numRows > 0 && numRows == jacStamp.size())
260 saveF.assign(saveF.size(),0.0);
261 pertF.assign(pertF.size(),0.0);
262 origF.assign(origF.size(),0.0);
264 saveQ.assign(saveQ.size(),0.0);
265 pertQ.assign(pertQ.size(),0.0);
266 origQ.assign(origQ.size(),0.0);
268 saveSoln.assign(saveSoln.size(),0.0);
269 pertSoln.assign(pertSoln.size(),0.0);
270 saveCurrSoln.assign(saveCurrSoln.size(),0.0);
272 saveLastState.assign(saveLastState.size(),0.0);
273 saveCurrState.assign(saveCurrState.size(),0.0);
274 saveNextState.assign(saveNextState.size(),0.0);
275 saveStateDerivs.assign(saveStateDerivs.size(),0.0);
276 for (i=0;i<numJacF.size();++i)
278 numJacF[i].assign(numJacF[i].size(),0.0);
279 saveJacF[i].assign(saveJacF[i].size(),0.0);
280 devJacF[i].assign(devJacF[i].size(),0.0);
281 diffJacF[i].assign(diffJacF[i].size(),0.0);
282 statusF[i].assign(statusF[i].size(),-1);
283 stencil[i].assign(stencil[i].size(),0);
285 numJacQ[i].assign(numJacQ[i].size(),0.0);
286 saveJacQ[i].assign(saveJacQ[i].size(),0.0);
287 devJacQ[i].assign(devJacQ[i].size(),0.0);
288 diffJacQ[i].assign(diffJacQ[i].size(),0.0);
289 statusQ[i].assign(statusQ[i].size(),-1);
295 int tmpSize= (numRows>numCols)?numRows:numCols;
297 for (i=0 ; i<tmpSize; ++i)
299 saveF[i] = Fvec[devLIDs[i]];
300 saveQ[i] = Qvec[devLIDs[i]];
302 saveSoln[i] = nextSol[devLIDs[i]];
303 saveCurrSoln[i] = currSol[devLIDs[i]];
304 pertSoln[i] = sqrtEta * (1.0 + fabs(saveSoln[i]));
307 for (i=0 ; i<numState ; ++i)
309 saveLastState[i] = lastSta[devStateLIDs[i]];
310 saveCurrState[i] = currSta[devStateLIDs[i]];
311 saveNextState[i] = nextSta[devStateLIDs[i]];
312 saveStateDerivs[i] = nextStaDeriv[devStateLIDs[i]];
316 for (i=0 ; i<numRows ; ++i)
318 jCol = devJacLIDs[i].size();
319 for (j=0 ; j<jCol ; ++j)
321 double valF = dFdxMat[devLIDs[i]][devJacLIDs[i][j]];
322 saveJacF[i][j] = valF;
323 double valQ = dQdxMat[devLIDs[i]][devJacLIDs[i][j]];
324 saveJacQ[i][j] = valQ;
331 for (i=0 ; i<numRows ; ++i)
333 jCol = devJacLIDs[i].size();
334 for (j=0 ; j<jCol ; ++j)
336 dFdxMat[devLIDs[i]][devJacLIDs[i][j]] = 0;
337 dQdxMat[devLIDs[i]][devJacLIDs[i][j]] = 0;
347 for (i=0 ; i<numRows ; ++i)
349 devJacF[i].assign(devJacF[i].size(),0.0);
350 devJacQ[i].assign(devJacQ[i].size(),0.0);
351 stencil[i].assign(stencil[i].size(),0);
353 jCol = devJacLIDs[i].size();
354 for (j=0 ; j<jCol ; ++j)
356 double valF = dFdxMat[devLIDs[i]][devJacLIDs[i][j]];
357 devJacF[i][jacStamp[i][j]] = valF;
358 double valQ = dQdxMat[devLIDs[i]][devJacLIDs[i][j]];
359 devJacQ[i][jacStamp[i][j]] = valQ;
360 stencil[i][jacStamp[i][j]] = 1;
366 for (i=0 ; i<numRows ; ++i)
368 Fvec[devLIDs[i]] = 0.0;
369 Qvec[devLIDs[i]] = 0.0;
375 for (i=0 ; i<numRows ; ++i)
377 origF[i] = Fvec[devLIDs[i]];
378 origQ[i] = Qvec[devLIDs[i]];
381 for (i=0 ; i<numRows ; ++i)
383 jCol = devJacLIDs[i].size();
384 for (j=0 ; j<jCol ; ++j)
386 statusF[i][jacStamp[i][j]] = -1;
387 statusQ[i][jacStamp[i][j]] = -1;
405 double ndFdx, adFdx, ddFdx, relError_dFdx;
406 double ndQdx, adQdx, ddQdx, relError_dQdx;
408 bool failedTest =
false;
409 for (i=0 ; i<numCols ; ++i)
412 if (*nameVec[devLIDs[i]] ==
"gnd")
continue;
414 for (j=0 ; j<numRows ; ++j)
416 nextSol[devLIDs[j]] = saveSoln[j];
417 currSol[devLIDs[j]] = saveCurrSoln[j];
418 Fvec[devLIDs[j]] = 0.0;
419 Qvec[devLIDs[j]] = 0.0;
422 for (j=0 ; j<numState ; ++j)
424 lastSta[devStateLIDs[j]] = saveLastState[j];
425 currSta[devStateLIDs[j]] = saveCurrState[j];
426 nextSta[devStateLIDs[j]] = saveNextState[j];
427 nextStaDeriv[devStateLIDs[j]] = saveStateDerivs[j];
431 double dX = pertSoln[i];
432 nextSol[devLIDs[i]] += dX;
437 for (j=0 ; j<numRows ; ++j)
439 pertF[j] = Fvec[devLIDs[j]];
440 pertQ[j] = Qvec[devLIDs[j]];
443 #ifdef Xyce_DEBUG_TESTJAC
447 for (j=0 ; j<numRows ; ++j)
450 if (*nameVec[devLIDs[j]] ==
"gnd")
continue;
454 if (stencil[j][i]!=1)
continue;
456 double dF = (pertF[j]-origF[j]);
457 double dQ = (pertQ[j]-origQ[j]);
458 numJacF[j][i] = dF/dX;
459 numJacQ[j][i] = dQ/dX;
461 ndFdx = numJacF[j][i];
462 adFdx = devJacF[j][i];
463 ddFdx = fabs(adFdx-ndFdx);
464 relError_dFdx = ddFdx/(relTol*fabs(ndFdx)+absTol);
466 diffJacF[j][i] = ddFdx;
467 relJacF[j][i] = relError_dFdx;
469 ndQdx = numJacQ[j][i];
470 adQdx = devJacQ[j][i];
471 ddQdx = fabs(adQdx-ndQdx);
472 relError_dQdx = ddQdx/(relTol*fabs(ndQdx)+absTol);
474 diffJacQ[j][i] = ddQdx;
475 relJacQ[j][i] = relError_dQdx;
477 #ifdef Xyce_DEBUG_TESTJAC
478 if (
isnan(numJacF[j][i]))
485 ExtendedString varNameI(*nameVec[devLIDs[i]]); varNameI.toUpper();
486 ExtendedString varNameJ(*nameVec[devLIDs[j]]); varNameJ.toUpper();
491 if (adFdx == 1 && ndFdx == 0)
507 if ( statusF[j][i] != 3 )
509 if (relError_dFdx > 1.0)
519 if (relError_dQdx > 1.0)
531 #ifdef Xyce_DEBUG_TESTJAC
544 tmpSize= (numRows>numCols)?numRows:numCols;
545 for (i=0 ; i<tmpSize; ++i)
547 Fvec[devLIDs[i]] = saveF[i];
548 Qvec[devLIDs[i]] = saveQ[i];
549 nextSol[devLIDs[i]] = saveSoln[i];
550 currSol[devLIDs[i]] = saveCurrSoln[i];
552 for (i=0 ; i<numState ; ++i)
554 lastSta[devStateLIDs[i]] = saveLastState[i];
555 currSta[devStateLIDs[i]] = saveCurrState[i];
556 nextSta[devStateLIDs[i]] = saveNextState[i];
557 nextStaDeriv[devStateLIDs[i]] = saveStateDerivs[i];
561 for (i=0 ; i<numRows ; ++i)
563 jCol = devJacLIDs[i].size();
564 for (j=0 ; j<jCol ; ++j)
566 dFdxMat[devLIDs[i]][devJacLIDs[i][j]] = saveJacF[i][j];
567 dQdxMat[devLIDs[i]][devJacLIDs[i][j]] = saveJacQ[i][j];
590 const std::vector<int> & devStateLIDs = instance.
getStaLIDVec();
591 int numState = devStateLIDs.size();
600 for (
int j=0 ; j<numState ; ++j)
602 nextStaDeriv[devStateLIDs[j]] =
603 solState.
pdt_ * (nextSta[devStateLIDs[j]]-currSta[devStateLIDs[j]]);
624 const std::vector<const std::string *> & nameVec,
628 const std::vector<int> & devLIDs = instance.
getDevLIDs();
632 const std::vector< std::vector<double> > & numJac =
mlData.
numJac;
633 const std::vector< std::vector<double> > & anaJac =
mlData.
devJac;
634 const std::vector< std::vector<double> > & diffJac =
mlData.
diffJac;
635 const std::vector< std::vector<double> > & relJac =
mlData.
relJac;
636 const std::vector< std::vector<int> > & stencil =
mlData.
stencil;
637 const std::vector< std::vector<int> > & status =
mlData.
status;
640 os << Xyce::section_divider << std::endl;
641 os <<
"dFdx matrix for " << instance.
getName();
645 os <<
": JACOBIAN TEST FAILURE";
649 os <<
": JACOBIAN TEST SUCCESS";
654 os <<
" Numerical Analytic absDiff relative Error Status Names (row, col)"<<std::endl;
657 int numCols = devLIDs.size();
658 int numRows = (status.size()<numCols)?status.size():numCols;
660 for (i = 0; i < numRows; ++i)
662 if (*nameVec[devLIDs[i]] ==
"gnd")
continue;
664 for (j = 0; j < numCols; ++j)
666 if (*nameVec[devLIDs[j]] ==
"gnd")
continue;
669 if (status[i][j]==-1)
continue;
672 if (stencil[i][j]!=1)
continue;
675 static char tmpChar[128];
676 static char prefix[4];
678 sprintf(prefix,
"%s",
"FT:");
680 if (status[i][j]==-2)
682 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e fail",prefix,
683 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
685 else if (status[i][j]==3)
688 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e NA ",prefix,
689 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
693 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e ",prefix,
694 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
697 os << std::string(tmpChar);
699 os <<
" ("<< *nameVec[devLIDs[i]]
700 <<
", " << *nameVec[devLIDs[j]]
702 <<
" row,col=[ " << i <<
", " << j <<
"]" << std::endl;
709 const std::vector< std::vector<double> > & numJac =
mlData.
numJacQ;
710 const std::vector< std::vector<double> > & anaJac =
mlData.
devJacQ;
711 const std::vector< std::vector<double> > & diffJac =
mlData.
diffJacQ;
712 const std::vector< std::vector<double> > & relJac =
mlData.
relJacQ;
713 const std::vector< std::vector<int> > & stencil =
mlData.
stencil;
714 const std::vector< std::vector<int> > & status =
mlData.
statusQ;
716 os <<
"dQdx matrix for " << instance.
getName();
720 os <<
": JACOBIAN TEST FAILURE";
724 os <<
": JACOBIAN TEST SUCCESS";
728 os <<
" Numerical Analytic absDiff relative Error Status Names (row, col)"<<std::endl;
731 int numCols = devLIDs.size();
732 int numRows = (status.size()<numCols)?status.size():numCols;
734 for (i = 0; i < numRows; ++i)
736 if (*nameVec[devLIDs[i]] ==
"gnd")
continue;
738 for (j = 0; j < numCols; ++j)
740 if (*nameVec[devLIDs[j]] ==
"gnd")
continue;
743 if (status[i][j]==-1)
continue;
746 if (stencil[i][j]!=1)
continue;
749 static char tmpChar[128];
750 if (status[i][j]==-2)
752 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e fail",
753 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
755 else if (status[i][j]==3)
758 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e NA ",
759 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
763 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e ",
764 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
767 os << std::string(tmpChar);
769 os <<
" ("<< *nameVec[devLIDs[i]]
770 <<
", " << *nameVec[devLIDs[j]]
772 <<
" row,col=[ " << i <<
", " << j <<
"]" << std::endl;
778 os <<
" Note: NA = untestable special case, such as IC=, etc." << std::endl;
779 os << Xyce::section_divider << std::endl;
785 Report::UserError() <<
"Numerical Jacobian test failure" << std::endl
786 <<
"If you want this failure to be a warning, rather than an error, "
787 <<
"then add .options device testjacwarn=1 to the netlist.";
791 Report::UserWarning() <<
"Numerical Jacobian test failure";
829 const std::vector<int> & devLIDs = instance.
getDevLIDs();
830 const std::vector< std::vector<double> > & devJac =
mlData.
devJac;
831 std::vector< std::vector<int> > & status =
mlData.
status;
832 int numRows, numCols;
833 numRows = devLIDs.size();
839 for (i=1 ; i<numRows ; ++i)
841 for (j=0 ; j<i ; ++j)
843 if (devLIDs[i] == devLIDs[j])
845 for (k=0 ; k<numCols ; ++k)
847 if (devJac[i][k] != devJac[j][k])
849 Report::UserWarning() <<
"In device " << instance.
getName() <<
" different non-zero values in row merge";
853 for (k=0 ; k<numRows ; ++k)
855 if (devJac[k][i] != devJac[k][j])
857 Report::UserWarning() <<
"In device " << instance.
getName() <<
" different non-zero values in column merge";
879 const std::vector<int> & devLIDs = instance.
getDevLIDs();
881 Xyce::dout() << Xyce::section_divider<<std::endl;
882 Xyce::dout() <<
"Perturbing (LID="<<devLIDs[i]<<
") " << *nameVec[devLIDs[i]] <<
" by " << dX << std::endl;
895 const std::vector<int> & devLIDs = instance.
getDevLIDs();
899 const std::vector< std::vector<double> > & numJac =
mlData.
numJac;
900 const std::vector< std::vector<double> > & relJac =
mlData.
relJac;
902 Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
903 Xyce::dout() <<
"dFdX: ";
904 Xyce::dout() <<
" (" << devLIDs[j] <<
", " << devLIDs[i] <<
") ";
905 Xyce::dout() << numJac[j][i];
906 Xyce::dout() <<
" Forig = " << origRHS[j];
907 Xyce::dout() <<
" Fperturb = " << pertRHS[j];
908 double dF = -(pertRHS[j]-origRHS[j]);
909 Xyce::dout() <<
" dF = " << dF;
910 Xyce::dout() <<
" (" << *nameVec[devLIDs[j]] <<
", " << *nameVec[devLIDs[i]] <<
") ";
911 Xyce::dout() << std::endl;
912 Xyce::dout() <<
" relative error = " << relJac[j][i] << std::endl;
925 Xyce::dout() << Xyce::section_divider<<std::endl;
const InstanceName & getName() const
Linear::Vector * lastStaVectorPtr
double testJac_absTol
abstol for num. jacobian diagnostic.
std::vector< double > saveStateDerivs
const SolverState & solState
double pdt_
Previous delta time alpha/dt (Many devices)
Linear::Vector * currSolVectorPtr
Linear::Vector * nextSolVectorPtr
const std::vector< IdVector > & getDevJacLIDs() const
Linear::Vector * daeQVectorPtr
Pure virtual class to augment a linear system.
void resizeTestJacStateData(int size)
void resizeTestJacQData(int size)
virtual bool loadDAEFVector()=0
std::vector< double > pertSoln
std::vector< double > saveLastState
std::vector< std::vector< double > > numJac
std::vector< std::vector< double > > devJac
virtual bool loadDAEQVector()=0
std::vector< double > pertRHS
void testDebugOut(DeviceInstance &instance, const std::vector< const std::string * > &nameVec, int i, int j)
virtual bool loadDAEdFdx()=0
double testJac_relTol
reltol for num. jacobian diagnostic
void mergeTest(DeviceInstance &instance)
std::vector< std::vector< int > > statusQ
void setOrigFlag(bool origFlag_local)
const IdVector & getStaLIDVec() const
std::vector< std::vector< double > > diffJacQ
void printJacobian_(std::ostream &os, const DeviceInstance &instance, const std::vector< const std::string * > &nameVec, bool failed)
std::vector< double > saveRHS
const IdVector & getDevLIDs() const
std::vector< std::vector< int > > status
NumericalJacobian(MatrixLoadData &mlData1, const SolverState &ss1, const ExternData &ed1, const DeviceOptions &do1)
std::vector< double > origRHS
const ExternData & extData
bool testDAEMatrices(DeviceInstance &instance, const std::vector< const std::string * > &nameVec)
std::vector< double > pertQ
void testDebugHead(DeviceInstance &instance, const std::vector< const std::string * > &nameVec, int i, double dX)
const DeviceOptions & devOptions
void setMergeRowColChecked(bool mergeRowColChecked_local)
Linear::Vector * nextStaVectorPtr
Linear::Matrix * dFdxMatrixPtr
virtual bool loadDAEdQdx()=0
std::vector< std::vector< double > > relJacQ
void testDebugTail(DeviceInstance &instance, const std::vector< const std::string * > &nameVec)
virtual bool updatePrimaryState()=0
std::vector< std::vector< double > > saveJac
std::vector< double > saveCurrSoln
std::vector< double > saveCurrState
std::vector< std::vector< double > > saveJacQ
bool updateDependentParameters(const Linear::Vector &vars)
void loadLocalDAEVectors(DeviceInstance &instance)
virtual bool updateSecondaryState()
virtual const JacobianStamp & jacobianStamp() const
void resizeTestJacSolData(int size)
Linear::Vector * currStaVectorPtr
Linear::Vector * daeFVectorPtr
std::vector< double > saveSoln
std::vector< std::vector< double > > devJacQ
std::vector< double > origQ
double testJac_SqrtEta
dx = numJacSqrtEta * (1.0 + std::fabs(soln[i]));
std::vector< std::vector< int > > stencil
std::vector< std::vector< double > > relJac
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
Linear::Matrix * dQdxMatrixPtr
std::vector< std::vector< double > > numJacQ
std::vector< double > saveNextState
std::vector< std::vector< double > > diffJac
Linear::Vector * nextStaDerivVectorPtr
bool getMergeRowColChecked() const
std::vector< double > saveQ