Beispiel #1
0
    void average_face_to_cellcenter (MultiFab& cc, int dcomp, const std::vector<MultiFab*>& fc)
    {
	BL_ASSERT(cc.nComp() >= dcomp + BL_SPACEDIM);
	BL_ASSERT(fc.size() == BL_SPACEDIM);
	BL_ASSERT(fc[0]->nComp() == 1);

	Real dx[3] = {1.0,1.0,1.0};
	Real problo[3] = {0.,0.,0.};
	int coord_type = 0;

#ifdef _OPENMP
#pragma omp parallel
#endif
	for (MFIter mfi(cc,true); mfi.isValid(); ++mfi) 
	{
	    const Box& bx = mfi.tilebox();

	    BL_FORT_PROC_CALL(BL_AVG_FC_TO_CC,bl_avg_fc_to_cc)
		(bx.loVect(), bx.hiVect(),
		 BL_TO_FORTRAN_N(cc[mfi],dcomp),
		 D_DECL(BL_TO_FORTRAN((*fc[0])[mfi]),
			BL_TO_FORTRAN((*fc[1])[mfi]),
			BL_TO_FORTRAN((*fc[2])[mfi])),
		 dx, problo, coord_type);
	}
    }
Beispiel #2
0
    void average_face_to_cellcenter (MultiFab& cc, const PArray<MultiFab>& fc, const Geometry& geom)
    {
	BL_ASSERT(cc.nComp() >= BL_SPACEDIM);
	BL_ASSERT(fc.size() == BL_SPACEDIM);
	BL_ASSERT(fc[0].nComp() == 1); // We only expect fc to have the gradient perpendicular to the face

	const Real* dx     = geom.CellSize();
	const Real* problo = geom.ProbLo();
	int coord_type = Geometry::Coord();

#ifdef _OPENMP
#pragma omp parallel
#endif
	for (MFIter mfi(cc,true); mfi.isValid(); ++mfi) 
	{
	    const Box& bx = mfi.tilebox();

	    BL_FORT_PROC_CALL(BL_AVG_FC_TO_CC,bl_avg_fc_to_cc)
		(bx.loVect(), bx.hiVect(),
		 BL_TO_FORTRAN(cc[mfi]),
		 D_DECL(BL_TO_FORTRAN(fc[0][mfi]),
			BL_TO_FORTRAN(fc[1][mfi]),
			BL_TO_FORTRAN(fc[2][mfi])),
		 dx, problo, coord_type);
	}
    }
Beispiel #3
0
    void average_down (MultiFab& S_fine, MultiFab& S_crse, 
                       int scomp, int ncomp, const IntVect& ratio)
    {
        BL_ASSERT(S_crse.nComp() == S_fine.nComp());

        //
        // Coarsen() the fine stuff on processors owning the fine data.
        //
        BoxArray crse_S_fine_BA = S_fine.boxArray(); crse_S_fine_BA.coarsen(ratio);

        MultiFab crse_S_fine(crse_S_fine_BA,ncomp,0);

#ifdef _OPENMP
#pragma omp parallel
#endif
        for (MFIter mfi(crse_S_fine,true); mfi.isValid(); ++mfi)
        {
            //  NOTE: The tilebox is defined at the coarse level.
            const Box& tbx = mfi.tilebox();

            //  NOTE: We copy from component scomp of the fine fab into component 0 of the crse fab
            //        because the crse fab is a temporary which was made starting at comp 0, it is
            //        not part of the actual crse multifab which came in.

            BL_FORT_PROC_CALL(BL_AVGDOWN,bl_avgdown)
                (tbx.loVect(), tbx.hiVect(),
                 BL_TO_FORTRAN_N(S_fine[mfi],scomp),
                 BL_TO_FORTRAN_N(crse_S_fine[mfi],0),
                 ratio.getVect(),&ncomp);
        }

        S_crse.copy(crse_S_fine,0,scomp,ncomp);
   }
Beispiel #4
0
    void average_down (MultiFab& S_fine, MultiFab& S_crse, const Geometry& fgeom, const Geometry& cgeom, 
                       int scomp, int ncomp, const IntVect& ratio)
    {
  
        if (S_fine.is_nodal() || S_crse.is_nodal())
        {
            BoxLib::Error("Can't use BoxLib::average_down for nodal MultiFab!");
        }

#if (BL_SPACEDIM == 3)
	BoxLib::average_down(S_fine, S_crse, scomp, ncomp, ratio);
	return;
#else

        BL_ASSERT(S_crse.nComp() == S_fine.nComp());

        //
        // Coarsen() the fine stuff on processors owning the fine data.
        //
	const BoxArray& fine_BA = S_fine.boxArray();
        BoxArray crse_S_fine_BA = fine_BA; 
	crse_S_fine_BA.coarsen(ratio);

        MultiFab crse_S_fine(crse_S_fine_BA,ncomp,0);

	MultiFab fvolume;
	fgeom.GetVolume(fvolume, fine_BA, 0);

#ifdef _OPENMP
#pragma omp parallel
#endif
        for (MFIter mfi(crse_S_fine,true); mfi.isValid(); ++mfi)
        {
            //  NOTE: The tilebox is defined at the coarse level.
            const Box& tbx = mfi.tilebox();

            //  NOTE: We copy from component scomp of the fine fab into component 0 of the crse fab
            //        because the crse fab is a temporary which was made starting at comp 0, it is
            //        not part of the actual crse multifab which came in.
            BL_FORT_PROC_CALL(BL_AVGDOWN_WITH_VOL,bl_avgdown_with_vol)
                (tbx.loVect(), tbx.hiVect(),
                 BL_TO_FORTRAN_N(S_fine[mfi],scomp),
                 BL_TO_FORTRAN_N(crse_S_fine[mfi],0),
                 BL_TO_FORTRAN(fvolume[mfi]),
                 ratio.getVect(),&ncomp);
	}

        S_crse.copy(crse_S_fine,0,scomp,ncomp);
#endif
   }
Beispiel #5
0
Real
Adv::estTimeStep (Real)
{
    // This is just a dummy value to start with 
    Real dt_est  = 1.0e+20;

    const Real* dx = geom.CellSize();
    const Real* prob_lo = geom.ProbLo();
    const Real cur_time = state[State_Type].curTime();
    const MultiFab& S_new = get_new_data(State_Type);

#ifdef _OPENMP
#pragma omp parallel reduction(min:dt_est)
#endif
    {
	FArrayBox uface[BL_SPACEDIM];

	for (MFIter mfi(S_new, true); mfi.isValid(); ++mfi)
	{
	    for (int i = 0; i < BL_SPACEDIM ; i++) {
		const Box& bx = mfi.nodaltilebox(i);
		uface[i].resize(bx,1);
	    }

	    BL_FORT_PROC_CALL(GET_FACE_VELOCITY,get_face_velocity)
		(level, cur_time,
		 D_DECL(BL_TO_FORTRAN(uface[0]),
			BL_TO_FORTRAN(uface[1]),
			BL_TO_FORTRAN(uface[2])),
		 dx, prob_lo);

	    for (int i = 0; i < BL_SPACEDIM; ++i) {
		Real umax = uface[i].norm(0);
		if (umax > 1.e-100) {
		    dt_est = std::min(dt_est, dx[i] / umax);
		}
	    }
	}
    }

    ParallelDescriptor::ReduceRealMin(dt_est);
    dt_est *= cfl;

    if (verbose && ParallelDescriptor::IOProcessor())
	std::cout << "Adv::estTimeStep at level " << level << ":  dt_est = " << dt_est << std::endl;
    
    return dt_est;
}
Beispiel #6
0
    void average_edge_to_cellcenter (MultiFab& cc, int dcomp, const std::vector<MultiFab*>& edge)
    {
	BL_ASSERT(cc.nComp() >= dcomp + BL_SPACEDIM);
	BL_ASSERT(edge.size() == BL_SPACEDIM);
	BL_ASSERT(edge[0]->nComp() == 1);
#ifdef _OPENMP
#pragma omp parallel
#endif
	for (MFIter mfi(cc,true); mfi.isValid(); ++mfi) 
	{
	    const Box& bx = mfi.tilebox();

	    BL_FORT_PROC_CALL(BL_AVG_EG_TO_CC,bl_avg_eg_to_cc)
		(bx.loVect(), bx.hiVect(),
		 BL_TO_FORTRAN_N(cc[mfi],dcomp),
		 D_DECL(BL_TO_FORTRAN((*edge[0])[mfi]),
			BL_TO_FORTRAN((*edge[1])[mfi]),
			BL_TO_FORTRAN((*edge[2])[mfi])));
	}	
    }
Beispiel #7
0
    void average_cellcenter_to_face (PArray<MultiFab>& fc, const MultiFab& cc, const Geometry& geom)
    {
	BL_ASSERT(cc.nComp() == 1);
	BL_ASSERT(cc.nGrow() >= 1);
	BL_ASSERT(fc.size() == BL_SPACEDIM);
	BL_ASSERT(fc[0].nComp() == 1); // We only expect fc to have the gradient perpendicular to the face

	const Real* dx     = geom.CellSize();
	const Real* problo = geom.ProbLo();
	int coord_type = Geometry::Coord();

#ifdef _OPENMP
#pragma omp parallel
#endif
	for (MFIter mfi(cc,true); mfi.isValid(); ++mfi) 
	{
	    const Box& xbx = mfi.nodaltilebox(0);
#if (BL_SPACEDIM > 1)
	    const Box& ybx = mfi.nodaltilebox(1);
#endif
#if (BL_SPACEDIM == 3)
	    const Box& zbx = mfi.nodaltilebox(2);
#endif
	    
	    BL_FORT_PROC_CALL(BL_AVG_CC_TO_FC,bl_avg_cc_to_fc)
		(xbx.loVect(), xbx.hiVect(),
#if (BL_SPACEDIM > 1)
		 ybx.loVect(), ybx.hiVect(),
#endif
#if (BL_SPACEDIM == 3)
		 zbx.loVect(), zbx.hiVect(),
#endif
		 D_DECL(BL_TO_FORTRAN(fc[0][mfi]),
			BL_TO_FORTRAN(fc[1][mfi]),
			BL_TO_FORTRAN(fc[2][mfi])),
		 BL_TO_FORTRAN(cc[mfi]),
		 dx, problo, coord_type);
	}
    }
Beispiel #8
0
    // Average fine face-based MultiFab onto crse fine-centered MultiFab.
    // This routine assumes that the crse BoxArray is a coarsened version of the fine BoxArray.
    void average_down_faces (PArray<MultiFab>& fine, PArray<MultiFab>& crse, IntVect& ratio)
    {
	BL_ASSERT(crse.size()  == BL_SPACEDIM);
	BL_ASSERT(fine.size()  == BL_SPACEDIM);
	BL_ASSERT(crse[0].nComp() == 1);
	BL_ASSERT(fine[0].nComp() == 1);

#ifdef _OPENMP
#pragma omp parallel
#endif
        for (int n=0; n<BL_SPACEDIM; ++n) {
            for (MFIter mfi(crse[n],true); mfi.isValid(); ++mfi)
            {
                const Box& tbx = mfi.tilebox();

                BL_FORT_PROC_CALL(BL_AVGDOWN_FACES,bl_avgdown_faces)
                    (tbx.loVect(),tbx.hiVect(),
                     BL_TO_FORTRAN(fine[n][mfi]),
                     BL_TO_FORTRAN(crse[n][mfi]),
                     ratio.getVect(),n);
            }
        }
    }
void Radiation::get_groups(int verbose)
{
  group_print_factor   = 1.0;
  group_units          = " (units are Hz)";

  Array<Real> dlognugroup;

  if (RadTests::do_rad_sphere) {

    xnu.resize(nGroups+1, 0.0);  

    // fundamental constants in CGS
    Real ev2erg = 1.e-6*convert_MeV_erg;
    
    Real E_min = 0.5e0*ev2erg;
    Real E_max = 306e3*ev2erg;
    
    // alpha is the geometric spacing between groups
    Real alpha = pow((E_max/E_min), 1.e0/static_cast<Real>(nGroups));
    
    xnu[0] = E_min/hPlanck;
    
    for(int i = 1; i <= nGroups; i++) {
        xnu[i] = alpha*xnu[i-1];
    }
  }
  else if (SolverType == MGFLDSolver && radiation_type == Neutrino) {

    xnu.resize(nGroups+3, 0.0); 
    nugroup.resize(nGroups, 0.0);
    dnugroup.resize(nGroups, 0.0);
    dlognugroup.resize(nGroups, 0.0);

    Array<Real> lowest, highest;
    ParmParse pp("radiation");
    pp.getarr( "lowestGroupMeV",  lowest, 0, nNeutrinoSpecies);
    pp.getarr("highestGroupMeV", highest, 0, nNeutrinoSpecies);

    Real hPlanckMeV = hPlanck / convert_MeV_erg; // Planck in (MeV sec)

    group_print_factor = hPlanckMeV;
    group_units        = " (units are MeV)";

    int ibase = 0;
    for (int ispec = 0; ispec < nNeutrinoSpecies; ispec++) {
      if (nNeutrinoGroups[ispec] > 0) {
        BL_ASSERT(nNeutrinoGroups[ispec] > 1); // no "gray" species
        Real lowlog =  log( lowest[ispec]);
        Real faclog = ((log(highest[ispec]) - lowlog)
                       / (nNeutrinoGroups[ispec] - 1));
        for (int igroup = 0; igroup < nNeutrinoGroups[ispec]; igroup++) {
          int i = ibase + igroup;
          nugroup[i] = exp(lowlog + igroup * faclog) / hPlanckMeV;
        }
      }
      ibase += nNeutrinoGroups[ispec];
    }

    // set up xnu & dnu & dlognu
    int ibase_nu = 0;
    int ibase_xnu = 0;
    for (int ispec = 0; ispec < nNeutrinoSpecies; ispec++) {
      if (nNeutrinoGroups[ispec] > 0) {
	int igroup, inu, ixnu;
        for (igroup = 1; igroup < nNeutrinoGroups[ispec]; igroup++) {
          inu = ibase_nu + igroup;
	  ixnu = ibase_xnu + igroup;
	  xnu[ixnu] = sqrt(nugroup[inu-1] * nugroup[inu]);
        }
	igroup = 0;
	inu = ibase_nu + igroup;
	ixnu = ibase_xnu + igroup;
	xnu[ixnu] = nugroup[inu]*nugroup[inu]/xnu[ixnu+1];
	igroup = nNeutrinoGroups[ispec];
	inu = ibase_nu + igroup;
	ixnu = ibase_xnu + igroup;
	xnu[ixnu] = nugroup[inu-1]*nugroup[inu-1]/xnu[ixnu-1];

	for (igroup=0; igroup < nNeutrinoGroups[ispec]; igroup++) {
          inu = ibase_nu + igroup;
	  ixnu = ibase_xnu + igroup;
	  dnugroup[inu] = xnu[ixnu+1] - xnu[ixnu]; 
	  dlognugroup[inu] = log(xnu[ixnu+1]) - log(xnu[ixnu]); 
	}
      }
      ibase_nu  += nNeutrinoGroups[ispec];
      ibase_xnu += nNeutrinoGroups[ispec]+1;
    }
    
  }
  else if (SolverType == MGFLDSolver) {

    // xnu is being used by MGFLDSolver

    xnu.resize(nGroups+3, 0.0);   // large enough for three neutrino species
    nugroup.resize(nGroups, 1.0);
    dnugroup.resize(nGroups, 0.0);
    dlognugroup.resize(nGroups, 0.0);

    ParmParse pp("radiation");

    if (nGroups > 1) {
      Real lowest;
      pp.get("lowestGroupHz", lowest);
      
      Real groupGrowFactor;
      if (pp.query("groupGrowFactor", groupGrowFactor)) {
	xnu[0] = lowest;
	
	Real firstGroupWidthHz;
	pp.get("firstGroupWidthHz", firstGroupWidthHz);
	dnugroup[0] = firstGroupWidthHz;
	
	xnu[1] = xnu[0] + dnugroup[0];
	
	if (lowest == 0.0) {
	  nugroup[0] = 0.5*dnugroup[0];
	  dlognugroup[0] = 2.0 * (log(xnu[1]) - log(nugroup[0]));
	}
	else {
	  nugroup[0] = sqrt(xnu[0]*xnu[1]);
	  dlognugroup[0] = log(xnu[1]) - log(xnu[0]);
	}
	
	for (int i=1; i<nGroups; i++) {
	  dnugroup[i] = dnugroup[i-1] * groupGrowFactor;
	  xnu[i+1] = xnu[i] + dnugroup[i];
	  nugroup[i] = sqrt(xnu[i]*xnu[i+1]);
	  dlognugroup[i] = log(xnu[i+1]) - log(xnu[i]);
	}
      }
      else {
	Real highest;
	pp.get("highestGroupHz", highest);
	
	Real loglowest = log10(lowest);
	Real loghighest = log10(highest);
	Real dlognu = (loghighest - loglowest) / Real(nGroups);
	
	for (int i=0; i<nGroups; i++) {
	  xnu[i] = pow(10.0, loglowest+i*dlognu);
	  nugroup[i] = pow(10.0, loglowest+(i+0.5)*dlognu);
	}
	xnu[nGroups] = highest;
	
	for (int i=0; i<nGroups; i++) {
	  dnugroup[i] = xnu[i+1] - xnu[i];
	  dlognugroup[i] = log(xnu[i+1]) - log(xnu[i]);
	}
      }
    }
  }
  else {
    cout << "What groups to use?" << endl;
    exit(1);
  }

  if (nugroup.size() == 0) {  // if not initialized above
    nugroup.resize(nGroups, 0.0);

    if (nNeutrinoSpecies == 0) {
      for (int i = 0; i < nGroups; i++) {
        nugroup[i] = sqrt(xnu[i] * xnu[i+1]);
      }
    }
    else {
      int ibase = 0;
      for (int ispec = 0; ispec < nNeutrinoSpecies; ispec++) {
        for (int igroup = 0; igroup < nNeutrinoGroups[ispec]; igroup++) {
          int i = ibase + igroup;
          nugroup[i] = 0.5 * (xnu[igroup] + xnu[igroup+1]);
        }
        ibase += nNeutrinoGroups[ispec];
      }
    }
  }

  if (dnugroup.size() == 0) {  // if not initialized above
    dnugroup.resize(nGroups, 0.0);
    dlognugroup.resize(nGroups, 0.0);

    if (SolverType == MGFLDSolver && xnu.size() > 0) {
      for (int i=0; i<nGroups; i++) {
	dnugroup[i] = xnu[i+1] - xnu[i];
	dlognugroup[i] = log(xnu[i+1]) - log(xnu[i]);
      }
    }
    else if (nNeutrinoSpecies == 0) {
      int i = 0;
      dnugroup[i] = 0.5 * (nugroup[i+1] - nugroup[i]);
      for (i = 1; i < nGroups - 1; i++) {
        dnugroup[i] = 0.5 * (nugroup[i+1] - nugroup[i-1]);
      }
      i = nGroups - 1;
      dnugroup[i] = 0.5 * (nugroup[i] - nugroup[i-1]);
    }
    else {
      int ibase = 0;
      for (int ispec = 0; ispec < nNeutrinoSpecies; ispec++) {
        if (nNeutrinoGroups[ispec] == 0) {
          // no groups for this species, do nothing
        }
        else if (nNeutrinoGroups[ispec] == 1) {
          // should we support "gray" species?
          cout << "Species with single energy group not supported" << endl;
          exit(1);
        }
        else {
          int i = ibase;
          dnugroup[i] = 0.5 * (nugroup[i+1] - nugroup[i]);
          for (i = ibase + 1; i < ibase + nNeutrinoGroups[ispec] - 1; i++) {
            dnugroup[i] = 0.5 * (nugroup[i+1] - nugroup[i-1]);
          }
          i = ibase + nNeutrinoGroups[ispec] - 1;
          dnugroup[i] = 0.5 * (nugroup[i] - nugroup[i-1]);
        }

        ibase += nNeutrinoGroups[ispec];
      }
    }
  }

  int nG0 = 0, nG1 = 0;
  if (nNeutrinoSpecies >= 2) {
    nG0 = nNeutrinoGroups[0];
    nG1 = nNeutrinoGroups[1];
  }
  else if (nNeutrinoSpecies == 1) {
    nG0 = nNeutrinoGroups[0];
    nG1 = 0;
  }

  if (SolverType == MGFLDSolver) { 
    BL_FORT_PROC_CALL(CA_INITGROUPS3,ca_initgroups3)
      (nugroup.dataPtr(), dnugroup.dataPtr(), dlognugroup.dataPtr(), xnu.dataPtr(), 
       nGroups, nG0, nG1);
  }
  else if (xnu.size() > 0) {
    BL_FORT_PROC_CALL(CA_INITGROUPS2,ca_initgroups2)
      (nugroup.dataPtr(), dnugroup.dataPtr(), xnu.dataPtr(), nGroups);
  }
  else {
    BL_FORT_PROC_CALL(CA_INITGROUPS,ca_initgroups)
      (nugroup.dataPtr(), dnugroup.dataPtr(), nGroups, nG0, nG1);
  }

  if (ParallelDescriptor::IOProcessor()) {

    ofstream groupfile;
    groupfile.open("group_structure.dat");

    groupfile << "# total number of groups = " << nGroups << endl;
    if (nNeutrinoSpecies > 0) {
      groupfile << "# " << nNeutrinoSpecies
                << " neutrino species, numbers of groups are: ";
      for (int n = 0; n < nNeutrinoSpecies; n++) {
        if (n > 0) {
          groupfile << ", ";
        }
        groupfile << nNeutrinoGroups[n];
      }
      groupfile << endl;
    }
    groupfile << "# group center, group weight" << group_units << endl;

    groupfile.precision(10);
    for (int i = 0; i < nGroups; i++) {
      groupfile.width(15);
      groupfile <<  nugroup[i] * group_print_factor << "\t";
      groupfile.width(15);
      groupfile << dnugroup[i] * group_print_factor << endl;
    }
    groupfile << endl;

    if (xnu.size() > 0) {
      groupfile << "# group lower boundaries" << endl;
      for (int i = 0; i < xnu.size(); i++) {
        groupfile << "group(" << i << ") = "
                  << xnu[i] * group_print_factor << endl;
      }
    }

    if (dlognugroup.size() > 0) {
      groupfile << endl;
      groupfile << "# group width in log space" << endl;
      for (int i = 0; i < dlognugroup.size(); i++) {
        groupfile << "group(" << i << ") = "
                  << dlognugroup[i] << endl;
      }      
    }

    groupfile.close();

    if (verbose >= 1) {
      write_groups(cout);
    }
  }
}