예제 #1
0
  int SerialProgram::ConnectivityMaps(SolverUtils::Mesh::Connectivity nodesToElems){

      std::ostringstream Ostr;
      std::stringstream ss;

      FunctionEntry("ConnectivityMaps");

      std::cout << "In ConnectivityMaps function" << std::endl;

      //resize nodeToNode map
      nodeToNode.resize(numNodes);

      int elem, node;

      //Generate node to node map
      //loop over every node
      for(int i=0; i < numNodes; i++){
        std::cout << "node " << i+1 << ":" << std::endl;
        //loop over every element for that node
        for(int j=0; j < nodesToElems[i].size(); j++){
          std::cout << "element " << nodesToElems[i][j] << ":" << std::endl;
          elem = nodesToElems[i][j]-1;
          //loop over every node for that element
          for(int k=0; k < numNodesPerElem; k++){
            node = elems[numNodesPerElem*elem + k];
            //don't add the node to its own list
            if(node == i+1)
              continue;
            //loop over all the entries for the nodeToNode map and
            //see if this node has been added yet
            bool newValue=true;
            for(int l=0; l < nodeToNode[i].size(); l++){
              if(node == nodeToNode[i][l]){
                newValue=false;
                break;
              }
            }
            //if its a new value add it
            if(newValue){
              nodeToNode[i].push_back(node);
            }
          }
        }//element around node loop
      }//node lope

      //print nodeToNode to check
      if(verblevel > 3){
        Ostr << "Node to node map:" << std::endl;
        for(int i=0; i < nodeToNode.size(); i++){
          Ostr << i+1 << ":" << std::endl;
          for(int j=0; j < nodeToNode[i].size(); j++){
            Ostr << nodeToNode[i][j] << " ";
          }
          Ostr << std::endl;
        }
      }

      //Generate list of element edges from node to node map
      //loop over every node
      numNodesPerElemEdge = 2;
      numElemEdges = 0;
      for(int i=0; i < numNodes; i++){
        //loop over every node connected to that node
        for(int j=0; j < nodeToNode[i].size(); j++){
          node = nodeToNode[i][j];
          //if the node # is greater than the current node then it
          //hasn't been processed yet so its a new edge
          if(node > i+1){
            elemEdges.push_back(i+1);
            elemEdges.push_back(node);
            numElemEdges++;
          }
        }//nodes around node loop
      }//node loop      

      //print nodeToNode to check
      if(verblevel > 3){
        Ostr << "Element edges:" << std::endl;
        for(int i=0; i < numElemEdges; i++){
          Ostr << i+1 << ":" << std::endl;
          for(int j=0; j < numNodesPerElemEdge; j++){
            Ostr << elemEdges[i*numNodesPerElemEdge + j] << " ";
          }
          Ostr << std::endl;
        }
      }

      //Genereate a map from elements to element edges
      numEdgesPerElem = 6; //Everything is pretty much hard coded
                           //for linear tets right now
      //loop over every element
      for(int i=0; i < numElems; i++){
        //loop over every node for the element
        for(int j=0; j < numNodesPerElem; j++){
          int n1, n2;
          n1 = elems[i*numNodesPerElem + j];
          //loop over every other node for the element
          for(int k=j+1; k < numNodesPerElem; k++){   
            n2 = elems[i*numNodesPerElem + k];
            //loop over every element edge to find what edge 
            //these two nodes are
            for(int l=0; l < numElemEdges; l++){
              if(n1 == elemEdges[l*numNodesPerElemEdge] &&
                 n2 == elemEdges[l*numNodesPerElemEdge + 1])
                elemToElemEdges.push_back(l+1);         
              else if(n2 == elemEdges[l*numNodesPerElemEdge] &&
                 n1 == elemEdges[l*numNodesPerElemEdge + 1])
                elemToElemEdges.push_back(l+1);         
            }//loop over every element edge
          }//loop over every other node for the element
        }//loop over every node for the element
      }//loop over every element

      //print elemToElemEdges to check
      if(verblevel > 3){
        Ostr << "Element to element edges:" << std::endl;
        for(int i=0; i < numElems; i++){
          Ostr << i+1 << ":" << std::endl;
          for(int j=0; j < numEdgesPerElem; j++){
            Ostr << elemToElemEdges[i*numEdgesPerElem + j] << " ";
          }
          Ostr << std::endl;
        }
      }

      StdOut(Ostr.str());
      Ostr.str("");

      FunctionExit("ConnectivityMaps");

    return 0;
 
  } //HigherOrderTets function
예제 #2
0
cTmpReechEpip::cTmpReechEpip
(
        bool aConsChan,
        const std::string & aNameOri,
        Box2dr aBoxImIn,
        ElDistortion22_Gen * anEpi,
        Box2dr aBox,
        double aStep,
        const std::string & aNameOut,
        const std::string & aPostMasq,
        int aNumKer ,
        bool Debug
) :
    mBoxImIn(aBoxImIn),
    mEpi    (anEpi),
    mStep   (aStep),
    mP0     (aBox._p0),
    mSzEpi  (aBox.sz()),
    mSzRed  (round_up (aBox.sz() / aStep) + Pt2di(1,1)),
    mRedIMasq  (mSzRed.x,mSzRed.y,0),
    mRedTMasq  (mRedIMasq),
    mRedImX    (mSzRed.x,mSzRed.y),
    mRedTImX   (mRedImX),
    mRedImY    (mSzRed.x,mSzRed.y),
    mRedTImY   (mRedImY)
{



    cInterpolateurIm2D<REAL4> * aPtrSCI = 0;


    if (aNumKer==0)
    {
        aPtrSCI = new cInterpolBilineaire<REAL4>;
    }
    else 
    {
      
       cKernelInterpol1D * aKer = 0;
       if (aNumKer==1)
          aKer = new cCubicInterpKernel(-0.5);
       else
          aKer = new cSinCardApodInterpol1D(cSinCardApodInterpol1D::eTukeyApod,aNumKer,aNumKer/2,1e-4,false);

       aPtrSCI =  new  cTabIM2D_FromIm2D<REAL4>   (aKer,1000,false);
       // cTabIM2D_FromIm2D<REAL4>   aSSCI (&aKer,1000,false);
    }

    cInterpolateurIm2D<REAL4> & aSCI = *aPtrSCI;



    Pt2di aPInd;

    for (aPInd.x=0 ; aPInd.x<mSzRed.x ; aPInd.x++)
    {
       for (aPInd.y=0 ; aPInd.y<mSzRed.y ; aPInd.y++)
       {
          bool Ok= false;
          Pt2dr aPEpi = ToFullEpiCoord(aPInd);
          Pt2dr aPIm =  anEpi->Inverse(aPEpi);
          if ((aPIm.x>mBoxImIn._p0.x) && (aPIm.y>mBoxImIn._p0.y) && (aPIm.x<mBoxImIn._p1.x) && (aPIm.y<mBoxImIn._p1.y))
          {
               Pt2dr aPEpi2 = anEpi->Direct(aPIm);
               if (euclid(aPEpi-aPEpi2) < 1e-2)
               {
                    Ok= true;
                    mRedTMasq.oset(aPInd,Ok);
               }
          }
          mRedTImX.oset(aPInd,aPIm.x);
          mRedTImY.oset(aPInd,aPIm.y);
       }
    }
    ELISE_COPY(mRedIMasq.all_pts(),dilat_d8(mRedIMasq.in(0),4),mRedIMasq.out());


    Tiff_Im aTifOri = Tiff_Im::StdConvGen(aNameOri.c_str(),aConsChan ? -1 :1 ,true);
    Tiff_Im aTifEpi  = Debug                       ?
                       Tiff_Im(aNameOut.c_str())     :
                       Tiff_Im
                       (
                           aNameOut.c_str(),
                           mSzEpi,
                           aTifOri.type_el(),
                           Tiff_Im::No_Compr,
                           aTifOri.phot_interp()
                       )                            ;

    Tiff_Im aTifMasq = aTifEpi;
    bool ExportMasq = (aPostMasq!="NONE");

// std::cout << "POSTMAS " << aPostMasq << "\n";

    if (ExportMasq)
    {
        std::string aNameMasq = StdPrefix(aNameOut)+ aPostMasq  +".tif";
        aTifMasq =  Debug                         ?
                    Tiff_Im(aNameMasq.c_str())    :
                    Tiff_Im
                    (
                        aNameMasq.c_str(),
                        mSzEpi,
                        GenIm::bits1_msbf,
                        Tiff_Im::No_Compr,
                        Tiff_Im::BlackIsZero
                    )                             ;
    }





    int aNbBloc=2000;
    int aBrd = aNumKer+10;
    Pt2di aSzBrd(aBrd,aBrd);

    int aX00 = 0;
    int aY00 = 0;

    for (int aX0=aX00 ; aX0<mSzEpi.x ; aX0+=aNbBloc)
    {
         int aX1 = ElMin(aX0+aNbBloc,mSzEpi.x);
         for (int aY0=aY00 ; aY0<mSzEpi.y ; aY0+=aNbBloc)
         {
// std::cout << "X0Y0 " << aX0 << " " << aY0 << "\n";

             int aY1 = ElMin(aY0+aNbBloc,mSzEpi.y);

             Pt2di aP0Epi(aX0,aY0);
             Pt2di aSzBloc(aX1-aX0,aY1-aY0);

             TIm2D<REAL4,REAL8> aTImX(aSzBloc);
             TIm2D<REAL4,REAL8> aTImY(aSzBloc);
             TIm2DBits<1>       aTImMasq(aSzBloc,0);

             Pt2dr aInfIm(1e20,1e20);
             Pt2dr aSupIm(-1e20,-1e20);
             bool  NonVide= false;

             for (int anX =aX0 ; anX<aX1  ; anX++)
             {
                 for (int anY =aY0 ; anY<aY1  ; anY++)
                 {
                     Pt2dr aIndEpi (anX/mStep , anY/mStep);
                     Pt2di aPIndLoc (anX-aX0,anY-aY0);
                     if (mRedTMasq.get(round_down(aIndEpi)))
                     {
                        double aXIm = mRedTImX.getr(aIndEpi,-1,true);
                        double aYIm = mRedTImY.getr(aIndEpi,-1,true);

                        if ((aXIm>0) && (aYIm>0))
                        {
                            // aTImMasq.oset(aPIndLoc,1);
                            aTImX.oset(aPIndLoc,aXIm);
                            aTImY.oset(aPIndLoc,aYIm);

                            aInfIm  = Inf(aInfIm,Pt2dr(aXIm,aYIm));
                            aSupIm  = Sup(aSupIm,Pt2dr(aXIm,aYIm));
                            NonVide= true;
                        }
                     }
                 }
             }
             Pt2di aP0BoxIm = Sup(Pt2di(0,0),Pt2di(round_down(aInfIm) - aSzBrd));
             Pt2di aP1BoxIm = Inf(aTifOri.sz(),Pt2di(round_down(aSupIm) + aSzBrd));
             Pt2di aSzIm = aP1BoxIm - aP0BoxIm;
             NonVide = NonVide && (aSzIm.x>0) && (aSzIm.y>0);
             if (NonVide)
             {

                 // std::vector<Im2D_REAL4>  aVIm;

                 std::vector<Im2D_REAL4>  aVIm= aTifOri.VecOfImFloat(aSzIm);

                 ELISE_COPY
                 (
                     rectangle(Pt2di(0,0),aSzIm),
                     trans(aTifOri.in(),aP0BoxIm),
                     StdOut(aVIm)
                 );

                 std::vector<Im2D_REAL4>  aVImEpi = aTifEpi.VecOfImFloat(aSzBloc);
                 ELISE_ASSERT(aVImEpi.size()==aVIm.size(),"Incohe in nb chan, cTmpReechEpip::cTmpReechEpip");

                 for (int aKIm=0 ; aKIm <int(aVImEpi.size()) ; aKIm++)
                 {
                      TIm2D<REAL4,REAL8> aImEpi(aVImEpi[aKIm]);
                      REAL4 ** aDataOri = aVIm[aKIm].data();
                      for (int anX =0 ; anX<aSzBloc.x ; anX++)
                      {
                           for (int anY =0 ; anY<aSzBloc.y ; anY++)
                           {

                               Pt2di aIndEpi(anX,anY);
                               aImEpi.oset(aIndEpi,0);
                               Pt2di anIndEpiGlob  = aIndEpi + aP0Epi;

                               Pt2dr aIndEpiRed (anIndEpiGlob.x/mStep , anIndEpiGlob.y/mStep);
                               if (mRedTMasq.get(round_down(aIndEpiRed),0))
                               {
                                   double aXIm = mRedTImX.getr(aIndEpiRed,-1,true);
                                   double aYIm = mRedTImY.getr(aIndEpiRed,-1,true);
                                   Pt2dr aPImLoc = Pt2dr(aXIm,aYIm) - Pt2dr(aP0BoxIm);
                                   double aV= 128;
                                   if ((aPImLoc.x>aNumKer+2) && (aPImLoc.y>aNumKer+2) && (aPImLoc.x<aSzIm.x-aNumKer-3) && (aPImLoc.y<aSzIm.y-aNumKer-3))
                                   {
                                       aTImMasq.oset(aIndEpi,1);
                                       aV = aSCI.GetVal(aDataOri,aPImLoc);
                                       // aV= 255;
                                   }
                                   aImEpi.oset(aIndEpi,aV);
                               }
                           }
                      }
                 }
                 ELISE_COPY
                 (
                     rectangle(aP0Epi,aP0Epi+aSzBloc),
                     Tronque(aTifEpi.type_el(),trans(StdInput(aVImEpi),-aP0Epi)),
                     aTifEpi.out()
                 );
             }
             if (ExportMasq)
             {
                ELISE_COPY
                (
                    rectangle(aP0Epi,aP0Epi+aSzBloc),
                    trans(aTImMasq._the_im.in(0),-aP0Epi),
                    aTifMasq.out()
                );
             }
             // std::cout << "ReechDONE " <<  aX0 << " "<< aY0 << "\n";

         }
    }
}
예제 #3
0
 void ProgramVersion::CLIVersion ()
 {
   StdOut() << Version() << endl;
 }
    int SerialProgram::Run()
    {
      // FunctionEntry("NAME"): Updates the user-defined stack and 
      // the program profiles with timing information. The placement
      // of FunctionEntry and FunctionExit calls is at the developer's
      // discretion.  
      FunctionEntry("Run");

      // ---------- The Program -----------------
      // This program just "copies" the input file
      // to the output file.
      //

      // Open the specified input file for reading
      Inf.open(input_name.c_str());
      if(!Inf){
        // If the input file failed to open, notify to
        // the error stream and return non-zero
        std::ostringstream Ostr;
        Ostr << "SerialProgram:Run: Error: Could not output input file, " 
             << input_name << ".";
        ErrOut(Ostr.str());
        // don't forget to tell the profiler/stacker the
        // function is exiting.
        FunctionExit("Run");
        return(1);
      }

      // Open the specified output file for writing
      bool use_outfile = false;
      if(!output_name.empty()){
        use_outfile = true;
        Ouf.open(output_name.c_str());
        if(!Ouf){
          // If the output file failed to open, notify
          // to error stream and return non-zero
          std::ostringstream Ostr;
          Ostr << "SerialProgram:Run: Error: Unable to open output file, " << output_name << ".";
          ErrOut(Ostr.str());
          // don't forget to tell the profiler/stacker the
          // function is exiting.
          FunctionExit("Run");
          return(1);
        }
      }

      // Read lines from the input file and repeat them 
      // to the output file.
      std::string line;
      while(std::getline(Inf,line)){
        if(use_outfile)
          Ouf << line << std::endl;
        else
          StdOut(line+"\n");
      }
      // Close both files
      Ouf.close();
      Inf.close();
      
      //
      // ---------- Program End -----------------


      // Update the stacker/profiler that we are exiting 
      // this function.
      FunctionExit("Run");
      // return 0 for success
      return(0);
    };
예제 #5
0
  int SerialProgram::WriteOutput(){

      std::ostringstream Ostr;
      std::stringstream ss;


      // Open the specified output file for writing
      bool use_outfile = false;
      if(!output_name.empty()){
        use_outfile = true;
        Ouf.open(output_name.c_str());
        if(!Ouf){
          // If the output file failed to open, notify
          // to error stream and return non-zero
          std::ostringstream ErrOstr;
          ErrOstr << "Error: Unable to open output file, " << output_name << ".";
          StdOut(Ostr.str());
          Ostr.str("");
          ErrOut(ErrOstr.str());
          ErrOstr.str("");
          // don't forget to tell the profiler/stacker the
          // function is exiting.
          FunctionExit("Run");
          return(1);
        }
      }

      // Write mesh info to output file or screen
      ss.clear();
      ss.str("");

      //Write Patran packet 25 Intro (unused) 
      ss << "unused line" << std::endl;
      ss << "unused line" << std::endl;
      //Write Patran packet 26 
      ss << "26 1 1 1 " << numNodes << " " << numElems << " 1 1 1" << std::endl;
      ss << "unused line" << std::endl;

      unsigned int ePos, expPos; 
      std::stringstream numSS;
      std::string output, exponent;
      //Write Patran packet 1 node coordinates
      for(int i=0; i < numNodes; i++){
        ss << "1 " << i+1 << std::endl;
      
        if(fabs(nodes[3*i+0]) > 1.0e-10 || nodes[3*i+0] == 0.0){
        numSS << std::setprecision(9) <<  std::scientific << nodes[3*i + 0]; 
        ePos = numSS.str().find("e");
        expPos = numSS.str().find_last_of("0");
        //std::cout << "numSS.str() = " << numSS.str() << std::endl;
        //std::cout << "expPos = " << expPos << std::endl;
        //std::cout << "numSS.str().size() = " << numSS.str().size() << std::endl;
        if(expPos == numSS.str().size()-1)
          exponent = "0";
        else
          exponent = numSS.str().substr(expPos+1,numSS.str().size());       
        output = numSS.str().substr(0,ePos+2) + exponent;
        }
        else{//we have to be careful with numbers that have two digit exponents
        //in scientific notation because Rocfrac expects all numbers to take a  
        //specific number of columns.
          if(nodes[3*i+0] < 0.0)
            numSS << std::setprecision(8) << std::scientific << nodes[3*i + 0];
          else
            numSS << std::setprecision(9) << std::scientific << nodes[3*i + 0];
         
          output = numSS.str();
        }
        ss << std::setw(16) << output;
        numSS.str("");
        numSS.clear();

        if(fabs(nodes[3*i+1]) > 1.0e-10 || nodes[3*i+1] == 0.0){
        numSS << std::setprecision(9) <<  std::scientific << nodes[3*i + 1]; 
        ePos = numSS.str().find("e");
        expPos = numSS.str().find_last_of("0");
        //std::cout << "numSS.str() = " << numSS.str() << std::endl;
        //std::cout << "expPos = " << expPos << std::endl;
        //std::cout << "numSS.str().size() = " << numSS.str().size() << std::endl;
        if(expPos == numSS.str().size()-1)
          exponent = "0";
        else
          exponent = numSS.str().substr(expPos+1,numSS.str().size());       
        output = numSS.str().substr(0,ePos+2) + exponent;
        }
        else{//we have to be careful with numbers that have two digit exponents
        //in scientific notation because Rocfrac expects all numbers to take a  
        //specific number of columns.
          if(nodes[3*i+1] < 0.0)
            numSS << std::setprecision(8) << std::scientific << nodes[3*i + 1];
          else
            numSS << std::setprecision(9) << std::scientific << nodes[3*i + 1];
         
          output = numSS.str();
        }
        ss << std::setw(16) << output;
        numSS.str("");
        numSS.clear();

        if(fabs(nodes[3*i+2]) > 1.0e-10 || nodes[3*i+2] == 0.0){
        numSS << std::setprecision(9) <<  std::scientific << nodes[3*i + 2]; 
        ePos = numSS.str().find("e");
        expPos = numSS.str().find_last_of("0");
        //std::cout << "numSS.str() = " << numSS.str() << std::endl;
        //std::cout << "expPos = " << expPos << std::endl;
        //std::cout << "numSS.str().size() = " << numSS.str().size() << std::endl;
        if(expPos == numSS.str().size()-1)
          exponent = "0";
        else
          exponent = numSS.str().substr(expPos+1,numSS.str().size());       
        output = numSS.str().substr(0,ePos+2) + exponent;
        }
        else{//we have to be careful with numbers that have two digit exponents
        //in scientific notation because Rocfrac expects all numbers to take a  
        //specific number of columns.
          if(nodes[3*i+2] < 0.0)
            numSS << std::setprecision(8) << std::scientific << nodes[3*i + 2];
          else
            numSS << std::setprecision(9) << std::scientific << nodes[3*i + 2];
         
          output = numSS.str();
        }
        ss << std::setw(16) << output << std::endl;
        numSS.str("");
        numSS.clear();

        ss << "unused line" << std::endl;
      }
    
      //Write Patran packet 2 element connectivities 
      for(int i=0; i < numElems; i++){
        ss << "2 " << i+1 << " " << elemShape << std::endl
           << "       " <<  numNodesPerElem << "       0"
           << "       0" << std::endl;
        for(int j=0; j < numNodesPerElem; j++){
          ss << elems[i*numNodesPerElem + j] << " ";
        }
        ss << std::endl;
      }

      //Write Patran packet 8 (all nodes with this boundary type)
      for(int i=0; i < numNodes; i++){
        for(int k=0; k < nodeBCs[i].size(); k++){
          if(nodeBCs[i][k] == 8){
            ss << "8 " << i+1 << " 1 2" << std::endl;
            ss << "       0";
            for(int j=0; j < 3; j++)
              ss << int(nodeBCValues[i][k][j]);
            ss << "000" <<  std::endl;
            for(int j=3; j < 6; j++){
              if(nodeBCValues[i][k][j-3] != 0)
                ss << " " << nodeBCValues[i][k][j];
            }
            ss << std::endl;
          }
        }
      }
   

      //Write Patran packet 6 (all elements with this boundary type)
      //loop over all the elements
      //std::cout << "bcs of type 6: " << std::endl;
      for(int i=0; i < numElems; i++){
        //std::cout << "elem " << i+1 << ": " << std::endl;
        //loop over the domains for that element (we only want
        //to print one domain's bcs for the element at a time
        for(int doms=0; doms < elemsToDomains[i].size(); doms++){
          int domain=elemsToDomains[i][doms]-1;
          //std::cout << "domain " << domain+1 << std::endl;
          //loop over the boundary flags for that domain
          for(int j=0; j < domainBCs[domain].size(); j++){ 
            int bcCount=0;
            if(domainBCs[domain][j] == 6){
              //std::cout << "bc " << j+1 << ": " << std::endl;
              ss << "6 " << i+1 << " 1 2 0 0 0 0 0" << std::endl;
              ss << "111100000";
              //loop over the nodes for that element
              for(int k=0; k < numNodesPerElem; k++){
                bool onBC=false;
                int node = elems[i*numNodesPerElem + k]-1;
                //std::cout << "node " << k+1 << " (" << node+1 << ")" << std::endl; 
                //loop over the bc flags for that node
                for(int l=0; l < nodeBCs[node].size(); l++){
                  if(nodeBCs[node][l] == 6){
                    //check if the bcs have the same values
                    for(int m=0; m < nodeBCValues[node][l].size(); m++){
                      if(nodeBCValues[node][l][m] != domainBCValues[domain][j][m])
                        break;
                      else if(m == nodeBCValues[node][l].size()-1){
                        onBC=true;
                        bcCount++;
                        //std::cout << "has bc" << std::endl;
                      }
                    }
                  }
                }//loop over node bcs
                if(onBC){
                  //now check that the node is on that domain
                  int domCount;
                  for(domCount=0; domCount < nodesToDomains[node].size(); domCount++){
                    if(nodesToDomains[node][domCount] == domain+1){
                      //std::cout << "node on domain (writing it)" << std::endl;
                      ss << "1";
                      break;
                    }
                  }
                  if(domCount == nodesToDomains[node].size())
                    ss << "0";
                }
                else
                  ss << "0";
              }//loop over nodes for the element
              //Fill in with 0's at the end if we are using tet elements
              if(numNodesPerElem == 4)
                ss << "0000";
              ss << std::endl;
              for(int m=0; m < domainBCValues[domain][j].size(); m++)
                ss << domainBCValues[domain][j][m] << " ";
              ss << std::endl;
            }//if it is bc type 6
          }//loop over bc flags for domain
        }//loop over the domains for the element
      }//loop over all elements
      ss << "99 0 0 1";

      if(use_outfile){
        Ouf << ss.str();
      }  
      else
        StdOut(ss.str());
      // Close output file
      Ouf.close();
 
      StdOut(Ostr.str());
      Ostr.str("");

    return 0;
 
  } //ReadOutput function
예제 #6
0
    int ParallelProgram::Run()
    {
      // FunctionEntry("NAME"): Updates the user-defined stack and 
      // the program profiles with timing information.  The placement
      // of FunctionEntry and FunctionExit calls is at the developer's
      // discretion.  
      FunctionEntry("Run");

      int myid  = _communicator.Rank();
      int nproc = _communicator.Size();
      bool use_file = !output_name.empty();

      // Put out a quick blurb about number of procs just
      // to give the user confidence we are actually running
      // in parallel.  Note that when using the "StdOut" method
      // that it automatically does output only on rank 0. If 
      // the developer wants asyncrhonous output, then they 
      // have to revert to using standard streams.
      std::ostringstream RepStr;
      if(verblevel > 1)
        RepStr << "Running on " << nproc << " processors." << std::endl;
      StdOut(RepStr.str());
      _communicator.Barrier();
      if(verblevel > 1)
        StdOut("All procesors ready.\n");

      // Open the specified output file for writing on rank 0
      if(use_file && !myid){
        Ouf.open(output_name.c_str(),std::ios::app);
        if(!Ouf){
          // If the output file failed to open, notify
          // to error stream and return non-zero
          std::ostringstream Ostr;
          Ostr << "Error: Unable to open output file, " << output_name << ".";
          ErrOut(Ostr.str());
          // In parallel, we don't return right away since 
          // this part of the code is only done on proc 0.
          // Instead, the error value is set in the communicator
          // which will indicate to all processors that there 
          // has been some error.
          _communicator.SetExit(1);
        }
      }
      // Check to see if an error condition was set 
      // in the file open block above.  If so, then
      // return with an error code.
      if(_communicator.Check()){
          // don't forget to tell the profiler/stacker the
          // function is exiting.
          FunctionExit("Run");
          return(1);
      }
        
      // Correct value of PI to several places
      double PIVAL = 3.141592653589793238462643383;

      // All processors should already have this as it 
      // came from the command line - but just in case,
      // we broadcast it here to make sure.
      FunctionEntry("Broadcast");
      _communicator.BroadCast(ndiv,0);
      FunctionExit("Broadcast");
      
      // This block partitions the 
      // domain [0,1] with ndiv 
      // intervals among nproc processors
      int nper = ndiv/nproc;
      int nvol = nper*nproc;
      int leftover = ndiv - nvol;
      int myn = nper;
      if(myid < leftover)
        myn++;
      int mystart = 0;
      for(int i = 0; i < myid;i++){
        mystart += nper;
        if(i < leftover)
          mystart++;
      }   
      // If there are less divisions than processors, then
      // just forget about domain decomposition and do everything
      // on processor 0.
      if(nper == 0){
        if(myid == 0) myn = ndiv;
        else myn = 0;
      }
        
      // Use the results from domain decomposition to 
      // set the domain [a,b] for this processor and get the 
      // stepsize.
      double h   = 1.0/(static_cast<double>(ndiv));
      double a = h*mystart;
      double b = a + h*myn;

      // Integrate f on this processor's subdomain using trapezoid quadrature
      FunctionEntry("TrapezoidMethod");
      double my_tpi = 0.0;
      if(myn > 0){ // if there are points in this processor's domain
        try {
          FunctionEntry("TrapezoidQuadrature");
          my_tpi = GridConversion::TrapezoidQuadrature(f,a,b,myn);
          FunctionExit("TrapezoidQuadrature");
        } catch (...){
          StdOut("Numerical limits of GridConversion::TrapezoidQuadrature exceeded.");
          my_tpi = 0.0;
        }
      }
      double tpi = 0.0;
      // Sum up the contributions from each processor and store the results on
      // processor 0 in "tpi".
      FunctionEntry("Reduce"); // time the communication
      _communicator.Reduce(my_tpi, tpi,IRAD::Comm::DTDOUBLE, IRAD::Comm::SUMOP, 0);
      FunctionExit("Reduce");  // end of the communication
      FunctionExit("TrapezoidMethod");

      // Integrate f on this processor's subdomain using midpoint quadrature
      FunctionEntry("MidPointMethod");
      double my_mppi = 0.0;
      if(myn > 0) {  // if there are points in this processor's domain
        try{
          FunctionEntry("MidPointQuadrature");
          my_mppi = GridConversion::MidPointQuadrature(f,a,b,myn);
          FunctionExit("MidPointQuadrature");
        } catch (...){
          StdOut("Numerical limits of GridConversion::MidPointQuadrature exceeded.");
          my_mppi = 0.0;
        }
      }
      double mppi = 0.0;
      // Sum up the contributions from each processor and store the results on
      // processor 0 in "mppi".
      FunctionEntry("Reduce"); // time the communication
      _communicator.Reduce(my_mppi, mppi,IRAD::Comm::DTDOUBLE, IRAD::Comm::SUMOP, 0);
      FunctionExit("Reduce");  // end of the communication
      FunctionExit("MidPointMethod");
      
      // Report the results to stdout or to file if one was specified.
      FunctionEntry("IO");
      if (!myid) {
        if(use_file){
          Ouf << ndiv << " " << std::setprecision(16) << tpi << " " 
              << std::setprecision(4)  << std::fabs(tpi-PIVAL) << " "
              << std::setprecision(16) << mppi << " " 
              << std::setprecision(4)  << std::fabs(mppi-PIVAL) << " "
              << std::endl;
          Ouf.close();
        }
        else if(verblevel) {
          std::ostringstream Ostr;
          Ostr << "With " << ndiv << " divisions, PI was calculated:" << std::endl
               << "MidPointQuadrature:  "
               << std::setprecision(16) << mppi << "\t\t" 
               << std::setprecision(4) << std::fabs(mppi - PIVAL) << std::endl
               << "TrapezoidQuadrature: " 
               << std::setprecision(16) << tpi << "\t\t"
               << std::setprecision(4)  << std::fabs(tpi - PIVAL) << std::endl;
          StdOut(Ostr.str());
        }
      }
      FunctionExit("IO");
      //
      // ---------- Program End ----------------  
      
      // Update the stacker/profiler that we are exiting 
      // this function.
      FunctionExit("Run");
      // return 0 for success
      return(0);
    };