void recombine( gamete_pointer base_gamete, gamete_pointer other_gamete, typename gamete_type::bitset_type * res, unsigned int nRec, typename recombination_method_type::result_type & result_status ) {
        ++m_nRecomb;
        m_nRecombEvents += nRec;

        typename gamete_type::alphabet_t::pointer  alpha = base_gamete->getAlphabet();

        recombination_points rec_points;
        generateRecombination( rec_points, nRec );

        recombination_method_type recomb( base_gamete->getBits(), res, alpha, &rec_points, &result_status );

        boost::to_block_range( *other_gamete->getBits(), recomb );
    }
Beispiel #2
0
void 
ONE_commonTerms(ONEdevice *pDevice, BOOLEAN currentOnly, 
                BOOLEAN tranAnalysis, ONEtranInfo *info)
{
  ONEelem *pElem;
  ONEedge *pEdge;
  ONEnode *pNode;
  int index, eIndex;
  double psi1, psi2, psi, nConc=0.0, pConc=0.0, nC, pC, nP1, pP1;
  double dPsiN, dPsiP;
  double bPsiN, dbPsiN, bMPsiN, dbMPsiN;
  double bPsiP, dbPsiP, bMPsiP, dbMPsiP;
  double mun, dMun, mup, dMup;
  double conc1, conc2;
  double cnAug, cpAug;


  /* evaluate all node (including recombination) and edge quantities */
  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
    pElem = pDevice->elemArray[eIndex];
    cnAug = pElem->matlInfo->cAug[ELEC];
    cpAug = pElem->matlInfo->cAug[HOLE];
    for (index = 0; index <= 1; index++) {
      if (pElem->evalNodes[index]) {
	pNode = pElem->pNodes[index];
	if (pNode->nodeType != CONTACT) {
	  psi = pDevice->dcSolution[pNode->psiEqn];
	  if (pElem->elemType == SEMICON) {
	    nConc = pDevice->dcSolution[pNode->nEqn];
	    pConc = pDevice->dcSolution[pNode->pEqn];
	    if (Srh) {
	      recomb(nConc, pConc,
		  pNode->tn, pNode->tp, cnAug, cpAug, pNode->nie,
		  &pNode->uNet, &pNode->dUdN, &pNode->dUdP);
	    } else {
	      pNode->uNet = 0.0;
	      pNode->dUdN = 0.0;
	      pNode->dUdP = 0.0;
	    }
	    if (pNode->baseType == P_TYPE && pConc <= 0.0) {
	      pConc = pNode->na;
	    } else if (pNode->baseType == N_TYPE && nConc <= 0.0) {
	      nConc = pNode->nd;
	    }
	  }
	} else {
	  /* a contact node */
	  psi = pNode->psi;
	  if (pElem->elemType == SEMICON) {
	    nConc = pNode->nConc;
	    pConc = pNode->pConc;
	  }
	}
	/* store info in the state tables */
	*(pDevice->devState0 + pNode->nodePsi) = psi;
	if (pElem->elemType == SEMICON) {
	  *(pDevice->devState0 + pNode->nodeN) = nConc;
	  *(pDevice->devState0 + pNode->nodeP) = pConc;
	  if (tranAnalysis && pNode->nodeType != CONTACT) {
	    pNode->dNdT = integrate(pDevice->devStates, info, pNode->nodeN);
	    pNode->dPdT = integrate(pDevice->devStates, info, pNode->nodeP);
	  }
	}
      }
    }
    pEdge = pElem->pEdge;
    pNode = pElem->pLeftNode;
    if (pNode->nodeType != CONTACT) {
      psi1 = pDevice->dcSolution[pNode->psiEqn];
    } else {
      psi1 = pNode->psi;
    }
    pNode = pElem->pRightNode;
    if (pNode->nodeType != CONTACT) {
      psi2 = pDevice->dcSolution[pNode->psiEqn];
    } else {
      psi2 = pNode->psi;
    }
    pEdge->dPsi = psi2 - psi1;
    *(pDevice->devState0 + pEdge->edgeDpsi) = pEdge->dPsi;
  }
  /* calculate the current densities and mobility values */
  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
    pElem = pDevice->elemArray[eIndex];
    pEdge = pElem->pEdge;
    if (pElem->elemType == SEMICON) {
      dPsiN = pEdge->dPsi + pEdge->dCBand;
      dPsiP = pEdge->dPsi - pEdge->dVBand;
      bernoulli(dPsiN, &bPsiN, &dbPsiN, &bMPsiN, &dbMPsiN, !currentOnly);
      bernoulli(dPsiP, &bPsiP, &dbPsiP, &bMPsiP, &dbMPsiP, !currentOnly);
      nC = *(pDevice->devState0 + pElem->pLeftNode->nodeN);
      nP1 = *(pDevice->devState0 + pElem->pRightNode->nodeN);
      pC = *(pDevice->devState0 + pElem->pLeftNode->nodeP);
      pP1 = *(pDevice->devState0 + pElem->pRightNode->nodeP);
      conc1 = pElem->pLeftNode->totalConc;
      conc2 = pElem->pRightNode->totalConc;
      pEdge->jn = (bPsiN * nP1 - bMPsiN * nC);
      pEdge->jp = (bPsiP * pC - bMPsiP * pP1);
      
      
      mun = pEdge->mun;
      dMun = 0.0;
      mup = pEdge->mup;
      dMup = 0.0;
      MOBfieldDep(pElem->matlInfo, ELEC, dPsiN * pElem->rDx, &mun, &dMun);
      MOBfieldDep(pElem->matlInfo, HOLE, dPsiP * pElem->rDx, &mup, &dMup);
      
      
      mun *= pElem->rDx;
      dMun *= pElem->rDx * pElem->rDx;
      mup *= pElem->rDx;
      dMup *= pElem->rDx * pElem->rDx;
      

      
      /*
       * The base continuity equation makes use of mu/dx in eg. The base
       * length has already been calculated and converted to normalized,
       * reciprocal form during setup. The name should be changed, but that's
       * a big hassle.
       */
      for (index = 0; index <= 1; index++) {
	if (pElem->evalNodes[index]) {
	  pNode = pElem->pNodes[index];
	  if (pNode->baseType == N_TYPE) {
	    pNode->eg = pEdge->mun * pDevice->baseLength;
	  } else if (pNode->baseType == P_TYPE) {
	    pNode->eg = pEdge->mup * pDevice->baseLength;
	  }
	}
      }

      pEdge->jn *= mun;
      pEdge->jp *= mup;
      
      
      if (!currentOnly) {
	if (dMun == 0.0) {
	  pEdge->dJnDpsiP1 = mun * (dbPsiN * nP1 - dbMPsiN * nC);
	} else {
	  pEdge->dJnDpsiP1 = dMun * (bPsiN * nP1 - bMPsiN * nC)
	      + mun * (dbPsiN * nP1 - dbMPsiN * nC);
	}
	pEdge->dJnDn = -mun * bMPsiN;
	pEdge->dJnDnP1 = mun * bPsiN;
	if (dMup == 0.0) {
	  pEdge->dJpDpsiP1 = mup * (dbPsiP * pC - dbMPsiP * pP1);
	} else {
	  pEdge->dJpDpsiP1 = dMup * (bPsiP * pC - bMPsiP * pP1)
	      + mup * (dbPsiP * pC - dbMPsiP * pP1);
	}
	pEdge->dJpDp = mup * bPsiP;
	pEdge->dJpDpP1 = -mup * bMPsiP;
      }
    }
    if (tranAnalysis) {
      pEdge->jd = -integrate(pDevice->devStates, info,
	  pEdge->edgeDpsi) * pElem->rDx;
    }
  }
}
    gamete_pointer method1( gamete_pointer base_gamete, gamete_pointer other_gamete, unsigned int gen ) {
#ifdef LOGGING
        static unsigned int nCalls = 0;
        std::ostringstream oss;
        oss << gen <<  "." << nCalls++;
        std::string log_key = oss.str();
#endif

        unsigned int nMut = m_rng->nextPoisson( m_mu );
        unsigned int nRec = 0;
        gamete_pointer res = NULL;

        if( base_gamete != other_gamete ) {
            nRec = m_rng->nextPoisson( m_rho );

            if( m_rng->nextBool() ) {
                res = base_gamete;
                base_gamete = other_gamete;
                other_gamete = res;
                res = NULL;
            }
        } else if( nMut == 0 ) {
            // both gametes are the same
            // AND no new mutations will be added
            // hence just return a copy
#ifdef LOGGING
            global_log.put( log_key + ".result", "Same gamete; Copying base gamete");
#endif
            return base_gamete->copy();
//        } else {
//            // both gametes are the same
//            // recombination will result in no new gametes
//            // therefore skip recombinations.
//            // there will be mutations, so clone one of the gametes
//            assert( nMut > 0 );
//            assert( nRec == 0 );
        }

#ifdef LOGGING
        global_log.put( log_key + ".nRec", nRec );
        global_log.put( log_key + ".nMut", nMut );
#endif

        if( nRec > 0 ) {
            ++m_nRecomb;
            m_nRecombEvents += nRec;

            typename gamete_type::bitset_type symm_diff;
            typename alphabet_type::pointer  alpha = base_gamete->getAlphabet();

            recombination_points rec_points;
            generateRecombination( rec_points, nRec );

#ifdef LOGGING
            state_log_type p;
            for( unsigned int i = 0; i < rec_points.size(); ++i ) {
                state_log_type t;
                t.put( "", rec_points[i]);
                p.push_back( std::make_pair( "", t ) );
            }

            global_log.add_child( log_key + ".points", p );
#endif

#ifdef LOGGING
            typename recombination_method_type::result_type stats(gen);
#else
            typename recombination_method_type::result_type stats;
#endif

            recombination_method_type recomb( base_gamete->getBits(), &symm_diff, alpha, &rec_points, &stats );

            boost::to_block_range( *other_gamete->getBits(), recomb );

            if( nMut == 0) {
                if( stats.is_empty ) {
#ifdef LOGGING
                    global_log.put( log_key + ".result" , "EMPTY");
#endif
                    return gamete_type::EMPTY.copy();
                } else if( stats.match_base ) {

#ifdef LOGGING
                    global_log.put( log_key + ".result" , "Matched Base");
#endif
                    return base_gamete->copy();
                } else if( stats.match_alt ) {
#ifdef LOGGING
                    global_log.put( log_key + ".result" , "Matched Alternate");
#endif

                    return other_gamete->copy();
                } else {
#ifdef LOGGING
                    global_log.put( log_key + ".result" , "New gamete, no new mutations");
#endif
                    res = new gamete_type( symm_diff, alpha );
                    return res;
                }
            } else {
#ifdef LOGGING
                global_log.put( log_key + ".result", "New gamete, New mutations");
#endif
                res = new gamete_type( symm_diff, alpha );
            }
        } else if( nMut == 0 ) {
#ifdef LOGGING
            global_log.put( log_key + ".result", "Different Gametes; No Mutaions; Copy random gamete" );
#endif
            return base_gamete->copy();
        } else {
#ifdef LOGGING
            global_log.put( log_key + ".result", "Different Gamete; Clone random gamete");
#endif
            res = base_gamete->clone();
        }

        assert( res != NULL);
        assert( nMut > 0 );

        ++m_nMut;
        m_nMutEvents += nMut;

#ifdef LOGGING
        state_log_type m;
#endif
        while( nMut-- ) {
            typedef symbol_generator< typename alphabet_type::locus_t, typename alphabet_type::allele_t, typename alphabet_type::index_type, alphabet_type > sgen_type;
            typedef typename sgen_type::symbol_type symbol_type;

            static sgen_type sgen;
            symbol_type s = sgen( res->getAlphabet(), (infinite_site * ) NULL );
            //std::cout << "Adding variant: " << s << std::endl;
#ifdef LOGGING
            state_log_type _m;
            _m.put( "", s );

            m.push_back( std::make_pair("", _m));
#endif
            res->addVariant( s );
        }

#ifdef LOGGING
        global_log.add_child( log_key + ".mutations", m);
#endif
        return res;
    }