46 #include <Xyce_config.h>
50 #include <N_UTL_Misc.h>
71 #include <N_ERH_ErrorMgr.h>
73 #include <N_LAS_Vector.h>
74 #include <N_LAS_Matrix.h>
99 val_local(mlData1.val_local),
100 Qval_local(mlData1.Qval_local),
101 col_local(mlData1.col_local),
102 row_local(mlData1.row_local),
103 internalFlag(mlData1.internalFlag),
119 : mlData(right.mlData),
123 val_local(right.val_local),
124 Qval_local(right.Qval_local),
125 col_local(right.col_local),
126 row_local(right.row_local),
127 internalFlag(right.internalFlag),
128 solState (right.solState),
129 extData (right.extData),
130 devOptions(right.devOptions),
131 maxCols(right.maxCols)
179 const std::vector<int> & devLIDs = instance.
getDevLIDs();
180 const std::vector<int> & devStateLIDs = instance.
getStaLIDVec();
181 const std::vector< std::vector<int> > & devJacLIDs = instance.
getDevJacLIDs();
182 const std::vector< std::vector<int> > & jacStamp = instance.
jacobianStamp();
186 std::vector< std::vector<double> > & numJacF =
mlData.
numJac;
187 std::vector< std::vector<double> > & saveJacF =
mlData.
saveJac;
188 std::vector< std::vector<double> > & devJacF =
mlData.
devJac;
189 std::vector< std::vector<double> > & diffJacF =
mlData.
diffJac;
190 std::vector< std::vector<double> > & relJacF =
mlData.
relJac;
192 std::vector< std::vector<double> > & numJacQ =
mlData.
numJacQ;
194 std::vector< std::vector<double> > & devJacQ =
mlData.
devJacQ;
196 std::vector< std::vector<double> > & relJacQ =
mlData.
relJacQ;
198 std::vector< std::vector<int> > & statusF =
mlData.
status;
233 int numRows, numCols;
234 numCols = devLIDs.size();
235 numRows = jacStamp.size();
237 int testSize= (numRows>numCols)?numRows:numCols;
238 if (testSize > saveF.size())
244 int numState = devStateLIDs.size();
245 if (numState > saveCurrState.size())
252 if(devJacLIDs.empty())
254 #ifdef Xyce_DEBUG_DEVICE
255 Report::UserWarning() << instance.
getName() <<
" does not have jacLIDs available";
261 if (instance.
getOrigFlag() && numRows > 0 && numRows == jacStamp.size())
265 saveF.assign(saveF.size(),0.0);
266 pertF.assign(pertF.size(),0.0);
267 origF.assign(origF.size(),0.0);
269 saveQ.assign(saveQ.size(),0.0);
270 pertQ.assign(pertQ.size(),0.0);
271 origQ.assign(origQ.size(),0.0);
273 saveSoln.assign(saveSoln.size(),0.0);
274 pertSoln.assign(pertSoln.size(),0.0);
275 saveCurrSoln.assign(saveCurrSoln.size(),0.0);
277 saveLastState.assign(saveLastState.size(),0.0);
278 saveCurrState.assign(saveCurrState.size(),0.0);
279 saveNextState.assign(saveNextState.size(),0.0);
280 saveStateDerivs.assign(saveStateDerivs.size(),0.0);
281 for (i=0;i<numJacF.size();++i)
283 numJacF[i].assign(numJacF[i].size(),0.0);
284 saveJacF[i].assign(saveJacF[i].size(),0.0);
285 devJacF[i].assign(devJacF[i].size(),0.0);
286 diffJacF[i].assign(diffJacF[i].size(),0.0);
287 statusF[i].assign(statusF[i].size(),-1);
288 stencil[i].assign(stencil[i].size(),0);
290 numJacQ[i].assign(numJacQ[i].size(),0.0);
291 saveJacQ[i].assign(saveJacQ[i].size(),0.0);
292 devJacQ[i].assign(devJacQ[i].size(),0.0);
293 diffJacQ[i].assign(diffJacQ[i].size(),0.0);
294 statusQ[i].assign(statusQ[i].size(),-1);
300 int tmpSize= (numRows>numCols)?numRows:numCols;
302 for (i=0 ; i<tmpSize; ++i)
304 saveF[i] = Fvec[devLIDs[i]];
305 saveQ[i] = Qvec[devLIDs[i]];
307 saveSoln[i] = nextSol[devLIDs[i]];
308 saveCurrSoln[i] = currSol[devLIDs[i]];
309 pertSoln[i] = sqrtEta * (1.0 + fabs(saveSoln[i]));
312 for (i=0 ; i<numState ; ++i)
314 saveLastState[i] = lastSta[devStateLIDs[i]];
315 saveCurrState[i] = currSta[devStateLIDs[i]];
316 saveNextState[i] = nextSta[devStateLIDs[i]];
317 saveStateDerivs[i] = nextStaDeriv[devStateLIDs[i]];
321 for (i=0 ; i<numRows ; ++i)
323 jCol = devJacLIDs[i].size();
324 for (j=0 ; j<jCol ; ++j)
326 double valF = dFdxMat[devLIDs[i]][devJacLIDs[i][j]];
327 saveJacF[i][j] = valF;
328 double valQ = dQdxMat[devLIDs[i]][devJacLIDs[i][j]];
329 saveJacQ[i][j] = valQ;
336 for (i=0 ; i<numRows ; ++i)
338 jCol = devJacLIDs[i].size();
339 for (j=0 ; j<jCol ; ++j)
341 dFdxMat[devLIDs[i]][devJacLIDs[i][j]] = 0;
342 dQdxMat[devLIDs[i]][devJacLIDs[i][j]] = 0;
352 for (i=0 ; i<numRows ; ++i)
354 devJacF[i].assign(devJacF[i].size(),0.0);
355 devJacQ[i].assign(devJacQ[i].size(),0.0);
356 stencil[i].assign(stencil[i].size(),0);
358 jCol = devJacLIDs[i].size();
359 for (j=0 ; j<jCol ; ++j)
361 double valF = dFdxMat[devLIDs[i]][devJacLIDs[i][j]];
362 devJacF[i][jacStamp[i][j]] = valF;
363 double valQ = dQdxMat[devLIDs[i]][devJacLIDs[i][j]];
364 devJacQ[i][jacStamp[i][j]] = valQ;
365 stencil[i][jacStamp[i][j]] = 1;
371 for (i=0 ; i<numRows ; ++i)
373 Fvec[devLIDs[i]] = 0.0;
374 Qvec[devLIDs[i]] = 0.0;
380 for (i=0 ; i<numRows ; ++i)
382 origF[i] = Fvec[devLIDs[i]];
383 origQ[i] = Qvec[devLIDs[i]];
386 for (i=0 ; i<numRows ; ++i)
388 jCol = devJacLIDs[i].size();
389 for (j=0 ; j<jCol ; ++j)
391 statusF[i][jacStamp[i][j]] = -1;
392 statusQ[i][jacStamp[i][j]] = -1;
410 double ndFdx, adFdx, ddFdx, relError_dFdx;
411 double ndQdx, adQdx, ddQdx, relError_dQdx;
413 bool failedTest =
false;
414 for (i=0 ; i<numCols ; ++i)
417 if (nameVec[devLIDs[i]] ==
"gnd")
continue;
419 for (j=0 ; j<numRows ; ++j)
421 nextSol[devLIDs[j]] = saveSoln[j];
422 currSol[devLIDs[j]] = saveCurrSoln[j];
423 Fvec[devLIDs[j]] = 0.0;
424 Qvec[devLIDs[j]] = 0.0;
427 for (j=0 ; j<numState ; ++j)
429 lastSta[devStateLIDs[j]] = saveLastState[j];
430 currSta[devStateLIDs[j]] = saveCurrState[j];
431 nextSta[devStateLIDs[j]] = saveNextState[j];
432 nextStaDeriv[devStateLIDs[j]] = saveStateDerivs[j];
436 double dX = pertSoln[i];
437 nextSol[devLIDs[i]] += dX;
442 for (j=0 ; j<numRows ; ++j)
444 pertF[j] = Fvec[devLIDs[j]];
445 pertQ[j] = Qvec[devLIDs[j]];
448 #ifdef Xyce_DEBUG_TESTJAC
452 for (j=0 ; j<numRows ; ++j)
455 if (nameVec[devLIDs[j]] ==
"gnd")
continue;
459 if (stencil[j][i]!=1)
continue;
461 double dF = (pertF[j]-origF[j]);
462 double dQ = (pertQ[j]-origQ[j]);
463 numJacF[j][i] = dF/dX;
464 numJacQ[j][i] = dQ/dX;
466 ndFdx = numJacF[j][i];
467 adFdx = devJacF[j][i];
468 ddFdx = fabs(adFdx-ndFdx);
469 relError_dFdx = ddFdx/(relTol*fabs(ndFdx)+absTol);
471 diffJacF[j][i] = ddFdx;
472 relJacF[j][i] = relError_dFdx;
474 ndQdx = numJacQ[j][i];
475 adQdx = devJacQ[j][i];
476 ddQdx = fabs(adQdx-ndQdx);
477 relError_dQdx = ddQdx/(relTol*fabs(ndQdx)+absTol);
479 diffJacQ[j][i] = ddQdx;
480 relJacQ[j][i] = relError_dQdx;
482 #ifdef Xyce_DEBUG_TESTJAC
483 if (isnan(numJacF[j][i]))
490 ExtendedString varNameI(nameVec[devLIDs[i]]); varNameI.toUpper();
491 ExtendedString varNameJ(nameVec[devLIDs[j]]); varNameJ.toUpper();
496 if (adFdx == 1 && ndFdx == 0)
512 if ( statusF[j][i] != 3 )
514 if (relError_dFdx > 1.0)
524 if (relError_dQdx > 1.0)
536 #ifdef Xyce_DEBUG_TESTJAC
541 #ifdef Xyce_DEBUG_DEVICE
553 tmpSize= (numRows>numCols)?numRows:numCols;
554 for (i=0 ; i<tmpSize; ++i)
556 Fvec[devLIDs[i]] = saveF[i];
557 Qvec[devLIDs[i]] = saveQ[i];
558 nextSol[devLIDs[i]] = saveSoln[i];
559 currSol[devLIDs[i]] = saveCurrSoln[i];
561 for (i=0 ; i<numState ; ++i)
563 lastSta[devStateLIDs[i]] = saveLastState[i];
564 currSta[devStateLIDs[i]] = saveCurrState[i];
565 nextSta[devStateLIDs[i]] = saveNextState[i];
566 nextStaDeriv[devStateLIDs[i]] = saveStateDerivs[i];
570 for (i=0 ; i<numRows ; ++i)
572 jCol = devJacLIDs[i].size();
573 for (j=0 ; j<jCol ; ++j)
575 dFdxMat[devLIDs[i]][devJacLIDs[i][j]] = saveJacF[i][j];
576 dQdxMat[devLIDs[i]][devJacLIDs[i][j]] = saveJacQ[i][j];
599 const std::vector<int> & devStateLIDs = instance.
getStaLIDVec();
600 int numState = devStateLIDs.size();
609 for (
int j=0 ; j<numState ; ++j)
611 nextStaDeriv[devStateLIDs[j]] =
612 solState.
pdt * (nextSta[devStateLIDs[j]]-currSta[devStateLIDs[j]]);
633 const std::vector<std::string> & nameVec,
637 const std::vector<int> & devLIDs = instance.
getDevLIDs();
641 const std::vector< std::vector<double> > & numJac =
mlData.
numJac;
642 const std::vector< std::vector<double> > & anaJac =
mlData.
devJac;
643 const std::vector< std::vector<double> > & diffJac =
mlData.
diffJac;
644 const std::vector< std::vector<double> > & relJac =
mlData.
relJac;
645 const std::vector< std::vector<int> > & stencil =
mlData.
stencil;
646 const std::vector< std::vector<int> > & status =
mlData.
status;
649 os << Xyce::section_divider << std::endl;
650 os <<
"dFdx matrix for " << instance.
getName();
654 os <<
": JACOBIAN TEST FAILURE";
658 os <<
": JACOBIAN TEST SUCCESS";
663 os <<
" Numerical Analytic absDiff relative Error Status Names (row, col)"<<std::endl;
666 int numCols = devLIDs.size();
667 int numRows = (status.size()<numCols)?status.size():numCols;
669 for (i = 0; i < numRows; ++i)
671 if (nameVec[devLIDs[i]] ==
"gnd")
continue;
673 for (j = 0; j < numCols; ++j)
675 if (nameVec[devLIDs[j]] ==
"gnd")
continue;
678 if (status[i][j]==-1)
continue;
681 if (stencil[i][j]!=1)
continue;
684 static char tmpChar[128];
685 static char prefix[4];
687 sprintf(prefix,
"%s",
"FT:");
689 if (status[i][j]==-2)
691 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e fail",prefix,
692 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
694 else if (status[i][j]==3)
697 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e NA ",prefix,
698 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
702 sprintf(tmpChar,
"%s %12.4e %12.4e %12.4e %12.4e ",prefix,
703 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
706 os << std::string(tmpChar);
708 os <<
" ("<< nameVec[devLIDs[i]]
709 <<
", " << nameVec[devLIDs[j]]
711 <<
" row,col=[ " << i <<
", " << j <<
"]" << std::endl;
718 const std::vector< std::vector<double> > & numJac =
mlData.
numJacQ;
719 const std::vector< std::vector<double> > & anaJac =
mlData.
devJacQ;
720 const std::vector< std::vector<double> > & diffJac =
mlData.
diffJacQ;
721 const std::vector< std::vector<double> > & relJac =
mlData.
relJacQ;
722 const std::vector< std::vector<int> > & stencil =
mlData.
stencil;
723 const std::vector< std::vector<int> > & status =
mlData.
statusQ;
725 os <<
"dQdx matrix for " << instance.
getName();
729 os <<
": JACOBIAN TEST FAILURE";
733 os <<
": JACOBIAN TEST SUCCESS";
737 os <<
" Numerical Analytic absDiff relative Error Status Names (row, col)"<<std::endl;
740 int numCols = devLIDs.size();
741 int numRows = (status.size()<numCols)?status.size():numCols;
743 for (i = 0; i < numRows; ++i)
745 if (nameVec[devLIDs[i]] ==
"gnd")
continue;
747 for (j = 0; j < numCols; ++j)
749 if (nameVec[devLIDs[j]] ==
"gnd")
continue;
752 if (status[i][j]==-1)
continue;
755 if (stencil[i][j]!=1)
continue;
758 static char tmpChar[128];
759 if (status[i][j]==-2)
761 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e fail",
762 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
764 else if (status[i][j]==3)
767 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e NA ",
768 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
772 sprintf(tmpChar,
"QT: %12.4e %12.4e %12.4e %12.4e ",
773 numJac[i][j], anaJac[i][j], diffJac[i][j], relJac[i][j]);
776 os << std::string(tmpChar);
778 os <<
" ("<< nameVec[devLIDs[i]]
779 <<
", " << nameVec[devLIDs[j]]
781 <<
" row,col=[ " << i <<
", " << j <<
"]" << std::endl;
787 os <<
" Note: NA = untestable special case, such as IC=, etc." << std::endl;
788 os << Xyce::section_divider << std::endl;
794 Report::UserError() <<
"Numerical Jacobian test failure" << std::endl
795 <<
"If you want this failure to be a warning, rather than an error, "
796 <<
"run with .options device testjacwarn=1 in the netlist.";
800 Report::UserWarning() <<
"Numerical Jacobian test failure";
838 const std::vector<int> & devLIDs = instance.
getDevLIDs();
839 const std::vector< std::vector<double> > & devJac =
mlData.
devJac;
840 std::vector< std::vector<int> > & status =
mlData.
status;
841 int numRows, numCols;
842 numRows = devLIDs.size();
848 for (i=1 ; i<numRows ; ++i)
850 for (j=0 ; j<i ; ++j)
852 if (devLIDs[i] == devLIDs[j])
854 for (k=0 ; k<numCols ; ++k)
856 if (devJac[i][k] != devJac[j][k])
858 Report::UserWarning() <<
"In device " + instance.
getName() <<
" different non-zero values in row merge";
862 for (k=0 ; k<numRows ; ++k)
864 if (devJac[k][i] != devJac[k][j])
866 Report::UserWarning() <<
"In device " + instance.
getName() <<
" different non-zero values in column merge";
888 const std::vector<int> & devLIDs = instance.
getDevLIDs();
890 Xyce::dout() << Xyce::section_divider<<std::endl;
891 Xyce::dout() <<
"Perturbing (LID="<<devLIDs[i]<<
") " << nameVec[devLIDs[i]] <<
" by " << dX << std::endl;
904 const std::vector<int> & devLIDs = instance.
getDevLIDs();
908 const std::vector< std::vector<double> > & numJac =
mlData.
numJac;
909 const std::vector< std::vector<double> > & relJac =
mlData.
relJac;
911 Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
912 Xyce::dout() <<
"dFdX: ";
913 Xyce::dout() <<
" (" << devLIDs[j] <<
", " << devLIDs[i] <<
") ";
914 Xyce::dout() << numJac[j][i];
915 Xyce::dout() <<
" Forig = " << origRHS[j];
916 Xyce::dout() <<
" Fperturb = " << pertRHS[j];
917 double dF = -(pertRHS[j]-origRHS[j]);
918 Xyce::dout() <<
" dF = " << dF;
919 Xyce::dout() <<
" (" << nameVec[devLIDs[j]] <<
", " << nameVec[devLIDs[i]] <<
") ";
920 Xyce::dout() << std::endl;
921 Xyce::dout() <<
" relative error = " << relJac[j][i] << std::endl;
934 Xyce::dout() << Xyce::section_divider<<std::endl;