46 #include <Xyce_config.h>
52 #include <N_UTL_Misc.h>
74 #include <N_ERH_ErrorMgr.h>
78 #include <N_LAS_Vector.h>
79 #include <N_LAS_Matrix.h>
81 #include <Teuchos_RefCountPtr.hpp>
82 using Teuchos::RefCountPtr;
89 namespace MutIndNonLin2 {
149 NULL,
U_VOLT,
CAT_NONE,
"Smoothing coefficient for voltage difference over first inductor");
181 NULL,
U_VOLT,
CAT_NONE,
"Smoothing coefficient for voltage difference over first inductor");
228 NULL,
U_NONE,
CAT_NONE,
"Flag to use voltage limiting on Mag and R internal variables" );
231 NULL,
U_NONE,
CAT_NONE,
"Threshold over which newton interation changes in Mag are limited." );
234 NULL,
U_NONE,
CAT_NONE,
"Threshold over which newton interation changes in R are limited." );
254 :
DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
256 temp(getDeviceOptions().temp.getImmutableValue<double>()),
259 dP_dBranchCurrentSum(0.0),
262 branchCurrentSum(0.0),
265 oldBranchCurrentSum(0.0),
269 includeDeltaM(false),
270 useRKIntegration(false),
271 outputStateVarsFlag( false )
273 #ifdef Xyce_DEBUG_DEVICE
274 Xyce::dout() <<
"In Instance constructor" << std::endl;
332 LO[i].resize( numInductors );
334 dHe_dI.resize(numInductors);
338 dP_dI.resize( numInductors );
353 std::string filename(
"Inductor_" );
355 filename.append(
".dat" );
357 replace( filename.begin(), filename.end(),
'%',
'_' );
358 replace( filename.begin(), filename.end(),
':',
'_' );
361 outputFileStreamPtr->open( filename.c_str() );
362 if( !(*outputFileStreamPtr) )
364 std::string msg(
"Instance constructor.\n");
365 msg +=
"\tCould not open file for output of state variables. name =" +
getName();
366 N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
368 (*outputFileStreamPtr).setf(std::ios::scientific, std::ios::floatfield );
369 (*outputFileStreamPtr).width(20);
370 (*outputFileStreamPtr).precision(12);
428 jacStamp[2*numInductors + i].resize(numInductors + 2);
435 jacStamp[2*i ][0] = 2*numInductors + i;
437 jacStamp[2*i+1][0] = 2*numInductors + i;
450 jacStamp[2*numInductors + i][0] = 2*i;
451 jacStamp[2*numInductors + i][1] = 2*i + 1;
454 jacStamp[2*numInductors + i][j+2] = 2*numInductors + j;
471 #ifdef Xyce_DEBUG_DEVICE
474 Xyce::dout() <<
"Instance::Instance----------" << std::endl;
475 Xyce::dout() <<
"numExtVars = " <<
numExtVars <<
", " << ibev << std::endl
476 <<
"numIntVars = " <<
numIntVars <<
", " << ibiv << std::endl
478 <<
"numInductors = " << numInductors << std::endl
479 <<
"jacStamp = " << std::endl;
480 for(
int i = 0; i<
jacStamp.size(); ++i )
482 Xyce::dout() <<
"jacStamp[ " << i <<
" ] = { ";
483 for(
int j=0; j<
jacStamp[i].size(); ++j)
486 if( j != (
jacStamp[i].size() -1 ) )
488 Xyce::dout() <<
", ";
491 Xyce::dout() <<
" }" << std::endl;
514 std::string msg(
"Instance destructor.\n");
515 msg +=
"\tCould not close file for output of state variables. name =" +
getName();
516 N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
522 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
523 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
524 for ( ; currentInductor != endInductor ; ++currentInductor)
526 if (*currentInductor != NULL)
528 delete *currentInductor;
529 *currentInductor = NULL;
544 const std::vector<int> & extLIDVecRef)
557 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
558 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
561 while( currentInductor != endInductor )
563 (*currentInductor)->li_Pos =
extLIDVec[ i++ ];
564 (*currentInductor)->li_Neg =
extLIDVec[ i++ ];
565 (*currentInductor)->li_Branch = intLIDVec[ j++ ];
576 #ifdef Xyce_DEBUG_DEVICE
579 Xyce::dout() <<
"Instance::registerLIDs------------------------" << std::endl;
582 while( currentInductor != endInductor )
584 Xyce::dout() <<
"Inductor [ " << i++ <<
" ] "
585 <<
" li_Pos = " << (*currentInductor)->li_Pos
586 <<
" li_Neg = " << (*currentInductor)->li_Neg
587 <<
" li_Branch = " << (*currentInductor)->li_Branch << std::endl;
592 Xyce::dout() <<
" li_deltaMagVar = " <<
li_deltaMagVar << std::endl;
611 std::string baseString(
getName() +
"_");
612 std::string tempString;
613 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
614 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
617 while( currentInductor != endInductor )
619 tempString = baseString + (*currentInductor)->name +
"_branch";
621 intNameMap[ (*currentInductor)->li_Branch ] = tempString;
645 #ifdef Xyce_DEBUG_DEVICE
648 Xyce::dout() <<
"Instance::registerStateLIDs-------------------" << std::endl;
677 #ifdef Xyce_DEBUG_DEVICE
680 Xyce::dout() <<
"Instance::registerJacLIDs ----------------------------" << std::endl;
682 Xyce::dout() <<
"jacLIDVec = " << std::endl;
683 for(
int i = 0; i<
jacStamp.size(); ++i )
685 Xyce::dout() <<
"jacLIDVec[ " << i <<
" ] = { ";
686 for(
int j=0; j<jacLIDVec[i].size(); ++j)
688 Xyce::dout() << jacLIDVec[i][j];
689 if( j != ( jacLIDVec[i].size() -1 ) )
691 Xyce::dout() <<
", ";
694 Xyce::dout() <<
" }" << std::endl;
699 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
700 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
702 while( currentInductor != endInductor )
704 (*currentInductor)->APosEquBraVarOffset = jacLIDVec[ 2*i ][ 0 ];
705 (*currentInductor)->ANegEquBraVarOffset = jacLIDVec[ 2*i + 1 ][ 0 ];
706 (*currentInductor)->vPosOffset = jacLIDVec[ 2*
numInductors + i ][ 0 ];
707 (*currentInductor)->vNegOffset = jacLIDVec[ 2*
numInductors + i ][ 1 ];
709 (*currentInductor)->ABraEquPosNodeOffset = jacLIDVec[ 2*
numInductors + i ][ 0 ];
710 (*currentInductor)->ABraEquNegNodeOffset = jacLIDVec[ 2*
numInductors + i ][ 1 ];
715 (*currentInductor)->ABraEquBraVarOffset = jacLIDVec[ 2*numInductors + i ][ j + 2 ];
717 (*currentInductor)->inductorCurrentOffsets[ j ] = jacLIDVec[ 2*numInductors + i ][ j + 2 ];
734 #ifdef Xyce_DEBUG_DEVICE
739 while( currentInductor != endInductor )
741 Xyce::dout() <<
"Inductor [ " << i <<
" ] " << (*currentInductor)->name << std::endl
742 <<
" APosEquBraVarOffset = " << (*currentInductor)->APosEquBraVarOffset << std::endl
743 <<
" ANegEquBraVarOffset = " << (*currentInductor)->ANegEquBraVarOffset << std::endl
744 <<
" vPosOffset = " << (*currentInductor)->vPosOffset << std::endl
745 <<
" vNegOffset = " << (*currentInductor)->vNegOffset << std::endl
746 <<
" ABraEquPosNodeOffset = " << (*currentInductor)->ABraEquPosNodeOffset << std::endl
747 <<
" ABraEquNegNodeOffset = " << (*currentInductor)->ABraEquNegNodeOffset << std::endl
748 <<
" ABraEquBraVarOffset = " << (*currentInductor)->ABraEquBraVarOffset << std::endl
749 <<
" magOffset = " << (*currentInductor)->magOffset << std::endl;
750 Xyce::dout() <<
"\tInductor branch offsets = { ";
753 Xyce::dout() << (*currentInductor)->inductorCurrentOffsets[ j ] <<
", ";
755 Xyce::dout() <<
"} " << std::endl;
759 Xyce::dout() << std::endl;
763 Xyce::dout() <<
"deltaMEquInductorOffsets = ";
805 bool bsuccess =
true;
810 std::vector< InductorInstanceData* >::iterator currentData =
instanceData.begin();
815 (*currentData)->L = ((*currentData)->baseL)*factor;
835 bool bsuccess =
true;
836 #ifdef Xyce_DEBUG_DEVICE
839 Xyce::dout() <<
"Instance::updateIntermediateVars" << std::endl;
874 double qV = (DeltaV / Vinf) * (V1Pos - V1Neg);
876 double tanh_qV = 0.0;
893 double H = Happ - (Gap / Path) * latestMag * Ms;
894 double He = H + Alpha * latestMag * Ms;
896 double H = Happ - (Gap / Path) * latestMag;
897 double He = H + Alpha * latestMag;
900 double Heo = BetaH*A;
903 double gap_path = Gap / Path;
905 double Heo2 = Heo*Heo;
906 double sq_Heo2He2 = sqrt(Heo2 + He2);
909 double Man = Ms * He / ( A + sq_Heo2He2 );
911 double delM = Man - latestMag*Ms;
913 double delM = Man - latestMag;
916 double delM2 = delM*delM;
917 double delM02 = delM0*delM0;
918 double sq_delM02delM2 = sqrt( delM02 + delM2 );
923 double Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
924 double Manp = Ms * (A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
925 P = ( C * Manp + (1 - C) * Mirrp) / ((1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp)*Ms);
927 double Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
928 double Manp = Ms*(A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
929 P = ( C * Manp + (1 - C) * Mirrp) / (1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp);
960 if( fabs( MagVarUpdate ) > 0.25 * Ms )
977 double dP_Denom = 1.0 + (gap_path - Alpha)*C*Manp + gap_path * (1.0-C) * Mirrp;
985 dManp_dI[i] = ( -Ms * He / (pow(A + sq_Heo2He2, 2.0)*sq_Heo2He2)) *
986 ( (Heo2 / (Heo2 + He2)) + (2.0*(A + Heo2 / sq_Heo2He2)/(A+sq_Heo2He2)) ) *
dHe_dI[i];
988 ddelM_dI[i] = (Ms / (A + sq_Heo2He2)) * (1.0 - He2/((A + sq_Heo2He2)*sq_Heo2He2)) *
dHe_dI[i];
990 dMirrp_dI[i] = (1.0/(2.0*(Kirr - Alpha*sq_delM02delM2))) *
991 (tanh_qV + delM/sq_delM02delM2 +
992 (2.0*Alpha*delM*(delM*tanh_qV +
993 sq_delM02delM2)/(2.0*(Kirr-Alpha*sq_delM02delM2)*sq_delM02delM2))) *
ddelM_dI[i];
996 ( (C*Manp + (1.0-C)*Mirrp)/pow(dP_Denom,2.0) ) *
1018 std::vector< InductorInstanceData* >::iterator
1020 std::vector< InductorInstanceData* >::iterator
1025 while( currentInductor != endInductor )
1057 bool bsuccess =
true;
1058 #ifdef Xyce_DEBUG_DEVICE
1061 Xyce::dout() <<
"Instance::updatePrimaryState---------------" << std::endl
1062 <<
"\tname = " <<
getName() << std::endl;
1073 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1074 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1076 while( currentInductor != endInductor )
1078 double current = solVector[ ( (*currentInductor)->li_Branch) ];
1079 if( (
getSolverState().dcopFlag) && ((*currentInductor)->ICGiven) )
1081 current = (*currentInductor)->IC;
1084 staVector[((*currentInductor)->li_currentState)] = current;
1103 bool bsuccess =
true;
1137 for(
int i=0; i<2; i++)
1164 bool returnVal=
false;
1169 (*maskVectorPtr)[li_MagVar] = 0.0;
1192 bool bsuccess =
true;
1194 #ifdef Xyce_DEBUG_DEVICE
1197 Xyce::dout() <<
"Instance::loadDAEQVector------------------------" << std::endl
1198 <<
"\tname = " <<
getName() << std::endl;
1214 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1215 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1217 while( currentInductor != endInductor )
1219 if( (
getSolverState().dcopFlag) && (*currentInductor)->ICGiven ==
true )
1245 while( currentInductor != endInductor )
1248 (*daeQVecPtr)[((*currentInductor)->li_Branch)] +=
LOI[ i ];
1276 #ifdef Xyce_DEBUG_DEVICE
1279 Xyce::dout() <<
"Instance::loadDAEFVector------------------------" << std::endl
1280 <<
"\tname = " <<
getName() << std::endl;
1292 double mid = 1.0 + (1.0 - (Gap / Path))*
P;
1295 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1296 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1298 while( currentInductor != endInductor )
1300 double current = solVector[(*currentInductor)->li_Branch];
1301 double vNodePos = solVector[(*currentInductor)->li_Pos];
1302 double vNodeNeg = solVector[(*currentInductor)->li_Neg];
1305 (*daeFVecPtr)[((*currentInductor)->li_Pos)] += current;
1307 (*daeFVecPtr)[((*currentInductor)->li_Neg)] += -current;
1309 (*daeFVecPtr)[((*currentInductor)->li_Branch)] += -((vNodePos - vNodeNeg)/mid);
1340 bool bsuccess =
true;
1343 #ifdef Xyce_DEBUG_DEVICE
1346 Xyce::dout() <<
"Instance::loadDAEdQdx-----------------------" << std::endl
1347 <<
"\tname = " <<
getName() << std::endl;
1353 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1354 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1356 while( currentInductor != endInductor )
1360 (*dQdxMatPtr)[((*currentInductor)->li_Branch)]
1361 [(*currentInductor)->inductorCurrentOffsets[j]] +=
LO[i][j];
1386 bool bsuccess =
true;
1388 #ifdef Xyce_DEBUG_DEVICE
1391 Xyce::dout() <<
"Instance::loadDAEdFdx----------------------" << std::endl
1392 <<
"\tname = " <<
getName() << std::endl;
1407 #ifdef MS_FACTORING2
1408 double mid = 1.0 + (1.0 - (Gap/Path))*
P*
model_.
Ms;
1410 double mid = 1.0 + (1.0 - (Gap/Path))*
P;
1413 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1414 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1415 while( currentInductor != endInductor )
1418 (*dFdxMatPtr)[((*currentInductor)->li_Pos)] [((*currentInductor)->APosEquBraVarOffset)] += 1.0;
1419 (*dFdxMatPtr)[((*currentInductor)->li_Neg)] [((*currentInductor)->ANegEquBraVarOffset)] += -1.0;
1420 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][((*currentInductor)->ABraEquPosNodeOffset)] += -1.0/mid;
1421 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][((*currentInductor)->ABraEquNegNodeOffset)] += 1.0/mid;
1423 double delV = solVector[(*currentInductor)->li_Pos] - solVector[(*currentInductor)->li_Neg];
1428 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][(*currentInductor)->inductorCurrentOffsets[j]] +=
1429 delV * (1.0 - (Gap/Path)) *
dP_dI[j]/(mid*mid);
1465 bool bsuccess =
true;
1470 #ifdef MS_FACTORING2
1473 double latestMag =
MagVar;
1478 (*outputFileStreamPtr)
1485 (*outputFileStreamPtr)
1509 bool bsuccess =
true;
1526 varTypeVec[i] =
'I';
1544 template <
typename ScalarT>
1546 const ScalarT & Mag,
const ScalarT & CurrentSum,
1547 const ScalarT & Vpos,
const ScalarT & Vneg)
1566 ScalarT qV = (DeltaV / Vinf) * (Vpos - Vneg);
1568 ScalarT tanh_qV = 0.0;
1571 ScalarT tanh_qV = tanh(qV);
1582 ScalarT Happ = CurrentSum / Path;
1584 #ifdef MS_FACTORING2
1585 ScalarT H = Happ - (Gap / Path) * Mag * Ms;
1586 ScalarT He = H + Alpha * Mag * Ms;
1588 ScalarT H = Happ - (Gap / Path) * Mag;
1589 ScalarT He = H + Alpha * Mag;
1592 ScalarT Heo = BetaH*A;
1595 ScalarT gap_path = Gap / Path;
1596 ScalarT He2 = He*He;
1597 ScalarT Heo2 = Heo*Heo;
1598 ScalarT sq_Heo2He2 = sqrt(Heo2 + He2);
1601 ScalarT Man = Ms * He / ( A + sq_Heo2He2 );
1602 #ifdef MS_FACTORING2
1603 ScalarT delM = Man - Mag*Ms;
1605 ScalarT delM = Man - Mag;
1608 ScalarT delM2 = delM*delM;
1609 ScalarT delM02 = delM0*delM0;
1610 ScalarT sq_delM02delM2 = sqrt( delM02 + delM2 );
1612 #ifdef MS_FACTORING2
1613 ScalarT Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
1614 ScalarT Manp = Ms * (A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
1615 ScalarT Pval = ( C * Manp + (1 - C) * Mirrp) / ((1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp)*Ms);
1617 ScalarT Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
1618 ScalarT Manp = Ms*(A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
1619 ScalarT Pval = ( C * Manp + (1 - C) * Mirrp) / (1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp);
1649 std::vector<Instance*>::iterator iter;
1653 for (iter=first; iter!=last; ++iter)
1655 (*iter)->processParams();
1673 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
1689 useRKIntegration(0),
1691 tnom(getDeviceOptions().tnom)
1731 std::vector<Instance*>::iterator iter;
1735 for (iter=first; iter!=last; ++iter)
1753 std::vector<Instance*>::const_iterator iter;
1761 os <<
"Number of MutIndNonLin instances: " << isize << std::endl;
1762 os <<
" name=\t\tmodelName\tParameters" << std::endl;
1763 for (i=0, iter=first; iter!=last; ++iter, ++i)
1765 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
1791 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1805 .registerDevice(
"min", 2)
1806 .registerModelType(
"min", 2);