void
avtConnComponentsWeightedVariableQuery::PostExecute(void)
{
    // sum vals across all processors

    double *sum_res_dbl = new double[nComps];
    SumDoubleArrayAcrossAllProcessors(&sumPerComp[0], sum_res_dbl, nComps);
    memcpy(&sumPerComp[0],sum_res_dbl,nComps * sizeof(double));

    delete [] sum_res_dbl;

    // create output message
    if(PAR_Rank() == 0)
    {
        std::string msg = "";
        char buff[2048];

        if(nComps == 1)
        {SNPRINTF(buff,2048,"Found %d connected component\n",nComps);}
        else
        {SNPRINTF(buff,2048,"Found %d connected components\n",nComps);}

        msg += buff;

        std::string format  =  "Component %d Weighted Sum = (" 
                              + queryAtts.GetFloatFormat() +")\n";

        for(int i=0;i<nComps;i++)
        {
            SNPRINTF(buff,1024,
                     format.c_str(),
                     i,
                    sumPerComp[i]);

            msg += buff;
        }

        // set output message
        SetResultMessage(msg);
        // set output values
        SetResultValues(sumPerComp);
    }
}
void
avtAggregateChordLengthDistributionQuery::PostExecute(void)
{
    int   i;

    int times = 0;
    char name[1024];
    sprintf(name, "cld_a%d.ult", times++);

    if (PAR_Rank() == 0)
    {
        bool lookingForUnused = true;
        while (lookingForUnused)
        {
            ifstream ifile(name);
            if (ifile.fail())
                lookingForUnused = false;
            else
                sprintf(name, "cld_a%d.ult", times++);
        }
    }

    char msg[1024];
    sprintf(msg, "The aggregate chord length distribution has been outputted "
            "as an Ultra file (%s), which can then be imported into VisIt.", 
            name);
    SetResultMessage(msg);
    SetResultValue(0.);

    int *nc2 = new int[numBins];
    SumIntArrayAcrossAllProcessors(numChords, nc2, numBins);
    delete [] numChords;
    numChords = nc2;

    if (PAR_Rank() == 0)
    {
        double binWidth = (maxLength-minLength) / numBins;
        double totalArea = 0.;
        for (i = 0 ; i < numBins ; i++)
            totalArea += binWidth*numChords[i];
        if (totalArea == 0.)
        {
            sprintf(msg, "The chord length distribution could not be "
                    "calculated because none of the lines intersected the data"
                    " set.  If you have used a fairly large number of lines, "
                    "then this may be indicative of an error state.");
            SetResultMessage(msg);
            return;
        }

        ofstream ofile(name);
        if (ofile.fail())
        {
            sprintf(msg, "Unable to write out file containing distribution.");
            SetResultMessage(msg);
            return;
        }
        ofile << "# Chord length distribution - aggregate" << endl;

        for (int i = 0 ; i < numBins ; i++)
        {
            //double x = minLength + (i+0.5)*binWidth;
            double x1 = minLength + (i)*binWidth;
            double x2 = minLength + (i+1)*binWidth;
            double y = numChords[i] / totalArea; // Make it be 
                            // a distribution ... the area under the curve: 1
            ofile << x1 << " " << y << endl;
            ofile << x2 << " " << y << endl;
        }
    }
}
void
avtConnComponentsCentroidQuery::PostExecute(void)
{
    // get # of cells per component (from all processors)
    int    *sum_res_int = new int[nComps];
    SumIntArrayAcrossAllProcessors(&nCellsPerComp[0], sum_res_int, nComps);
    memcpy(&nCellsPerComp[0],sum_res_int,nComps * sizeof(int));

    delete [] sum_res_int;

    // get centroid values (from all processors)
    double *sum_res_dbl = new double[nComps];

    SumDoubleArrayAcrossAllProcessors(&xCentroidPerComp[0],
                                      sum_res_dbl,
                                      nComps);

    memcpy(&xCentroidPerComp[0],sum_res_dbl,nComps * sizeof(double));

    SumDoubleArrayAcrossAllProcessors(&yCentroidPerComp[0],
                                      sum_res_dbl,
                                      nComps);

    memcpy(&yCentroidPerComp[0],sum_res_dbl,nComps * sizeof(double));

    SumDoubleArrayAcrossAllProcessors(&zCentroidPerComp[0],
                                      sum_res_dbl,
                                      nComps);

    memcpy(&zCentroidPerComp[0],sum_res_dbl,nComps * sizeof(double));

    delete [] sum_res_dbl;

    // create output message

    if(PAR_Rank() == 0)
    {
        std::string msg = "";
        char buff[2048];

        if(nComps == 1)
        {SNPRINTF(buff,2048,"Found %d connected component\n",nComps);}
        else
        {SNPRINTF(buff,2048,"Found %d connected components\n",nComps);}

        msg += buff;

        // pack values into a a single vector for query output
        std::vector<double> result_vec(nComps *3);

        for(int i=0;i<nComps;i++)
        {
            // get number of cells for current component
            double n_comp_cells =  (double)nCellsPerComp[i];
            // calculate centriod values for the current component
            xCentroidPerComp[i] /= n_comp_cells;
            yCentroidPerComp[i] /= n_comp_cells;
            zCentroidPerComp[i] /= n_comp_cells;

            // pack into result vector
            result_vec[i*3 + 0] = xCentroidPerComp[i];
            result_vec[i*3 + 1] = yCentroidPerComp[i];
            result_vec[i*3 + 2] = zCentroidPerComp[i];
        }

    
        std::string format  =  "Component %d [%d cells] Centroid = (" 
                            + queryAtts.GetFloatFormat()  +","
                            + queryAtts.GetFloatFormat()  +","
                            + queryAtts.GetFloatFormat()  +")\n";
    
        // prepare the output message
        for(int i=0;i<nComps;i++)
        {
            SNPRINTF(buff,1024,
                     format.c_str(),
                    i,
                    nCellsPerComp[i],
                    xCentroidPerComp[i],
                    yCentroidPerComp[i],
                    zCentroidPerComp[i]);

            msg += buff;
        }

        // set result message
        SetResultMessage(msg);

        // set result values
        SetResultValues(result_vec);
    }
}
void
avtIndividualChordLengthDistributionQuery::PostExecute(void)
{
    int   i;

    int times = 0;
    char name[1024];
    sprintf(name, "cld_i%d.ult", times++);

    if (PAR_Rank() == 0)
    {
        bool lookingForUnused = true;
        while (lookingForUnused)
        {
            ifstream ifile(name);
            if (ifile.fail())
                lookingForUnused = false;
            else
                sprintf(name, "cld_i%d.ult", times++);
        }
    }

    char msg[1024];
    sprintf(msg, "The chord length distribution has been outputted as an "
                 "Ultra file (%s), which can then be imported into VisIt.", 
                 name);
    SetResultMessage(msg);
    SetResultValue(0.);

    int *nc2 = new int[numBins];
    SumIntArrayAcrossAllProcessors(numChords, nc2, numBins);
    delete [] numChords;
    numChords = nc2;

    if (PAR_Rank() == 0)
    {
        double binWidth = (maxLength-minLength) / numBins;
        double totalArea = 0.;
        for (i = 0 ; i < numBins ; i++)
            totalArea += binWidth*numChords[i];
        if (totalArea == 0.)
        {
            sprintf(msg, "The chord length distribution could not be "
                   "calculated because none of the lines intersected "
                   "the data set. If you have used a fairly large number "
                   "of lines, then this may be indicative of an error state.");
            SetResultMessage(msg);
            return;
        }

        ofstream ofile(name);
        if (ofile.fail())
        {
            sprintf(msg, "Unable to write out file containing distribution.");
            SetResultMessage(msg);
        }
        if (!ofile.fail())
            ofile << "# Chord length distribution - individual" << endl;

        MapNode result_node;
        doubleVector curve;

        for (int i = 0 ; i < numBins ; i++)
        {
            double x1 = minLength + (i)*binWidth;
            double x2 = minLength + (i+1)*binWidth;
            double y = numChords[i] / totalArea; // Make it be a distribution ...
                                                 // the area under the curve: 1
            curve.push_back(x1);
            curve.push_back(y);
            curve.push_back(x2);
            curve.push_back(y);
            if (!ofile.fail())
            {
                ofile << x1 << " " << y << endl;
                ofile << x2 << " " << y << endl;
            }
        }
        result_node["chord_length_distribution_individual"] = curve;
        SetXmlResult(result_node.ToXML());
        SetResultValues(curve);
    }
}
void
avtMassDistributionQuery::PostExecute(void)
{
    int   i;

    avtWeightedVariableSummationQuery summer;
    avtDataObject_p dob = GetInput();
    summer.SetInput(dob);
    QueryAttributes qa;
    summer.PerformQuery(&qa);
    double totalMass = qa.GetResultsValue()[0];

    bool didVolume  = false;
    bool didRVolume = false;
    bool didSA      = false;
    if (totalMass == 0.)
    {
        if (dob->GetInfo().GetAttributes().GetTopologicalDimension() == 3)
        {
            avtTotalVolumeQuery tvq;
            avtDataObject_p dob = GetInput();
            tvq.SetInput(dob);
            QueryAttributes qa;
            tvq.PerformQuery(&qa);
            totalMass = qa.GetResultsValue()[0];
            didVolume = true;
        }
        else if (dob->GetInfo().GetAttributes().GetMeshCoordType() == AVT_RZ
              || dob->GetInfo().GetAttributes().GetMeshCoordType() == AVT_ZR)
        {
            avtTotalRevolvedVolumeQuery rvq;
            avtDataObject_p dob = GetInput();
            rvq.SetInput(dob);
            QueryAttributes qa;
            rvq.PerformQuery(&qa);
            totalMass = qa.GetResultsValue()[0];
            didRVolume = true;
        }
        else
        {
            avtTotalSurfaceAreaQuery saq;
            avtDataObject_p dob = GetInput();
            saq.SetInput(dob);
            QueryAttributes qa;
            saq.PerformQuery(&qa);
            totalMass = qa.GetResultsValue()[0];
            didSA = true;
        }
    }

    int times = 0;
    char name[1024];
    sprintf(name, "md%d.ult", times++);

    if (PAR_Rank() == 0)
    {
        bool lookingForUnused = true;
        while (lookingForUnused)
        {
            ifstream ifile(name);
            if (ifile.fail())
                lookingForUnused = false;
            else
                sprintf(name, "md%d.ult", times++);
        }
    }

    char msg[1024];
    const char *mass_string = (didVolume ? "volume" : 
                              (didRVolume ? "revolved volume" : 
                              (didSA ? "area" : "mass")));
    
    std::string format = "The %s distribution has been outputted as an "             
             "Ultra file (%s), which can then be imported into VisIt.  The"
             " total %s considered was " + queryAtts.GetFloatFormat() +"\n";
    SNPRINTF(msg,1024,format.c_str(),
                 mass_string, name, mass_string, totalMass);
    SetResultMessage(msg);
    SetResultValue(0.);

    double *m2 = new double[numBins];
    SumDoubleArrayAcrossAllProcessors(mass, m2, numBins);
    delete [] mass;
    mass = m2;

    double totalMassFromLines = 0.;
    for (i = 0 ; i < numBins ; i++)
        totalMassFromLines += mass[i];

    if (PAR_Rank() == 0)
    {
        if (totalMassFromLines == 0.)
        {
            sprintf(msg, "The mass distribution could not be calculated "
                    "becuase none of the lines intersected the data set."
                    "  If you have used a fairly large number of lines, then "
                    "this may be indicative of an error state.");
            SetResultMessage(msg);
            return;
        }

        ofstream ofile(name);
        if (ofile.fail())
        {
            sprintf(msg, "Unable to write out file containing distribution.");
            SetResultMessage(msg);
        }
        if (!ofile.fail())
            ofile << "# Mass distribution" << endl;

        MapNode result_node;
        doubleVector curve;

        double binWidth = (maxLength-minLength) / numBins;
        for (int i = 0 ; i < numBins ; i++)
        {
            double x1 = minLength + (i)*binWidth;
            double x2 = minLength + (i+1)*binWidth;
            double y = (totalMass*mass[i]) / (totalMassFromLines*binWidth); 
            curve.push_back(x1);
            curve.push_back(y);
            curve.push_back(x2);
            curve.push_back(y);
            if (!ofile.fail())
            {
                ofile << x1 << " " << y << endl;
                ofile << x2 << " " << y << endl;
            }
        }
        result_node["mass_distribution"] = curve;
        SetXmlResult(result_node.ToXML());
        SetResultValues(curve);
    }
}
void
avtStreamlineInfoQuery::PostExecute()
{
    //Everyone communicate data to proc 0.
#ifdef PARALLEL
    int nProcs = PAR_Size();
    int *counts = new int[nProcs];
    for (int i = 0; i < nProcs; i++)
        counts[i] = 0;
    
    counts[PAR_Rank()] = slData.size();
    Collect(counts, nProcs);
    
    int tag = GetUniqueMessageTag();
    MPI_Status stat;
    if (PAR_Rank() == 0)
    {
        for (int i = 1; i < nProcs; i++)
        {
            if (counts[i] > 0)
            {
                float *vals = new float[counts[i]];
                void *ptr = (void *)&vals[0];
                MPI_Recv(ptr, counts[i], MPI_FLOAT, i, tag, VISIT_MPI_COMM, &stat);

                for (int j = 0; j < counts[i]; j++)
                    slData.push_back(vals[j]);
                delete [] vals;
            }
        }
    }
    else
    {
        if (slData.size() > 0)
        {
            void *ptr = (void *)&slData[0];
            MPI_Send(ptr, slData.size(), MPI_FLOAT, 0, tag, VISIT_MPI_COMM);
        }
    }
    delete [] counts;
#endif
    
    std::string msg;
    char str[128];
    int i = 0, sz = slData.size();

    int slIdx = 0;
    MapNode result_node;
    while (i < sz)
    {
        sprintf(str, "Streamline %d: Seed %f %f %f Arclength %f\n", slIdx, slData[i], slData[i+1], slData[i+2], slData[i+3]);
        MapNode sl_res_node;
        doubleVector sl_res_seed;
        sl_res_seed.push_back(slData[i]);
        sl_res_seed.push_back(slData[i+1]);
        sl_res_seed.push_back(slData[i+2]);
        sl_res_node["seed"] = sl_res_seed;
        sl_res_node["arclength"] = slData[i+3];
        i+=4;
        msg += str;

        if (dumpSteps)
        {
            int numSteps =  (int)slData[i++];
            doubleVector sl_steps;
            for (int j = 0; j < numSteps; j++)
            {
                sprintf(str, " %f %f %f \n", slData[i], slData[i+1], slData[i+2]);// slData[i+3], slData[i+4]);
                sl_steps.push_back(slData[i]);
                sl_steps.push_back(slData[i+1]);
                sl_steps.push_back(slData[i+2]);
                i+=5;
                msg += str;
            }
            sl_res_node["steps"] = sl_steps;
        }
        sprintf(str, "streamline %d", slIdx);
        result_node[str] = sl_res_node;
        slIdx++;
    }

    SetResultMessage(msg.c_str());
    SetXmlResult(result_node.ToXML());
}