void
avtADIOSBasicFileFormat::ComputeStartCount(uint64_t *globalDims,
                                           int dim,
                                           uint64_t *start,
                                           uint64_t *count)
{
#if PARALLEL
    int domCount[3] = {0, 0, 0};
    int s[3] = {start[0],start[1],start[2]}, c[3] = {count[0],count[1],count[2]};
    avtDatabase::ComputeRectilinearDecomposition(dim, PAR_Size(),
                                                 globalDims[0], globalDims[1], globalDims[2],
                                                 &domCount[0], &domCount[1], &domCount[2]);
    
    // Determine this processor's logical domain (e.g. domain ijk) indices
    int domLogicalCoords[3] = {0, 0, 0};
    avtDatabase::ComputeDomainLogicalCoords(dim, domCount, PAR_Rank(),
                                            domLogicalCoords);
    
    // Compute domain bounds.
    for (int i = 0; i < 3; i++)
    {
        avtDatabase::ComputeDomainBounds(globalDims[i], domCount[i], domLogicalCoords[i],
                                         &(s[i]),
                                         &(c[i]));
        
        c[i]++;
        if (s[i]+c[i] >= globalDims[i])
            c[i]--;
        
        start[i] = s[i];
        count[i] = c[i];
    }
#endif
}
Esempio n. 2
0
void
PAR_WaitForDebugger(void)
{
#ifdef PARALLEL
    volatile int i = 0;
    if(PAR_Rank() == 0)
    {
        do {
            // nothing
        } while(i == 0);
    }
    Barrier();
#endif
}
Esempio n. 3
0
bool
avtLCSFilter::NativeMeshIterativeCalc(std::vector<avtIntegralCurve*> &ics)
{
    int offset = 0;

    if( *fsle_dt == NULL )
    {
      fsle_dt = CreateIterativeCalcDataTree(GetInputDataTree());
      
      if (GetInput()->GetInfo().GetAttributes().DataIsReplicatedOnAllProcessors())
        if (PAR_Rank() != 0)
          fsle_dt = new avtDataTree();

      SetOutputDataTree(fsle_dt);
    }

    return MultiBlockIterativeCalc(fsle_dt, ics, offset);
}
void
avtMemoryUsageQuery::PerformQuery(QueryAttributes *atts)
{
    // grab memory usage per engine process
    unsigned long m_size, m_rss;
    
    avtMemory::GetMemorySize(m_size, m_rss);
    
    if(m_size == 0 || m_rss == 0)
    {
        memSizeVals.clear();
        atts->SetResultsValue(memSizeVals);
        atts->SetResultsMessage("The Memory Usage Query is not supported on "
                                "this platform");
        return;
    }
    
    // convert to megabytes    
    double m_size_mb = ( (double)m_size / 1048576.0);
    
    int nprocs = PAR_Size();
    int rank   = PAR_Rank();

    memSizeVals.resize(nprocs);
    for (int i= 0; i < nprocs; i++)
        memSizeVals[i] = 0.0;

    memSizeVals[rank] = m_size_mb;

#ifdef PARALLEL
    // get values from other procs to the root
    if (nprocs > 1 )
    {
        MPI_Gather(&m_size_mb, 1, MPI_DOUBLE, 
                   &memSizeVals[0], 1, MPI_DOUBLE, 
                   0, VISIT_MPI_COMM);
    }
#endif

    atts->SetResultsValue(memSizeVals);
    queryAtts = *atts;
    std::string msg = GetResultMessage();
    atts->SetResultsMessage(msg);
}
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);
    }
}
Esempio n. 6
0
void
avtIntegrationRF::OutputRawValues(const char *filename)
{
    int nvals = windowSize[0]*windowSize[1];
    double *out_vals = new double[nvals];
    SumDoubleArrayAcrossAllProcessors(vals, out_vals, nvals);

    if (PAR_Rank() == 0)
    {
        ofstream ofile(filename);
        if (ofile.fail())
        {
            avtCallback::IssueWarning("The integration option for the ray"
                    " casted volume rendering could not output a file, because"
                    " it could not open the file.");
        }

        ofile << windowSize[0] << " " << windowSize[1] << endl;
        for (int i = 0 ; i < nvals ; i++)
            ofile << out_vals[i] << endl;
    }

    if (!issuedWarning)
    {
        char msg[1024];
        SNPRINTF(msg, 1024, "The integration was outputted to the file \"%s\".  "
                 "If you are running client/server, the file is located where "
                 "the remote server is running.  This message will only be issued"
                 " once per VisIt session.  Further renderings will overwrite"
                 " previous versions of this file.", filename);
        avtCallback::IssueWarning(msg);
        issuedWarning = true;
    }

    delete [] out_vals;
}
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);
    }
}
Esempio n. 8
0
void
avtResampleFilter::ResampleInput(void)
{
    int  i, j, k;

    avtDataset_p output = GetTypedOutput();
    double bounds[6] = { 0, 0, 0, 0, 0, 0 };
    bool is3D = GetBounds(bounds);

    debug4 << "Resampling over space: " << bounds[0] << ", " << bounds[1]
           << ": " << bounds[2] << ", " << bounds[3] << ": " << bounds[4]
           << ", " << bounds[5] << endl;
    
    //
    // Our resampling leaves some invalid values in the data range.  The
    // easiest way to bypass this is to get the data range from the input and
    // pass it along (since resampling does not change it in theory).
    //
    double range[2];
    if (GetInput()->GetInfo().GetAttributes().ValidActiveVariable())
    {
        GetDataExtents(range);
        output->GetInfo().GetAttributes().GetDesiredDataExtents()->Set(range);
    }

    avtViewInfo view;
    double scale[3];
    CreateViewFromBounds(view, bounds, scale);

    //
    // What we want the width, height, and depth to be depends on the
    // attributes.
    //
    int width, height, depth;
    GetDimensions(width, height, depth, bounds, is3D);

    //
    // If there are no variables, then just create the mesh and exit.
    //
    bool thereAreNoVariables = 
          (GetInput()->GetInfo().GetAttributes().GetNumberOfVariables() <= 0);
    if (thereAreNoVariables)
    {
        if (PAR_Rank() == 0)
        {
            vtkRectilinearGrid *rg = CreateGrid(bounds, width, height, depth,
                                      0, width, 0, height, cellCenteredOutput, is3D);
            avtDataTree_p tree = new avtDataTree(rg, 0);
            rg->Delete();
            SetOutputDataTree(tree);
        }
        else
        {
            //
            // Putting in a NULL data tree can lead to seg faults, etc.
            //
            avtDataTree_p dummy = new avtDataTree();
            SetOutputDataTree(dummy);
        }

        return;
    }

    //
    // World space is a right-handed coordinate system.  Image space (as used
    // in the sample point extractor) is a left-handed coordinate system.
    // This is because large X is at the right and large Y is at the top.
    // The z-buffer has the closest points at z=0, so Z is going away from the
    // screen ===> left handed coordinate system.  If we reflect across X,
    // then this will account for the difference between the coordinate 
    // systems.
    //
    scale[0] *= -1.;

    //
    // We don't want an Update to go all the way up the pipeline, so make
    // a terminating source corresponding to our input.
    //
    avtDataset_p ds;
    avtDataObject_p dObj = GetInput();
    CopyTo(ds, dObj);
    avtSourceFromAVTDataset termsrc(ds);

    //
    // The sample point extractor expects everything to be in image space.
    //
    avtWorldSpaceToImageSpaceTransform trans(view, scale);
    trans.SetInput(termsrc.GetOutput());

    bool doKernel = 
        (GetInput()->GetInfo().GetAttributes().GetTopologicalDimension() == 0);
    avtSamplePointExtractor extractor(width, height, depth);
    extractor.SendCellsMode(false);
    extractor.Set3DMode(is3D);
    extractor.SetInput(trans.GetOutput());
    if (doKernel)
        extractor.SetKernelBasedSampling(true);
    avtSamplePoints_p samples = extractor.GetTypedOutput();

    //
    // If the selection this filter exists to create has already been handled,
    // or if there are no pieces for this processor to process, then we can skip
    // execution. But, take care to emulate the same collective
    // calls other processors may make before returning.
    //
    if (GetInput()->GetInfo().GetAttributes().GetSelectionApplied(selID))
    {
        debug1 << "Bypassing Resample operator because database plugin "
                  "claims to have applied the selection already" << endl;

        SetOutputDataTree(GetInputDataTree());

        // we can save a lot of time if we know everyone can bypass
        if (UnifyMaximumValue(0) == 0)
            return;

        // here is some dummied up code to match collective calls below
        int effectiveVars = samples->GetNumberOfRealVariables();
        double *ptrtmp = new double[width*height*depth];
        for (int jj = 0; jj < width*height*depth; jj++)
            ptrtmp[jj] = -FLT_MAX;
        for (i = 0 ; i < effectiveVars ; i++)
            Collect(ptrtmp, width*height*depth);
        delete [] ptrtmp;
        return;
    }
    else
    {
        UnifyMaximumValue(1);
    }

    //
    //
    // PROBLEM SIZED WORK OCCURS BEYOND THIS POINT
    // If you add (or remove) collective calls below this point, make sure to
    // put matching sequence into bypass code above
    //
    //

    avtSamplePointCommunicator communicator;
    avtImagePartition partition(width, height, PAR_Size(), PAR_Rank());
    communicator.SetImagePartition(&partition);
    bool doDistributedResample = false;
#ifdef PARALLEL
    doDistributedResample = atts.GetDistributedResample();
#endif

    if (doDistributedResample)
    {
        partition.SetShouldProduceOverlaps(true);
        avtDataObject_p dob;
        CopyTo(dob, samples);
        communicator.SetInput(dob);
        samples = communicator.GetTypedOutput();
    }

    // Always set up an arbitrator, even if user selected random.
    bool arbLessThan = !atts.GetUseArbitrator() || atts.GetArbitratorLessThan();
    std::string arbName = atts.GetArbitratorVarName();
    if (arbName == "default")
        arbName = primaryVariable;
    extractor.SetUpArbitrator(arbName, arbLessThan);

    //
    // Since this is Execute, forcing an update is okay...
    //
    samples->Update(GetGeneralContract());

    if (samples->GetInfo().GetValidity().HasErrorOccurred())
    {
        GetOutput()->GetInfo().GetValidity().ErrorOccurred();
        GetOutput()->GetInfo().GetValidity().SetErrorMessage(
                          samples->GetInfo().GetValidity().GetErrorMessage());
    }

    //
    // Create a rectilinear dataset that is stretched according to the 
    // original bounds.
    //
    int width_start  = 0;
    int width_end    = width;
    int height_start = 0;
    int height_end   = height;
    if (doDistributedResample)
    {
        partition.GetThisPartition(width_start, width_end, height_start, 
                                   height_end);
        width_end += 1;
        height_end += 1;
    }

    //
    // If we have more processors than domains, we have to handle that
    // gracefully.  Communicate how many variables there are so that those
    // that don't have data can play well.
    //
    int realVars  = samples->GetNumberOfRealVariables();
    int numArrays = realVars;
    if (doKernel)
        numArrays++;
    vtkDataArray **vars = new vtkDataArray*[numArrays];
    for (i = 0 ; i < numArrays ; i++)
    {
        vars[i] = vtkDoubleArray::New();
        if (doKernel && (i == numArrays-1))
            vars[i]->SetNumberOfComponents(1);
        else
        {
            vars[i]->SetNumberOfComponents(samples->GetVariableSize(i));
            vars[i]->SetName(samples->GetVariableName(i).c_str());
        }
    }

    if (doKernel)
        samples->GetVolume()->SetUseKernel(true);

    avtImagePartition *ip = NULL;
    if (doDistributedResample)
        ip = &partition;

    // We want all uncovered regions to get the default value.  That is
    // what the first argument of GetVariables is for.  But if the
    // default value is large, then it will screw up the collect call below,
    // which uses MPI_MAX for an all reduce.  So give uncovered regions very
    // small values now (-FLT_MAX) and then replace them later.
    double defaultPlaceholder = -FLT_MAX;
    samples->GetVolume()->GetVariables(defaultPlaceholder, vars, 
                                       numArrays, ip);

    if (!doDistributedResample)
    {
        //
        // Collect will perform the parallel collection.  Does nothing in
        // serial.  This will only be valid on processor 0.
        //
        for (i = 0 ; i < numArrays ; i++)
        {
            double *ptr = (double *) vars[i]->GetVoidPointer(0);
            Collect(ptr, vars[i]->GetNumberOfComponents()*width*height*depth);
        }
    }
    
    // Now replace the -FLT_MAX's with the default value.  (See comment above.)
    for (i = 0 ; i < numArrays ; i++)
    {
        int numTups = vars[i]->GetNumberOfComponents()
                    * vars[i]->GetNumberOfTuples();
        if (numTups > 0)
        {
            double *ptr = (double *) vars[i]->GetVoidPointer(0);
            for (j = 0 ; j < numTups ; j++)
                ptr[j] = (ptr[j] == defaultPlaceholder 
                                 ? atts.GetDefaultVal() 
                                 : ptr[j]);
        }
    }
   
    bool iHaveData = false;
    if (doDistributedResample)
        iHaveData = true;
    if (PAR_Rank() == 0)
        iHaveData = true;
    if (height_end > height)
        iHaveData = false;
    if (iHaveData)
    {
        vtkRectilinearGrid *rg = CreateGrid(bounds, width, height, depth,
                                        width_start, width_end, height_start,
                                        height_end, cellCenteredOutput, is3D);

        if (doKernel)
        {
            double min_weight = avtPointExtractor::GetMinimumWeightCutoff();
            vtkDataArray *weights = vars[numArrays-1];
            int numVals = weights->GetNumberOfTuples();
            for (i = 0 ; i < realVars ; i++)
            {
                for (j = 0 ; j < vars[i]->GetNumberOfComponents() ; j++)
                {
                    for (k = 0 ; k < numVals ; k++)
                    {
                        double weight = weights->GetTuple1(k);
                        if (weight <= min_weight)
                            vars[i]->SetComponent(k, j, atts.GetDefaultVal());
                        else
                            vars[i]->SetComponent(k, j, 
                                         vars[i]->GetComponent(k, j) / weight);
                    }
                }
            }
        }

        //
        // Attach these variables to our rectilinear grid.
        //
        for (i = 0 ; i < realVars ; i++)
        {
            const char *varname = vars[i]->GetName();
            if (strcmp(varname, primaryVariable) == 0)
            {
                if (vars[i]->GetNumberOfComponents() == 3)
                    if (cellCenteredOutput)
                        rg->GetCellData()->SetVectors(vars[i]);
                    else
                        rg->GetPointData()->SetVectors(vars[i]);
                else if (vars[i]->GetNumberOfComponents() == 1)
                {
                    if (cellCenteredOutput)
                    {
                        rg->GetCellData()->AddArray(vars[i]);
                        rg->GetCellData()->SetScalars(vars[i]);
                    }
                    else
                    {
                        rg->GetPointData()->AddArray(vars[i]);
                        rg->GetPointData()->SetScalars(vars[i]);
                    }
                }
                else
               {
                    if (cellCenteredOutput)
                        rg->GetCellData()->AddArray(vars[i]);
                    else
                        rg->GetPointData()->AddArray(vars[i]);
               }
            }
            else
            {
                if (cellCenteredOutput)
                    rg->GetCellData()->AddArray(vars[i]);
                else
                    rg->GetPointData()->AddArray(vars[i]);
            }
        }

        avtDataTree_p tree = new avtDataTree(rg, 0);
        rg->Delete();
        SetOutputDataTree(tree);
    }
    else
    {
        //
        // Putting in a NULL data tree can lead to seg faults, etc.
        //
        avtDataTree_p dummy = new avtDataTree();
        SetOutputDataTree(dummy);
    }

    for (i = 0 ; i < numArrays ; i++)
    {
        vars[i]->Delete();
    }
    delete [] vars;
}
// ****************************************************************************
//  Method: FormatDebugImage
//
//  Purpose: Figure out a name for our debug image.  This is complicated in the
//           IceT case, because IceT can call our render function as much as it
//           wants.
//
//  Programmer: Tom Fogal
//  Creation:   May 18, 2011
//
// ****************************************************************************
void IceTNetworkManager::FormatDebugImage(char* out, size_t len,
                                          const char* prefix) const
{
  SNPRINTF(out, len, "%s-%03d-%03u", prefix, PAR_Rank(), this->renderings);
}
Esempio n. 10
0
int
EngineMain(int argc, char *argv[])
{
    // Start timings asap to get info on initialization activity
    TimingsManager::Initialize("");
    for (int i=1; i<argc; i++)
    {
        if (strcmp(argv[i], "-timing")==0 || strcmp(argv[i], "-timings")==0)
            visitTimer->Enable();
    }

    Engine *engine = EngineBase::GetEngine();

    // Do some pre-connect initialization
    engine->Initialize(&argc, &argv, true);
    debug1 << "Engine::Initialize completed." << endl;

    // Try to connect to the viewer
    if (engine->ConnectViewer(&argc, &argv))
    {
        debug1 << "Engine::ConnectViewer completed." << endl;

        // Do the post-connect initialization
        engine->SetUpViewerInterface(&argc, &argv);
        debug1 << "Engine::SetupViewerInterface completed." << endl;

        // Do the rest of the engine initialization.
        engine->InitializeCompute();
        debug1 << "Engine::InitializeCompute completed." << endl;

        // Begin the engine's event processing loop.
#ifdef PARALLEL
        debug1 << "Entering PAR_EventLoop" << endl;
        engine->PAR_EventLoop();
#else
        debug1 << "Entering EventLoop" << endl;
        engine->EventLoop();
#endif
    }
    else
    {
        // Connect failed
        if (PAR_Rank() == 0)
        {
             debug1 << "The engine could not connect to the viewer due to a "
                  << "networking problem.  The engine is exiting" << endl;
             cerr << "The engine could not connect to the viewer due to a "
                  << "networking problem.  The engine is exiting" << endl;
        }
    }

    if (DebugStream::Level1()) 
    {
        debug1 << "ENGINE exited." << endl;
    }
    engine->Finalize();

#ifdef DEBUG_MEMORY_LEAKS
    delete engine;
    vtkVisItUtility::CleanupStaticVTKObjects();
    avtFileDescriptorManager::DeleteInstance();
#endif

#ifdef PARALLEL
    PAR_Exit();
#endif
    return 0;
}
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
avtExtractPointFunction2DFilter::Execute()
{
    // Check consistency
    if (atts.GetI().size() != atts.GetJ().size())
    {
        EXCEPTION1(ImproperUseException,
                "I and J arrays need to have the same number of elements.");
    }

    const size_t num_functions = atts.GetI().size();
    std::vector<double*> function_data(num_functions, 0);
    bool klInformationSet = false;
    double dvpar = 1.0;
    double dmu = 1.0;
    int v_base_index[2] = { 0, 0 };
    int v_dims[2] = { 0, 0 };

    // Get the input data tree
    avtDataTree_p in_tree = GetInputDataTree();

    if (in_tree->IsEmpty())
    {
        SetOutputDataTree(in_tree);
        return;
    }

    int nLeaves = 0;
    vtkDataSet **leaves = in_tree->GetAllLeaves(nLeaves);

    // Get all data sets
    // FIXME: Structured grids should be simple as well
    vtkRectilinearGrid *rgrid = 0; // HACK: This just uses the last instance
    vtkDataArray *data = 0; // HACK: This just uses the last instance
    for (int i = 0; i < nLeaves; ++i)
    {
        // Ensure that we are working on rectilinear grid
        rgrid = dynamic_cast<vtkRectilinearGrid*>(leaves[i]);
        if (!rgrid)
            EXCEPTION1(ImproperUseException,
                       "Can only extract point function for a rectilinear grid.");

        // Dimensions of data set
        int dims[3];
        rgrid->GetDimensions(dims);
        // We want number of cells as grid dimension, not number of samples
        for (int d=0; d<3; ++d)
            dims[d]--;

        vtkIntArray *arr = dynamic_cast<vtkIntArray*>(rgrid->GetFieldData()->GetArray("base_index"));
        int base_index[3] = { 0, 0, 0 };
        if (arr)
            for (int d = 0; d < 3; ++d)
                base_index[d] = arr->GetValue(d);

        int i_min = base_index[0];
        int i_max = base_index[0] + dims[0] - 1;
        int j_min = base_index[1];
        int j_max = base_index[1] + dims[1] - 1;

        // FIXME: Take avtRealDims into account
        // arr = dynamic_cast<vtkIntArray*>(rgrid->GetFieldData()->GetArray("avtRealDims"));
        // int avtRealDims[6] = { 0, 0, 0, 0, 0, 0 };
        // if (arr)
        //     for (int d = 0; d < 6; ++d)
        //         avtRealDims[d] = arr->GetValue(d);

        vtkDoubleArray *dx_arr = dynamic_cast<vtkDoubleArray*>(rgrid->GetFieldData()->GetArray("dx_array"));
        vtkIntArray *v_base_index_arr = dynamic_cast<vtkIntArray*>(rgrid->GetFieldData()->GetArray("v_base_index"));
        vtkIntArray *v_dims_arr = dynamic_cast<vtkIntArray*>(rgrid->GetFieldData()->GetArray("v_dims"));

        const char *justTheVar = pipelineVariable + strlen("operators/ExtractPointFunction2D/");
 
        if (!klInformationSet)
        {
           if (dx_arr)
            {
                dvpar = dx_arr->GetValue(0);
                dmu = dx_arr->GetValue(1);
            }
            if (v_base_index_arr && v_dims_arr)
            {
                for (int i = 0; i < 2; ++i)
                {
                    v_base_index[i] = v_base_index_arr->GetValue(i);
                    v_dims[i] = v_dims_arr->GetValue(i);
                }
            }
            else
            {
                EXCEPTION1(ImproperUseException,
                        "Internal error: Velocity base index and dimensions not set by database plugin.");
            }
        }
        else
        {
           if (dx_arr)
            {
                if (dvpar != dx_arr->GetValue(0))
                    EXCEPTION1(ImproperUseException, "Internal error: dvpar mismatch.");
                if (dmu != dx_arr->GetValue(1))
                    EXCEPTION1(ImproperUseException, "Internal error: dmu mismatch.");
            }
            if (v_base_index_arr && v_dims_arr)
            {
                for (int i = 0; i < 2; ++i)
                {
                    if (v_base_index[i] != v_base_index_arr->GetValue(i))
                        EXCEPTION1(ImproperUseException, "Internal error: v_base_index mismatch.");
                    if (v_dims[i] != v_dims_arr->GetValue(i))
                        EXCEPTION1(ImproperUseException, "Internal error: v_dims mismatch.");
                }
            }
        }

        data = rgrid->GetCellData()->GetArray(justTheVar); // FIXME HACK: Outside for loop to ensure that processor 0 has a data pointer

        if (!data)
        {
            EXCEPTION1(VisItException, "Internal error: Could not get data for array variable (maybe due to an operator requesting ghost zones).");
        }

        const std::vector<int> &i_vals = atts.GetI();
        const std::vector<int> &j_vals = atts.GetJ();
        for (size_t curr_tuple = 0; curr_tuple < i_vals.size(); ++curr_tuple)
            if (i_min <= i_vals[curr_tuple] && i_vals[curr_tuple] <= i_max && j_min <= j_vals[curr_tuple] && j_vals[curr_tuple] <= j_max)
            {
                int ijk_f[3] = { i_vals[curr_tuple] - base_index[0], j_vals[curr_tuple] - base_index[1], 0 };
                vtkIdType id_f = rgrid->ComputeCellId(ijk_f);
                function_data[curr_tuple] = new double[v_dims[0]*v_dims[1]];
                for (vtkIdType comp = 0; comp < v_dims[0]*v_dims[1]; ++comp)
                    function_data[curr_tuple][comp] = data->GetComponent(id_f, comp);
            }
    }

#ifdef PARALLEL
    // Determine (on processor 0) where data resides
    std::vector<int> function2proc_map(function_data.size(), -1);
    for (size_t curr_func = 0; curr_func < function_data.size(); ++curr_func)
        if (function_data[curr_func]) function2proc_map[curr_func] = PAR_Rank();
    std::vector<int> tmp_function2proc_map(function2proc_map);
    MPI_Reduce(&tmp_function2proc_map[0], &function2proc_map[0], function2proc_map.size(), MPI_INT, MPI_MAX, 0, VISIT_MPI_COMM);

    // HACK: Send all data to processor 0
    // FIXME: Better distribution among processors
    // FIXME: Non-blocking send/receive
    if (PAR_Rank() == 0)
    {
        for (size_t curr_func = 0; curr_func < function_data.size(); ++curr_func)
            if (function2proc_map[curr_func] >= 1)
            {
                function_data[curr_func] = new double[v_dims[0]*v_dims[1]];
                MPI_Status status;
                MPI_Recv(function_data[curr_func], v_dims[0]*v_dims[1], MPI_DOUBLE, function2proc_map[curr_func], MPI_ANY_TAG, VISIT_MPI_COMM, &status);
            }
    }
    else
    {
        for (size_t curr_func = 0; curr_func < function_data.size(); ++curr_func)
            if (function_data[curr_func])
                MPI_Send(function_data[curr_func], v_dims[0]*v_dims[1], MPI_DOUBLE, 0, 0, VISIT_MPI_COMM);
    }

    if (PAR_Rank() == 0)
    {
#endif
        vtkRectilinearGrid *ogrid = vtkRectilinearGrid::New();
        ogrid->SetDimensions(v_dims[0]+1, v_dims[1]+1, function_data.size());
        vtkDataArray *xCoords = rgrid->GetXCoordinates()->NewInstance();
        xCoords->SetNumberOfTuples(v_dims[0]+1);
        for (int k = 0; k < v_dims[0]+1; ++k)
            xCoords->SetTuple1(k, (v_base_index[0]+k)*dvpar);
        ogrid->SetXCoordinates(xCoords);
        xCoords->Delete();
        vtkDataArray *yCoords = rgrid->GetXCoordinates()->NewInstance();
        yCoords->SetNumberOfTuples(v_dims[1]+1);
        for (int l = 0; l < v_dims[1]+1; ++l)
            yCoords->SetTuple1(l, (v_base_index[1]+l)*dmu);
        ogrid->SetYCoordinates(yCoords);
        yCoords->Delete();
        vtkDataArray *zCoords = rgrid->GetXCoordinates()->NewInstance();
        zCoords->SetNumberOfTuples(function_data.size());
        for (int f = 0; f < function_data.size(); ++f)
            zCoords->SetTuple1(f, f);
        ogrid->SetZCoordinates(zCoords);
        zCoords->Delete();

        // FIXME: v_base_index, dvpar and dmu are only defined if there is any data on rank 0
        spatialExtents[0] = v_base_index[0] * dvpar;
        spatialExtents[1] = (v_base_index[0] + v_dims[0]) * dvpar;
        spatialExtents[2] = v_base_index[1] * dmu;
        spatialExtents[3] = (v_base_index[1] + v_dims[1]) * dmu;
        spatialExtents[4] = 0;
        spatialExtents[5] = function_data.size() - 1;

        // FIXME: data is only defined if there is any data on rank 0
        vtkDataArray *odata = data->NewInstance();
        odata->SetNumberOfComponents(1);
        odata->SetNumberOfTuples(v_dims[0]*v_dims[1]*function_data.size());
        for (int k = 0; k < v_dims[0]; ++k)
            for (int l = 0; l < v_dims[1]; ++l)
                for (int f = 0; f < function_data.size(); ++f)
                {
                    int ijk_t[3] = { k, l, f };
                    vtkIdType id_t = ogrid->ComputeCellId(ijk_t);
                    double val = function_data[f] ? function_data[f][k*v_dims[1]+l] : 0;
                    odata->SetTuple1(id_t, val);
                    if (val < range[0]) range[0] = val;
                    if (val > range[1]) range[1] = val;
                }
        odata->SetName(outVarName.c_str());
        ogrid->GetCellData()->SetScalars(odata);
        odata->Delete();

#if 0
        vtkDataSetWriter *wrtr = vtkDataSetWriter::New();
        wrtr->SetFileTypeToASCII();
        wrtr->SetInputData(ogrid);
        wrtr->SetFileName("debug.vtk");
        wrtr->Write();
#endif

        SetOutputDataTree(new avtDataTree(ogrid, 1));
#ifdef PARALLEL
    }
    else
    {
        SetOutputDataTree(new avtDataTree());
    }
#endif

    for (std::vector<double*>::iterator it = function_data.begin(); it != function_data.end(); ++it)
        delete[] *it;
}
Esempio n. 14
0
bool
avtGTCFileFormat::Initialize()
{
    const char *mName = "avtGTCFileFormat::Initialize: ";

    if(initialized)
        return true;

    // Init HDF5 and turn off error message printing.
    H5open();
    H5Eset_auto( NULL, NULL );

    bool err = false;

    // Check for a valid GTC file
    if( H5Fis_hdf5( GetFilename() ) < 0 )
      EXCEPTION1( InvalidFilesException, GetFilename() );

    if ((fileHandle = H5Fopen(GetFilename(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
      EXCEPTION1( InvalidFilesException, GetFilename() );
    
    if ((particleHandle = H5Dopen(fileHandle, "particle_data")) < 0)
    {
      H5Fclose(fileHandle);
      EXCEPTION1( InvalidFilesException, GetFilename() );
    }

    // At this point consider the file to truly be a GTC file. If
    // some other file NonCompliantExceptions will be thrown.

    // Continue as normal reporting NonCompliantExceptions

    //Check variable's size.
    hid_t dataspace = H5Dget_space(particleHandle);
    hsize_t dims[3];
    hid_t sid = H5Dget_space(particleHandle);
    int ndims = H5Sget_simple_extent_dims(dataspace, dims, NULL);
    if(ndims < 0 || ndims > 2)
    {
        debug4 << mName << "Could not determine number of dimensions" << endl;
        H5Sclose(sid);
        H5Dclose(particleHandle);
        H5Fclose(fileHandle);
        EXCEPTION1( InvalidVariableException, "GTC Dataset Extents - Dataset 'particle_data' has an invalid extents");
    }
    
    debug4 << mName << "Determining variable size" << endl;
    int val = H5Sget_simple_extent_dims(sid, dims, NULL);

    if(val < 0 || dims[1] < 3)
    {
        debug4 << mName << "Could not determine variable size" << endl;
        H5Sclose(sid);
        H5Dclose(particleHandle);
        H5Fclose(fileHandle);
        EXCEPTION1( InvalidVariableException, "GTC Dataset Extents - Dataset 'particle_data' has an insufficient number of variables");
    }
    H5Sclose(dataspace);

    debug4 << mName << "variable size (" << dims[0] << ", " << dims[1] << ")" << endl;

    nTotalPoints = dims[0];
    nVars = dims[1];

#ifdef PARALLEL
    nProcs = PAR_Size();
    rank = PAR_Rank();
    nPoints = nTotalPoints / nProcs;
    int remainder = nTotalPoints % nProcs;

    startOffset = rank * nPoints;
    if ( rank < remainder )
        startOffset += rank;
    else
        startOffset += remainder;

    if ( rank < remainder )
        nPoints++;
#else
    nPoints = nTotalPoints;
    startOffset = 0;
#endif
    
    initialized = true;
    
    return initialized;
}
Esempio n. 15
0
void
avtDataBinningFilter::Execute(void)
{
    ConstructDataBinningAttributes dba = atts.CreateConstructionAtts();
    std::vector<double> bb = dba.GetBinBoundaries();
    if (! atts.GetDim1SpecifyRange())
    {
        if (atts.GetDim1BinBasedOn() == DataBinningAttributes::Variable)
        {
            std::string v1name = atts.GetDim1Var();
            if (v1name == "default")
                v1name = pipelineVariable;
            double range[2];
            GetDataExtents(range, v1name.c_str());
            bb[0] = range[0];
            bb[1] = range[1];
        }
        else
        {
            int dim = (atts.GetDim1BinBasedOn()-DataBinningAttributes::X);
            double range[6];
            GetSpatialExtents(range);
            bb[0] = range[2*dim];
            bb[1] = range[2*dim+1];
        }
    }
    if ((! atts.GetDim2SpecifyRange()) && (atts.GetNumDimensions() == DataBinningAttributes::Two ||
                                         atts.GetNumDimensions() == DataBinningAttributes::Three))
    {
        if (atts.GetDim2BinBasedOn() == DataBinningAttributes::Variable)
        {
            std::string v2name = atts.GetDim2Var();
            if (v2name == "default")
                v2name = pipelineVariable;
            double range[2];
            GetDataExtents(range, v2name.c_str());
            bb[2] = range[0];
            bb[3] = range[1];
        }
        else
        {
            int dim = (atts.GetDim2BinBasedOn()-DataBinningAttributes::X);
            double range[6];
            GetSpatialExtents(range);
            bb[2] = range[2*dim];
            bb[3] = range[2*dim+1];
        }
    }
    if ((! atts.GetDim3SpecifyRange()) && atts.GetNumDimensions() == DataBinningAttributes::Three)
    {
        if (atts.GetDim3BinBasedOn() == DataBinningAttributes::Variable)
        {
            std::string v3name = atts.GetDim3Var();
            if (v3name == "default")
                v3name = pipelineVariable;
            double range[2];
            GetDataExtents(range, v3name.c_str());
            bb[4] = range[0];
            bb[5] = range[1];
        }
        else
        {
            int dim = (atts.GetDim3BinBasedOn()-DataBinningAttributes::X);
            double range[6];
            GetSpatialExtents(range);
            bb[4] = range[2*dim];
            bb[5] = range[2*dim+1];
        }
    }
    dba.SetBinBoundaries(bb);

    avtDataBinningConstructor dbc;
    dbc.SetInput(GetInput());
    avtDataBinning *d = dbc.ConstructDataBinning(&dba, lastContract, false);

    if (atts.GetOutputType() == DataBinningAttributes::OutputOnBins)
    {
        if (PAR_Rank() == 0)
        {
            vtkDataSet *ds = d->CreateGrid();
            if (atts.GetNumDimensions() == DataBinningAttributes::One)
                ds->GetPointData()->GetScalars()->SetName(varname.c_str());
            else
                ds->GetCellData()->GetScalars()->SetName(varname.c_str());
            ds->GetCellData()->SetActiveScalars(varname.c_str());
            SetOutputDataTree(new avtDataTree(ds, -1));
            double range[2] = { FLT_MAX, -FLT_MAX };
            GetDataRange(ds, range, varname.c_str(), false);
            avtDataAttributes &dataAtts = GetOutput()->GetInfo().GetAttributes();
            dataAtts.GetThisProcsOriginalDataExtents(varname.c_str())->Set(range);
            dataAtts.GetThisProcsActualDataExtents(varname.c_str())->Set(range);
    
            ds->Delete();
        }
        else
            SetOutputDataTree(new avtDataTree());
     
        avtDataAttributes &dataAtts = GetOutput()->GetInfo().GetAttributes();
        int dim = ( (atts.GetNumDimensions() == DataBinningAttributes::One) ? 1
                  : ((atts.GetNumDimensions() == DataBinningAttributes::Two) ? 2 : 3));
        dataAtts.GetThisProcsOriginalSpatialExtents()->Set(&bb[0]);
        dataAtts.GetOriginalSpatialExtents()->Set(&bb[0]);
    }
    else if (atts.GetOutputType() == DataBinningAttributes::OutputOnInputMesh)
    {
        double range[2] = { FLT_MAX, -FLT_MAX };
        bool hadError = false;
        avtDataTree_p tree = CreateArrayFromDataBinning(GetInputDataTree(), d, range, hadError);
        if (UnifyMaximumValue((int) hadError) > 0)
        {
            avtCallback::IssueWarning("The data binning could not be placed on the input "
                    "mesh.  This is typically because the data binning is over different "
                    "centerings (zonal and nodal) and can not be meaningfully placed back "
                    "on the input mesh.  Try recentering one of the variables to remove "
                    "this ambiguity.");
            SetOutputDataTree(new avtDataTree());
        }
        else
        {
            SetOutputDataTree(tree);
            avtDataAttributes &dataAtts = GetOutput()->GetInfo().GetAttributes();
            dataAtts.GetThisProcsOriginalDataExtents(varname.c_str())->Set(range);
            dataAtts.GetThisProcsActualDataExtents(varname.c_str())->Set(range);
        }
    }
    
    delete d;
}
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());
}
Esempio n. 17
0
bool
avtLCSFilter::RectilinearGridIterativeCalc( std::vector<avtIntegralCurve*> &ics )
{
    //algorithm sends index to global datastructure as well as end points.
    //Send List of index into global array to rank 0
    //Send end positions into global array to rank 0

    size_t nics = ics.size();

    //loop over all the intelgral curves and add it back to the
    //original list of seeds.
    intVector indices(nics);
    doubleVector points(nics*3);
    doubleVector times(nics);

    for(size_t i=0, j=0; i<nics; ++i, j+=3)
    {
        avtStreamlineIC * ic = (avtStreamlineIC *) ics[i];

        indices[i] = ic->id;
        avtVector point = ic->GetEndPoint();

        points[j+0] = point[0];
        points[j+1] = point[1];
        points[j+2] = point[2];

        if( doPathlines )
          times[i] = ic->GetTime() - seedTime0;
        else
          times[i] = ic->GetTime();
    }

    int* all_indices = 0;
    int* index_counts = 0;

    double* all_points = 0;
    int *point_counts = 0;

    double* all_times = 0;
    int *time_counts = 0;

    Barrier();

    CollectIntArraysOnRootProc(all_indices, index_counts,
                               &indices.front(), (int)indices.size());

    CollectDoubleArraysOnRootProc(all_points, point_counts,
                                  &points.front(), (int)points.size());

    CollectDoubleArraysOnRootProc(all_times, time_counts,
                                  &times.front(), (int)times.size());

    Barrier();

    //root should now have index into global structure and all
    //matching end positions.
    if(PAR_Rank() != 0)
    {
        return true;
    }
    else
    {
        //variable name.
        std::string var = outVarRoot + outVarName;

        //now global grid has been created.
        if( fsle_ds == 0 )
          fsle_ds = CreateIterativeCalcDataSet();

        // Get the stored data arrays
        vtkDoubleArray *exponents = (vtkDoubleArray *)
          fsle_ds->GetPointData()->GetArray(var.c_str());
        vtkDoubleArray *component = (vtkDoubleArray *)
          fsle_ds->GetPointData()->GetArray("component");
        vtkDoubleArray *times = (vtkDoubleArray *)
          fsle_ds->GetPointData()->GetArray("times");

        size_t nTuples = exponents->GetNumberOfTuples();

        // Storage for the points and times
        std::vector<avtVector> remapPoints(nTuples);
        std::vector<double> remapTimes(nTuples);

        //update remapPoints with new value bounds from integral curves.
        int par_size = PAR_Size();
        size_t total = 0;
        for(int i = 0; i < par_size; ++i)
        {
            if(index_counts[i]*3 != point_counts[i] ||
               index_counts[i]   != time_counts[i])
            {
              EXCEPTION1(VisItException,
                         "Index count does not the result count." );
            }

            total += index_counts[i];
        }

        for(size_t j=0, k=0; j<total; ++j, k+=3)
        {
            size_t index = all_indices[j];

            if(nTuples <= index)
            {
              EXCEPTION1(VisItException,
                         "More integral curves were generatated than "
                         "grid points." );
            }

            remapPoints[index].set( all_points[k+0],
                                    all_points[k+1],
                                    all_points[k+2]);

            remapTimes[index] = all_times[j];
        }

        // Store the times for the exponent.
        for(size_t l=0; l<nTuples; ++l)
          times->SetTuple1(l, remapTimes[l]);

        //use static function in avtGradientExpression to calculate
        //gradients.  since this function only does scalar, break our
        //vectors into scalar components and calculate one at a time.

        vtkDataArray* jacobian[3];

        for(int i = 0; i < 3; ++i)
        {
            // Store the point component by component
            for(size_t l=0; l<nTuples; ++l)
                component->SetTuple1(l, remapPoints[l][i]);

            jacobian[i] =
              avtGradientExpression::CalculateGradient(fsle_ds, "component");
        }

        for (size_t i = 0; i < nTuples; i++)
          component->SetTuple1(i, std::numeric_limits<double>::epsilon());

        //now have the jacobian - 3 arrays with 3 components.
        ComputeLyapunovExponent(jacobian, component);
        
        jacobian[0]->Delete();
        jacobian[1]->Delete();
        jacobian[2]->Delete();
      
        // Compute the FSLE
        ComputeFSLE( component, times, exponents );

        bool haveAllExponents = true;

        // For each integral curve check it's mask value to see it
        // additional integration is required.

        // ARS - FIX ME not parallelized!!!!!!!!
        for(size_t i=0; i<ics.size(); ++i)
        {
          avtStreamlineIC * ic = (avtStreamlineIC *) ics[i];

          int ms = ic->GetMaxSteps();

          if( ms < maxSteps )
          {
            ic->SetMaxSteps(ms+1);
            ic->status.ClearTerminationMet();
          }

          size_t l = ic->id; // The curve id is the index into the VTK data.

          // Check to see if all exponents have been found.
          if( exponents->GetTuple1(l) == std::numeric_limits<double>::min() &&
              ms < maxSteps )
            haveAllExponents = false;
        }

        //cleanup.
        if (all_indices)   delete [] all_indices;
        if (index_counts)  delete [] index_counts;

        if (all_points)    delete [] all_points;
        if (point_counts)  delete [] point_counts;

        if (all_times)    delete [] all_times;
        if (time_counts)  delete [] time_counts;

        return haveAllExponents;
    }
}
Esempio n. 18
0
// ****************************************************************************
//  Function: VisIt_MPI_Bcast
//
//  Purpose: A smarter broadcast that gives VisIt control over polling
//  behavior. MPI's Bcast method can wind up doing a 'spin-wait' eating cpu
//  resources. Our implementation, here, is both similar and different to
//  that.
//
//  In our Bcast method, all processors (except for root) start by posting a
//  non-blocking receive. A non-blocking receive can be tested for completion
//  using MPI_Test. All processors (again except for root), enter a polling
//  loop calling MPI_Test to check to see if the receive completed. For the
//  first several seconds of inactivity, they poll as fast as they can (this
//  is equivalent to MPI's spin-wait behavior). However, after not too much
//  time, they begin to introduce delays, using nanosleep, into this polling
//  loop. The delays substantially reduce the load on the cpu.
//
//  The broadcast itself is initiated at the root and proceeds in tree-like
//  fashion. The root sends a message to the highest power of 2 ranked
//  processor that is less than the communicator size. As that processor
//  completes its recieve, it exits from its polling loop and enters the
//  're-send to other processors' phase of the broadcast. It begins to send
//  messages to other processors and, simultaneously, the root also continues
//  to send messages to other processors. More processors complete their
//  recieves and then send the message on to still other processors. This
//  continues in tree-like fashion based on the MPI rank of the processors
//  until everyone has finished sending messages to those they are responsible
//  for. As the process continues, all odd-numbered processors only ever
//  execute a receive. All even numbered processors execute the receive and
//  then a variable number of sends depending on their rank relative to the
//  next closest power-of-2.
//
//  In the case of a 13 processor run, this is how the broadcast phase would
//  proceed...
//
//  1) P0->P8
//  2) PO->P4                          P8->P12
//  3) P0->P2,         P4->P6,         P8->P10
//  4) P0->P1, P2->P3, P4->P5, P6->P7, P8->P9, P10->P11
//
//  The first thing each processor does is to compute who it will recieve
//  the message from. That is determined by zeroing the lowest-order '1' bit
//  in the binary expression of the processor's rank. The difference between
//  that processor and the executing processor is a power-of-2. The executing
//  processor then sends the message to all processors that are above it in
//  rank by all powers-of-2 between 1 and the difference less one power of 2.
//
//  Programmer: Mark C. Miller
//  Creation:   February 12, 2007
//
//  Modifications:
//
//    Mark C. Miller, Wed Feb 14 14:36:11 PST 2007
//    Added class statics to control behavior and fall back to MPI's Bcast
//    when we specify 0 sleep time.
// ****************************************************************************
int
MPIXfer::VisIt_MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root,
                         MPI_Comm comm)
{
    //
    // Fall back to MPI broadcast if zero sleep time is specified
    //
    if (nanoSecsOfSleeps <= 0)
    {
        static bool first = true;
        if (first)
            debug5 << "Using MPI's Bcast; not VisIt_MPI_Bcast" << endl;
        first = false;
        MPI_Bcast(buf, count, datatype, root, comm);
        return 2;
    }

    int rank = PAR_Rank();
    int size = PAR_Size();
    MPI_Status mpiStatus;

    //
    // Make proc 0 the root if it isn't already
    //
    if (root != 0)
    {
        if (rank == root) // only original root does this
            MPI_Send(buf, count, datatype, 0, UI_BCAST_TAG, comm);
        if (rank == 0)    // only new root (zero) does this
            MPI_Recv(buf, count, datatype, root, UI_BCAST_TAG, comm, &mpiStatus);
        root = 0;         // everyone does this
    }

    //
    // Compute who the executing proc. will recieve its message from.
    //
    int srcProc = 0;
    for (int i = 0; i < 31; i++)
    {
        int mask = 0x00000001;
        int bit = (rank >> i) & mask;
        if (bit == 1)
        {
            int mask1 = ~(0x00000001 << i);
            srcProc = (rank & mask1);
            break;
        }
    }

    //
    // Polling Phase
    //
    if (rank != 0)
    {
        //
        // Everyone posts a non-blocking recieve
        //
        MPI_Request bcastRecv;
        MPI_Irecv(buf, count, datatype, srcProc, UI_BCAST_TAG, comm, &bcastRecv);

        //
        // Main polling loop
        //
        double startedIdlingAt = TOA_THIS_LINE;
        int mpiFlag;
        bool first = true;
        while (true)
        {
            // non-blocking test for recv completion
            MPI_Test(&bcastRecv, &mpiFlag, &mpiStatus);
            if (mpiFlag == 1)
                break;

            //
            // Note: We could add logic here to deal with engine idle timeout
            // instead of using the alarm mechanism we currently use.
            //

            //
            // Insert nanosleeps into the polling loop as determined by
            // amount of time we've been sitting here in this loop
            //
            double idleTime = TOA_THIS_LINE - startedIdlingAt;
            if (idleTime > secsOfSpinBeforeSleeps)
            {
                if (first)
                    debug5 << "VisIt_MPI_Bcast started using " << nanoSecsOfSleeps / 1.0e9
                           << " seconds of nanosleep" << endl;
                first = false;
#if defined(_WIN32)
                SleepEx((DWORD)(nanoSecsOfSleeps/1e6), false);
#else
                struct timespec ts = {0, nanoSecsOfSleeps};
                nanosleep(&ts, 0);
#endif
            }
        }
    }

    //
    // Send on to other processors phase
    //

    //
    // Determine highest rank proc above the executing proc
    // that it is responsible to send a message to.
    //
    int deltaProc = (rank - srcProc) >> 1;
    if (rank == 0)
    {
        deltaProc = 1;
        while ((deltaProc << 1) < PAR_Size())
            deltaProc = deltaProc << 1;
    }

    //
    // Send message to other procs the executing proc is responsible for
    //
    while (deltaProc > 0)
    {
        if (rank + deltaProc < size)
            MPI_Send(buf, count, datatype, rank + deltaProc, UI_BCAST_TAG, comm);
        deltaProc = deltaProc >> 1;
    }

    return 0;
}
Esempio n. 19
0
void 
avtLCSFilter::CreateRectilinearGridIterativeCalcOutput(std::vector<avtIntegralCurve*> &ics)
{
    //root should now have index into global structure and all
    //matching end positions.
    if(PAR_Rank() != 0)
    {
        avtDataTree* dummy = new avtDataTree();
        SetOutputDataTree(dummy);
    }
    else
    {
      if (fsle_ds->GetDataObjectType() != VTK_RECTILINEAR_GRID)
      {
        EXCEPTION1(VisItException,
                   "Can only compute CreateRectilinearGridIterativeCalcOutput on "
                   "rectilinear grids. ");
      }

      //variable name.
      std::string var = outVarRoot + outVarName;

      vtkDoubleArray *exponents = (vtkDoubleArray *)
        fsle_ds->GetPointData()->GetArray(var.c_str());

      int nTuples = exponents->GetNumberOfTuples();

      //min and max values over all datasets of the tree.
      double minv =  std::numeric_limits<double>::max();
      double maxv = -std::numeric_limits<double>::max();
      
      int count = 0;

      for(size_t i=0; i<ics.size(); ++i)
      {
        avtStreamlineIC * ic = (avtStreamlineIC *) ics[i];

        size_t l = ic->id; // The curve id is the index into the VTK data.

        double lambda = exponents->GetTuple1(l);

        if( lambda == -std::numeric_limits<double>::max() )
        {
          lambda = 0;
          exponents->SetTuple1(l, lambda );
        }
        else
        {
          ++count;
          ic->status.ClearTerminationMet();

          if( clampLogValues && lambda < 0 )
          {
            lambda = 0;
            exponents->SetTuple1(l, lambda );
          }
        }

        minv = std::min(lambda, minv);
        maxv = std::max(lambda, maxv);
      }

      if( count <= nTuples/10 )
      {
        if( minSizeValue == std::numeric_limits<double>::max() )
          minSizeValue = 0.0;

        if( maxSizeValue == -std::numeric_limits<double>::max() )
          maxSizeValue = 0.0;

        char str[1028];

        SNPRINTF(str, 1028, "\n%d%% of the nodes (%d of %d nodes) "
                 "exaimed produced a valid exponent (%f to %f). "
                 "This may be due to too large of a size limit (%f), "
                 "too small of an integration step (%f), or "
                 "too few integration steps (%d out of %d where taken), or "
                 "simply due to the nature of the data. "
                 "The size range was from %f to %f. ",
                 (int) (100.0 * (double) count / (double) nTuples),
                 count, nTuples,
                 minv, maxv,
                 maxSize, maxStepLength, numSteps, maxSteps,
                 minSizeValue, maxSizeValue );

        avtCallback::IssueWarning(str);
      }
      
      // Make the exponents the the active scalars.
      fsle_ds->GetPointData()->SetActiveScalars(var.c_str());

      // Remove the working arrays.
      fsle_ds->GetPointData()->RemoveArray("component");
      fsle_ds->GetPointData()->RemoveArray("times");

      std::string str = CreateCacheString();
      StoreArbitraryVTKObject(SPATIAL_DEPENDENCE | DATA_DEPENDENCE,
                              outVarName.c_str(), -1, -1,
                              str.c_str(), fsle_ds);
      
      int index = 0;//what does index mean in this context?
      avtDataTree* dt = new avtDataTree(fsle_ds,index);
      int x = 0;
      dt->GetAllLeaves(x);
      
      SetOutputDataTree(dt);
      
      //set atts.
      avtDataAttributes &dataatts = GetOutput()->GetInfo().GetAttributes();
      avtExtents* e = dataatts.GetThisProcsActualDataExtents();
      
      double range[2];
      range[0] = minv;
      range[1] = maxv;
      e->Set(range);
    }
}
Esempio n. 20
0
void
avtZoneDumpFilter::PostExecute()
{
    // skip dump if not enabled
    if(!atts.GetEnabled())
        return;

#ifdef PARALLEL
    // loop index
    int i;

    // get the number of processors and the current processor id
    int nprocs = PAR_Size();
    int procid = PAR_Rank();

    // get the number of zone infos to send
    int  n_snd_zones = zones.size();
    // size of each zone info
    int  zinfo_size = ZoneInfo::PackedSize();
    // calculate the total send message size
    int  snd_msg_size = n_snd_zones * zinfo_size;
    // send buffer
    unsigned char *snd_msg = NULL;

    // vars for the root processor
    // size of the gather message
    int  rcv_msg_size = 0;
    // holds size of the msg from each other processor
    int *rcv_count = NULL;
    // holds the displacement of the msg from each other processor
    int *rcv_disp  = NULL;
    // receive buffer
    unsigned char *rcv_msg = NULL;

    if(procid == 0)
    {
        // allocate space for these for root proc only
        rcv_count = new int[nprocs];
        rcv_disp  = new int[nprocs];
    }

    // gather message sizes from all procs to root proc
    MPI_Gather(&snd_msg_size,1, MPI_INT,
               rcv_count, 1, MPI_INT,
               0, VISIT_MPI_COMM);

    // find message offsets and total rcv size
    if(procid == 0)
    {
        rcv_disp[0]  = 0;
        rcv_msg_size = rcv_count[0];

        for( i=1; i<nprocs;i++)
        {
            rcv_disp[i]   = rcv_count[i-1]  +  rcv_disp[i-1];
            rcv_msg_size += rcv_count[i];
        }
    }

    // get total # of zone infos
    int nrcv_zones = rcv_msg_size / zinfo_size;

    // create msg to send to the root proc
    if(snd_msg_size > 0)
    {
        snd_msg= new unsigned char[snd_msg_size];
        unsigned char *snd_msg_ptr = snd_msg;

        // pack zone infos
        for(i=0; i < n_snd_zones; i++)
        {
            zones[i].Pack(snd_msg_ptr);
            snd_msg_ptr+= zinfo_size;
        }
    }

    if(procid == 0 && rcv_msg_size > 0)
    {
        // create the rcv buffer for the root proc
        rcv_msg = new unsigned char[rcv_msg_size];
    }

    // gather all zone infos
    MPI_Gatherv(snd_msg, snd_msg_size, MPI_UNSIGNED_CHAR,
                rcv_msg, rcv_count, rcv_disp, MPI_UNSIGNED_CHAR,
                0,VISIT_MPI_COMM);

    if(procid == 0 )
    {
        // unpack all rcvd zones
        std::vector<ZoneInfo> rcv_zones(nrcv_zones);

        unsigned char *rcv_msg_ptr = rcv_msg;

        for( i = 0; i < nrcv_zones; i++)
        {
            rcv_zones[i].Unpack(rcv_msg_ptr);
            rcv_msg_ptr += zinfo_size;
        }

        // save all zones
        SaveOutput(atts.GetOutputFile(),rcv_zones);
    }

    // cleanup

    if(snd_msg)
        delete[] snd_msg;

    if(rcv_msg)
        delete[] rcv_msg;

    if(rcv_count)
        delete[] rcv_count;

    if(rcv_disp)
        delete[] rcv_disp;
#else

    // for serial case, simply dump out zones found during the exe pass.
    SaveOutput(atts.GetOutputFile(),zones);

#endif
}
void
avtLocateAndPickNodeQuery::PerformQuery(QueryAttributes *qa)
{
    // Preparation work
    avtDataRequest_p dataRequest = 
        GetInput()->GetOriginatingSource()->GetFullDataRequest();

    avtDataAttributes &inAtts = GetInput()->GetInfo().GetAttributes();
    avtDataValidity &inVal = GetInput()->GetInfo().GetValidity();

    pickAtts.SetActiveVariable(dataRequest->GetVariable());
    pickAtts.SetGhostType(inAtts.GetContainsGhostZones());
    pickAtts.SetTimeStep(qa->GetTimeStep());
    pickAtts.SetPickType(PickAttributes::Node);

    // Do the locate part of the query
    lnq->SetInput(GetInput());
    lnq->SetPickAtts(&pickAtts);
    lnq->SetSILRestriction(querySILR); 
    lnq->SetTimeVarying(true);
    lnq->PerformQuery(qa);

    SetPickAtts(lnq->GetPickAtts());

    if (pickAtts.GetLocationSuccessful())
    {
        // Do the pick part of the query
        npq->SetInput(GetInput()->GetQueryableSource()->GetOutput());
        npq->SetPickAtts(&pickAtts);
        npq->SetSILRestriction(querySILR); 
        npq->SetSkippedLocate(false); 
        npq->SetTimeVarying(true);
        npq->SetNeedTransform(inVal.GetPointsWereTransformed());
        if (inAtts.HasInvTransform() && inAtts.GetCanUseInvTransform())
            npq->SetInvTransform(inAtts.GetInvTransform());
        npq->PerformQuery(qa);

        SetPickAtts(npq->GetPickAtts());
    }

    if (PAR_Rank() == 0) 
    {
        doubleVector vals;
        if (pickAtts.GetFulfilled())
        {
            // Special indication that the pick point should not be displayed.
            double cp[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
            std::string msg;
            pickAtts.SetCellPoint(cp);
            pickAtts.CreateOutputString(msg);
            qa->SetResultsMessage(msg);
            if ( pickAtts.GetNumVarInfos() == 1)
            {
                vals = pickAtts.GetVarInfo(0).GetValues();
                qa->SetResultsValue(vals[vals.size()-1]);
            }
            else
            {
                for (int i = 0; i < pickAtts.GetNumVarInfos(); ++i)
                {
                    vals.push_back(pickAtts.GetVarInfo(i).GetValues()[0]);
                }
                qa->SetResultsValues(&vals[0], (int)vals.size());
            }
        }
        else
        {
            char msg[120]; 
            SNPRINTF(msg, 120, "Could not retrieve information from domain "
                     " %d node %d.", domain, node);
            qa->SetResultsMessage(msg);
            qa->SetResultsValue(vals);
        }
    }
    pickAtts.PrepareForNewPick();
}
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
avtQueryOverTimeFilter::CreateFinalOutput()
{
    if (ParallelizingOverTime())
    {
        double *totalQRes;
        int    *qResMsgs;
        CollectDoubleArraysOnRootProc(totalQRes, qResMsgs,
                                      &(qRes[0]), qRes.size());
        double *totalTimes;
        int    *timesMsgs;
        CollectDoubleArraysOnRootProc(totalTimes, timesMsgs,
                                      &(times[0]), times.size());
        if (PAR_Rank() == 0)
        {
            int i;
            int nResults = 0;
            int maxIterations = 0;
            for (i = 0 ; i < PAR_Size() ; i++)
            {
                nResults += timesMsgs[i];
                maxIterations = (timesMsgs[i] > maxIterations ? timesMsgs[i]
                                 : maxIterations);
            }

            std::vector<double> finalQRes(nResults, 0.);
            std::vector<double> finalTimes(nResults, 0.);
            int index = 0;
            for (int j = 0 ; j < maxIterations ; j++)
            {
                int loc = 0;
                for (i = 0 ; i < PAR_Size() ; i++)
                {
                    if (timesMsgs[i] > j)
                    {
                        finalQRes[index]  = totalQRes[loc+j];
                        finalTimes[index] = totalTimes[loc+j];
                        index++;
                    }
                    loc += timesMsgs[i];
                }
            }
            qRes = finalQRes;
            times = finalTimes;
            delete [] totalQRes;
            delete [] qResMsgs;
            delete [] totalTimes;
            delete [] timesMsgs;
        }
        else
        {
            SetOutputDataTree(new avtDataTree());
            finalOutputCreated = true;
            return;
        }
    }

    if (qRes.size() == 0)
    {
        debug4 << "Query failed at all timesteps" << endl;
        avtCallback::IssueWarning("Query failed at all timesteps");
        avtDataTree_p dummy = new avtDataTree();
        SetOutputDataTree(dummy);
        return;
    }
    if (useTimeForXAxis && qRes.size()/nResultsToStore != times.size())
    {
        debug4 << "QueryOverTime ERROR, number of results ("
               << qRes.size() << ") does not equal number "
               << "of timesteps (" << times.size() << ")." << endl;
        avtCallback::IssueWarning(
            "\nQueryOverTime error, number of results does not equal "
            "number of timestates.  Curve being created may be missing "
            "some values.  Please contact a VisIt developer.");
    }
    else if (nResultsToStore > 1 && qRes.size() % nResultsToStore != 0)
    {
        debug4 << "QueryOverTime ERROR, number of results ("
               << qRes.size() << ") is not a multiple of " << nResultsToStore
               << "and therefore cannot generate x,y pairs." << endl;
        avtCallback::IssueWarning(
            "\nQueryOverTime error, number of results is incorrect.  "
            "Curve being created may be missing some values.  "
            "Please contact a VisIt developer.");
    }
    if (skippedTimes.size() != 0)
    {
        std::ostringstream osm;
        osm << "\nQueryOverTime (" << atts.GetQueryAtts().GetName().c_str()
            << ") experienced\n"
            << "problems with the following timesteps and \n"
            << "skipped them while generating the curve:\n   ";

        for (int j = 0; j < skippedTimes.size(); j++)
            osm << skippedTimes[j] << " ";
        osm << "\nLast message received: " << errorMessage.c_str() << ends;
        debug4 << osm.str() << endl;
        avtCallback::IssueWarning(osm.str().c_str());
    }

    stringVector vars = atts.GetQueryAtts().GetVariables();
    bool multiCurve = false;
    if (atts.GetQueryAtts().GetQueryInputParams().HasNumericEntry("curve_plot_type"))
    {
        multiCurve = (atts.GetQueryAtts().GetQueryInputParams().GetEntry("curve_plot_type")->ToInt() == 1);
    }
    avtDataTree_p tree = CreateTree(times, qRes, vars, multiCurve);
    SetOutputDataTree(tree);
    finalOutputCreated = true;
}