46 #include <Xyce_config.h>
51 #include <N_UTL_Misc.h>
61 #include <N_LOA_Loader.h>
63 #include <N_LAS_Matrix.h>
64 #include <N_LAS_Vector.h>
65 #include <N_LAS_Solver.h>
66 #include <N_LAS_Problem.h>
67 #include <N_LAS_System.h>
68 #include <N_LAS_Builder.h>
70 #include <N_ERH_ErrorMgr.h>
73 #include <N_TOP_Topology.h>
75 #include <N_UTL_Expression.h>
76 #include <N_UTL_Algorithm.h>
77 #include <N_UTL_OptionBlock.h>
81 #include <N_PDS_Manager.h>
82 #include <N_PDS_Comm.h>
83 #include <N_PDS_Serial.h>
84 #include <N_PDS_MPI.h>
100 N_TOP_Topology & topTmp,
105 solveDirectFlag_(false),
106 solveAdjointFlag_(true),
107 outputScaledFlag_(false),
108 outputUnscaledFlag_(true),
109 maxParamStringSize_(0),
110 stdOutputFlag_(true),
111 fileOutputFlag_(false),
112 dakotaFileOutputFlag_(false),
116 objFuncGiven_(false),
117 objFuncGIDsetup_(false),
125 sqrtEtaGiven_(false),
128 savedRHSVectorPtr_(0),
129 savedNewtonVectorPtr_(0),
248 std::string idString,
249 std::vector<double> & paramVals,
250 std::vector<double> & sensitivities,
251 std::vector<double> & scaled_sensitivities)
254 #ifdef Xyce_PARALLEL_MPI
255 N_PDS_Comm *pdsCommPtr =
pdsMgrPtr_->getPDSComm();
256 int myPID = pdsCommPtr->procID();
260 Xyce::dout() <<
"\n"<<idString <<
" Sensitivities of objective function:"
264 Xyce::dout() <<
"\t"<<std::setw(13)<<
"Value";
265 Xyce::dout() <<
"\t"<<std::setw(13)<<
"Sensitivity";
266 Xyce::dout() <<
"\t"<<std::setw(13)<<
"Normalized"<<std::endl;
272 Xyce::dout() <<
"\t" << std::setw(13)<< std::scientific<< std::setprecision(4)
273 << paramVals[iparam];
275 Xyce::dout() <<
"\t" << std::setw(13)<< std::scientific<< std::setprecision(4)
276 << sensitivities[iparam];
278 Xyce::dout() <<
"\t" << std::setw(13)<< std::scientific<< std::setprecision(4)
279 << scaled_sensitivities[iparam] << std::endl;
282 #ifdef Xyce_PARALLEL_MPI
283 pdsCommPtr->barrier();
296 std::string idString,
297 std::vector<double> & paramVals,
298 std::vector<double> & sensitivities,
299 std::vector<double> & scaled_sensitivities)
302 #ifdef Xyce_PARALLEL_MPI
303 N_PDS_Comm *pdsCommPtr =
pdsMgrPtr_->getPDSComm();
304 int myPID = pdsCommPtr->procID();
308 std::ostringstream numSolvesOStr;
310 std::string dodpFileName =
netlistFileName_ + numSolvesOStr.str() +
"_dodp" + idString +
".txt";
311 FILE *fp = fopen(dodpFileName.c_str(),
"w");
314 fprintf(fp,
"\t%16.8e\n", sensitivities[iparam]);
318 #ifdef Xyce_PARALLEL_MPI
319 pdsCommPtr->barrier();
332 std::string idString,
333 std::vector<double> & paramVals,
334 std::vector<double> & sensitivities,
335 std::vector<double> & scaled_sensitivities)
337 #ifdef Xyce_PARALLEL_MPI
338 N_PDS_Comm *pdsCommPtr =
pdsMgrPtr_->getPDSComm();
339 int myPID = pdsCommPtr->procID();
346 std::string dakotaFileName =
netlistFileName_ +
"_dodp" + idString +
"_all.txt";
347 FILE *fp2 = fopen(dakotaFileName.c_str(),
"w");
349 fprintf(fp2,
"%s",
"\n[\n");
352 fprintf(fp2,
"\t%16.8e\n", sensitivities[iparam]);
354 fprintf(fp2,
"%s",
"]\n");
357 #ifdef Xyce_PARALLEL_MPI
358 pdsCommPtr->barrier();
373 std::vector<double> & objectiveVec,
374 std::vector<double> & dOdpVec,
375 std::vector<double> & dOdpAdjVec,
376 std::vector<double> & scaled_dOdpVec,
377 std::vector<double> & scaled_dOdpAdjVec)
395 objectiveVec.clear();
453 std::vector<double> & objectiveVec,
454 std::vector<double> & dOdpVec,
455 std::vector<double> & dOdpAdjVec,
456 std::vector<double> & scaled_dOdpVec,
457 std::vector<double> & scaled_dOdpAdjVec)
480 objectiveVec.clear();
582 #ifdef Xyce_DEBUG_NONLINEAR
585 Xyce::dout() << std::endl;
586 Xyce::dout() <<
"In Sensitivity::solveDirect" << std::endl;
607 #ifdef Xyce_DEBUG_NONLINEAR
620 rhsVectorPtr_->update(1.0, *(sensRHSPtrVector[iparam]), 0.0);
627 #ifdef Xyce_DEBUG_NONLINEAR
631 Xyce::dout() <<
"iparam="<<iparam <<
"\t" <<
paramNameVec_[iparam] <<std::endl;
634 Xyce::dout() <<
"dXdp[" << std::setw(3) << k <<
"] = "<< std::setw(15)<< std::scientific
635 << std::setprecision(8)<< (*(dXdpPtrVector_[iparam]))[k]
639 std::ostringstream filename;
641 filename << std::setw(3) << std::setfill(
'0') << iparam;
643 dXdpPtrVector_[iparam]->writeToFile(const_cast<char *>(filename.str().c_str()));
649 bool Transpose =
false;
650 (DQdxDXdpPtrVector_[iparam])->putScalar(0.0);
651 dQdx.matvec( Transpose , *(dXdpPtrVector_[iparam]), *(DQdxDXdpPtrVector_[iparam]) );
656 loaderPtr_->loadFinalSensitivityDerivatives ();
665 double tmp =
dOdXVectorPtr_->dotProduct( (*(dXdpPtrVector_[iparam])) );
718 bool bsuccess =
true;
727 bool foundLocal(
false);
728 bool foundLocal2(
false);
730 N_PDS_Comm & comm = *(
pdsMgrPtr_->getPDSComm());
731 int myPID = comm.procID();
741 std::list<int> svGIDList1, dummyList;
743 foundLocal =
top_.getNodeSVarGIDs(NodeID(
expVarNames_[i], Xyce::_VNODE), svGIDList1, dummyList, type1);
744 found =
static_cast<int>(foundLocal);
745 Xyce::Parallel::AllReduce(comm.comm(), MPI_LOR, &found, 1);
750 foundLocal2 =
top_.getNodeSVarGIDs(NodeID(
expVarNames_[i], Xyce::_DNODE), svGIDList1, dummyList, type1);
752 found2 =
static_cast<int>(foundLocal2);
753 Xyce::Parallel::AllReduce(comm.comm(), MPI_LOR, &found2, 1);
755 if (!found && !found2)
757 static std::string tmp =
"objective function variable not found!\n";
758 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::USR_FATAL, tmp);
764 if(svGIDList1.size()==1)
766 tmpGID = svGIDList1.front();
786 tmpVal = (*nextSolVectorPtrPtr_)->getElementByGlobalIndex(tmpGID, 0);
789 Xyce::Parallel::AllReduce(comm.comm(), MPI_MAX, &root, 1);
791 comm.bcast( &tmpVal, 1, root );
806 #ifdef Xyce_DEBUG_NONLINEAR
809 Xyce::dout() <<
"i="<<i<<
" gid = " << tmpGID <<
" dodx = "<< tmpDODX << std::endl;
824 static std::string tmp =
" ***** WARNING: objective function was not specified.\n\n";
825 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_FATAL_0, tmp);
830 #ifdef Xyce_DEBUG_NONLINEAR
834 dOdXVectorPtr_->writeToFile(const_cast<char *>(filename.c_str()));
852 #ifdef Xyce_DEBUG_NONLINEAR
855 Xyce::dout() << std::endl;
856 Xyce::dout() <<
"In Sensitivity::solveAdjoint" << std::endl;
873 #ifdef Xyce_DEBUG_NONLINEAR
887 std::string msg(
"Sensitivity::solveAdjoint. Solver failed\n");
888 N_ERH_ErrorMgr::report (N_ERH_ErrorMgr::DEV_FATAL, msg);
895 #ifdef Xyce_DEBUG_NONLINEAR
909 double tmp = -1.0 *
lambdaVectorPtr_->dotProduct(*(dfdpPtrVector_[iparam]));
973 N_LAS_System & lasSys_ = (*lasSysPtr_);
992 std::vector<std::string>::iterator firstParam =
paramNameVec_.begin ();
993 std::vector<std::string>::iterator lastParam =
paramNameVec_.end ();
994 std::vector<std::string>::iterator iterParam;
995 for ( iterParam=firstParam, iparam=0;
996 iterParam!=lastParam; ++iterParam, ++iparam )
998 std::string paramName(*iterParam);
1002 double paramOrig = 0.0;
1003 bool found =
loaderPtr_->getParamAndReduce(paramName, paramOrig);
1006 std::string msg(
"Sensitivity::loadSensitivityResiduals: cannot find parameter ");
1008 N_ERH_ErrorMgr::report (N_ERH_ErrorMgr::DEV_FATAL, msg);
1013 bool analyticAvailable =
false;
1016 analyticAvailable =
loaderPtr_->analyticSensitivitiesAvailable (paramName);
1018 if (analyticAvailable)
1020 std::vector<double> dfdpVec;
1021 std::vector<double> dqdpVec;
1022 std::vector<double> dbdpVec;
1024 std::vector<int> FindicesVec;
1025 std::vector<int> QindicesVec;
1026 std::vector<int> BindicesVec;
1028 loaderPtr_->getAnalyticSensitivities(paramName,
1029 dfdpVec,dqdpVec,dbdpVec,
1030 FindicesVec, QindicesVec, BindicesVec);
1032 dfdpPtrVector_[iparam]->putScalar(0.0);
1033 dqdpPtrVector_[iparam]->putScalar(0.0);
1034 dbdpPtrVector_[iparam]->putScalar(0.0);
1036 int Fsize=FindicesVec.size();
1037 for (
int i=0;i<Fsize;++i)
1039 N_LAS_Vector & dfdpRef = *(dfdpPtrVector_[iparam]);
1040 dfdpRef[FindicesVec[i]] = dfdpVec[i];
1043 int Qsize=QindicesVec.size();
1044 for (
int i=0;i<Qsize;++i)
1046 N_LAS_Vector & dqdpRef = *(dqdpPtrVector_[iparam]);
1047 dqdpRef[QindicesVec[i]] = dqdpVec[i];
1050 int Bsize=BindicesVec.size();
1051 for (
int i=0;i<Bsize;++i)
1053 N_LAS_Vector & dbdpRef = *(dbdpPtrVector_[iparam]);
1054 dbdpRef[BindicesVec[i]] = dbdpVec[i];
1057 dfdpPtrVector_[iparam]->fillComplete();
1058 dqdpPtrVector_[iparam]->fillComplete();
1059 dbdpPtrVector_[iparam]->fillComplete();
1061 #ifdef Xyce_DEBUG_NONLINEAR
1064 Xyce::dout() << *iterParam <<
": ";
1065 Xyce::dout().setf(std::ios::scientific);
1066 Xyce::dout() << std::endl;
1071 <<
"dfdp["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dfdpPtrVector_[iparam]))[k1]
1072 <<
" dqdp["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dqdpPtrVector_[iparam]))[k1]
1073 <<
" dbdp["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dbdpPtrVector_[iparam]))[k1]
1081 #ifdef Xyce_DEBUG_NONLINEAR
1084 Xyce::dout() << std::endl <<
" Calculating numerical df/dp, dq/dp and db/dp for: ";
1085 Xyce::dout() << *iterParam << std::endl;
1095 double dp =
sqrtEta_ * (1.0 + fabs(paramOrig));
1096 double paramPerturbed = paramOrig;
1100 paramPerturbed += dp;
1104 paramPerturbed -= dp;
1108 static std::string tmp =
"difference=central not supported.\n";
1109 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1113 static std::string tmp =
"difference not recognized!\n";
1114 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1117 #ifdef Xyce_DEBUG_NONLINEAR
1121 <<
" dp = " << std::setw(11)<< std::scientific<< std::setprecision(4) << dp
1122 <<
" original value = " << std::setw(16)<< std::scientific<< std::setprecision(9) << paramOrig
1123 <<
" modified value = " << std::setw(16)<< std::scientific<< std::setprecision(9) << paramPerturbed
1127 loaderPtr_->setParam (paramName, paramPerturbed);
1142 dfdpPtrVector_[iparam]->putScalar(0.0);
1145 dfdpPtrVector_[iparam]->scale(rdp);
1148 dqdpPtrVector_[iparam]->putScalar(0.0);
1151 dqdpPtrVector_[iparam]->scale(rdp);
1154 dbdpPtrVector_[iparam]->putScalar(0.0);
1157 dbdpPtrVector_[iparam]->scale(rdp);
1159 #ifdef Xyce_DEBUG_NONLINEAR
1162 Xyce::dout() << *iterParam <<
": ";
1163 Xyce::dout().width(15); Xyce::dout().precision(7); Xyce::dout().setf(std::ios::scientific);
1164 Xyce::dout() <<
"deviceSens_dp = " << dp << std::endl;
1170 <<
"fpert["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
pertFVectorPtr_))[k1]
1171 <<
" forig["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
origFVectorPtr_))[k1]
1172 <<
" dfdp ["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dfdpPtrVector_[iparam]))[k1]
1176 Xyce::dout() << std::endl;
1180 <<
"qpert["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
pertQVectorPtr_))[k1]
1181 <<
" qorig["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
origQVectorPtr_))[k1]
1182 <<
" dqdp ["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dqdpPtrVector_[iparam]))[k1]
1186 Xyce::dout() << std::endl ;
1190 <<
"bpert["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
pertBVectorPtr_))[k1]
1191 <<
" borig["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(
origBVectorPtr_))[k1]
1192 <<
" dbdp ["<<std::setw(3)<<k1<<
"]= "<<std::setw(15)<<std::scientific<<std::setprecision(8)<<(*(dbdpPtrVector_[iparam]))[k1]
1197 std::ostringstream filename;
1199 filename << std::setw(3) << std::setfill(
'0') << iparam;
1201 dfdpPtrVector_[iparam]->writeToFile(const_cast<char *>(filename.str().c_str()));
1204 filename << netlistFileName_ <<
"_fpert";
1205 filename << std::setw(3) << std::setfill(
'0') << iparam;
1207 pertFVectorPtr_->writeToFile(const_cast<char *>(filename.str().c_str()));
1210 filename << netlistFileName_ <<
"_dqdp";
1211 filename << std::setw(3) << std::setfill(
'0') << iparam;
1213 dqdpPtrVector_[iparam]->writeToFile(const_cast<char *>(filename.str().c_str()));
1216 filename << netlistFileName_ <<
"_qpert";
1217 filename << std::setw(3) << std::setfill(
'0') << iparam;
1219 pertQVectorPtr_->writeToFile(const_cast<char *>(filename.str().c_str()));
1222 filename << netlistFileName_ <<
"_dbdp";
1223 filename << std::setw(3) << std::setfill(
'0') << iparam;
1225 dbdpPtrVector_[iparam]->writeToFile(const_cast<char *>(filename.str().c_str()));
1228 filename << netlistFileName_ <<
"_bpert";
1229 filename << std::setw(3) << std::setfill(
'0') << iparam;
1231 pertBVectorPtr_->writeToFile(const_cast<char *>(filename.str().c_str()));
1260 bool bsuccess =
true;
1261 std::list<N_UTL_Param>::const_iterator iter = OB.getParams().begin();
1262 std::list<N_UTL_Param>::const_iterator end = OB.getParams().end();
1265 for ( ; iter != end; ++ iter)
1267 if (iter->uTag() ==
"OBJFUNC")
1270 expPtr_ =
new N_UTL_Expression(iter->stringValue());
1273 else if ( std::string( iter->uTag() ,0,5) ==
"PARAM")
1275 ExtendedString tag = iter->stringValue();
1280 int sz = tag.size();
1288 Xyce::Report::UserWarning() << iter->uTag()
1289 <<
" is not a recognized sensitivity solver option.\n" << std::endl;
1300 std::vector<std::string> nodes;
1301 expPtr_->get_names(XEXP_NODE, nodes);
1302 std::vector<std::string> instances;
1303 expPtr_->get_names(XEXP_INSTANCE, instances);
1307 std::vector<std::string>::iterator iter;
1308 for (iter=instances.begin();iter!=instances.end();++iter)
1310 ExtendedString tmpString = *iter;
1311 tmpString.toUpper ();
1328 #ifdef Xyce_DEBUG_NONLINEAR
1331 std::vector<std::string>::iterator iter;
1332 std::vector<std::string>::iterator begin =
paramNameVec_.begin();
1333 std::vector<std::string>::iterator end =
paramNameVec_.end ();
1335 for (iter=begin;iter!=end;++iter)
1337 Xyce::dout() << *iter<<std::endl;
1357 bool bsuccess =
true;
1358 std::list<N_UTL_Param>::const_iterator it = OB.getParams().begin();
1359 std::list<N_UTL_Param>::const_iterator end = OB.getParams().end();
1360 for ( ; it != end; ++ it)
1362 if ((*it).uTag() ==
"ADJOINT")
1365 static_cast<bool>((*it).getImmutableValue<
bool>());
1367 else if ((*it).uTag() ==
"DIRECT")
1370 static_cast<bool>((*it).getImmutableValue<
bool>());
1372 else if ((*it).uTag() ==
"OUTPUTSCALED")
1375 static_cast<bool>((*it).getImmutableValue<
bool>());
1377 else if ((*it).uTag() ==
"OUTPUTUNSCALED")
1380 static_cast<bool>((*it).getImmutableValue<
bool>());
1382 else if ((*it).uTag() ==
"STDOUTPUT")
1385 static_cast<bool>((*it).getImmutableValue<
bool>());
1387 else if ((*it).uTag() ==
"DAKOTAFILE")
1390 static_cast<bool>((*it).getImmutableValue<
bool>());
1392 else if ((*it).uTag() ==
"DIAGNOSTICFILE")
1395 static_cast<bool>((*it).getImmutableValue<
bool>());
1397 else if ((*it).uTag() ==
"FORCEFD")
1400 static_cast<bool>((*it).getImmutableValue<
bool>());
1402 else if ((*it).uTag() ==
"DIFFERENCE")
1404 ExtendedString sval=(*it).stringValue();
1410 else if(sval==
"REVERSE")
1414 else if(sval==
"CENTRAL")
1417 static std::string tmp =
"difference=central not supported.\n";
1418 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1422 static std::string tmp =
"difference not recognized!\n";
1423 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1426 else if ((*it).uTag() ==
"SQRTETA")
1428 sqrtEta_ = (*it).getImmutableValue<
double>();
1431 #ifdef Xyce_DEBUG_NONLINEAR
1432 else if ((*it).uTag() ==
"DEBUGLEVEL")
1439 Xyce::Report::UserWarning() << (*it).uTag()
1440 <<
" is not a recognized sensitivity solver option.\n" << std::endl;
1461 bool bsuccess =
true;
1475 bool bsuccess =
true;