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_" );
354 filename.append(
getName().getEncodedName() );
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 UserError(*
this) <<
"Could not open file " << filename <<
" for output of state variables";
367 (*outputFileStreamPtr).setf(std::ios::scientific, std::ios::floatfield );
368 (*outputFileStreamPtr).width(20);
369 (*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::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
515 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
516 for ( ; currentInductor != endInductor ; ++currentInductor)
518 if (*currentInductor != NULL)
520 delete *currentInductor;
521 *currentInductor = NULL;
536 const std::vector<int> & extLIDVecRef)
549 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
550 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
553 while( currentInductor != endInductor )
555 (*currentInductor)->li_Pos =
extLIDVec[ i++ ];
556 (*currentInductor)->li_Neg =
extLIDVec[ i++ ];
557 (*currentInductor)->li_Branch = intLIDVec[ j++ ];
568 #ifdef Xyce_DEBUG_DEVICE
571 Xyce::dout() <<
"Instance::registerLIDs------------------------" << std::endl;
574 while( currentInductor != endInductor )
576 Xyce::dout() <<
"Inductor [ " << i++ <<
" ] "
577 <<
" li_Pos = " << (*currentInductor)->li_Pos
578 <<
" li_Neg = " << (*currentInductor)->li_Neg
579 <<
" li_Branch = " << (*currentInductor)->li_Branch << std::endl;
584 Xyce::dout() <<
" li_deltaMagVar = " <<
li_deltaMagVar << std::endl;
603 for (std::vector< InductorInstanceData* >::const_iterator it =
instanceData.begin(), end =
instanceData.end(); it != end; ++it)
628 #ifdef Xyce_DEBUG_DEVICE
631 Xyce::dout() <<
"Instance::registerStateLIDs-------------------" << std::endl;
660 #ifdef Xyce_DEBUG_DEVICE
663 Xyce::dout() <<
"Instance::registerJacLIDs ----------------------------" << std::endl;
665 Xyce::dout() <<
"jacLIDVec = " << std::endl;
666 for(
int i = 0; i<
jacStamp.size(); ++i )
668 Xyce::dout() <<
"jacLIDVec[ " << i <<
" ] = { ";
669 for(
int j=0; j<jacLIDVec[i].size(); ++j)
671 Xyce::dout() << jacLIDVec[i][j];
672 if( j != ( jacLIDVec[i].size() -1 ) )
674 Xyce::dout() <<
", ";
677 Xyce::dout() <<
" }" << std::endl;
682 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
683 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
685 while( currentInductor != endInductor )
687 (*currentInductor)->APosEquBraVarOffset = jacLIDVec[ 2*i ][ 0 ];
688 (*currentInductor)->ANegEquBraVarOffset = jacLIDVec[ 2*i + 1 ][ 0 ];
689 (*currentInductor)->vPosOffset = jacLIDVec[ 2*
numInductors + i ][ 0 ];
690 (*currentInductor)->vNegOffset = jacLIDVec[ 2*
numInductors + i ][ 1 ];
692 (*currentInductor)->ABraEquPosNodeOffset = jacLIDVec[ 2*
numInductors + i ][ 0 ];
693 (*currentInductor)->ABraEquNegNodeOffset = jacLIDVec[ 2*
numInductors + i ][ 1 ];
698 (*currentInductor)->ABraEquBraVarOffset = jacLIDVec[ 2*numInductors + i ][ j + 2 ];
700 (*currentInductor)->inductorCurrentOffsets[ j ] = jacLIDVec[ 2*numInductors + i ][ j + 2 ];
717 #ifdef Xyce_DEBUG_DEVICE
722 while( currentInductor != endInductor )
724 Xyce::dout() <<
"Inductor [ " << i <<
" ] " << (*currentInductor)->name << std::endl
725 <<
" APosEquBraVarOffset = " << (*currentInductor)->APosEquBraVarOffset << std::endl
726 <<
" ANegEquBraVarOffset = " << (*currentInductor)->ANegEquBraVarOffset << std::endl
727 <<
" vPosOffset = " << (*currentInductor)->vPosOffset << std::endl
728 <<
" vNegOffset = " << (*currentInductor)->vNegOffset << std::endl
729 <<
" ABraEquPosNodeOffset = " << (*currentInductor)->ABraEquPosNodeOffset << std::endl
730 <<
" ABraEquNegNodeOffset = " << (*currentInductor)->ABraEquNegNodeOffset << std::endl
731 <<
" ABraEquBraVarOffset = " << (*currentInductor)->ABraEquBraVarOffset << std::endl
732 <<
" magOffset = " << (*currentInductor)->magOffset << std::endl;
733 Xyce::dout() <<
"\tInductor branch offsets = { ";
736 Xyce::dout() << (*currentInductor)->inductorCurrentOffsets[ j ] <<
", ";
738 Xyce::dout() <<
"} " << std::endl;
742 Xyce::dout() << std::endl;
746 Xyce::dout() <<
"deltaMEquInductorOffsets = ";
788 bool bsuccess =
true;
793 std::vector< InductorInstanceData* >::iterator currentData =
instanceData.begin();
798 (*currentData)->L = ((*currentData)->baseL)*factor;
818 bool bsuccess =
true;
819 #ifdef Xyce_DEBUG_DEVICE
822 Xyce::dout() <<
"Instance::updateIntermediateVars" << std::endl;
857 double qV = (DeltaV / Vinf) * (V1Pos - V1Neg);
859 double tanh_qV = 0.0;
876 double H = Happ - (Gap / Path) * latestMag * Ms;
877 double He = H + Alpha * latestMag * Ms;
879 double H = Happ - (Gap / Path) * latestMag;
880 double He = H + Alpha * latestMag;
883 double Heo = BetaH*A;
886 double gap_path = Gap / Path;
888 double Heo2 = Heo*Heo;
889 double sq_Heo2He2 = sqrt(Heo2 + He2);
892 double Man = Ms * He / ( A + sq_Heo2He2 );
894 double delM = Man - latestMag*Ms;
896 double delM = Man - latestMag;
899 double delM2 = delM*delM;
900 double delM02 = delM0*delM0;
901 double sq_delM02delM2 = sqrt( delM02 + delM2 );
906 double Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
907 double Manp = Ms * (A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
908 P = ( C * Manp + (1 - C) * Mirrp) / ((1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp)*Ms);
910 double Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
911 double Manp = Ms*(A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
912 P = ( C * Manp + (1 - C) * Mirrp) / (1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp);
943 if( fabs( MagVarUpdate ) > 0.25 * Ms )
960 double dP_Denom = 1.0 + (gap_path - Alpha)*C*Manp + gap_path * (1.0-C) * Mirrp;
968 dManp_dI[i] = ( -Ms * He / (pow(A + sq_Heo2He2, 2.0)*sq_Heo2He2)) *
969 ( (Heo2 / (Heo2 + He2)) + (2.0*(A + Heo2 / sq_Heo2He2)/(A+sq_Heo2He2)) ) *
dHe_dI[i];
971 ddelM_dI[i] = (Ms / (A + sq_Heo2He2)) * (1.0 - He2/((A + sq_Heo2He2)*sq_Heo2He2)) *
dHe_dI[i];
973 dMirrp_dI[i] = (1.0/(2.0*(Kirr - Alpha*sq_delM02delM2))) *
974 (tanh_qV + delM/sq_delM02delM2 +
975 (2.0*Alpha*delM*(delM*tanh_qV +
976 sq_delM02delM2)/(2.0*(Kirr-Alpha*sq_delM02delM2)*sq_delM02delM2))) *
ddelM_dI[i];
979 ( (C*Manp + (1.0-C)*Mirrp)/pow(dP_Denom,2.0) ) *
1001 std::vector< InductorInstanceData* >::iterator
1003 std::vector< InductorInstanceData* >::iterator
1008 while( currentInductor != endInductor )
1040 bool bsuccess =
true;
1041 #ifdef Xyce_DEBUG_DEVICE
1044 Xyce::dout() <<
"Instance::updatePrimaryState---------------" << std::endl
1045 <<
"\tname = " <<
getName() << std::endl;
1056 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1057 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1059 while( currentInductor != endInductor )
1061 double current = solVector[ ( (*currentInductor)->li_Branch) ];
1062 if( (
getSolverState().dcopFlag) && ((*currentInductor)->ICGiven) )
1064 current = (*currentInductor)->IC;
1067 staVector[((*currentInductor)->li_currentState)] = current;
1086 bool bsuccess =
true;
1120 for(
int i=0; i<2; i++)
1147 bool returnVal=
false;
1152 (*maskVectorPtr)[li_MagVar] = 0.0;
1175 bool bsuccess =
true;
1177 #ifdef Xyce_DEBUG_DEVICE
1180 Xyce::dout() <<
"Instance::loadDAEQVector------------------------" << std::endl
1181 <<
"\tname = " <<
getName() << std::endl;
1197 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1198 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1200 while( currentInductor != endInductor )
1202 if( (
getSolverState().dcopFlag) && (*currentInductor)->ICGiven ==
true )
1228 while( currentInductor != endInductor )
1231 (*daeQVecPtr)[((*currentInductor)->li_Branch)] +=
LOI[ i ];
1259 #ifdef Xyce_DEBUG_DEVICE
1262 Xyce::dout() <<
"Instance::loadDAEFVector------------------------" << std::endl
1263 <<
"\tname = " <<
getName() << std::endl;
1275 double mid = 1.0 + (1.0 - (Gap / Path))*
P;
1278 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1279 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1281 while( currentInductor != endInductor )
1283 double current = solVector[(*currentInductor)->li_Branch];
1284 double vNodePos = solVector[(*currentInductor)->li_Pos];
1285 double vNodeNeg = solVector[(*currentInductor)->li_Neg];
1288 (*daeFVecPtr)[((*currentInductor)->li_Pos)] += current;
1290 (*daeFVecPtr)[((*currentInductor)->li_Neg)] += -current;
1292 (*daeFVecPtr)[((*currentInductor)->li_Branch)] += -((vNodePos - vNodeNeg)/mid);
1323 bool bsuccess =
true;
1326 #ifdef Xyce_DEBUG_DEVICE
1329 Xyce::dout() <<
"Instance::loadDAEdQdx-----------------------" << std::endl
1330 <<
"\tname = " <<
getName() << std::endl;
1336 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1337 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1339 while( currentInductor != endInductor )
1343 (*dQdxMatPtr)[((*currentInductor)->li_Branch)]
1344 [(*currentInductor)->inductorCurrentOffsets[j]] +=
LO[i][j];
1369 bool bsuccess =
true;
1371 #ifdef Xyce_DEBUG_DEVICE
1374 Xyce::dout() <<
"Instance::loadDAEdFdx----------------------" << std::endl
1375 <<
"\tname = " <<
getName() << std::endl;
1390 #ifdef MS_FACTORING2
1391 double mid = 1.0 + (1.0 - (Gap/Path))*
P*
model_.
Ms;
1393 double mid = 1.0 + (1.0 - (Gap/Path))*
P;
1396 std::vector< InductorInstanceData* >::iterator currentInductor =
instanceData.begin();
1397 std::vector< InductorInstanceData* >::iterator endInductor =
instanceData.end();
1398 while( currentInductor != endInductor )
1401 (*dFdxMatPtr)[((*currentInductor)->li_Pos)] [((*currentInductor)->APosEquBraVarOffset)] += 1.0;
1402 (*dFdxMatPtr)[((*currentInductor)->li_Neg)] [((*currentInductor)->ANegEquBraVarOffset)] += -1.0;
1403 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][((*currentInductor)->ABraEquPosNodeOffset)] += -1.0/mid;
1404 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][((*currentInductor)->ABraEquNegNodeOffset)] += 1.0/mid;
1406 double delV = solVector[(*currentInductor)->li_Pos] - solVector[(*currentInductor)->li_Neg];
1411 (*dFdxMatPtr)[((*currentInductor)->li_Branch)][(*currentInductor)->inductorCurrentOffsets[j]] +=
1412 delV * (1.0 - (Gap/Path)) *
dP_dI[j]/(mid*mid);
1448 bool bsuccess =
true;
1453 #ifdef MS_FACTORING2
1456 double latestMag =
MagVar;
1461 (*outputFileStreamPtr)
1468 (*outputFileStreamPtr)
1492 bool bsuccess =
true;
1509 varTypeVec[i] =
'I';
1527 template <
typename ScalarT>
1529 const ScalarT & Mag,
const ScalarT & CurrentSum,
1530 const ScalarT & Vpos,
const ScalarT & Vneg)
1549 ScalarT qV = (DeltaV / Vinf) * (Vpos - Vneg);
1551 ScalarT tanh_qV = 0.0;
1554 ScalarT tanh_qV = tanh(qV);
1565 ScalarT Happ = CurrentSum / Path;
1567 #ifdef MS_FACTORING2
1568 ScalarT H = Happ - (Gap / Path) * Mag * Ms;
1569 ScalarT He = H + Alpha * Mag * Ms;
1571 ScalarT H = Happ - (Gap / Path) * Mag;
1572 ScalarT He = H + Alpha * Mag;
1575 ScalarT Heo = BetaH*A;
1578 ScalarT gap_path = Gap / Path;
1579 ScalarT He2 = He*He;
1580 ScalarT Heo2 = Heo*Heo;
1581 ScalarT sq_Heo2He2 = sqrt(Heo2 + He2);
1584 ScalarT Man = Ms * He / ( A + sq_Heo2He2 );
1585 #ifdef MS_FACTORING2
1586 ScalarT delM = Man - Mag*Ms;
1588 ScalarT delM = Man - Mag;
1591 ScalarT delM2 = delM*delM;
1592 ScalarT delM02 = delM0*delM0;
1593 ScalarT sq_delM02delM2 = sqrt( delM02 + delM2 );
1595 #ifdef MS_FACTORING2
1596 ScalarT Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
1597 ScalarT Manp = Ms * (A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
1598 ScalarT Pval = ( C * Manp + (1 - C) * Mirrp) / ((1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp)*Ms);
1600 ScalarT Mirrp = (delM * tanh_qV + sq_delM02delM2 ) / (2*( Kirr- Alpha * sq_delM02delM2));
1601 ScalarT Manp = Ms*(A + Heo2/sq_Heo2He2) / pow(A + sq_Heo2He2, 2.0);
1602 ScalarT Pval = ( C * Manp + (1 - C) * Mirrp) / (1 + (gap_path - Alpha) * C * Manp + gap_path * (1-C) * Mirrp);
1632 std::vector<Instance*>::iterator iter;
1636 for (iter=first; iter!=last; ++iter)
1638 (*iter)->processParams();
1656 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
1672 useRKIntegration(0),
1674 tnom(getDeviceOptions().tnom)
1714 std::vector<Instance*>::iterator iter;
1718 for (iter=first; iter!=last; ++iter)
1736 std::vector<Instance*>::const_iterator iter;
1744 os <<
"Number of MutIndNonLin instances: " << isize << std::endl;
1745 os <<
" name=\t\tmodelName\tParameters" << std::endl;
1746 for (i=0, iter=first; iter!=last; ++iter, ++i)
1748 os <<
" " << i <<
": " << (*iter)->getName() <<
"\t";
1774 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1788 .registerDevice(
"min", 2)
1789 .registerModelType(
"min", 2);