⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcc.cpp

📁 pic 模拟程序!面向对象
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    int jNGD = static_cast<int>(xTemp.e2());    Scalar cellVol = grid->cellVolume(iNGD, jNGD);        Scalar numNeutralAtoms;    try{      numNeutralAtoms =  (ptrNGD->getNGD(iNGD,jNGD)) * cellVol;     }    catch(Oops& oops2){      oops2.prepend("MCCPackage::ionization: Error: \n");//OK      throw oops2;    }        // Calculate number of physical ions created    Scalar numIons = pg->get_np2c(index);    // Check that numNeutral > numIons     if ( numNeutralAtoms > numIons ) {       // create the electron species computational particle with       // number of physical electrons equal to numIons      pList->add(new Particle(pg->get_x(index), uEjected, eSpecies,                               numIons, pg->isVariableWeight() ) );      // continue with the ionization and reset the       // Neutral Gas Density accordingly.      Scalar stmp = (numNeutralAtoms - numIons)/cellVol;       ptrNGD->set(iNGD, jNGD,  stmp);            // create n=ionzFraction ions from isotropic gas distribution      for (int i=0; i<ionzFraction; i++) {	uIon = gasDistribution->get_V();	pList->add(new Particle(pg->get_x(index), uIon, iSpecies,				pg->get_np2c(index)/ionzFraction, pg->isVariableWeight()));      }    } else {       // this is the case of numIons >= numNeutralAtoms      // if so, set numIons = numNeutralAtoms      //        set density to zero      //        replace pg->getnp2c(index) with numNeutralAtoms and      //        replace pg->isVariableWeight() with "true" when       //        creating the Particle(...).      // create the electron species particle      pList->add(new Particle(pg->get_x(index), uEjected, eSpecies,                               numNeutralAtoms, true) );                                    ptrNGD->set(iNGD, jNGD, 0.0);            // create n=ionzFraction ions from isotropic gas distribution      for (int i=0; i<ionzFraction; i++) {      uIon = gasDistribution->get_V();      pList->add(new Particle(pg->get_x(index), uIon, iSpecies,			      numNeutralAtoms/ionzFraction, true));      }    }    // Now generate the new normalized momentum vector for    //   the scattered primary.    Vector3 uScatter;    uScatter = newMomentum(u, newEnergy, thetaP, phiP);		//    cout << " initial gamma*v = " << u.magnitude()        << endl;		//    cout << " final   gamma*v = " << uScatter.magnitude() << endl;		//    cout << " difference is:    " << uScatter.magnitude()-u.magnitude() << endl;		//    cout << endl << endl;    u = uScatter;		//    v = u.magnitude();  }}void MCCPackage::ionElastic(CrossSection& cx){  Scalar up1, up2, up3, mag;  Scalar r11, r12, r13, r21, r22, r23, r31, r32, r33;			  Scalar coschi= sqrt(frand());  Scalar sinchi = sqrt(1. -coschi*coschi);	  Scalar phi1  = TWOPI*frand();  Scalar cosphi = cos(phi1);  Scalar sinphi = sin(phi1);	  r13 = u.e1()/v;  r23 = u.e2()/v;  r33 = u.e3()/v;	  if(r33 == 1.0) { up1= 0;  up2= 1;  up3= 0; }  else           { up1= 0;  up2= 0;  up3= 1; }    r12 = r23*up3 -r33*up2;  r22 = r33*up1 -r13*up3;  r32 = r13*up2 -r23*up1;  mag = sqrt(r12*r12 + r22*r22 + r32*r32) + 1E-30;	  r12/= mag;  r22/= mag;  r32/= mag;	  r11 = r22*r33 -r32*r23;  r21 = r32*r13 -r12*r33;  r31 = r12*r23 -r22*r13;	  u.set_e1(v*coschi*(r11*sinchi*cosphi +r12*sinchi*sinphi +r13*coschi));  u.set_e2(v*coschi*(r21*sinchi*cosphi +r22*sinchi*sinphi +r23*coschi));   u.set_e3(v*coschi*(r31*sinchi*cosphi +r32*sinchi*sinphi +r33*coschi));}void MCCPackage::chargeExchange(CrossSection& cx){  u.set_e1(0);  u.set_e2(0);  u.set_e3(0);}/* Method for calculating energy imparted to a secondary (ejected) *   electron, using a parametric model that captures relativistic *   physics for large impact energy and agrees with data at low energy. * * The calculations underlying this method are contained in the *   Tech-X notes, "RNG Calculations for Scattering in XOOPIC," by *   David Bruhwiler (August 28, 2000). * * The parametric model is a relativistic generalization of the *   work by Rudd et al., Phys. Rev. A 44, 1644 (1991) and Phys. *   Rev. A 47, 1866 (1993).  The relativistic generalization is *   described in the Tech-X notes, "Rudd's Differential Cross *   Section for Electron Impact Ionization," by David Bruhwiler, *   (July 17, 2000). */Scalar MCCPackage::ejectedEnergy(const CrossSection& cx,                                 const Scalar& impactEnergy) {	// First, we need to calculate a random # between 0 and A_>,  //   where A_> = f1(T) * (T-I) / f2(T) / (T+I), with I the threshold	//   ionization energy and T the kinetic energy of the impacting	//   electron "impactEnergy".  Scalar I = cx.get_threshold();  if (impactEnergy <= I) return 0.;  Scalar tPlusMC    = impactEnergy + ELECTRON_MASS_EV;	Scalar twoTplusMC = impactEnergy + tPlusMC;  Scalar tPlusI     = impactEnergy + I;  Scalar tMinusI    = impactEnergy - I;  Scalar invTplusMCsq = 1. / ( tPlusMC * tPlusMC );  Scalar tPlusIsq     = tPlusI * tPlusI;  Scalar iOverT       = I / impactEnergy;  Scalar funcT1 = 14./3. + .25 * tPlusIsq * invTplusMCsq                - ELECTRON_MASS_EV * twoTplusMC * iOverT * invTplusMCsq;  Scalar funcT2 = 5./3. - iOverT - 2.*iOverT*iOverT/3.                + .5 * I * tMinusI * invTplusMCsq                + ELECTRON_MASS_EV*twoTplusMC*I*invTplusMCsq*log(iOverT)/tPlusI;  Scalar aGreaterThan = funcT1 * tMinusI / funcT2 / tPlusI;	// We may have to try several times before the "rejection method"	//   lets us keep our ejected energy test value, wTest.	//   Here we define a bool for the while construct and also	//   declare some floating point variables needed inside.  int needToTryAgain = 1;  Scalar randomFW, wTest, wPlusI, wPlusIsq;  Scalar invTminusW, invTminusWsq, invTminusW3;  Scalar probabilityRatio;  while (needToTryAgain==1) {  	// The random number, called F(W) in the notes and randomFW here,  	//   is the antiderivative of a phony_but_simple probability, which  	//   is always >= the correct_but_messy probability.		//    do {randomFW=frand();} while (randomFW<=0. || randomFW>=1.);    randomFW = frand() * aGreaterThan;  	// wTest is the inverse of F(W)    wTest = I*funcT2*randomFW/(funcT1-funcT2*randomFW);  	// Because we are not working directly with the distribution function,    //   we must use the "rejection method".  This involves generating    //   another random number and seeing whether it is > the ratio of  	//   the true probability over the phony_but_simple probability.    wPlusI       = wTest + I;    wPlusIsq     = wPlusI * wPlusI;    invTminusW   = 1./(impactEnergy-wTest);    invTminusWsq = invTminusW * invTminusW;    invTminusW3  = invTminusW * invTminusWsq;    probabilityRatio = ( 1. + 4.*I/wPlusI/3. + wPlusIsq*invTminusWsq                            + 4.*I*wPlusIsq*invTminusW3/3.                         - ELECTRON_MASS_EV*twoTplusMC*wPlusI*invTminusW*invTplusMCsq  											 + wPlusIsq*invTplusMCsq ) / funcT1;    if ( probabilityRatio >= (Scalar)frand() ) needToTryAgain = 0;		//    else cout << "** wTest was rejected..." << endl;	}  // end of while construct	//  cout << "** wTest was accepted!" << endl << endl;  // wTest is the energy of the ejected particle;  the scattered primary	//   has energy T-(W+I)	//  cout << endl;	//  cout << " impact  energy = " << impactEnergy << endl;	//	cout << " ejected energy = " << wTest << endl;  return wTest;}/* Method for calculating the scattering angles (theta, phi) with *   respect to the initial direction of the primary electron, for *   both the primary and secondary electrons in an impact-ionizaiton *   event. * * Unchanged imput variables are eImpact and eSecondary. * Empty variables passed in by reference to hold the desired results *   are:  thetaPrimary, thetaSecondary, phiPrimary and phiSecondary. * * The calculations underlying this method are contained in the *   Tech-X notes, "RNG Calculations for Scattering in XOOPIC," by *   David Bruhwiler (August 28, 2000). * * The parametric model is discussed in the Tech-X notes, "Rudd's *   Differential Cross Section for Electron Impact Ionization," *   by David Bruhwiler, (July 17, 2000). */void MCCPackage::primarySecondaryAngles(const CrossSection& cx,            const Scalar& eImpact,  const Scalar& eSecondary,                  Scalar& thetaPrimary,   Scalar& phiPrimary,                  Scalar& thetaSecondary, Scalar& phiSecondary) {    // Bail out, if impact energy < ionization threshold energy.  Scalar I = cx.get_threshold();  if (eImpact <= I) {    thetaPrimary   = 0.;    thetaSecondary = 0.;    phiPrimary   = 0.;    phiSecondary = 0.;    return;	}    // First, we generate a Monte Carlo value for thetaPrimary --    // We begin with the definition of some temporaries:  Scalar ePrimary = eImpact - eSecondary - I;  Scalar w         = ePrimary;  Scalar wPlusI    = w       + I;  Scalar wPlusI2MC = wPlusI  + 2.*ELECTRON_MASS_EV;  Scalar tPlus2MC  = eImpact + 2.*ELECTRON_MASS_EV;  Scalar alpha;  alpha  = ELECTRON_MASS_EV / ( eImpact + ELECTRON_MASS_EV );  alpha *= 0.6 * alpha;  Scalar g2_T_W = sqrt( wPlusI * tPlus2MC / wPlusI2MC / eImpact );  Scalar g3_T_W = alpha * sqrt( I * (1.-wPlusI/eImpact) / w );	//  cout << "  g2-1 = " << g2_T_W - 1. << endl;	//  cout << "  g3   = " << g3_T_W << endl;  Scalar fTheta = frand();  thetaPrimary = acos( g2_T_W + g3_T_W * tan(                  (1.-fTheta) * atan( (1.-g2_T_W) / g3_T_W )                     - fTheta * atan( (1.+g2_T_W) / g3_T_W ) ) );	//  cout << " thetaPrimary = " << thetaPrimary << endl;  	// Second, we generate a Monte Carlo value for phiPrimary --  phiPrimary = TWOPI * frand();    // Third, we generate a Monte Carlo value for thetaSecondary --  w         = eSecondary;  wPlusI    = w + I;  wPlusI2MC = wPlusI + 2.*ELECTRON_MASS_EV;  g2_T_W = sqrt( wPlusI * tPlus2MC / wPlusI2MC / eImpact );  g3_T_W = alpha * sqrt( I * (1.-wPlusI/eImpact) / w );  fTheta = frand();  thetaSecondary = acos( g2_T_W + g3_T_W * tan(                    (1.-fTheta) * atan2( (Scalar)(1.-g2_T_W) , (Scalar)g3_T_W )                       - fTheta * atan2( (Scalar)(1.+g2_T_W) , (Scalar)g3_T_W ) ) );  	// Fourth, we generate a Monte Carlo value for phiSecondary --  	// In the low-energy limit, phiPrimary and phiSecondary are  	//   uncorrelated.  In the high-energy limit, they are 100%  	//   correlated.  Our approach is to implement a sort of sliding  	//   scale, in which the correlation increases as ePrimary and    //   eSecondary both increase.  Scalar eCritical = 10. * I;  Scalar a_T_W = 0.;  if ( eSecondary>eCritical && ePrimary>eCritical ) {    a_T_W = sqrt((eSecondary-eCritical)*(ePrimary-eCritical))/eCritical;		//    cout << "  a_T_W = " << a_T_W << endl;	}  Scalar delta = TWOPI/(1.+a_T_W);	//  cout << "  delta/(2*pi) = " << delta/TWOPI << endl;  phiSecondary = phiPrimary + M_PI + (frand()-.5)*delta;	//  cout << "  phiSecondary-(phiPrimary+PI) = "	//       << phiSecondary-phiPrimary-M_PI << endl;	return;}/* Method for calculating the scattering angles (theta, phi) with *   respect to the initial direction of the electron, for elastic *   electron-neutral scattering. * * Unchanged input variables are eImpact and the cross section cx. * Empty variables passed in by reference to hold the desired results *   are:  thetaScatter and phiScatter. * * The calculations underlying this method are contained in the *   Tech-X notes, "RNG Calculations for Scattering in XOOPIC," by *   David Bruhwiler (August 28, 2000). * * The parametric model is discussed in the Tech-X notes, "Elastic *   and Inelastic Scattering at all Energies," by David Bruhwiler, *   (July 26, 2000). */void MCCPackage::elasticScatteringAngles(                    const Scalar& eImpact, const CrossSection& cx,                          Scalar& thetaScatter, Scalar& phiScatter) {    // First, we generate a Monte Carlo value for thetaScatter --    // We begin with the definition of some temporaries:  Scalar atomicNum = cx.getAtomicNumber();  Scalar gMinus1  = eImpact / ELECTRON_MASS_EV;  Scalar gamma    = gMinus1 + 1.;  Scalar beta     = sqrt((gamma+1.)*gMinus1)/gamma;  Scalar betaMin  = 1.8e-3;  Scalar thetaMin = pow( atomicNum, 1./3. ) * (1.+betaMin)                  / ( 192. * gamma * (beta+betaMin) );  Scalar thetaMinSq = thetaMin * thetaMin;  Scalar fTheta = frand();  thetaScatter = acos( (1.+thetaMinSq)                         - thetaMinSq * (2.+thetaMinSq)                         / (2.*(1-fTheta) + thetaMinSq) );	//  if (eImpact>1e10) {		//    cout << endl;		//    cout << "impact energy = " << eImpact << endl;		//    cout << "thetaMin      = " << thetaMin << endl;		//    cout << "thetaElastic  = " << thetaScatter << endl;	//	}  	// Next, we generate a Monte Carlo value for phiScatter --  phiScatter = TWOPI * frand();	return;}/* Given an initial normalized momentum vel=p/(m*gamma) (m/s), a new *   energy, and the scattering angles (wrt to initial direction *   defined by u) theta and phi, this method calculates and *   returns a new momentum. * * Note that the magnitude of u is not important -- only the *   direction is used.  Thus, this method can be used for *   elastic scattering, for the primary in an ionization event, *   and also for the ejected secondary. * * All of the input variables are unchanged. * The new momentum is returned.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -