示例#1
0
void DiracAntiSpinor::SetP4(const Vector4<double> &__p4,
			    const double &__mass){

  Matrix <complex<double> > sigP(2,2);
  Matrix <complex<double> > chi(2,1);
  PauliSigma sigma;

  _p4 = __p4;
  _mass = __mass;

  complex<double> norm = sqrt(__p4.E() + __mass);
  complex<double> epm = __p4.E() + __mass;
  sigP = sigma[1]*__p4.X() + sigma[2]*__p4.Y() + sigma[3]*__p4.Z();

  // spin up
  chi(0,0) = 0.;  
  chi(1,0) = 1.;  
  _spinors[1](2,0) = chi(0,0)*norm;
  _spinors[1](3,0) = chi(1,0)*norm;
  _spinors[1](0,0) = ((sigP*chi)(0,0))*norm/epm;
  _spinors[1](1,0) = ((sigP*chi)(1,0))*norm/epm;

  // spin down
  chi(0,0) = 1.;
  chi(1,0) = 0.;
  _spinors[0](2,0) = chi(0,0)*norm;
  _spinors[0](3,0) = chi(1,0)*norm;
  _spinors[0](0,0) = ((sigP*chi)(0,0))*norm/epm;
  _spinors[0](1,0) = ((sigP*chi)(1,0))*norm/epm;
  
  this->_SetProjector();
}
示例#2
0
int makeProbe( cfpix &cpix, int nx, int ny,
          double xp, double yp, float p[], 
          double wavlen, double k2max, double pixel, int multiMode,
          int ismoth )
{ 
    int ix, iy, npixels;
    double alx, aly, k2, chi0, pi, dx2p, dy2p;

    /*    PIXEL = diagonal width of pixel squared
        if a pixel is on the aperture boundary give it a weight
        of 1/2 otherwise 1 or 0
    */
    npixels = 0;
    pi = 4.0 * atan( 1.0 );

    dx2p = 2.0*pi*xp;
    dy2p = 2.0*pi*yp;

    for( iy=0; iy<ny; iy++) {
        aly = wavlen * ky[iy];  /* y component of angle alpha */
        for( ix=0; ix<nx; ix++) {
            k2 = kx2[ix] + ky2[iy];
            alx = wavlen * kx[ix];  /* x component of angle alpha */
            if ( ( ismoth != 0) && 
                ( fabs(k2-k2max) <= pixel) ) {
                   chi0 = (2.0*pi/wavlen) * chi( p, alx, aly, multiMode )
                           - ( (dx2p*kx[ix]) + (dy2p*ky[iy]) );
                cpix.re(ix,iy) = (float) ( 0.5 * cos(chi0));  /* real */
                cpix.im(ix,iy) = (float) (-0.5 * sin(chi0));  /* imag */
                /* printf("smooth by 0.5 at ix=%d, iy=%d\n", ix, iy ); */
            } else if ( k2 <= k2max ) {
                   chi0 = (2.0*pi/wavlen) * chi( p, alx, aly, multiMode )
                           - ( (dx2p*kx[ix]) + (dy2p*ky[iy]) );
                cpix.re(ix,iy) = (float)  cos(chi0);  /* real */
                cpix.im(ix,iy) = (float) -sin(chi0);  /* imag */
                npixels++;
            } else {
                cpix.re(ix,iy) = cpix.im(ix,iy) = 0.0F;
            }
        }  /* end for( ix=0... )  */
    }  /* end for( iy=0... )  */


    cpix.ifft();   //  inverse transform back to real space

    return( npixels );

}  /* end makeProbe()  */
示例#3
0
void LLSideTrayListener::getTabs(const LLSD& event) const
{
    LLSD reply;

    LLSideTray* tray = mGetter();
    LLSD::Integer ord(0);
    for (LLSideTray::child_list_const_iter_t chi(tray->beginChild()), chend(tray->endChild());
         chi != chend; ++chi, ++ord)
    {
        LLView* child = *chi;
        // How much info is important? Toss in as much as seems reasonable for
        // each tab. But to me, at least for the moment, the most important
        // item is the tab name.
        LLSD info;
        // I like the idea of returning a map keyed by tab name. But as
        // compared to an array of maps, that loses sequence information.
        // Address that by indicating the original order in each map entry.
        info["ord"] = ord;
        info["visible"] = bool(child->getVisible());
        info["enabled"] = bool(child->getEnabled());
        info["available"] = child->isAvailable();
        reply[child->getName()] = info;
    }

    sendReply(reply, event);
}
//evaluates add_i polynomial for layer 59+d of the F0 circuit
void
FLT_add_lvl2(mpz_t rop, const mpz_t* r, int mi, int mip1, int ni, int nip1, const mpz_t prime)
{
   mpz_t tmp, ans;
   mpz_init(tmp);
   mpz_init(ans);

   //even ps go to nip1-1 for in1 and p/2 for both in2
   one_sub(ans, r[0]);
   /*
   uint64 ans1 = 1+PRIME-r[0];
   uint64 temp;
   */

   //now make sure p>>1 matches in2
   check_equal(ans, &r[1], &r[mi+mip1], 0, mip1, prime);

   //make sure in1 matches nip1-1
   chi(tmp, nip1-1, r+mi, mip1, prime);
   modmult(rop, tmp, ans, prime);
   /*
   ans1 = myModMult(ans1, chi(nip1-1, r+mi, mip1));
   return ans1;
   */

   mpz_clear(tmp);
   mpz_clear(ans);
}
示例#5
0
// evaluate v(xi,eta) on reference element using local node numbering
double eval(const double v[3], double xi, double eta) {
    double sum = 0.0;
    int    L;
    for (L = 0; L < 3; L++)
        sum += v[L] * chi(L,xi,eta);
    return sum;
}
示例#6
0
文件: gI.c 项目: Tim-Frederik/EliTim
double C_gi_photoz(double l, double zm, double DZ, double zphot){
	double RES,res,k,fK,D_a,GIz,hoverh0,z,a,norm,dz;
	double array[3] = {l,zphot,zm};
	dz = 0.02;
	RES = 0;
	norm = 0.;
	for (z = zm-DZ/2.0+dz/2.0; z< zm+DZ/2.0; z +=dz){
		norm +=pow(zdistr(z),2.0)*dz;
		array[2] = z;
		a = 1./(1+z);
		if (zphot<0.5){
			fK     = f_K(chi(a));
			k      = array[0]/fK;
			D_a=growfac(a,1.,1.)/growfac(1.,1.,1.);
			hoverh0 = sqrt(cosmology.Omega_m /(a*a*a) + (1.-cosmology.Omega_m -cosmology.Omega_v )/(a*a) + omv_vareos(a) );
			
			res= a*a*hoverh0/fK/fK;
			
			res = res*0.0134*cosmology.Omega_m/D_a*P_delta(a, k)*pow(zdistr(z),2.0);
		}
		else{res = int_GSL_integrate_qag2(int_for_C_gi_photoz,(void*)array,0.35,0.999,NULL,1000)*pow(zdistr(z),2.0);}
		RES += res*dz;
		
	}
	return cosmology.bias*RES/(norm*norm*10.0);
}
void KeccakPermutationOnWords(UINT64 *state)
{
    unsigned int i;

    //displayStateAsWords(3, "Same, as words", state);

    for(i=0; i<nrRounds; i++) {
        //displayRoundNumber(3, i);

        theta(state);
        //displayStateAsWords(3, "After theta", state);

        rho(state);
        //displayStateAsWords(3, "After rho", state);

        pi(state);
        //displayStateAsWords(3, "After pi", state);

        chi(state);
        //displayStateAsWords(3, "After chi", state);

        iota(state, i);
        //displayStateAsWords(3, "After iota", state);
    }
}
示例#8
0
void keccak_coproc(UINT64 *A)
{
    unsigned int i;
    for(i=0;i<nrRounds;i++) { 
        theta(A);
        rho(A);
        pi(A);
        chi(A);
        iota(A,i);
    }
}
LLSD LLCommandDispatcher::enumerate()
{
    LLSD response;
    LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance());
    for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()),
            chend(registry.mMap.end());
            chi != chend; ++chi)
    {
        LLSD info;
        info["untrusted"] = chi->second.mUntrustedBrowserAccess;
        info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess);
        response[chi->first] = info;
    }
    return response;
}
示例#10
0
文件: gI.c 项目: Tim-Frederik/EliTim
double int_for_C_gi_photoz (double a, void *params){
	double res,k,fK,D_a,GIz,hoverh0;
	double *array = (double*)params;
	
	fK     = f_K(chi(a));
	k      = array[0]/fK;
	D_a=growfac(a,1.,1.)/growfac(1.,1.,1.);
	hoverh0 = sqrt(cosmology.Omega_m /(a*a*a) + (1.-cosmology.Omega_m -cosmology.Omega_v )/(a*a) + omv_vareos(a) );
	
	res= a*a*hoverh0/fK/fK;
	
	res = res*0.0134*cosmology.Omega_m/D_a*P_delta(a, k);
	if (array[1] > 0.5){res = res*pow(p_zspec(1./a-1.,array[3])/(a*a),2.0);}
	return res;
}
void MainHandler::release()
{
  //printf("MainHandler::release()\n");
  QDictIterator<CompoundHandler> chi(m_compoundsLoaded);
  CompoundHandler *ch;
  for (chi.toFirst();(ch=chi.current());++chi)
  {
    debug(1,"Compound %s not released\n",ch->name()->latin1());
  }
  graphhandler_exit();
  dochandler_exit();
  memberhandler_exit();
  sectionhandler_exit();
  compoundhandler_exit();
  delete this;
}
示例#12
0
    Ts do_eval(const Tp& p)
    {
      Ts result(0);
      for(int i=(this->get_data_set()).size()-1;i>=0;--i)
	{
	  Ty chi(this->get_data_set().get_data(0).get_y().size());
	  for(int j=0;j<chi.size();++j)
	    {
	      Ty model_y(this->eval_model(this->get_data_set().get_data(i).get_x(),p));
	      if(model_y[j]>this->get_data_set().get_data(i).get_y()[j])
		{
		  chi[j]=(this->get_data_set().get_data(i).get_y()[j]-model_y[j])/this->get_data_set().get_data(i).get_y_upper_err()[j];
		}
	      else
		{
		  chi[j]=(this->get_data_set().get_data(i).get_y()[j]-model_y[j])/this->get_data_set().get_data(i).get_y_lower_err()[j];
		}
	    }
	  result+=sum(chi*chi);
	  
	}
      return result;
    }
示例#13
0
double stellar_evo::dmsegdt(){                            //Equation (?) AGLB2013
  double dmsegdt = 0;
  dmsegdt += chi()*mynode->MS/mynode->t_rhp;            
  return dmsegdt;
}
示例#14
0
int main()
{
    char filein[NCMAX], fileout[NCMAX], filestart[NCMAX],
        filebeam[NCMAX], description[NCMAX],
        filecross[NCMAX], cline[NCMAX];
  
    const char version[] = "21-nov-2012 (ejk)";

    int lstart=0, lpartl=0, lbeams=0, lwobble=0, lcross=0, nwobble=1;
    int ix, iy, iz, nx, ny, nz, nzout, ixmid, iymid, i, nslic0, islice,
        nacx,nacy, iqx, iqy, iwobble, ndf, idf, nbout, ib,
        ncellx, ncelly, ncellz, iycross, ns, NPARAM;
    int *hbeam, *kbeam;
    int natom, *Znum, *Znum2, istart, na, done, status, multiMode;
    long nbeams, nillum;
    long  ltime;
    unsigned long iseed;
    long32 nxl, nyl;   /*  tiffsubs 32 bit integer type */

    float *x, *y, *z, *occ, *wobble;
    float *x2, *y2, *z2, *occ2;
   
    float wmin, wmax, xmin,xmax, ymin, ymax, zmin, zmax;

    float *kx, *ky, *xpos, *ypos, *param, *sparam;
    float k2, k2max, scale, v0, mm0, wavlen, rx, ry,
        ax, by, cz, pi, rmin, rmax, aimin, aimax,
        rx2,ry2, ctiltx, ctilty, tctx, tcty,
        acmin, acmax, Cs3, Cs5, df, df0, sigmaf, dfdelt, aobj,
        qx, qy, qy2, q2, q2min, q2max, sumdf, pdf, k2maxo,
        temperature, ycross, dx, dy;

    float tr, ti, wr, wi;

    float **wave0r, **wave0i, **pix, **depthpix,
        *propxr, *propxi, *propyr, *propyi;

    cfpix wave;            /* complex probe wave functions */
    cfpix trans;           /* complex transmission functions */
    cfpix temp ;           /* complex scratch wavefunction */

    double sum, timer, xdf, chi0, chi1, chi2, chi3, t, zslice,
        deltaz, phirms, rsq, vz, alx, aly;
        
    FILE *fp1;

    floatTIFF myFile;

/*  echo version date and get input file name */

    printf("autoslic(e) version dated %s\n", version);
    printf("Copyright (C) 1998-2012 Earl J. Kirkland\n" );
    printf( "This program is provided AS-IS with ABSOLUTELY NO WARRANTY\n "
        " under the GNU general public license\n\n" );

    printf("perform CTEM multislice with automatic slicing and FFTW\n");
#ifdef USE_OPENMP
    printf( "and multithreaded using openMP\n");
#endif
    printf( "\n" );
    
    pi = (float) (4.0 * atan( 1.0 ));
    NPARAM = myFile.maxParam();
    param = (float*) malloc1D( NPARAM, sizeof(float), "param" );
    sparam = (float*) malloc1D( NPARAM, sizeof(float), "sparam" );
    for( ix=0; ix<NPARAM; ix++ ) param[ix] = 0.0F;

    printf("Name of file with input atomic "
           "potential in x,y,z format:\n");
    ns = scanf("%s", filein );

/*  get simulation options */

    printf("Replicate unit cell by NCELLX,NCELLY,NCELLZ :\n");
    ns = scanf("%d %d %d", &ncellx, &ncelly, &ncellz);
    if( ncellx < 1 ) ncellx = 1;
    if( ncelly < 1 ) ncelly = 1;
    if( ncellz < 1 ) ncellz = 1;

    printf("Name of file to get binary output of multislice result:\n");
    ns = scanf("%s", fileout );

    lpartl = askYN("Do you want to include partial coherence");

    if( lpartl == 1 ) {
        printf("Illumination angle min, max in mrad:\n");
        ns = scanf("%f %f", &acmin, &acmax);
        acmin  = acmin  * 0.001F;
        acmax  = acmax  * 0.001F;
        printf("Spherical aberration Cs3, Cs5(in mm.):\n");
        ns = scanf("%g %g", &Cs3, &Cs5);
        param[pCS]  = (float) ( Cs3*1.0e7 );
        param[pCS5] = (float) ( Cs5*1.0e7 );
        printf("Defocus, mean, standard deviation, and"
               " sampling size (in Angstroms) =\n");
        ns = scanf("%f %f %f", &df0, &sigmaf, &dfdelt);
        param[pDEFOCUS] = (float) df0;
        printf("Objective aperture (in mrad) =\n");
        ns = scanf("%f", &aobj);
        aobj = aobj * 0.001F;
#ifdef MANY_ABERR
    /*   get higher order aberrations if necessary */
    printf("type higher order aber. name (as C32a, etc.) followed\n"
        " by a value in mm. (END to end)\n");
    done = multiMode = 0;
    do{
        ns = scanf( "%20s", cline );
        if( strstr( cline, "END" ) != NULL ) {
            done = 1;
        } else {
            ns = scanf( "%lg", &vz );
            status = readCnm( cline, param, vz );        
            if( status < 0 ) {
                printf( "unrecognized aberration, exit...\n");
                exit( EXIT_SUCCESS );
            } else multiMode = 1;
        }
    } while( !done );

#endif
        lstart = 0;
    } else {
        printf("NOTE, the program image must also be run.\n");
        lstart = askYN("Do you want to start from previous result");
    }

    if ( lstart == 1 ) {
        printf("Name of file to start from:\n");
        ns = scanf("%s", filestart);
    } else {
        printf("Incident beam energy in kev:\n");
        ns = scanf("%g", &v0);
        printf("Wavefunction size in pixels, Nx,Ny:\n");
        ns = scanf("%d %d", &nx, &ny );
    }

    printf("Crystal tilt x,y in mrad.:\n");
    ns = scanf("%f %f", &ctiltx, &ctilty);
    ctiltx = ctiltx /1000;
    ctilty = ctilty /1000;

    /*  remember that the slice thickness must be > atom size
        to use projected atomic potential */
    printf("Slice thickness (in Angstroms):\n");
    ns = scanf("%lf", &deltaz );
    if( deltaz < 1.0 ) {
        printf("WARNING: this slice thickness is probably too thin"
            " for autoslice to work properly.\n");
    }

    if( lpartl == 0 ) {
        lbeams = askYN("Do you want to record the (real,imag) value\n"
        " of selected beams vs. thickness");
        if( lbeams == 1 ) {
            printf("Name of file for beams info:\n");
            ns = scanf("%s", filebeam );
            printf("Number of beams:\n");
            ns = scanf("%d", &nbout);
            if( nbout<1 ) nbout = 1;
            hbeam = (int*) malloc1D( nbout, sizeof(int), "hbeam" );
            kbeam = (int*) malloc1D( nbout, sizeof(int), "kbeam" );
            for( ib=0; ib<nbout; ib++) {
                printf("Beam %d, h,k=\n", ib+1);
                ns = scanf("%d %d", &hbeam[ib], &kbeam[ib] );
            }
        }
    }

    lwobble = askYN("Do you want to include thermal vibrations");
    if( lwobble == 1 ) {
        printf( "Type the temperature in degrees K:\n");
        ns = scanf( "%g", &temperature );
        printf( "Type number of configurations to average over:\n");
        ns = scanf( "%d", &nwobble );
        if( nwobble < 1 ) nwobble = 1;
        /* get random number seed from time if available 
            otherwise ask for a seed */
        ltime = (long) time( NULL );
        iseed = (unsigned) ltime;
        if( ltime == -1 ) {
            printf("Type initial seed for random number generator:\n");
            ns = scanf("%ld", &iseed);
        } else
            printf( "Random number seed initialized to %ld\n", iseed );
    } else temperature = 0.0F;

    if( lpartl == 0 ) {
        lcross = askYN("Do you want to output intensity vs. depth cross section");
        if( lcross == 1 ){
            printf( "Type name of file to get depth profile image:\n");
            ns = scanf("%s", filecross );
            printf( "Type y position of depth cross section (in Ang.):\n");
            ns = scanf("%f", &ycross );
        }
    }

/* start timing the actual computation just for fun */

    timer = cputim();
#ifdef USE_OPENMP
    walltimer = walltim();  /* wall time for opneMP */
#endif

/*  get starting value of transmitted wavefunction if required
   (this can only be used in coherent mode)
    remember to save params for final output pix  */

    if ( lstart == 1 ) {
        if( myFile.read( filestart ) != 1 ) {
            printf("Cannot open input file: %s .\n", filestart ); 
            exit( 0 );
        }

        if( myFile.getnpix() != 2 ) {
           printf("Input file %s must be complex, can't continue.\n",
               filestart );
           exit( 0 );
        }

        nx =  myFile.nx();
        ny =  myFile.ny();

        wave0r = (float**) malloc2D( nx, ny, sizeof(float), "waver" );
        nx = nx/2;
        wave0i = wave0r + nx;

        //  save starting pix for later
        for( ix=0; ix<nx; ix++) for( iy=0; iy<ny; iy++) {
                wave0r[ix][iy] = myFile(ix,iy);
                wave0i[ix][iy] = myFile(ix+nx,iy);
        }

        //  save parameters to verify successive images are same size etc.
        for( i=0; i<NPARAM; i++) sparam[i] = myFile.getParam( i );

        ax = sparam[pDX] * nx;
        by = sparam[pDY] * ny;
        v0     = sparam[pENERGY];
        nslic0 = (int) sparam[pNSLICES];
        printf("Starting pix range %g to %g real\n"
               "           %g to %g imag\n",
               sparam[pRMIN], sparam[pRMAX], sparam[pIMIN], sparam[pIMAX] );
        printf("Beam voltage = %g kV\n", v0);
        printf("Old crystal tilt x,y = %g, %g mrad\n", 1000.*sparam[pXCTILT],
            1000.*sparam[pYCTILT]);

    } else nslic0 = 0;     /* end if( lstart...) */

/*  calculate relativistic factor and electron wavelength */

    mm0 = 1.0F + v0/511.0F;
    wavlen = (float) wavelength( v0 );
    printf("electron wavelength = %g Angstroms\n", wavlen);

/*  read in specimen coordinates and scattering factors */

    natom = ReadXYZcoord( filein, ncellx, ncelly, ncellz,
        &ax, &by, &cz, &Znum, &x, &y, &z, &occ, &wobble,
        description, NCMAX );

    printf("%d atomic coordinates read in\n", natom );
    printf("%s", description );

    printf("Size in pixels Nx, Ny= %d x %d = %d beams\n",
           nx,ny, nx*ny);
    printf("Lattice constant a,b = %12.4f, %12.4f\n", ax,by);

    /*  calculate the total specimen volume and echo */
    xmin = xmax = x[0];
    ymin = ymax = y[0];
    zmin = zmax = z[0];
    wmin = wmax = wobble[0];

    for( i=0; i<natom; i++) {
        if( x[i] < xmin ) xmin = x[i];
        if( x[i] > xmax ) xmax = x[i];
        if( y[i] < ymin ) ymin = y[i];
        if( y[i] > ymax ) ymax = y[i];
        if( z[i] < zmin ) zmin = z[i];
        if( z[i] > zmax ) zmax = z[i];
        if( wobble[i] < wmin ) wmin = wobble[i];
        if( wobble[i] > wmax ) wmax = wobble[i];
    }
    printf("Total specimen range is\n %g to %g in x\n"
           " %g to %g in y\n %g to %g in z\n", xmin, xmax,
           ymin, ymax, zmin, zmax );
    if( lwobble == 1 )
        printf("Range of thermal rms displacements (300K) = %g to %g\n",
            wmin, wmax );
    
#ifdef USE_OPENMP
    /*  force LUT init. to avoid redundant init in parallel form */ 
    rsq = 0.5;  /* arbitrary position */   
    for( i=0; i<natom; i++) vz =  vzatomLUT( Znum[i], rsq );
#endif

/*  calculate spatial frequencies and positions for future use */

    rx = 1.0F/ax;
    rx2= rx*rx;
    ry = 1.0F/by;
    ry2= ry*ry;
    ixmid = nx/2;
    iymid = ny/2;
    nxl = nx;
    nyl = ny;

    kx   = (float*) malloc1D( nx, sizeof(float), "kx" );
    kx2  = (float*) malloc1D( nx, sizeof(float), "kx2" );
    xpos = (float*) malloc1D( nx, sizeof(float), "xpos" );
    freqn( kx, kx2, xpos, nx, ax );

    ky   = (float*) malloc1D( ny, sizeof(float), "ky" );
    ky2  = (float*) malloc1D( ny, sizeof(float), "ky2" );
    ypos = (float*) malloc1D( ny, sizeof(float), "ypos" );
    freqn( ky, ky2, ypos, ny, by );

/*  allocate some more arrays and initialize wavefunction */

    trans.resize( nx, ny );
    trans.init();

    wave.resize( nx, ny );
    wave.copyInit( trans );

    if( lstart == 0 ) {
        for( ix=0; ix<nx; ix++)
        for( iy=0; iy<ny; iy++) {
            wave.re(ix,iy) = 1.0F;  /*  real part */
            wave.im(ix,iy) = 1.0F;  /*  imag part */
        }
    } else {
        for( ix=0; ix<nx; ix++)
        for( iy=0; iy<ny; iy++) {
            wave.re(ix,iy) = wave0r[ix][iy];  /*  real part */
            wave.im(ix,iy) = wave0i[ix][iy];  /*  imag part */
        }
    }

    if( lcross == 1 ) {
        /* nz may be too small with thermal vibrations so add a few extra */
        nz = (int) ( (zmax-zmin)/ deltaz + 3.5);
        depthpix = (float**) malloc2D( nx, nz,
            sizeof(float), "depthpix" );
        for( ix=0; ix<nx; ix++)
        for( iz=0; iz<nz; iz++)  depthpix[ix][iz] = 0.0F;
        iycross = (int) ( 0.5 + (ny * ycross / by));
        while( iycross < 0 ) iycross += ny;
        iycross = iycross%ny;  /* make periodic in ny */
        printf("save xz cross section at iy= %d pixels\n", iycross );
    }

 /*  calculate propagator function  */
 
    k2max = nx/(2.0F*ax);
    tctx = ny/(2.0F*by);
    if( tctx < k2max ) k2max = tctx;
    k2max = BW * k2max;
    printf("Bandwidth limited to a real space resolution of %f Angstroms\n",
                     1.0F/k2max);
    printf("   (= %.2f mrad)  for symmetrical anti-aliasing.\n",
         wavlen*k2max*1000.0F);
    k2max = k2max*k2max;

    tctx = (float) (2.0 * tan(ctiltx));
    tcty = (float) (2.0 * tan(ctilty));
    
    propxr = (float*) malloc1D( nx, sizeof(float), "propxr" );
    propxi = (float*) malloc1D( nx, sizeof(float), "propxi" );
    propyr = (float*) malloc1D( ny, sizeof(float), "propyr" );
    propyi = (float*) malloc1D( ny, sizeof(float), "propyi" );

    scale = pi * ((float)deltaz);

    for( ix=0; ix<nx; ix++) {
        t = scale * ( kx2[ix]*wavlen - kx[ix]*tctx );
        propxr[ix] = (float)  cos(t);
        propxi[ix] = (float) -sin(t);
    }
    for( iy=0; iy<ny; iy++) {
        t = scale * ( ky2[iy]*wavlen - ky[iy]*tcty );
        propyr[iy] = (float)  cos(t);
        propyi[iy] = (float) -sin(t);
    }


/*  iterate the multislice algorithm proper

   NOTE: zero freg is in the bottom left corner and
     expands into all other corners - not in the center
     this is required for the FFT - don't waste time rearranging

  partial coherence method
   force the integrals to include the origin and to be symmetric
   about the origin and to have the same periodic boundary
   conditions as the sampling grid
*/
    if( lpartl == 1 ) {

        printf("Illumination angle sampling (in mrad) = %f, %f\n\n",
            1000.*rx*wavlen, 1000.*ry*wavlen);

        pix = (float**) malloc2D( nx, ny, sizeof(float), "pix" );
        for( ix=0; ix<nx; ix++)
        for( iy=0; iy<ny; iy++) pix[ix][iy] = 0.0F;
        
        temp.resize( nx, ny );
	temp.copyInit( trans );

        ndf = (int) ( ( 2.5F * sigmaf ) / dfdelt );

        nacx = (int) ( ( acmax / ( wavlen * rx ) ) + 1.5F );
        nacy = (int) ( ( acmax / ( wavlen * ry ) ) + 1.5F );

        q2max = acmax / wavlen;
        q2max = q2max*q2max;

        q2min = acmin / wavlen;
        q2min = q2min*q2min;

        k2maxo = aobj / wavlen;
        k2maxo = k2maxo*k2maxo;

        chi1 = pi * wavlen;
        chi2 = 0.5 * Cs3 * wavlen *wavlen;
        chi3 = Cs5 * wavlen*wavlen*wavlen*wavlen /3.0;
        nillum = 0;

        /* for Monte Carlo stuff */
        x2      = (float*) malloc1D( natom, sizeof(float), "x2" );
        y2      = (float*) malloc1D( natom, sizeof(float), "y2" );
        z2      = (float*) malloc1D( natom, sizeof(float), "z2" );
        occ2    = (float*) malloc1D( natom, sizeof(float), "occ2" );
        Znum2   =   (int*) malloc1D( natom, sizeof(int), "Znum2" );

        if( lwobble == 0 )
            sortByZ( x, y, z, occ, Znum, natom );

/*  integrate over the illumination angles */

        for( iwobble=0; iwobble<nwobble; iwobble++) {
            if( lwobble == 1 ) printf("configuration # %d\n", iwobble+1 );
            for( iqy= -nacy; iqy<=nacy; iqy++) {
                qy = iqy * ry;
                qy2 = qy * qy;
        
                for( iqx= -nacx; iqx<=nacx; iqx++) {
                    qx = iqx * rx;
                    q2 = qx*qx + qy2;
        
                    if( (q2 <= q2max) && (q2 >= q2min) ) {
                        nillum += 1;
                        for( ix=0; ix<nx; ix++) {
                            for( iy=0; iy<ny; iy++) {
                                t = 2.0*pi*( qx*xpos[ix] + qy*ypos[iy] );
                                wave.re(ix,iy) = (float) cos(t);  /* real */
                                wave.im(ix,iy) = (float) sin(t);  /* imag */
                            }
                        }
                        /*  add random thermal displacements scaled by temperature
                                if requested 
                            remember that initial wobble is at 300K for each direction */
                        if( lwobble == 1 ){
                            scale = (float) sqrt(temperature/300.0) ;
                            for( i=0; i<natom; i++) {
                                x2[i] = x[i] + (float)(wobble[i]*rangauss(&iseed)*scale);
                                y2[i] = y[i] + (float)(wobble[i]*rangauss(&iseed)*scale);
                                z2[i] = z[i] + (float)(wobble[i]*rangauss(&iseed)*scale);
                                occ2[i] = occ[i];
                                Znum2[i] = Znum[i];
                            }
                            printf( "Sorting atoms by depth...\n");
                            sortByZ( x2, y2, z2, occ2, Znum2, natom );
                            zmin = z2[0];       /* reset zmin/max after wobble */
                            zmax = z2[natom-1];
                            printf("Thickness range with thermal displacements"
                                   " is %g to %g (in z)\n", zmin, zmax );
                        } else for( i=0; i<natom; i++) {
                            x2[i] = x[i];
                            y2[i] = y[i];
                            z2[i] = z[i];
                            occ2[i] = occ[i];
                            Znum2[i] = Znum[i];
                        }
            
                        zslice = 0.75*deltaz;  /*  start a little before top of unit cell */
                        istart = 0;
            
                        while( istart < natom ) {
            
                            /* find range of atoms for current slice */
                            na = 0;
                            for(i=istart; i<natom; i++) 
                            if( z2[i] < zslice ) na++; else break;
            
                            /* calculate transmission function, skip if layer empty */
                            if( na > 0 ) {
                                trlayer( &x2[istart], &y2[istart], &occ2[istart],
                                    &Znum2[istart],na, ax, by, v0, 
                                    trans,  nxl, nyl, &phirms, &nbeams, k2max );
                
                                wave *= trans;  // transmit
                            }
            
                            /* remember: prop needed here to get anti-aliasing
                                    right */
 			    wave.fft();
                            propagate( wave, propxr, propxi,
                                propyr, propyi,
                                kx2,  ky2,  k2max, nx, ny );
			    wave.ifft();
            
                            zslice += deltaz;
                            istart += na;
            
                        } /* end while(zslice<=..) */
          
                        scale = 1.0F / ( ((float)nx) * ((float)ny) );
                        sum = 0.0;
                        for( ix=0; ix<nx; ix++) {
                            for( iy=0; iy<ny; iy++)
                                sum += wave.re(ix,iy)*wave.re(ix,iy)
                                    + wave.im(ix,iy)*wave.im(ix,iy);
                        }
                        sum = sum * scale;
             
                        printf("Illumination angle = %7.3f, %7.3f mrad",
                            1000.*qx*wavlen, 1000.*qy*wavlen);
                        printf(", integrated intensity= %f\n", sum );
            
                        /*-------- integrate over +/- 2.5 sigma of defocus ------------ */
    
                        wave.fft();
                        sumdf = 0.0F;
            
                        for( idf= -ndf; idf<=ndf; idf++) {
                            param[pDEFOCUS] = df = df0 + idf*dfdelt;
            
                            for( ix=0; ix<nx; ix++) {
                                alx = wavlen * kx[ix];  /* x component of angle alpha */
                                for( iy=0; iy<ny; iy++) {
                                    aly = wavlen * ky[iy];  /* y component of angle alpha */
                                    k2 = kx2[ix] + ky2[iy];
                                    if( k2 <= k2maxo ) {
                                        chi0 = (2.0*pi/wavlen) * chi( param, 
                                                alx, aly, multiMode );
                                        tr = (float)  cos(chi0);
                                        ti = (float) -sin(chi0);
                                        wr = wave.re(ix,iy);
                                        wi = wave.im(ix,iy);
                                        temp.re(ix,iy) = wr*tr - wi*ti;
                                        temp.im(ix,iy) = wr*ti + wi*tr;
                                    } else {
                                        temp.re(ix,iy) = 0.0F;  /* real */
                                        temp.im(ix,iy) = 0.0F;  /* imag */
                                    }
                                }  /*  end for( iy=0... ) */
                            }   /*  end for( ix=0... ) */

                            temp.ifft();
            
                            xdf = (double) ( (df - df0) /sigmaf );
                            pdf = (float) exp( -0.5F * xdf*xdf );
                            sumdf += pdf;
            
                            for( ix=0; ix<nx; ix++) {
                                for( iy=0; iy<ny; iy++) {
                                    wr = temp.re(ix,iy);
                                    wi = temp.im(ix,iy);
                                    pix[ix][iy] += pdf* ( wr*wr + wi*wi );
                                }
                            }
            
                        }/* end for(idf..) */
                    }/* end if( q2...) */
        
                } /* end for( iqx..) */
            } /* end for( iqy..) */
        } /* end for( iwobble...) */


        printf("Total number of illumination angle = %ld\n",
                nillum);
        printf("Total number of defocus values = %d\n", 2*ndf+1);
        /*  remember that nillum already includes nwobble so don't
             divide by nwobble! */
        scale = 1.0F / ( ((float)nillum) * sumdf );
        rmin  = pix[0][0] * scale;
        rmax  = rmin;
        aimin = 0.0F;
        aimax = 0.0F;

        for( ix=0; ix<nx; ix++)
        for( iy=0; iy<ny; iy++) {
            pix[ix][iy] = pix[ix][iy] * scale;
            if( pix[ix][iy] < rmin ) rmin = pix[ix][iy];
            if( pix[ix][iy] > rmax ) rmax = pix[ix][iy];
        }

/* ---- start coherent method below ----------------
        (remember that waver,i[][] was initialize above) */

    } else {

        if( lbeams ==1 ) {
            fp1 = fopen( filebeam, "w" );
            if( NULL == fp1 ) {
                printf("can't open file %s\n", filebeam);
                exit(0);
            }
            fprintf( fp1, " (h,k) = " );
            for(ib=0; ib<nbout; ib++)
                fprintf(fp1," (%d,%d)", hbeam[ib], kbeam[ib]);
            fprintf( fp1, "\n" );
            fprintf( fp1, "nslice, (real,imag) (real,imag) ...\n\n");
            for( ib=0; ib<nbout; ib++) {
                if( hbeam[ib] < 0 ) hbeam[ib] = nx + hbeam[ib];
                if( kbeam[ib] < 0 ) kbeam[ib] = ny + kbeam[ib];
                if( hbeam[ib] < 0 ) hbeam[ib] = 0;
                if( kbeam[ib] < 0 ) kbeam[ib] = 0;
                if( hbeam[ib] > nx-1 ) hbeam[ib] = nx-1;
                if( kbeam[ib] > ny-1 ) kbeam[ib] = ny-1;
            }
        }

        /*  add random thermal displacements scaled by temperature if requested 
            remember that initial wobble is at 300K for each direction */
        if( lwobble == 1 ){
            scale = (float) sqrt(temperature/300.0) ;
            for( i=0; i<natom; i++) {
                x[i] += (float) (wobble[i] * rangauss( &iseed ) * scale);
                y[i] += (float) (wobble[i] * rangauss( &iseed ) * scale);
                z[i] += (float) (wobble[i] * rangauss( &iseed ) * scale);
            }
        }

        printf( "Sorting atoms by depth...\n");
        sortByZ( x, y, z, occ, Znum, natom );

        if( lwobble == 1 ){
            zmin = z[0];        /* reset zmin/max after wobble */
            zmax = z[natom-1];
            printf("Thickness range with thermal displacements"
                " is %g to %g (in z)\n", zmin, zmax );
        }

        scale = 1.0F / ( ((float)nx) * ((float)ny) );

        zslice = 0.75*deltaz;  /*  start a little before top of unit cell */
        istart = 0;
        islice = 1;

        while( (istart < natom) && ( zslice < (zmax+deltaz) ) ) {

            /* find range of atoms for current slice */
            na = 0;
            for(i=istart; i<natom; i++) 
            if( z[i] < zslice ) na++; else break;

            /* calculate transmission function, skip if layer empty */
            if( na > 0 ) {
                trlayer( &x[istart], &y[istart], &occ[istart],
                    &Znum[istart], na, ax, by, v0, trans,
                    nxl, nyl, &phirms, &nbeams, k2max );
    
                /*??? printf("average atompot comparison = %g\n", 
                           phirms/(wavlen*mm0) ); */
    
                wave *= trans;    //  transmit
            }       

            /*  bandwidth limit */
            wave.fft();
            if( lbeams== 1 )  {
                fprintf( fp1, "%5d", islice);
                for( ib=0; ib<nbout; ib++) 
                    fprintf(fp1, "%10.6f %10.6f",
                        scale*wave.re(hbeam[ib],kbeam[ib]),   /* real */
                        scale*wave.im(hbeam[ib],kbeam[ib]) ); /* imag */
                    fprintf( fp1, "\n");
            }
            /* remember: prop needed here to get anti-aliasing right */
            propagate( wave, propxr, propxi,
                propyr, propyi, kx2,  ky2,  k2max, nx, ny );
            wave.ifft();

            /* save depth cross section if requested */
            if( (lcross == 1) && (islice<=nz) ) {
                for( ix=0; ix<nx; ix++) {
                    depthpix[ix][islice-1] = 
                        wave.re(ix,iycross)*wave.re(ix,iycross)
                           + wave.im(ix,iycross)*wave.im(ix,iycross);
                }
                nzout = islice;
            }

            sum = 0.0;
            for( ix=0; ix<nx; ix++) {
                for( iy=0; iy<ny; iy++)
                    sum += wave.re(ix,iy)*wave.re(ix,iy) +
                        wave.im(ix,iy)*wave.im(ix,iy);
            }
            sum = sum * scale;

            printf("z= %f A, %ld beams, %d coord., \n"
               "     aver. phase= %f, total intensity = %f\n",
               zslice, nbeams, na, phirms, sum );

            zslice += deltaz;
            istart += na;
            islice++;

        } /* end while(istart<natom..) */
    
        rmin  = wave.re(0,0);
        rmax  = rmin;
        aimin = wave.im(0,0);
        aimax = aimin;

        for( ix=0; ix<nx; ix++) {
            for( iy=0; iy<ny; iy++) {
                wr = wave.re(ix,iy);
                wi = wave.im(ix,iy);
                if( wr < rmin ) rmin = wr;
                if( wr > rmax ) rmax = wr;
                if( wi < aimin ) aimin = wi;
                if( wi > aimax ) aimax = wi;
            }
        }

    } /* end else .. coherent section */

/*  output results and find min and max to echo
    remember that complex pix are stored in the file in FORTRAN
        order for compatibility */

    if( lstart == 1 )
        for( ix=0; ix<NPARAM; ix++ ) param[ix] = sparam[ix];
    param[pRMAX]  = rmax;
    param[pIMAX]  = aimax;
    param[pRMIN]  = rmin;
    param[pIMIN]  = aimin;
    param[pXCTILT]  = ctiltx;
    param[pYCTILT] = ctilty;
    param[pENERGY] = v0;
    param[pDX] = dx = (float) ( ax/((float)nx) );
    param[pDY] = dy = (float) ( by/((float)ny) );
    param[pWAVEL] = wavlen;
    param[pNSLICES] = 0.0F;  /* ??? */
    if ( lpartl == 1 ) {
        param[pDEFOCUS] = df0;
        param[pOAPERT] = aobj;
        param[pCAPERT] = acmax;
        param[pDDF] = sigmaf;
    }

    for( ix=0; ix<NPARAM; ix++ ) myFile.setParam( ix, param[ix] );

    if ( lpartl == 1 ) {
        myFile.resize( nx, ny );
        myFile.setnpix( 1 );
        for( ix=0; ix<nx; ix++) for( iy=0; iy<ny; iy++)
            myFile(ix,iy) = pix[ix][iy];
        i = myFile.write( fileout, rmin, rmax, aimin, aimax, dx, dy );

    } else {

        myFile.resize( 2*nx, ny );
        myFile.setnpix( 2 );
        for( ix=0; ix<nx; ix++) for( iy=0; iy<ny; iy++) {
            myFile(ix,iy)    = wave.re(ix,iy);
            myFile(ix+nx,iy) = wave.im(ix,iy);
        }

        i = myFile.write( fileout, rmin, rmax, aimin, aimax, dx, dy );
    }

    if( i != 1 ) printf( "autoslice cannot write TIF file %s\n",
            fileout );
    printf( "pix range %g to %g real,\n"
        "      %g to %g imag\n",  rmin,rmax,aimin,aimax );

    /*  output depth cross section if requested */
    if( lcross == 1 ){
        rmin  = depthpix[0][0];
        rmax  = rmin;

        for( ix=0; ix<nx; ix++)
        for( iz=0; iz<nzout; iz++) {
            wr = depthpix[ix][iz];
            if( wr < rmin ) rmin = wr;
            if( wr > rmax ) rmax = wr;
        }
        myFile.setParam( pRMAX, rmax );
        myFile.setParam( pIMAX, 0.0F );
        myFile.setParam( pRMIN, rmin );
        myFile.setParam( pIMIN, 0.0F );
        myFile.setParam( pDY, dy = (float) ( deltaz ) );

        myFile.resize( nx, nzout );
        myFile.setnpix( 1 );
        for( ix=0; ix<nx; ix++) for( iz=0; iz<nzout; iz++) {
            myFile(ix,iz) = depthpix[ix][iz];
        }
        i = myFile.write( filecross, rmin, rmax, aimin, aimax, dx, dy );

        if( i != 1 ) printf( "autoslice cannot write TIF file %s\n",
                filecross );
        printf( "depth pix range %g to %g real,\n",  rmin,rmax );
    }

    printf("Total CPU time = %f sec.\n", cputim()-timer );
#ifdef USE_OPENMP
    printf("wall time = %g sec.\n", walltim() - walltimer);
#endif

    return 0;

} /* end main() */
示例#15
0
/*
 @brief     function that generates a neutron and measures how 
            far it travels before being absorbed.
 @details   a neutron is created in the bounding box using
            sample_location() for the first batch and sample_fission_site()
            for the rest of the batches. It moves a distance determined by
            sample_distance(). It is then either absorbed or
            scattered as determined by sample_interaction(). When
            it is absorbed, its distance from its starting point
            is appended to crow_distances. If the absorption creates
            a fission event, the number of neutrons emited is sampled.
            The location of the fission event is added to a list of fission
            events.
 @param     bounds a Boundaries object containing the limits
            of the bounding box
 @param     tallies a dictionary containing tallies of crow distances,
            leakages, absorptions, and fissions
 @param     mesh a Mesh object containing information about the mesh
 @param     old_fission_banks containing the old fission bank
 @param     new_fission_banks containing the new fission bank
 @param     num_groups the number of neutron energy groups
 @param     neutron_num an int used for indexing neutrons
 @param     z_bounds a vector containing the minimum and maximum geometry
            boundaries along the z axis since OpenMOC only handles 2D geometries
*/
void transportNeutron(Boundaries bounds, std::vector <Tally> &tallies,
        bool first_round, Mesh &mesh, Lattice* lattice, Fission* fission_banks,
        int num_groups, int neutron_num, Universe* root_universe,
        Geometry* geometry) {

    const double BOUNDARY_ERROR = 1e-10;
    
    Point* neutron_position = new Point();
    
    // new way to sample neutron and set its direction
    Neutron neutron(neutron_num);
    neutron.sampleDirection();
    
    // get and set neutron starting poinit
    if (first_round)
        bounds.sampleLocation(&neutron);
    else {
        fission_banks->sampleSite(&neutron);
    }

    // get mesh cell
    Point* neutron_starting_point;
    neutron.getPositionVector(neutron_starting_point);

    std::vector <int> cell (3);
    cell[0] = lattice->getLatX(neutron_starting_point);
    cell[1] = lattice->getLatY(neutron_starting_point);
    cell[2] = lattice->getLatZ(neutron_starting_point);
    
    neutron.setCell(cell);

    // set neutron group
    Material* cell_mat;
    Cell* cell_obj;
    int group;

    // get cell material
    LocalCoords* neutron_coord_position = new LocalCoords(
            neutron_starting_point->getX(), neutron_starting_point->getY(),
            neutron_starting_point->getZ());
    neutron_coord_position->setUniverse(root_universe);
    cell_obj = geometry->findCellContainingCoords(neutron_coord_position);
    cell_mat = cell_obj->getFillMaterial();
  
    std::vector <double> chi(num_groups);
    for (int g=0; g<num_groups; ++g) {
        chi[g] = cell_mat->getChiByGroup(g+1);
    }
    group = neutron.sampleNeutronEnergyGroup(chi);
    neutron.setGroup(group);
    
    // follow neutron while it's alive
    while (neutron.alive()) {

        neutron_coord_position->setX(neutron_position->getX());
        neutron_coord_position->setY(neutron_position->getY());
        neutron_coord_position->setZ(neutron_position->getZ());
        neutron_coord_position->setUniverse(root_universe);
        cell_obj = geometry->findCellContainingCoords(neutron_coord_position);
        cell_mat = cell_obj->getFillMaterial();
        
        //cell_mat = mesh.getMaterial(cell);
        group = neutron.getGroup();
        double neutron_distance;

        //sample a distance to travel in the material
        neutron_distance = 
            -log(neutron.arand()) / cell_mat->getSigmaTByGroup(group+1);
    
        // track neutron until collision or leakage
        while (neutron_distance > BOUNDARY_ERROR) {
            neutron.getPositionVector(neutron_position);

            // get cell boundaries
            std::vector <double> cell_mins (3);
            std::vector <double> cell_maxes (3);
            cell_mins[0] = lattice->getMinX() + cell[0] * lattice->getWidthX();
            cell_mins[1] = lattice->getMinY() + cell[1] * lattice->getWidthY();
            cell_mins[2] = lattice->getMinZ() + cell[2] * lattice->getWidthZ();
            cell_maxes[0] = lattice->getMinX() + 
                (cell[0] + 1) * lattice->getWidthX();
            cell_maxes[1] = lattice->getMinY() + 
                (cell[1] + 1) * lattice->getWidthY();
            cell_maxes[2] = lattice->getMinZ() + 
                (cell[2] + 1) * lattice->getWidthZ();

            // calculate distances to cell boundaries
            std::vector <std::vector <double> > distance_to_cell_edge(3);
            for (int axis=0; axis<3; ++axis) {
                distance_to_cell_edge[axis].resize(2);
                distance_to_cell_edge[axis][0] =
                    cell_mins[axis] - neutron.getPosition(axis);
                distance_to_cell_edge[axis][1] =
                    cell_maxes[axis] - neutron.getPosition(axis);
            }

            // create lim_bounds
            std::vector <int> cell_lim_bound;
            std::vector <int> box_lim_bound;
           
            // clear lim_bounds
            cell_lim_bound.clear();
            box_lim_bound.clear();

            // tempd contains the current smallest r
            double tempd;
            tempd = neutron_distance;

            // test each boundary
            double r;
            for (int axis=0; axis<3; ++axis) {
                for (int side=0; side<2; ++side) {

                    // r is variable that contains the distance
                    // along the direction vector to the boundary being tested.
                    r = distance_to_cell_edge[axis][side]
                        / neutron.getDirection(axis);

                    if (r > BOUNDARY_ERROR & r < tempd) {
                        tempd = r;
                        cell_lim_bound.clear();
                        cell_lim_bound.push_back(axis*2+side);
                    }
                    else if (r == tempd) {
                        cell_lim_bound.push_back(axis*2+side);
                    }
                }
            }

            // move neutron
            neutron.move(tempd);

            // add distance to cell flux
            mesh.fluxAdd(cell, tempd, group);

            // shorten neutron distance to collision
            neutron_distance -= tempd;

            // determine potential geometry boundaries
            for (int sur_side=0; sur_side <6; ++sur_side) {
                int axis = sur_side/2;
                int side = sur_side%2;

                // if sur_side is in cell_lim_bound
                if (std::find(cell_lim_bound.begin(),
                            cell_lim_bound.end(),sur_side)
                        != cell_lim_bound.end()) {
                    
                    if (neutron.getCell()[axis] == 0 && side ==0)
                        box_lim_bound.push_back(sur_side);

                    // if the neutron is on the max side of the cell and the
                    // cell is the highest cell in the geometry
                    if (axis == 0) {
                        if (neutron.getCell()[axis] == lattice->getNumX() - 1
                                && side == 1)
                            box_lim_bound.push_back(sur_side);
                    }
                    if (axis == 1) {
                        if (neutron.getCell()[axis] == lattice->getNumY() - 1
                                && side == 1)
                            box_lim_bound.push_back(sur_side);
                    }
                    if (axis == 2) {
                        if (neutron.getCell()[axis] == lattice->getNumZ() - 1
                                && side == 1)
                            box_lim_bound.push_back(sur_side);
                    }
                }
            }

            // check boundary conditions on all hit surfaces
            for (int sur_side=0; sur_side <6; ++sur_side) {
                int axis = sur_side/2;
                int side = sur_side%2;

                // if sur_side is in box_lim_bound
                if (std::find(box_lim_bound.begin(),
                            box_lim_bound.end(),sur_side)
                        != box_lim_bound.end()) {

                    // if the neutron is reflected
                    if (bounds.getSurfaceType(axis, side) == 1) {
                        neutron.reflect(axis);

                        // place neutron on boundary to eliminate roundoff error
                        double bound_val;
                        bound_val = bounds.getSurfaceCoord(axis, side);
                        neutron.setPosition(axis, bound_val);
                    }

                    // if the neutron escapes
                    if (bounds.getSurfaceType(axis, side) == 0) {
                        neutron.kill();
                        neutron_distance = 0;
                        tallies[LEAKS] += 1;
                        break;
                    }
                }
            }
 
            // get new neutron cell
            if (neutron_distance > 0) {
                cell[0] = lattice->getLatX(neutron_position);
                cell[1] = lattice->getLatY(neutron_position);
                cell[2] = lattice->getLatZ(neutron_position);
                
                // nudge neutron and find its cell
                neutron.move(1e-3);
                neutron.getPositionVector(neutron_position);

                // withinBounds seems to return true if the point is without
                if (lattice->withinBounds(neutron_position)) {
                    cell[0] = lattice->getLatX(neutron_position);
                    cell[1] = lattice->getLatY(neutron_position);
                    cell[2] = lattice->getLatZ(neutron_position);
                }
                neutron.move(-1e-3);
  
                neutron.setCell(cell);
            }
        }

        // check interaction
        if (neutron.alive()) {
            neutron_coord_position->setX(neutron_position->getX());
            neutron_coord_position->setY(neutron_position->getY());
            neutron_coord_position->setZ(neutron_position->getZ());
            neutron_coord_position->setUniverse(root_universe);
            cell_obj =
                geometry->findCellContainingCoords(neutron_coord_position);
            cell_mat = cell_obj->getFillMaterial();

            // calculate sigma_s for a group in order to sample an interaction
            std::vector <double> sigma_s_group;
            double sum_sigma_s_group=0;
            for (int g=1; g<=cell_mat->getNumEnergyGroups(); ++g) {
                sigma_s_group.push_back(cell_mat->getSigmaSByGroup(group+1, g));
                sum_sigma_s_group += cell_mat->getSigmaSByGroup(group+1, g);
            }

            // calculate sigma_a in order to sample an interaction
            double sigma_a;
            sigma_a =
                cell_mat->getSigmaTByGroup(group+1) - sum_sigma_s_group;

            // sample an interaction
            int neutron_interaction =
                (int) (neutron.arand() < (sigma_a
                            / cell_mat->getSigmaTByGroup(group+1)));
            
            // scattering event
            if (neutron_interaction == 0) {

                // sample scattered direction
                neutron.sampleDirection();

                // sample new energy group
                int new_group = neutron.sampleScatteredGroup(sigma_s_group,
                    group);

                // set new group
                neutron.setGroup(new_group);
            }

            // absorption event
            else {

                // tally absorption
                tallies[ABSORPTIONS] += 1;

                // sample for fission event
                group = neutron.getGroup();
                cell = neutron.getCell();
                neutron_coord_position->setX(neutron_position->getX());
                neutron_coord_position->setY(neutron_position->getY());
                neutron_coord_position->setZ(neutron_position->getZ());
                neutron_coord_position->setUniverse(root_universe);
                cell_obj =
                    geometry->findCellContainingCoords(neutron_coord_position);
                cell_mat = cell_obj->getFillMaterial();
                neutron.getPositionVector(neutron_position);

                // sample whether fission event occurs
                int fission_occurs =
                    neutron.arand() < cell_mat->getSigmaFByGroup(group+1)
                    / sigma_a;

                // fission event
                if (fission_occurs == 1) {

                    // sample number of neutrons released during fission
                    double nu = cell_mat->getNuSigmaFByGroup(1)
                        / cell_mat->getSigmaFByGroup(1);
                    int lower = (int) nu;
                    int add = (int) (neutron.arand() < nu -lower);
                    int num_neutrons = lower + add;
                    for (int i=0; i<num_neutrons; ++i) {
                        fission_banks->add(neutron_position);
                        tallies[FISSIONS] += 1;
                    }
                }

                // end neutron history
                neutron.kill();
            }
        }
    }

    // tally crow distance
    double crow_distance;
    crow_distance = neutron.getDistance(neutron_starting_point);
    tallies[CROWS] += crow_distance;
    tallies[NUM_CROWS] += 1;
}
void Foam::kineticTheoryModel::solve(const volTensorField& gradUat)
{
 if(kineticTheory_)
 {
     //if (!kineticTheory_)
     //{
     //    return;
     //}

     //const scalar sqrtPi = sqrt(mathematicalConstant::pi);
     if(Berzi_)
     {
	     Info << "Berzi Model is used" << endl;
     }
     else{
     const scalar sqrtPi = sqrt(constant::mathematical::pi);

     surfaceScalarField phi = 1.5*rhoa_*phia_*fvc::interpolate(alpha_);

     volTensorField dU = gradUat.T();//fvc::grad(Ua_);
     volSymmTensorField D = symm(dU);

     // NB, drag = K*alpha*beta,
     // (the alpha and beta has been extracted from the drag function for
     // numerical reasons)
     volScalarField Ur = mag(Ua_ - Ub_);
     volScalarField betaPrim = alpha_*(1.0 - alpha_)*draga_.K(Ur);

     // Calculating the radial distribution function (solid volume fraction is
     //  limited close to the packing limit, but this needs improvements)
     //  The solution is higly unstable close to the packing limit.
     gs0_ = radialModel_->g0
     (
         min(max(alpha_, 1e-6), alphaMax_ - 0.01),
         alphaMax_
     );

     // particle pressure - coefficient in front of Theta (Eq. 3.22, p. 45)
     volScalarField PsCoeff = granularPressureModel_->granularPressureCoeff
     (
         alpha_,
         gs0_,
         rhoa_,
         e_
     );

     // 'thermal' conductivity (Table 3.3, p. 49)
     kappa_ = conductivityModel_->kappa(alpha_, Theta_, gs0_, rhoa_, da_, e_);

     // particle viscosity (Table 3.2, p.47)
     mua_ = viscosityModel_->mua(alpha_, Theta_, gs0_, rhoa_, da_, e_);

     dimensionedScalar Tsmall
     (
         "small",
         dimensionSet(0 , 2 ,-2 ,0 , 0, 0, 0),
         1.0e-6
     );

     dimensionedScalar TsmallSqrt = sqrt(Tsmall);
     volScalarField ThetaSqrt = sqrt(Theta_);

     // dissipation (Eq. 3.24, p.50)
     volScalarField gammaCoeff =
         12.0*(1.0 - sqr(e_))*sqr(alpha_)*rhoa_*gs0_*(1.0/da_)*ThetaSqrt/sqrtPi;

     // Eq. 3.25, p. 50 Js = J1 - J2
     volScalarField J1 = 3.0*betaPrim;
     volScalarField J2 =
         0.25*sqr(betaPrim)*da_*sqr(Ur)
	/(max(alpha_, 1e-6)*rhoa_*sqrtPi*(ThetaSqrt + TsmallSqrt));

     // bulk viscosity  p. 45 (Lun et al. 1984).
     lambda_ = (4.0/3.0)*sqr(alpha_)*rhoa_*da_*gs0_*(1.0+e_)*ThetaSqrt/sqrtPi;

     // stress tensor, Definitions, Table 3.1, p. 43
     volSymmTensorField tau = 2.0*mua_*D + (lambda_ - (2.0/3.0)*mua_)*tr(D)*I;

     if (!equilibrium_)
     {
         // construct the granular temperature equation (Eq. 3.20, p. 44)
         // NB. note that there are two typos in Eq. 3.20
         // no grad infront of Ps
         // wrong sign infront of laplacian
         fvScalarMatrix ThetaEqn
         (
             fvm::ddt(1.5*alpha_*rhoa_, Theta_)
           + fvm::div(phi, Theta_, "div(phi,Theta)")
          ==
             fvm::SuSp(-((PsCoeff*I) && dU), Theta_)
           + (tau && dU)
           + fvm::laplacian(kappa_, Theta_, "laplacian(kappa,Theta)")
           + fvm::Sp(-gammaCoeff, Theta_)
           + fvm::Sp(-J1, Theta_)
           + fvm::Sp(J2/(Theta_ + Tsmall), Theta_)
         );

         ThetaEqn.relax();
         ThetaEqn.solve();
     }
     else
     {
         // equilibrium => dissipation == production
         // Eq. 4.14, p.82
         volScalarField K1 = 2.0*(1.0 + e_)*rhoa_*gs0_;
         volScalarField K3 = 0.5*da_*rhoa_*
             (
                 (sqrtPi/(3.0*(3.0-e_)))
        	*(1.0 + 0.4*(1.0 + e_)*(3.0*e_ - 1.0)*alpha_*gs0_)
        	+1.6*alpha_*gs0_*(1.0 + e_)/sqrtPi
             );

         volScalarField K2 =
             4.0*da_*rhoa_*(1.0 + e_)*alpha_*gs0_/(3.0*sqrtPi) - 2.0*K3/3.0;

         volScalarField K4 = 12.0*(1.0 - sqr(e_))*rhoa_*gs0_/(da_*sqrtPi);

         volScalarField trD = tr(D);
         volScalarField tr2D = sqr(trD);
         volScalarField trD2 = tr(D & D);

         volScalarField t1 = K1*alpha_ + rhoa_;
         volScalarField l1 = -t1*trD;
         volScalarField l2 = sqr(t1)*tr2D;
         volScalarField l3 = 4.0*K4*max(alpha_, 1e-6)*(2.0*K3*trD2 + K2*tr2D);

         Theta_ = sqr((l1 + sqrt(l2 + l3))/(2.0*(alpha_ + 1.0e-4)*K4));
     }

     Theta_.max(1.0e-15);
     Theta_.min(1.0e+3);

     volScalarField pf = frictionalStressModel_->frictionalPressure
     (
         alpha_,
         alphaMinFriction_,
         alphaMax_,
         Fr_,
         eta_,
         p_
     );

     PsCoeff += pf/(Theta_+Tsmall);

     PsCoeff.min(1.0e+10);
     PsCoeff.max(-1.0e+10);

     // update particle pressure
     pa_ = PsCoeff*Theta_;

     // frictional shear stress, Eq. 3.30, p. 52
     volScalarField muf = frictionalStressModel_->muf
     (
         alpha_,
         alphaMax_,
         pf,
         D,
         phi_
     );

    // add frictional stress
     mua_ += muf;
     
//-AO Inconsistency of equations	
     const scalar constSMALL = 0.001; //1.e-06;
     mua_ /= (fvc::average(alpha_) + scalar(constSMALL));
     lambda_ /= (fvc::average(alpha_) + scalar(constSMALL)); 
//-AO	
     
     mua_.min(1.0e+2);
     mua_.max(0.0);

     Info<< "kinTheory: max(Theta) = " << max(Theta_).value() << endl;

     volScalarField ktn = mua_/rhoa_;

     Info<< "kinTheory: min(nua) = " << min(ktn).value()
         << ", max(nua) = " << max(ktn).value() << endl;

     Info<< "kinTheory: min(pa) = " << min(pa_).value()
         << ", max(pa) = " << max(pa_).value() << endl;
	 
 
 //}

 /*
 volScalarField& Foam::kineticTheoryModel::ppMagf(const volScalarField& alphaUpdate)
 {
     volScalarField alpha = alphaUpdate;

     gs0_ = radialModel_->g0(min(alpha, alphaMinFriction_), alphaMax_); 
     gs0Prime_ = radialModel_->g0prime(min(alpha, alphaMinFriction_), alphaMax_);

     // Computing ppMagf
     ppMagf_ = Theta_*granularPressureModel_->granularPressureCoeffPrime
     (
	 alpha, 
	 gs0_, 
	 gs0Prime_, 
	 rhoa_, 
	 e_
     );

     volScalarField ppMagfFriction = frictionalStressModel_->frictionalPressurePrime
     (
	 alpha, 
	 alphaMinFriction_, 
	 alphaMax_,
         Fr_,
         eta_,
         p_
     );

     // NOTE: this might not be appropriate if J&J model is used (verify)
     forAll(alpha, cellI)
     {
	 if(alpha[cellI] >= alphaMinFriction_.value())
	 {
	     ppMagf_[cellI] = ppMagfFriction[cellI];
	 }
     }

     ppMagf_.correctBoundaryConditions();

     return ppMagf_;
 }
 */}
 
 }
 else if(mofidiedKineticTheoryPU_)
 {
     //if (!mofidiedKineticTheoryPU_)
     //{
     //    return;
     //}
     Info << " " << endl;
     Info << "Modified kinetic theory model - Chialvo-Sundaresan " << endl;

     bool testMKTimp(false);
     if(kineticTheoryProperties_.found("testMKTimp")) 
     {
	testMKTimp = true;
        Info << "Modified kinetic theory model - testing implementation (chi=1,eEff=e, ksi=1) " << endl;
     }

     bool diluteCorrection(false);          
     if(kineticTheoryProperties_.found("diluteCorrection")) 
     {
	testMKTimp = false;
	diluteCorrection = true;
        Info << "Modified kinetic theory model - Only dilute correction " << endl;
     }   

     bool denseCorrection(false);          
     if(kineticTheoryProperties_.found("denseCorrection")) 
     {
	testMKTimp = false;
	diluteCorrection = false;
	denseCorrection = true;
        Info << "Modified kinetic theory model - Only dense correction " << endl;
     }  
     
     bool frictionBlending(false); 
     if(kineticTheoryProperties_.found("frictionBlending")) 
     {
	frictionBlending = true;
        Info << "Modified kinetic theory model - Include Friction Blneding " << endl;
     } 
     
          
     if(decomposePp_) Info << "Decompose Pp into Pp - PpStar " << endl;

     bool verboseMKT(false);
     if(kineticTheoryProperties_.found("verboseMKT")) verboseMKT = true;
 
     const scalar Pi = constant::mathematical::pi;
     const scalar sqrtPi = sqrt(constant::mathematical::pi);
     const scalar constSMALL = 1.e-06; //1.e-06; 1.e-03;

     // Read from dictionary
     muFric_ = readScalar(kineticTheoryProperties_.lookup("muFriction"));
     eEff_ = e_ - 3.0 / 2.0 * muFric_ * exp(-3.0 * muFric_);
     // If only test MKT implementation 
     if(testMKTimp) eEff_ = e_;

     alphaf_ = readScalar(kineticTheoryProperties_.lookup("alphaDiluteInertialUpperLimit"));
     alphac_ = readScalar(kineticTheoryProperties_.lookup("alphaCritical"));
     alphad_ = readScalar(kineticTheoryProperties_.lookup("alphaDelta"));
     upsilons_ = readScalar(kineticTheoryProperties_.lookup("yieldStressRatio"));

     // Model parameters
     dimensionedScalar I0(0.2); // Table 2, p.15
     dimensionedScalar const_alpha(0.36); // Table 2, p.15
     dimensionedScalar const_alpha1(0.06); // Table 2, p.15

     // Calculating the radial distribution function (solid volume fraction is
     //  limited close to the packing limit, but this needs improvements)
     //  The solution is higly unstable close to the packing limit.

     gs0_ = radialModel_->g0jamming
     (
      Ua_.mesh(),
     //max(alpha, scalar(constSMALL)),
      min(max(alpha_, scalar(constSMALL)),alphaMax_ - 0.01),  //changed by YG
          alphaMax_,
      alphad_,  ///changed by YG
      alphac_ 
     );

     // particle pressure - coefficient in front of T (Eq. 1, p. 3)
     volScalarField PsCoeff	// -> rho_p * H 
     (
         granularPressureModel_->granularPressureCoeff
         (
             alpha_,
             gs0_,
             rhoa_,
             e_
         )
     );    

     PsCoeff.max(1.0e-15);
   //  PsCoeff.min(1.0e+10);
  //   PsCoeff.max(-1.0e+10);
     // Solid kinetic+collisional viscosity mua_ = nu_k^star + nu_c^star, Eq. 8,9, p.4
     // If Garzo-Dufty viscosity is used (viscosity is dimensionless), there is issue with dimension of mu1
     mua_ = viscosityModel_->mua(alpha_, Theta_, gs0_, rhoa_, da_, e_);	

     // Solid bulk viscosity mua_ = nu_k^star + nu_c^star, Eq. 10, p.4
     // If Garzo-Dufty viscosity is used (viscosity is dimensionless), there is issue with dimension of mu1
     // Create dimensionedScalar
     dimensionedScalar viscDim("zero", dimensionSet(1, -1, -1, 0, 0), 1.0);     
     lambda_ = viscDim * 384.0 / ( 25.0 * Pi ) * ( 1.0 + e_ ) * alpha_ * alpha_ * gs0_ ;  
     //lambda_ = (4.0/3.0)*sqr(alpha_)*rhoa_*da_*gs0_*(1.0+e_)*sqrt(Theta_)/sqrtPi;
     
     volScalarField ratioBulkShearVisc(lambda_/(mua_+lambda_));
     
     // J Eq.5, p3     
     volScalarField J_( 5.0 * sqrtPi / 96.0 * ( mua_ + lambda_ ) / viscDim ); // Dimension issue 

     // K Eq.6, p3
     volScalarField K_(12.0/sqrtPi*alpha_*alpha_*gs0_*(1.0-e_*e_));

     // K' Eq.26, p8 modified dissipation due to friction
     volScalarField Kmod_(K_*(1.0 - eEff_*eEff_)/(1.0 - e_*e_));

     // M Eq.30 p.9
     volScalarField M_( max( J_ / max( Kmod_, constSMALL) , const_alpha1 / sqrt( max(alphac_ - alpha_, constSMALL) ) ) ); 

     // Shear stress rate tensor
     volTensorField dU(gradUat.T());   
     volSymmTensorField D(symm(dU)); 
      
     // Shear stress rate (gammaDot)
     volScalarField gammaDot(sqrt(2.*magSqr(D)));
     dimensionedScalar gammaDotSmall("gammaDotSmall",dimensionSet(0 , 0 , -1 , 0 , 0, 0, 0), constSMALL);    

     // Dilute inertia temperature Eq.24, p8    
     volScalarField ThetaDil_ = ( J_ / max ( Kmod_ , 1e-1 ) ) * ( gammaDot * da_ ) * ( gammaDot * da_ );

     // Dense inertia temperature Eq.27, p8    
//     volScalarField ThetaDense_ =   const_alpha1 * ( gammaDot * da_ ) * ( gammaDot * da_ )
  //                               / sqrt( max(alphac_ - alpha_, constSMALL) ); 
volScalarField ThetaDense_ =   const_alpha1 * ( gammaDot * da_ ) * ( gammaDot * da_ )
                                  / sqrt( max(alphac_ - alpha_, alphad_) ) 
				  + max(alpha_ - (alphac_ - alphad_),0.0) * 0.5 *const_alpha1*( gammaDot * da_ ) * ( gammaDot * da_)*pow(alphad_,-1.5); 
     
				  
     // Theta
     Theta_ = max(ThetaDil_,ThetaDense_) ;

     if(testMKTimp || diluteCorrection) Theta_ = ThetaDil_;
     if(denseCorrection) Theta_ = ThetaDense_;
     
     // Limit granular temperature
     Theta_.max(1.0e-15);
     Theta_.min(1.0e+3);

     // Particle pressure
     pa_ = PsCoeff * Theta_;

     
     if(frictionBlending)
    {
/*      volScalarField pf = frictionalStressModel_->frictionalPressure
     (
         alpha_,
         alphaMinFriction_-0.001,
         alphaMax_,
         Fr_,
         eta_,
         p_
     );
      pa_  = pa_ + pf;
	*/
//	pa_ =pa_ + dimensionedScalar("1e24", dimensionSet(1, -1, -2, 0, 0), Fr_.value())*pow(max(alpha_ - (alphaMinFriction_), scalar(0)), 2/3);
			pa_ =pa_ + dimensionedScalar("5810", dimensionSet(1, 0, -2, 0, 0), 581.0)/da_*pow(max(alpha_ - (alphaMinFriction_-0.0), scalar(0)), 2.0/3.0);
//	pa_ =pa_ + dimensionedScalar("4.7e9", dimensionSet(1, -1, -2, 0, 0), 4.7e9)*pow(max(alpha_ - (alphaMinFriction_-0.0), scalar(0)), 1.56);
			
			
 // forAll(alpha_, cellI)
  //   {
//	 if(alpha_[cellI] >= (alphaMinFriction_.value()-0.00001))
//	 {
//	     pa_[cellI] = pa_[cellI] + 581.0/da_.value()*pow(alpha_[cellI] - (alphaMinFriction_.value()-0.00001), 2.0/3.0);
//	 }
  //   }

      
      }
     // Psi Eq.32, p.12
     dimensionedScalar psi(1.0 + 3.0/10.0*pow((1.0-e_*e_),-1.5)*(1.0-exp(-8.0*muFric_)));
     if(testMKTimp) psi = 1.0;
	 
     // Shear stress ratio in dilute regime, Eq.33, p.12
     dimensionedScalar paSmall("paSmall",dimensionSet(1, -1, -2, 0, 0), constSMALL);    
     volScalarField inertiaNumber( gammaDot * da_ / sqrt( (pa_ + paSmall) / rhoa_ ) );
	
     // Modified inertia number Eq.35, p.13
     volScalarField modInertiaNumber( inertiaNumber /  max( alpha_, constSMALL ) ); 
	 
     // Model parameters    
     volScalarField chi( 1.0 / ( pow( I0 / max( modInertiaNumber,constSMALL ) , 1.5 ) + 1.0 ));
     if(testMKTimp || diluteCorrection)  chi = max( modInertiaNumber,constSMALL ) / max( modInertiaNumber,constSMALL ) ;
          if(denseCorrection)  chi= modInertiaNumber - modInertiaNumber;
	
     // Beta + Sigma_tau Eq.49 p.14
     volScalarField beta(alpha_ * psi * J_ * sqrt( K_ /( max ( (Kmod_ * ( PsCoeff / rhoa_)), constSMALL ) ) ) ); 
     volScalarField sigmaTau( const_alpha / max( beta, constSMALL )  + ( 1 - const_alpha / max( beta, constSMALL ) ) * chi);
	 
     // Sigma_gamma Eq.51 p.14
     volScalarField sigmaGamma( beta * sqrt( PsCoeff/rhoa_ ) / max( ( Kmod_ * M_ ), constSMALL ) * sigmaTau);

     // dissipation
     volScalarField gammaCoeff
     (
         // van Wachem  (Eq. 3.24, p.50) 12.0*(1.0 - sqr(e_))*sqr(alpha_)*rhoa_*gs0_*(1.0/da_)*ThetaSqrt/sqrtPi
         // Chialvo & Sundaresan Eq.50 p.14 
         //rhoa_ / da_ * Kmod_ * Theta_ * sqrt(Theta_) * sigmaGamma
         rhoa_ / da_ * Kmod_ * sqrt(Theta_) * sigmaGamma    
     );

     // Blending function    
     volScalarField func_B( const_alpha + ( beta-const_alpha ) * chi );
	 
     // Shear stress ratio
     upsilon_ = upsilons_ * (1 - chi) + func_B * modInertiaNumber;

     // Shear stress
     volSymmTensorField S( D - 1./3.*tr(D)*I );    
     volSymmTensorField hatS( 2. * S / max( gammaDot, gammaDotSmall ) );
	 
     // Shear stress based on pressure and ratio	 
     tau_ = pa_ * upsilon_ * hatS;
   
     // Viscosity
     mua_ = ( pa_ * upsilon_ ) / (max( gammaDot, gammaDotSmall )) ; 	

     // Divide by alpha (to be consistent with OpenFOAM implementation)
/*      mua_ /= (fvc::average(alpha_) + scalar(0.001));
     tau_ /= (fvc::average(alpha_) + scalar(0.001)); 
     lambda_ /= (fvc::average(alpha_) + scalar(0.001)); */ 

        mua_ /= max(alpha_, scalar(constSMALL));

     // Limit mua
     mua_.min(3e+02);
     mua_.max(0.0);
     
     // Limit lambda
     lambda_ = mua_ * ratioBulkShearVisc;
	
     // Limit shear stress
     tau_ = mua_ * gammaDot * hatS;
     

    // tau_ /= max(alpha_, scalar(constSMALL));
    // lambda_ /= max(alpha_, scalar(constSMALL));
     
     //mua_ /= max(alpha_, scalar(constSMALL));
     //tau_ /= max(alpha_, scalar(constSMALL));
     //lambda_ /= max(alpha_, scalar(constSMALL));
          
     

     if(verboseMKT)
     {
     	#include "verboseMKT.H"
     }  

     //-AO, YG - Decompose particle pressure, Sundar's idea     
     if(decomposePp_)
     {
     	pa_ /= (fvc::average(alpha_) + scalar(0.001));
	//pa_.correctBoundaryConditions();
	pa_.max(1.0e-15);	  	  
     }  

 }
 else
 {
   return;
 }

}
示例#17
0
int test()
{
  std::vector<std::string> neutrals;
  std::vector<std::string> ions;
  neutrals.push_back("N2");
  neutrals.push_back("CH4");
  ions.push_back("N2+");
  ions.push_back("e");
  Scalar chi(100.L);
  std::vector<Scalar> lambda_ref,phy1AU,phy_on_top;
  std::ifstream flux_1AU("./input/hv_SSI.dat");
  std::string line;
  getline(flux_1AU,line);
  while(!flux_1AU.eof())
  {
     Scalar wv,ir,dirr;
     flux_1AU >> wv >> ir >> dirr;
     if(!lambda_ref.empty() && wv == lambda_ref.back())continue;
     lambda_ref.push_back(wv);//nm
     phy1AU.push_back(ir);//W/m2/nm
     phy_on_top.push_back(ir/std::pow(Planet::Constants::Saturn::d_Sun<Scalar>(),2));
  }
  flux_1AU.close();

  Planet::Chapman<Scalar> chapman(chi);
  Planet::PhotonFlux<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > photon(chapman);

  photon.set_photon_flux_top_atmosphere(lambda_ref,phy1AU,Planet::Constants::Saturn::d_Sun<Scalar>());

  std::vector<Scalar> molar_frac = {0.96,0.04,0.,0.};
  Scalar dens_tot(1e12);
  Planet::Atmosphere<Scalar, std::vector<Scalar>, std::vector<std::vector<Scalar> > > atm(neutrals,ions,photon);
  atm.make_altitude_grid(600.,1400.,10.);

  std::ifstream temp("input/temperature.dat");
  std::vector<Scalar> T0,Tz;
  getline(temp,line);
  while(!temp.eof())
  {
     Scalar t,tz,dt,dtz;
     temp >> t >> tz >> dt >> dtz;
     T0.push_back(t);
     Tz.push_back(tz);
  }
  temp.close();

  atm.set_temperature(T0,Tz);
  std::vector<Scalar> T = atm.temperature_top_to_bottom();

  std::vector<std::vector<Scalar> > MatrixTotalDensity;
  std::vector<Scalar> tot_dens = atm.total_density_top_to_bottom();

  std::vector<Scalar> lambda_N2,sigma_N2;
  std::vector<std::vector<Scalar> > sigma_rate_N2;
  sigma_rate_N2.resize(3);
  std::ifstream sig_N2("./input/N2_hv_cross-sections.dat");
  std::ifstream sig_CH4("./input/CH4_hv_cross-sections.dat");
  getline(sig_N2,line);
  getline(sig_CH4,line);
  while(!sig_N2.eof())
  {
     Scalar wv,sigt,sig1,sig2,sig3;
     sig_N2 >> wv >> sigt >> sig1 >> sig2 >> sig3;
     lambda_N2.push_back(wv/10.);//A -> nm
     sigma_N2.push_back(sigt*10.);//cm-2/A -> cm-2/nm
     sigma_rate_N2[0].push_back(sig1*10.);
     sigma_rate_N2[1].push_back(sig2*10.);
     sigma_rate_N2[2].push_back(sig3*10.);
  }
  sig_N2.close();
  atm.add_photoabsorption("N2",lambda_N2,sigma_N2);
  std::vector<Scalar> lambda_CH4,sigma_CH4;
  std::vector<std::vector<Scalar> > sigma_rate_CH4;
  sigma_rate_CH4.resize(9);
  while(!sig_CH4.eof())
  {
     Scalar wv,sigt,sig1,sig2,sig3,sig4,sig5,sig6,sig7,sig8,sig9;
     sig_CH4 >> wv >> sigt >> sig1 >> sig2 >> sig3 >> sig4 >> sig5 >> sig6 >> sig7 >> sig8 >> sig9;
     lambda_CH4.push_back(wv/10.);//A -> nm
     sigma_CH4.push_back(sigt*10.);//cm-2/A -> cm-2/nm
     sigma_rate_CH4[0].push_back(sig1*10.);
     sigma_rate_CH4[1].push_back(sig2*10.);
     sigma_rate_CH4[2].push_back(sig3*10.);
     sigma_rate_CH4[3].push_back(sig4*10.);
     sigma_rate_CH4[4].push_back(sig5*10.);
     sigma_rate_CH4[5].push_back(sig6*10.);
     sigma_rate_CH4[6].push_back(sig7*10.);
     sigma_rate_CH4[7].push_back(sig8*10.);
     sigma_rate_CH4[8].push_back(sig9*10.);
  }
  sig_CH4.close();
  atm.add_photoabsorption("CH4",lambda_CH4,sigma_CH4);

  atm.init_composition(molar_frac,dens_tot);

  int return_flag(0);

//Phy at top
  std::vector<Scalar> phy_top;
  phy_top.resize(lambda_ref.size(),0.L);
  for(unsigned int il = 0; il < lambda_ref.size(); il++)
  {
     phy_top[il] = phy1AU[il]/(Planet::Constants::Saturn::d_Sun<Scalar>() * Planet::Constants::Saturn::d_Sun<Scalar>());
     if(check_test(phy_top[il],photon.phy_at_top()[il],"Photon flux at top"))return_flag = 1;
  }

  std::ofstream out("phy_z.dat");
  std::ofstream out_the("phy_z_the.dat");
  out_the << "z N_N N+_N N2+ sCH2_H2 CH3_H CH2_H_H CH4+ CH3+_H CH2+_H2 CH+_H2_H H+_CH3 CH_H2_H" << std::endl;
  std::vector<Scalar> lamb = atm.hv_flux().lambda();
  std::vector<Scalar> sum_over_neutral;
  sum_over_neutral.resize(2,0.L);
  std::vector<Scalar> tau_theo;
  std::vector<Scalar> rate_N2,rate_CH4;
  rate_N2.resize(3);
  rate_CH4.resize(9);
  Scalar MN(14.008L), MC(12.011), MH(1.008L);
  Scalar MN2 = 2.L*MN , MCH4 = MC + 4.L*MH;
  unsigned int ialt(0);
  for(Scalar z = 1400.; z >= 600.; z -= 10.)
  {

    Scalar M_the = molar_frac[0] * MN2 + molar_frac[1] * MCH4;
    Scalar n_tot_the = dens_tot * std::exp(-(z - 600.) / 
                       ( (z + Planet::Constants::Titan::radius<Scalar>())    *
                         (600. + Planet::Constants::Titan::radius<Scalar>()) * 1e3L * //to m
                         ( (Planet::Constants::Universal::kb<Scalar>() * Antioch::Constants::Avogadro<Scalar>() * T[ialt]) /
                           (Planet::Constants::Universal::G<Scalar>() * Planet::Constants::Titan::mass<Scalar>() * M_the * 1e-3L) //to kg/mol
                         )
                       ));
    tau_theo.clear();
    tau_theo.resize(lambda_ref.size(),0.L);
    for(unsigned int i = 0; i < 2; i++)
    {
       sum_over_neutral[i] += molar_frac[i] * n_tot_the;
       for(unsigned int il = 0; il < lambda_ref.size(); il++)
       {
          tau_theo[il] += sum_over_neutral[i] * atm.photon_sigma(i).y_on_custom()[il]; //filtering
       }
    }

    std::vector<Scalar> tau_cal = photon.tau(z,sum_over_neutral);
    for(unsigned int il = 0; il < lambda_ref.size(); il++)
    {
      tau_theo[il] *= chapman.chapman(atm.a(z));
      if(check_test(tau_theo[il],tau_cal[il],"tau at altitude z"))return_flag = 1;
    }

    for(unsigned int ir = 0; ir < 3; ir++)
    {
      rate_N2[ir] = 0.L;
      for(unsigned int il = 0; il < lamb.size(); il++)
      {
        rate_N2[ir] += sigma_rate_N2[ir][il] * phy_on_top[il] * std::exp(-tau_theo[il]);
      }
    }

    for(unsigned int ir = 0; ir < 9; ir++)
    {
      rate_CH4[ir] = 0.L;
      for(unsigned int il = 0; il < lamb.size(); il++)
      {
        rate_CH4[ir] += sigma_rate_CH4[ir][il] * phy_on_top[il] * std::exp(-tau_theo[il]);
      }
    }

    std::vector<Scalar> phy_flux = atm.hv_flux().phy(z);
    for(unsigned int il = 0; il < phy_flux.size(); il++)
    {
       if(check_test(phy_on_top[il] * std::exp(-tau_theo[il]),phy_flux[il],"phy at altitude z and lambda"))return_flag = 1;
       out << lamb[il] << " " << phy_flux[il] << std::endl;
    }

    out_the << z << " ";
    for(unsigned int ir = 0; ir < 3; ir++)
    {
       out_the << rate_N2[ir] << " ";
    }
    for(unsigned int ir = 0; ir < 9; ir++)
    {
       out_the << rate_CH4[ir] << " ";
    }
    out_the << std::endl;
    
    out << std::endl;
    ialt++;
  }

  out.close();
  out_the.close();

  return return_flag;
}
示例#18
0
//**********************************************************************
Element_Linear2D::Element_Linear2D(std::vector<size_type> global_node_ids,
				   size_type global_element_index,
				   size_type local_element_index,
				   std::vector<double> x_node_coords,
				   std::vector<double> y_node_coords) :
  m_global_element_index(global_element_index),
  m_local_element_index(local_element_index),
  m_global_node_ids(global_node_ids),
  m_owns_node(4, false),
  m_coords_mem(Teuchos::arcp<double>(4*2)),
  m_phi_mem(Teuchos::arcp<double>(4*4)),
  m_grad_phi_mem(Teuchos::arcp<double>(4*4*2)),
  m_grad_phi_xy_mem(Teuchos::arcp<double>(4*4*2)),
  m_det_jacobian_mem(Teuchos::arcp<double>(4)),
  m_weights_mem(Teuchos::arcp<double>(4)),
  m_coords(&(m_coords_mem[0]),4,2),
  m_phi(&(m_phi_mem[0]),4,4),
  m_grad_phi(&(m_grad_phi_mem[0]),4,4,2),
  m_grad_phi_xy(&(m_grad_phi_xy_mem[0]),4,4,2),
  m_det_jacobian(&(m_det_jacobian_mem[0]),4),
  m_weights(&(m_weights_mem[0]),4)
{ 
  // Set node coordinatates
  m_coords(0,0) = x_node_coords[0];
  m_coords(0,1) = y_node_coords[0];
  m_coords(1,0) = x_node_coords[1];
  m_coords(1,1) = y_node_coords[1];
  m_coords(2,0) = x_node_coords[2];
  m_coords(2,1) = y_node_coords[2];
  m_coords(3,0) = x_node_coords[3];
  m_coords(3,1) = y_node_coords[3];
  
  // Quadrature rule defines number of quadrature points - 4
  std::vector<double> chi(4);
  std::vector<double> eta(4);

  chi[0] = -1.0 / std::sqrt(3);
  chi[1] =  1.0 / std::sqrt(3);
  chi[2] =  1.0 / std::sqrt(3);
  chi[3] = -1.0 / std::sqrt(3);

  eta[0] = -1.0 / std::sqrt(3);
  eta[1] = -1.0 / std::sqrt(3);
  eta[2] =  1.0 / std::sqrt(3);
  eta[3] =  1.0 / std::sqrt(3);

  m_weights[0] = 1.0;
  m_weights[1] = 1.0;
  m_weights[2] = 1.0;
  m_weights[3] = 1.0;

  for (size_type qp=0; qp < this->numQuadraturePoints(); ++qp) {
    // Phi
    shards::Array<double,shards::NaturalOrder,Node> phi_qp = 
      m_phi.truncate(qp);
    evaluatePhi(chi[qp], eta[qp], phi_qp);
    
    // Grad Phi in local element coordinates
    shards::Array<double,shards::NaturalOrder,Node,Dim> grad_phi_qp = 
      m_grad_phi.truncate(qp);
    evaluateGradPhi(chi[qp], eta[qp], grad_phi_qp);
    
    // Determinant of Jacobian and basis function gradients in 
    // real space
    shards::Array<double,shards::NaturalOrder,Node,Dim> grad_phi_xy_qp = 
      m_grad_phi_xy.truncate(qp);
    evaluateDetJacobianAndGradients(chi[qp], eta[qp], m_det_jacobian(qp),
				    grad_phi_qp, grad_phi_xy_qp);
  }
  
  
//   for (std::size_t i=0; i < m_grad_phi_xy.size(); ++i)
//     m_grad_phi_xy[i] = 0.0;

//   for (std::size_t qp=0; qp < this->numQuadraturePoints(); ++qp)
//     for (std::size_t node=0; node < this->numNodes(); ++node)
//       for (std::size_t dim=0; dim < 2; ++dim)
// 	m_grad_phi_xy(qp,node,dim) = 
// 	  (1.0 / m_det_jacobian(qp)) * m_grad_phi(qp,node,dim);

}
示例#19
0
int jitter (double *resi, double *e, double *stdy, double psrfreq, int nint, int nphase, double degree, FILE *fp)
// calculate the jitter parameter and its error
{
    //puts (argv[1]);
    //puts (argv[2]);

    //int nint=0; 
    //int nsample=0; 
    //double resi[64],e[64];
    //double x[1024],y[1024];

    //read (argv[1], &nint, resi, e);
    //read (argv[2], &nsample, x, y);

    //printf("Number of subint is: %d \n", nint);

    /////////////////////////////////////////////////////////////////////////////////
	// calculate jitter parameter
	double k;
	//k=nint-10.0;
	k = degree;

	double reduced_chi;

	double sigma_J;

	reduced_chi = 1.0;

	// initial guess of the result
	/////////////////////////////////////////////////////////////////////
	double up = 1.0e-5;
	double step = up/100.0;
	double low = 1.0e-5;

	while( chi(up, k, nint, resi, e, reduced_chi)*chi(low, k, nint, resi, e, reduced_chi) > 0 )
	{
		low = low - step;
	}
	/////////////////////////////////////////////////////////////////////

	sigma_J = zbrent(chi, low, up, 1.0e-16, k, nint, resi, e, reduced_chi);

    printf("low: %e \n", low);
    printf("sigma_J: %e \n", sigma_J);
    printf("reduced_chisqr: %e \n", chi(sigma_J, k, nint, resi, e, reduced_chi));

    ////////////////////////////////////////////////////////////////////////////////

    double U;
    U = u_0(stdy, nphase, psrfreq);

    ///////////////////////////////////////////////////////////////////////////////

    double jitter;
    //double N=floor(60*173.687946184761);

    //jitter=sqrt(N)*sigma_J/U;
    jitter = sigma_J/sqrt(U);
    printf ("jitter parameter is: %f\n", jitter);
    //printf ("jitter parameter is: %f\n", sqrt(N)*sigma_J/0.14e-3);
    //printf ("jitter parameter is: %f\n", sqrt(N)*sigma_J/1.02e-3);
	
	//////////////////////////////////////////////////////////////////////////////////
	// calculte the error of jitter parameter
	struct my_params params;
    double chisqr_new;

	Gamma_cal(k, &params);

	// initial guess of the result
	/////////////////////////////////////////////////////////////////////
	double up_e = k+10;
	double step_e = up_e/100.0;
	double low_e = up_e;
    //printf ("%lf %lf\n", low_e, up_e);

	while( error(up_e, &params, 500000)*error(low_e, &params, 500000) > 0 )
	{
		low_e = low_e - step_e;
	}
    //printf ("%lf %lf\n", low_e, up_e);
	/////////////////////////////////////////////////////////////////////

	//chisqr_new = zbrent_err(error, low_e-10.0, up_e+10.0, 1.0e-16, &params); // get the 1 sigma chisqr
	chisqr_new = zbrent_err(error, low_e, up_e, 1.0e-16, &params, 500000); // get the 1 sigma chisqr

	reduced_chi = chisqr_new/k;
    printf ("chisqr_new: %lf\n", chisqr_new);

	/////////////////////////////////////////////////////////////////////

	// initial guess of the result
	/////////////////////////////////////////////////////////////////////
	up = 1.0e-6;
	step = up/100.0;
	low = 1.0e-6;

	while( chi(up, k, nint, resi, e, reduced_chi)*chi(low, k, nint, resi, e, reduced_chi) > 0 )
	{
		low = low - step;
	}
	/////////////////////////////////////////////////////////////////////

	double sigma_J_error, jitter_error;
	//sigma_J_error = zbrent(chi, 1e-7, 1e-5, 1.0e-16, k, nint, resi, e, reduced_chi);   // for 1 sigma reduced_chi, get the sigma_J
	sigma_J_error = zbrent(chi, low, up, 1.0e-16, k, nint, resi, e, reduced_chi);   // for 1 sigma reduced_chi, get the sigma_J

	jitter_error = fabs(sigma_J_error/sqrt(U)-jitter);
    printf ("The error of jitter parameter is: %f\n", jitter_error);
	
	// print out the results
    fprintf (fp, "%lf %lf\n", jitter, jitter_error);

    return 0;
}
示例#20
0
//STARTBDRYRESIDUALS
PetscErrorCode FormFunction(SNES snes, Vec u, Vec F, void *ctx) {
    PetscErrorCode ierr;
    unfemCtx     *user = (unfemCtx*)ctx;
    const int    *abfn, *ae, *as, *abfs, *en, deg = user->quaddeg - 1;
    const Node   *aloc;
    const double *au;
    double       *aF, unode[3], gradu[2], gradpsi[3][2], uquad[4], aquad[4],
                 fquad[4], dx, dy, dx1, dx2, dy1, dy2, detJ,
                 ls, xmid, ymid, sint, xx, yy, sum;
    int          n, p, na, nb, k, l, q;

    PetscLogStagePush(user->resstage);  //STRIP
    ierr = VecGetArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecSet(F,0.0); CHKERRQ(ierr);
    ierr = VecGetArray(F,&aF); CHKERRQ(ierr);
    ierr = UMGetNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);

    // Dirichlet node residuals
    ierr = ISGetIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    for (n = 0; n < user->mesh->N; n++) {
        if (abfn[n] == 2)  // node is Dirichlet
            aF[n] = au[n] - user->gD_fcn(aloc[n].x,aloc[n].y);
    }

    // Neumann segment contributions
    ierr = ISGetIndices(user->mesh->s,&as); CHKERRQ(ierr);
    ierr = ISGetIndices(user->mesh->bfs,&abfs); CHKERRQ(ierr);
    for (p = 0; p < user->mesh->P; p++) {
        if (abfs[p] == 1) {  // segment is Neumann
            na = as[2*p+0];  // nodes at end of segment
            nb = as[2*p+1];
            // length of segment
            dx = aloc[na].x-aloc[nb].x;
            dy = aloc[na].y-aloc[nb].y;
            ls = sqrt(dx * dx + dy * dy);
            // midpoint rule; psi_na=psi_nb=0.5 at midpoint of segment
            xmid = 0.5*(aloc[na].x+aloc[nb].x);
            ymid = 0.5*(aloc[na].y+aloc[nb].y);
            sint = 0.5 * user->gN_fcn(xmid,ymid) * ls;
            // nodes at end of segment could be Dirichlet
            if (abfn[na] != 2)
                aF[na] -= sint;
            if (abfn[nb] != 2)
                aF[nb] -= sint;
        }
    }
    ierr = ISRestoreIndices(user->mesh->s,&as); CHKERRQ(ierr);
    ierr = ISRestoreIndices(user->mesh->bfs,&abfs); CHKERRQ(ierr);
//ENDBDRYRESIDUALS

//STARTELEMENTRESIDUALS
    // element contributions
    ierr = ISGetIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    for (k = 0; k < user->mesh->K; k++) {
        en = ae + 3*k;  // en[0], en[1], en[2] are nodes of element k
        // geometry of element
        dx1 = aloc[en[1]].x - aloc[en[0]].x;
        dx2 = aloc[en[2]].x - aloc[en[0]].x;
        dy1 = aloc[en[1]].y - aloc[en[0]].y;
        dy2 = aloc[en[2]].y - aloc[en[0]].y;
        detJ = dx1 * dy2 - dx2 * dy1;
        // gradients of hat functions
        for (l = 0; l < 3; l++) {
            gradpsi[l][0] = ( dy2 * dchi[l][0] - dy1 * dchi[l][1]) / detJ;
            gradpsi[l][1] = (-dx2 * dchi[l][0] + dx1 * dchi[l][1]) / detJ;
        }
        // u and grad u on element
        gradu[0] = 0.0;
        gradu[1] = 0.0;
        for (l = 0; l < 3; l++) {
            if (abfn[en[l]] == 2)
                unode[l] = user->gD_fcn(aloc[en[l]].x,aloc[en[l]].y);
            else
                unode[l] = au[en[l]];
            gradu[0] += unode[l] * gradpsi[l][0];
            gradu[1] += unode[l] * gradpsi[l][1];
        }
        // function values at quadrature points on element
        for (q = 0; q < Q[deg]; q++) {
            uquad[q] = eval(unode,xi[deg][q],eta[deg][q]);
            xx = aloc[en[0]].x + dx1 * xi[deg][q] + dx2 * eta[deg][q];
            yy = aloc[en[0]].y + dy1 * xi[deg][q] + dy2 * eta[deg][q];
            aquad[q] = user->a_fcn(uquad[q],xx,yy);
            fquad[q] = user->f_fcn(uquad[q],xx,yy);
        }
        // residual contribution for each node of element
        for (l = 0; l < 3; l++) {
            if (abfn[en[l]] < 2) { // if NOT a Dirichlet node
                sum = 0.0;
                for (q = 0; q < Q[deg]; q++)
                    sum += w[deg][q]
                             * ( aquad[q] * InnerProd(gradu,gradpsi[l])
                                 - fquad[q] * chi(l,xi[deg][q],eta[deg][q]) );
                aF[en[l]] += fabs(detJ) * sum;
            }
        }
    }

    ierr = ISRestoreIndices(user->mesh->e,&ae); CHKERRQ(ierr);
    ierr = ISRestoreIndices(user->mesh->bfn,&abfn); CHKERRQ(ierr);
    ierr = UMRestoreNodeCoordArrayRead(user->mesh,&aloc); CHKERRQ(ierr);
    ierr = VecRestoreArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecRestoreArray(F,&aF); CHKERRQ(ierr);
    PetscLogStagePop();  //STRIP
    return 0;
}
示例#21
0
ScalarFieldTilde SaLSA::hessian(const ScalarFieldTilde& phiTilde) const
{	return (-1./(4*M_PI*gInfo.detR)) * L(phiTilde) - chi(phiTilde);
}
示例#22
0
// For lots of subsets of size nwhich, compute the exact fit to those data
// points and the residuals from all the data points.
// copied with modification from MASS/src/lqs.c
// Copyright (C) 1998-2007	B. D. Ripley
// Copyright (C) 1999       R Development Core Team
// TODO: rewrite
void LQSEstimator::operator()(const Data& data, double* coef_ptr,
                            double* fitted_ptr, double* resid_ptr,
                            double* scale_ptr) {
  int nnew = nwhich, pp = p;
  int i, iter, nn = n, trial;
  int rank, info, n100 = 100;
  int firsttrial = 1;
  double a = 0.0, tol = 1.0e-7, sum, thiscrit, best = DBL_MAX, target, old,
    newp, dummy, k0 = pk0;

  const arma::vec& y = data.y;
  const arma::mat& x = data.x;

  double coef[p];
  arma::vec coef_vec(coef, p, false, true);
  double qraux[p];
  double work[2*p];
  double res[n];
  arma::vec res_vec(res, n, false, true);
  double yr[nwhich];
  double xr[nwhich * p];
  arma::vec yr_vec(yr, nwhich, false, true);
  arma::mat xr_mat(xr, nwhich, p, false, true);
  double bestcoef[p];
  int pivot[p];
  arma::uvec which_vec(nwhich);
  //int bestone[nwhich];

  target = (nn - pp)* (beta);

  for(trial = 0; trial < ntrials; trial++) {

    R_CheckUserInterrupt();

    // get this trial's subset
    which_vec = indices.col(trial);
    yr_vec = y.elem(which_vec);
    xr_mat = x.rows(which_vec);

    /* compute fit, find residuals */
    F77_CALL(dqrdc2)(xr, &nnew, &nnew, &pp, &tol, &rank, qraux, pivot, work);

    if(rank < pp) { sing++; continue; }

    F77_CALL(dqrsl)(xr, &nnew, &nnew, &rank, qraux, yr, &dummy, yr, coef,
             &dummy, &dummy, &n100, &info);

    res_vec = y - x * coef_vec;

    /* S estimation */
    if(firsttrial) {
      for(i = 0; i < nn; i ++) res[i] = fabs(res[i]);
      rPsort(res, nn, nn/2);
      old = res[nn/2]/0.6745;	 /* MAD provides the initial scale */
      firsttrial = 0;
    } else {
      /* only find optimal scale if it will be better than
       existing best solution */
      sum = 0.0;
      for(i = 0; i < nn; i ++) sum += chi(res[i], k0 * best);
      if(sum > target) continue;
      old = best;
    }

    /* now solve for scale S by re-substitution */
    for(iter = 0; iter < 30; iter++) {
      /*printf("iter %d, s = %f sum = %f %f\n", iter, old, sum, target);*/
      sum = 0.0;
      for(i = 0; i < nn; i ++) sum += chi(res[i], k0 * old);
      newp = sqrt(sum/target) * old;
      if(fabs(sum/target - 1.) < 1e-4) break;
      old = newp;
    }
    thiscrit = newp;

    /* first trial might be singular, so use fence */
    if(thiscrit < best) {
      sum = 0.0;
      for(i = 0; i < nn; i ++) sum += chi(res[i], k0 * best);
      best = thiscrit;
      for(i = 0; i < pp; i++) bestcoef[i] = coef[i];
      bestcoef[0] += a;
    }
  } /* for(trial in 0:ntrials) */

  crit = (best < 0.0) ? 0.0 : best;
  if(sample) PutRNGstate();
  /* lqs_free(); */

  // output
  arma::vec coef_out(coef_ptr, p, false, true);
  arma::vec fitted_out(fitted_ptr, n, false, true);
  arma::vec resid_out(resid_ptr, n, false, true);
  arma::vec scale_out(scale_ptr, 1, false, true);

  for (i = 0; i < p; i++) coef_out[i] = bestcoef[i];
  fitted_out = x * coef_out;
  resid_out = y - fitted_out;
  scale_out = crit;
}
示例#23
0
  //! \return whether partial charges were successfully assigned to this molecule
  bool EQEqCharges::ComputeCharges(OBMol &mol)
  {
    int i, j, a, c, N = mol.NumAtoms();
    double cellVolume;
    VectorXf chi(N), J(N), b(N), x(N);
    MatrixXf J_ij(N, N), A(N, N);
    OBUnitCell *obuc;
    matrix3x3 unitcell, fourier;
    vector3 dx;
    int numNeighbors[3];
    OBAtom *atom;

    // If parameters have not yet been loaded, do that
    if (!_paramFileLoaded)
    {
      if (ParseParamFile())
      {
        _paramFileLoaded = true;
      } else
      {
        return false;
      }
    }

    // Calculate atomic properties based around their ionic charge
    for (i = 0; i < N; i++)
    {
      atom = mol.GetAtom(i + 1);
      a = atom->GetAtomicNum();
      c = _chargeCenter[a];

      // Fail if ionization data is missing for any atom in the molecule
      if (_ionizations[a][c + 1] == -1 || _ionizations[a][c] == -1 || a > TABLE_OF_ELEMENTS_SIZE)
      {
        obErrorLog.ThrowError(__FUNCTION__, "Insufficient ionization data for atoms in the given molecule. Update `data/eqeqIonizations.txt` with missing information and re-run this function.", obError);
        return false;
      }

      J(i) = _ionizations[a][c + 1] - _ionizations[a][c];
      chi(i) = 0.5 * (_ionizations[a][c + 1] + _ionizations[a][c]) - (a == 1? 0 : c * J(i));
    }

    // If a unit cell is defined, use the periodic Ewald calculation
    if (mol.HasData(OBGenericDataType::UnitCell))
    {
      // Get unit cell and calculate its Fourier transform + volume
      obuc = (OBUnitCell *) mol.GetData(OBGenericDataType::UnitCell);
      unitcell = obuc->GetCellMatrix();
      fourier = (2 * PI * unitcell.inverse()).transpose();
      cellVolume = obuc->GetCellVolume();

      // Get the number of radial unit cells to use in x, y, and z
      numNeighbors[0] = int(ceil(minCellLength / (2.0 * (obuc->GetA())))) - 1;
      numNeighbors[1] = int(ceil(minCellLength / (2.0 * (obuc->GetB())))) - 1;
      numNeighbors[2] = int(ceil(minCellLength / (2.0 * (obuc->GetC())))) - 1;

      for (i = 0; i < N; i++)
      {
        atom = mol.GetAtom(i + 1);
        for (j = 0; j < N; j++)
        {
          dx = atom->GetVector() - (mol.GetAtom(j + 1))->GetVector();
          J_ij(i, j) = GetPeriodicEwaldJij(J(i), J(j), dx, (i == j), unitcell, fourier, cellVolume, numNeighbors);
        }
      }
    // If no unit cell, use the simplified nonperiodic calculation
    } else
    {
      for (i = 0; i < N; i++)
      {
        atom = mol.GetAtom(i + 1);
        for (j = 0; j < N; j++)
        {
          J_ij(i, j) = GetNonperiodicJij(J(i), J(j), atom->GetDistance(j + 1), (i == j));
        }
        return false;
      }
    }

    // Formulate problem as A x = b, where x is the calculated partial charges
    // First equation is a simple overall balance: sum(Q) = 0
    A.row(0) = VectorXf::Ones(N);
    b(0) = 0;

    // Remaining equations are based off of the fact that, at equilibrium, the
    // energy of the system changes equally for a change in any charge:
    //     dE/dQ_1 = dE/dQ_2 = ... = dE/dQ_N
    A.block(1, 0, N - 1, N) = J_ij.block(0, 0, N - 1, N) - J_ij.block(1, 0, N - 1, N);
    b.tail(N - 1) = chi.tail(N - 1) - chi.head(N - 1);

    // The solution is a list of charges in the system
    x = A.colPivHouseholderQr().solve(b);

    // Now we are done calculating, pass all this back to OpenBabel molecule
    mol.SetPartialChargesPerceived();
    OBPairData *dp = new OBPairData;
    dp->SetAttribute("PartialCharges");
    dp->SetValue("EQEq");
    dp->SetOrigin(perceived);
    mol.SetData(dp);

    m_partialCharges.clear();
    m_partialCharges.reserve(N);
    m_formalCharges.clear();
    m_formalCharges.reserve(N);

    for (i = 0; i < N; i ++)
    {
      atom = mol.GetAtom(i + 1);
      atom->SetPartialCharge(x(i));
      m_partialCharges.push_back(x(i));
      m_formalCharges.push_back(atom->GetFormalCharge());
    }

    obErrorLog.ThrowError(__FUNCTION__, "EQEq charges successfully assigned.", obInfo);
    return true;
  }
示例#24
0
int test()
{
    std::vector<std::string> neutrals;
    std::vector<std::string> ions;
    neutrals.push_back("N2");
    neutrals.push_back("CH4");
    ions.push_back("N2+");
    ions.push_back("e");

//photons
    std::vector<Scalar> lambda,phy1AU;
    read_hv_flux<Scalar>(lambda,phy1AU,"./input/hv_SSI.dat");
    Scalar chi(100.);
    Planet::Chapman<Scalar> chapman(chi);
    Planet::PhotonFlux<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > photon(chapman);
    photon.set_photon_flux_top_atmosphere(lambda,phy1AU,Planet::Constants::Saturn::d_Sun<Scalar>());

//densities
    std::vector<Scalar> molar_frac = {0.96,0.04,0.,0.};
    Scalar dens_tot(1e12);

//diffusion
    Planet::BinaryDiffusion<Scalar> N2N2(   Antioch::Species::N2,  Antioch::Species::N2 , 5.09e+16,0.81, Planet::DiffusionType::Massman);
    Planet::BinaryDiffusion<Scalar> N2CH4(  Antioch::Species::N2,  Antioch::Species::CH4, 7.34e+16,0.75, Planet::DiffusionType::Massman);
    Planet::BinaryDiffusion<Scalar> CH4CH4( Antioch::Species::CH4, Antioch::Species::CH4, 5.73e+16,0.50, Planet::DiffusionType::Massman);

//atmosphere
    Planet::Atmosphere<Scalar, std::vector<Scalar>, std::vector<std::vector<Scalar> > > atm(neutrals,ions,photon);
    atm.make_altitude_grid(600.,1400.,10.);

//temperature
    std::vector<Scalar> T0,Tz;
    read_temperature<Scalar>(T0,Tz,"input/temperature.dat");
    atm.set_temperature(T0,Tz);

//cross-section
    std::vector<Scalar> sigma;
    read_crossSection<Scalar>(lambda,sigma,"./input/N2_hv_cross-sections.dat",3);
    atm.add_photoabsorption("N2",lambda,sigma);

    read_crossSection<Scalar>(lambda,sigma,"./input/CH4_hv_cross-sections.dat",9);
    atm.add_photoabsorption("N2",lambda,sigma);
    atm.add_photoabsorption("CH4",lambda,sigma);

//init compo
    atm.init_composition(molar_frac,dens_tot);

//diffusion
    atm.diffusion().set_binary_coefficient(0,0,N2N2);
    atm.diffusion().set_binary_coefficient(0,1,N2CH4);
    atm.diffusion().set_binary_coefficient(1,1,CH4CH4);
    atm.make_diffusion();

//thermal coefficient
    Scalar K0(4.3e6L);
    atm.set_K0(K0);
    atm.make_thermal_coefficient();

//solver
    Planet::CrankNicholson<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > solver;
    int return_flag(0);

    return return_flag;
}