avtContract_p
avtLagrangianFilter::ModifyContract(avtContract_p in_contract)
{
    avtContract_p rv;
    const char *pipelineVariable = in_contract->GetDataRequest()->GetVariable();
    if (strncmp(pipelineVariable, "operators/Lagrangian", strlen("operators/Lagrangian")) == 0)
    {
        outVarName = pipelineVariable;
        const char *justTheVar = pipelineVariable + strlen("operators/Lagrangian");
        avtDataRequest_p dr = new avtDataRequest(in_contract->GetDataRequest(), justTheVar);
        rv = new avtContract(in_contract, dr);
    }
    else
    {
        rv = new avtContract(in_contract);
    }

    if (atts.GetYAxisSample() == LagrangianAttributes::Variable)
    {
        avtDataRequest_p in_dr = rv->GetDataRequest();
        avtDataRequest_p out_dr = new avtDataRequest(in_dr);
        out_dr->AddSecondaryVariable(atts.GetVariable().c_str());
        avtContract_p out_contract;
        out_contract = new avtContract(rv, out_dr);
        return avtPICSFilter::ModifyContract(out_contract);
    }
    else
        return avtPICSFilter::ModifyContract(rv);
}
void
avtOriginatingSource::InitPipeline(avtContract_p spec)
{
    if (!ArtificialPipeline())
    {
        if (!CanDoStreaming())
        {
            spec->NoStreaming();
        }

        //
        // Determine if the data specification is *all* of the data.  This is
        // important to things like facelists.
        //
        avtDataRequest_p data = spec->GetDataRequest();
        bool uad = data->GetSIL().UsesAllData();
        GetOutput()->GetInfo().GetValidity().SetUsingAllData(uad);
    
        bool uadom = data->GetSIL().UsesAllDomains();
        GetOutput()->GetInfo().GetValidity().SetUsingAllDomains(uadom);

        if (initializeProgressCallback != NULL &&
            streamingCheckFunction       != NULL)
        {
            //
            // Each filter is a stage, plus a stage to get the data.
            // With streaming, there are only calculate/send stages.
            //
            int nstages;
            if (streamingCheckFunction(streamingCheckFunctionArgs,spec))
            {
                nstages = 1;
                GetOutput()->GetInfo().GetValidity().SetWhetherStreaming(true);
            }
            else
            {
                int sourceStages = NumStagesForFetch(data);
                nstages = spec->GetNFilters() + sourceStages;
                GetOutput()->GetInfo().GetValidity().SetWhetherStreaming(false);
                if (numberOfExecutions > 1)
                    nstages *= numberOfExecutions;
            }
            bool shouldIssue = false;
            if (numberOfExecutions <= 1)
                shouldIssue = true;
            else if (numberOfExecutions > 1)
            {
                if (!haveIssuedProgress)
                {
                    shouldIssue = true;
                    haveIssuedProgress = true;
                }
            }
            if (shouldIssue)
                initializeProgressCallback(initializeProgressCallbackArgs,
                                           nstages);
        }
    }
}
avtContract_p
avtChannelCommFilter::ModifyContract(avtContract_p c)
{
    const char *meshname = c->GetDataRequest()->GetVariable()+strlen("operators/ChannelComm/");
    //avtDataRequest_p dr = new avtDataRequest(c->GetDataRequest(), meshname);
    ////dr->AddSecondaryVariable(atts.GetVelocity().c_str());
    avtDataRequest_p dr = new avtDataRequest(c->GetDataRequest(), atts.GetVelocity().c_str());
    return new avtContract(c, dr);
}
avtContract_p
avtStructuredChunkDataTreeIterator::ModifyContract(avtContract_p spec)
{
    downstreamRectilinearMeshOptimizations =
                                   spec->GetHaveRectilinearMeshOptimizations();
    downstreamCurvilinearMeshOptimizations =
                                   spec->GetHaveCurvilinearMeshOptimizations();
    downstreamGhostType =
                       spec->GetDataRequest()->GetDesiredGhostDataType();

    return spec;
}
示例#5
0
avtContract_p
avtDeformSphereGlyphFilter::ModifyContract(avtContract_p contract)
{
    //
    // Get the old contract.
    //
    avtDataRequest_p ds = contract->GetDataRequest();
    const char *primaryVariable = ds->GetVariable();

    //
    // Make a new one
    //
    avtDataRequest_p ndr = new avtDataRequest(ds);

    // If we're using the default variable, save its name
    if (atts.GetVar() == "Default")
    {
        var = primaryVariable;
    }
    else
    {
        var = atts.GetVar();
        ndr->AddSecondaryVariable(strdup(atts.GetVar().c_str()));
    }

    //
    // Create the new pipeline contract from the data request, and return
    //
    avtContract_p rv = new avtContract(contract, ndr);

    return rv;
}
示例#6
0
avtContract_p
avtContextFilter::ModifyContract(avtContract_p spec)
{
    avtDataRequest_p ds = spec->GetDataRequest();
    ds->AddSecondaryVariable(atts.GetContext().c_str());
    return spec;
}
void
avtConnectedComponentsFilter::InferVariableNameFromContract(avtContract_p c)
{
    avtDataRequest_p in_dr = c->GetDataRequest();

    bool foundIt = false;
    if (strncmp(in_dr->GetVariable(), "operators/ConnectedComponents/",
                strlen("operators/ConnectedComponents/")) == 0)
    {
        foundIt = true;
        varname = in_dr->GetVariable()+strlen("operators/ConnectedComponents/");
    }

    if (!foundIt)
    {
        std::vector<CharStrRef>   vars2nd = in_dr->GetSecondaryVariablesWithoutDuplicates();
        for (size_t i = 0 ; i < vars2nd.size() ; i++)
        if (strncmp(*(vars2nd[i]), "operators/ConnectedComponents/",
                    strlen("operators/ConnectedComponents/")) == 0)
        {
            foundIt = true;
            varname = *(vars2nd[i])+strlen("operators/ConnectedComponents/");
        }
    }

    if (!foundIt)
    {
        EXCEPTION1(VisItException, "Unable to determine variable name from contract");
    }
}
avtContract_p
avtMatvfExpression::ModifyContract(avtContract_p spec)
{
    // request post ghost material info, as long as we are not doing mir
    if( !spec->GetDataRequest()->MustDoMaterialInterfaceReconstruction() )
    {
        spec->GetDataRequest()->SetNeedPostGhostMaterialInfo(true);
        doPostGhost = true;
    }
    else
    {
        doPostGhost = false;
    }

    return spec;
}
LoadBalanceScheme
LoadBalancer::DetermineAppropriateScheme(avtContract_p input)
{

    //
    // See if we have already have decided.  If so, just return our cached
    // decision.
    //
    int index = input->GetPipelineIndex();
    const LBInfo &lbinfo = pipelineInfo[index];
    std::string dbname = lbinfo.db;
    avtDatabase *db = dbMap[dbname];

    avtDataRequest_p data = input->GetDataRequest();
    avtDatabaseMetaData *md = db->GetMetaData(db->GetMostRecentTimestep());
    string meshName;

    TRY
    {
        meshName = md->MeshForVar(data->GetVariable());
    }
    CATCHALL
    {
        // Probably a CMFE.
        return scheme;
    }
    ENDTRY;

    if (md->GetFormatCanDoDomainDecomposition())
        return LOAD_BALANCE_DBPLUGIN_DYNAMIC;

    const avtMeshMetaData *mmd = md->GetMesh(meshName);

    if (mmd && mmd->loadBalanceScheme != LOAD_BALANCE_UNKNOWN)
    {
        debug1 << "Default load balance scheme \""
               << LoadBalanceSchemeToString(scheme).c_str() << "\""
               << " being overridden in favor of \""
               << LoadBalanceSchemeToString(mmd->loadBalanceScheme).c_str() << "\""
               << " for mesh \"" << meshName.c_str() << "\"" << endl;
        return mmd->loadBalanceScheme;
    }

    return scheme;
}
示例#10
0
avtContract_p
avtMeshFilter::ModifyContract(avtContract_p spec)
{
    avtContract_p rv = new avtContract(spec);

    if (GetInput()->GetInfo().GetAttributes().GetTopologicalDimension() != 0)
    {
        rv->GetDataRequest()->TurnZoneNumbersOn();
    }
    else
    {
        std::string pointVar = atts.GetPointSizeVar();
        avtDataRequest_p dataRequest = spec->GetDataRequest();

        //
        // Find out if we REALLY need to add the secondary variable.
        //
        if (atts.GetPointSizeVarEnabled() && 
            pointVar != "default" &&
            pointVar != "\0" &&
            pointVar != dataRequest->GetVariable() &&
            !dataRequest->HasSecondaryVariable(pointVar.c_str()))
        {
            rv->GetDataRequest()->AddSecondaryVariable(pointVar.c_str());
            rv->SetCalculateVariableExtents(pointVar, true);
        }

        avtDataAttributes &data = GetInput()->GetInfo().GetAttributes();
        if (spec->GetDataRequest()->MayRequireZones() ||
            spec->GetDataRequest()->MayRequireNodes())
        {
            keepNodeZone = true;
            rv->GetDataRequest()->TurnNodeNumbersOn();
        }
        else
        {
            keepNodeZone = false;
        }
    }

    return rv;
}
avtContract_p
avtNMatsExpression::ModifyContract(avtContract_p spec)
{
    avtContract_p rv = 
                      avtSingleInputExpressionFilter::ModifyContract(spec);

    avtDataRequest_p ds = spec->GetDataRequest();
    ds->TurnZoneNumbersOn();

    return rv;
}
示例#12
0
avtContract_p
avtStreamlinePlot::EnhanceSpecification(avtContract_p in_contract)
{
    avtDataRequest_p in_dr = in_contract->GetDataRequest();
    const char *var = in_dr->GetVariable();
    avtDataRequest_p out_dr = new avtDataRequest(in_dr, "colorVar");
    out_dr->AddSecondaryVariable(var);
    out_dr->SetOriginalVariable(var);
    avtContract_p out_contract = new avtContract(in_contract, out_dr);
    return out_contract;
}
std::string
LoadBalancer::GetMeshName(avtContract_p input, int stateIndex)
{
    const LBInfo &lbinfo = pipelineInfo[input->GetPipelineIndex()];
    avtDatabase *db = dbMap[lbinfo.db];

    avtDataRequest_p data = input->GetDataRequest();
    avtDatabaseMetaData *md = db->GetMetaData(stateIndex);
    string meshName;

    TRY
    {
        meshName = md->MeshForVar(data->GetVariable());
    }
    CATCHALL
    {
    }
    ENDTRY

    return meshName;
}
示例#14
0
avtContract_p
avtIsovolumeFilter::ModifyContract(avtContract_p in_spec)
{
    avtContract_p spec = new avtContract(in_spec);

    const char *varname = NULL;
    if (atts.GetVariable() != "default")
        varname = atts.GetVariable().c_str();
    else
        varname = in_spec->GetDataRequest()->GetVariable();

    //
    // We will need the ghost zones so that we can interpolate along domain
    // boundaries and get no cracks in our isosurface.
    //
    avtDataAttributes &in_atts = GetInput()->GetInfo().GetAttributes();
    bool skipGhost = false;
    if (in_atts.ValidVariable(varname) &&
        in_atts.GetCentering(varname) == AVT_NODECENT)
        skipGhost = true;
    if (!skipGhost)
        spec->GetDataRequest()->SetDesiredGhostDataType(GHOST_ZONE_DATA);

    std::string iso_var(atts.GetVariable());
    if (iso_var == "default")
        iso_var = in_spec->GetDataRequest()->GetVariable();

    avtIntervalTree *it = GetMetaData()->GetDataExtents(iso_var.c_str());
    if (it != NULL)
    {
        double min = atts.GetLbound();
        double max = atts.GetUbound();
        std::vector<int> dl;
        it->GetElementsListFromRange(&min, &max, dl);
        spec->GetDataRequest()->GetRestriction()->RestrictDomains(dl);
    }

    return spec;
}
示例#15
0
avtContract_p
avtResampleFilter::ModifyContract(avtContract_p oldataRequest)
{
    //
    // Best copy constructor we have??
    //
    avtContract_p spec = new avtContract(oldataRequest,
                                         oldataRequest->GetDataRequest());

    //
    // First tell the file format reader that we are going to be doing a
    // resample selection.
    //
    avtResampleSelection *sel = new avtResampleSelection;
    int counts[3];
    counts[0] = atts.GetWidth();
    counts[1] = atts.GetHeight();
    counts[2] = atts.GetDepth();
    sel->SetCounts(counts);
    double starts[3];
    starts[0] = atts.GetMinX();
    starts[1] = atts.GetMinY();
    starts[2] = atts.GetMinZ();
    sel->SetStarts(starts);
    double stops[3];
    stops[0] = atts.GetMaxX();
    stops[1] = atts.GetMaxY();
    stops[2] = atts.GetMaxZ();
    sel->SetStops(stops);
    selID = spec->GetDataRequest()->AddDataSelection(sel);

    spec->NoStreaming();
    spec->SetHaveRectilinearMeshOptimizations(true);
    spec->GetDataRequest()->SetDesiredGhostDataType(NO_GHOST_DATA);
    if (atts.GetUseArbitrator())
    {
        if (atts.GetArbitratorVarName() != "default")
            spec->GetDataRequest()->
                     AddSecondaryVariable(atts.GetArbitratorVarName().c_str());
    }
    if (primaryVariable != NULL)
    {
        delete [] primaryVariable;
    }
    const char *pv = spec->GetDataRequest()->GetVariable();
    primaryVariable = new char[strlen(pv)+1];
    strcpy(primaryVariable, pv);
    return spec;
}
avtContract_p
avtExtremeValueAnalysisFilter::ModifyContract(avtContract_p in_contract)
{
    avtContract_p rv;
    if (strncmp(pipelineVariable, "operators/ExtremeValueAnalysis", strlen("operators/ExtremeValueAnalysis")) == 0)
    {
        outVarName = pipelineVariable;
        const char *justTheVar = pipelineVariable + strlen("operators/ExtremeValueAnalysis/");
        avtDataRequest_p dr = new avtDataRequest(in_contract->GetDataRequest(), justTheVar);
        rv = new avtContract(in_contract, dr);
    }
    else
    {
        rv = new avtContract(in_contract);
    }
    return rv;
}
avtContract_p
avtPeaksOverThresholdFilter::ModifyContract(avtContract_p in_contract)
{
    avtContract_p rv;
    if (strncmp(pipelineVariable, "operators/PeaksOverThreshold", strlen("operators/PeaksOverThreshold")) == 0)
    {
        outVarName = pipelineVariable;
        const char *justTheVar = pipelineVariable + strlen("operators/PeaksOverThreshold/");
        avtDataRequest_p dr = new avtDataRequest(in_contract->GetDataRequest(), justTheVar);
        rv = new avtContract(in_contract, dr);
    }
    else
    {
        rv = new avtContract(in_contract);
    }
    return rv;
}
示例#18
0
avtContract_p
avtModelBasedClusteringFilter::ModifyContract(avtContract_p in_contract)
{
    avtContract_p rv;
    if (strncmp(pipelineVariable, "operators/ModelBasedClustering", strlen("operators/ModelBasedClustering")) == 0)
    {
        outVarName = pipelineVariable;
        const char *justTheVar = pipelineVariable + strlen("operators/ModelBasedClustering/");
        avtDataRequest_p dr = new avtDataRequest(in_contract->GetDataRequest(), justTheVar);
        rv = new avtContract(in_contract, dr);
    }
    else
    {
        rv = new avtContract(in_contract);
    }
    return rv;
}
avtContract_p
avtLineoutFilter::ModifyContract(avtContract_p in_contract)
{
    avtContract_p rv;
    const char *opLineout = "operators/Lineout/";
    if (strncmp(pipelineVariable, opLineout, strlen(opLineout)) == 0)
    {
        const char *var = pipelineVariable + strlen(opLineout);
        avtDataRequest_p dr = new avtDataRequest(in_contract->GetDataRequest(), var);
        rv = new avtContract(in_contract, dr);
    }
    else
    {
        rv = new avtContract(in_contract);
    }

    useOriginalCells = false;
    if (!GetInput()->GetInfo().GetValidity().GetZonesPreserved())
    {
        rv->GetDataRequest()->TurnZoneNumbersOn();
        useOriginalCells = true;
        return rv;
    }

    //
    // Get the interval tree.
    //
    avtIntervalTree *it = GetMetaData()->GetSpatialExtents();
    if (it == NULL)
    {
        return rv;
    }

    double rayDir[3] = {point2[0]-point1[0], point2[1]-point1[1], 
                        point2[2]-point1[2]};   

    intVector domains;
    it->GetElementsList(point1, rayDir, domains);
    rv->GetDataRequest()->GetRestriction()->RestrictDomains(domains);

    return rv;
}
void
avtFluxFilter::InferVariableNameFromContract(avtContract_p c)
{
    avtDataRequest_p in_dr = c->GetDataRequest();

    bool foundIt = false;
    if (strncmp(in_dr->GetVariable(), "operators/Flux/",
                strlen("operators/Flux/")) == 0)
    {
        foundIt = true;
        if (atts.GetFlowField() == "default")
        {
             EXCEPTION1(VisItException, "You can't set the flow field as \"default\" "
                        "since the default field is not a vector.");
        }
        if (atts.GetWeight() && atts.GetWeightField() == "default")
        {
             EXCEPTION1(VisItException, "You can't set the weighting field as \"default\" "
                        "since that would lead to a recursive definition.");
        }
        varname = in_dr->GetVariable()+strlen("operators/Flux/");
    }

    if (!foundIt)
    {
        std::vector<CharStrRef>   vars2nd = in_dr->GetSecondaryVariablesWithoutDuplicates();
        for (size_t i = 0 ; i < vars2nd.size() ; i++)
        if (strncmp(*(vars2nd[i]), "operators/Flux/",
                    strlen("operators/Flux/")) == 0)
        {
            foundIt = true;
            varname = *(vars2nd[i])+strlen("operators/Flux/");
        }
    }

    if (!foundIt)
    {
        EXCEPTION1(VisItException, "Unable to determine variable name from contract");
    }
}
avtContract_p
avtApplyDataBinningExpression::ModifyContract(avtContract_p spec)
{
    if (theDataBinning == NULL)
    {
        // We should have failed before getting to this point...
        EXCEPTION2(ExpressionException, outputVariableName, 
                   "Could not locate the data binning.");
    }

    avtDataRequest_p ds = spec->GetDataRequest();
    avtDataRequest_p new_ds = new avtDataRequest(ds);
    avtDataBinningFunctionInfo *info = theDataBinning->GetFunctionInfo();
    int nVars = info->GetDomainNumberOfTuples();
    for (int i = 0 ; i < nVars ; i++)
        new_ds->AddSecondaryVariable(info->GetDomainTupleName(i).c_str());
    new_ds->AddSecondaryVariable(info->GetCodomainName().c_str());

    avtContract_p rv = new avtContract(spec, new_ds);
    rv = avtSingleInputExpressionFilter::ModifyContract(rv);
    return rv;
}
示例#22
0
avtContract_p
avtLabelPlot::EnhanceSpecification(avtContract_p spec)
{
    debug3 << "avtLabelPlot::EnhanceSpecification: 0" << endl;
    avtDataRequest_p ds = spec->GetDataRequest();

    //
    // The pipeline specification should really be const -- it is used
    // elsewhere, so we can't modify it and return it.  Make a copy and in
    // the new copy, indicate that we need structured indices.
    //
    avtDataRequest_p nds = new avtDataRequest(ds);
    nds->TurnZoneNumbersOn();
    nds->TurnNodeNumbersOn();
    nds->SetNeedStructuredIndices(true);
    nds->SetTransformVectorsDuringProject(false);
    avtContract_p rv = new avtContract(spec, nds);

    debug3 << "avtLabelPlot::EnhanceSpecification: 1" << endl;

    return rv;
}
avtContract_p
avtSurfaceFilter::ModifyContract(avtContract_p spec)
{
    double dataExtents[2];
    double spatialExtents[6];
    if (TryDataExtents(dataExtents))
    {
        avtDataset_p input = GetTypedInput();
        avtDatasetExaminer::GetSpatialExtents(input, spatialExtents);
        UnifyMinMax(spatialExtents,6);
        CalculateScaleValues(dataExtents, spatialExtents);
        stillNeedExtents = false;
    }
    else
    {
        spec->NoStreaming();
    }
    if (spec->GetDataRequest()->MayRequireZones()) 
    {
        spec->GetDataRequest()->TurnZoneNumbersOn();
    }
    if (spec->GetDataRequest()->MayRequireNodes()) 
    {
        spec->GetDataRequest()->TurnNodeNumbersOn();
    }

    //
    // We will need the ghost zones so that we can interpolate along domain
    // boundaries and get no cracks in our isosurface.
    //
    const char *varname = spec->GetDataRequest()->GetVariable();
    avtDataAttributes &in_atts = GetInput()->GetInfo().GetAttributes();
    bool skipGhost = false;
    if (in_atts.ValidVariable(varname) &&
        in_atts.GetCentering(varname) == AVT_NODECENT)
        skipGhost = true;
    if (!skipGhost)
        spec->GetDataRequest()->SetDesiredGhostDataType(GHOST_ZONE_DATA);

    return spec;
}
avtContract_p
avtMissingDataFilter::ModifyContract(avtContract_p c0)
{
    canDoCollectiveCommunication = ! c0->DoingOnDemandStreaming();

    // Store the contract.
    contract = new avtContract(c0);

    if (generateMode)
    {
        // Determine the list of variables that are missing data.
        stringVector varsMissingData(MissingDataVariables(contract->GetDataRequest(), &metadata));
        if(!varsMissingData.empty())
        {
            // Turn on both Nodes and Zones, to prevent another re-execution if
            // user switches between zone and node pick.
            contract->GetDataRequest()->TurnZoneNumbersOn();
            contract->GetDataRequest()->TurnNodeNumbersOn();
        }
    }

    // Return a copy of the modified contract.
    return new avtContract(contract);
}
void
avtDatasetToDatasetFilter::ExamineContract(avtContract_p s)
{
    avtDataRequest_p ds = s->GetDataRequest();

    // 
    // We need to know what the pipeline variable is so we can switch it
    // back when we are done.  It's also a nice thing to keep track of.
    // 
    if (pipelineVariable != NULL)
        delete[]pipelineVariable;

    const char *var = ds->GetVariable();
    pipelineVariable = new char[strlen(var) + 1];
    strcpy(pipelineVariable, var);

    if (switchVariables)
    {
        // 
        // Determine if the pipeline already knows if it needs the
        // active variable.
        // 
        bool    haveVariable = false;
        if (strcmp(activeVariable, pipelineVariable) == 0)
        {
            haveVariable = true;
        }
        const std::vector<CharStrRef> &var2nd = ds->GetSecondaryVariables();
        for (int i = 0; i < var2nd.size(); i++)
        {
            const char *v2 = *(var2nd[i]);
            if (strcmp(v2, activeVariable) == 0)
            {
                haveVariable = true;
            }
        }

        // 
        // Tell the pipeline about our active variable (if necessary) and
        // decide if we should remove the active variable when we are done.
        // 
        if (!haveVariable)
        {
            ds->AddSecondaryVariable(activeVariable);
            removeActiveVariableWhenDone = true;
            debug5 << GetType() << ": ExamineContract: Setting primary "
                   << "variable " << activeVariable 
                   << " to be removed at PostExecute." << endl;
        } else
        {
            removeActiveVariableWhenDone = false;
            debug5 << GetType() << ": ExamineContract: Leaving primary "
                   << "variable " << activeVariable 
                   << " where it is at PostExecute." << endl;
        }
    }

    // Iterate through the secondary variables.
    // Determine if the pipline already knows about each of them.
    for (int i = 0; i < secondaryVarList.size(); i++)
    {
        bool    haveVariable = false;

        if (strcmp(pipelineVariable, secondaryVarList[i]) == 0)
        {
            haveVariable = true;
        }

        const std::vector<CharStrRef> &var2nd = ds->GetSecondaryVariables();
        for (int j = 0; j < var2nd.size(); j++)
        {
            const char *v2 = *(var2nd[j]);
            if (strcmp(v2, secondaryVarList[i]) == 0)
                haveVariable = true;
        }

        if (!haveVariable)
        {
            ds->AddSecondaryVariable(secondaryVarList[i]);
            removeSecondaryVariable[i] = true;
            debug5 << GetType() << ": ExamineContract: Setting secondary "
                   << "variable " << secondaryVarList[i] 
                   << " to be removed at PostExecute." << endl;
        } else
        {
            removeSecondaryVariable[i] = false;
            debug5 << GetType() << ": ExamineContract: Leaving secondary "
                   << "variable " << secondaryVarList[i] 
                   << " where it is at PostExecute." << endl;
        }
    }
}
avtDataRequest_p
LoadBalancer::Reduce(avtContract_p input)
{
    avtDataRequest_p data = input->GetDataRequest();

    //
    // It is difficult for the load balancer to communicate with the originating
    // source because it is done through callbacks.
    // So we do it by setting a Boolean in the contract.  Since there is only
    // one path that involves actually doing data replication, and many that don't,
    // we will unset the Boolean now and reset it in the case we actually do
    // data replication.
    //

#ifdef PARALLEL
    // only used in parallel
    bool dataReplicationRequested = input->ReplicateSingleDomainOnAllProcessors();
#endif

    input->SetReplicateSingleDomainOnAllProcessors(false);

    //
    // Pipeline index 0 is reserved for meta-data.  It should already be
    // load balanced.
    //
    if (input->GetPipelineIndex() == 0)
    {
        return data;
    }

    //
    // Assess load balancing specially for serial engines.
    //
    if (nProcs <= 1)
    {
        bool doDynLB = CheckDynamicLoadBalancing(input);
        if (!doDynLB && scheme != LOAD_BALANCE_STREAM)
        {
            pipelineInfo[input->GetPipelineIndex()].complete = true;
            return data;
        }
        else
        {
            avtDataObjectSource::RegisterProgressCallback(NULL,NULL);
            avtSILRestriction_p orig_silr   = data->GetRestriction();
            avtSILRestriction_p silr        = new avtSILRestriction(orig_silr);
            avtDataRequest_p new_data =
                                          new avtDataRequest(data, silr);
            avtSILRestrictionTraverser trav(silr);

            vector<int> list;
            trav.GetDomainList(list);
    
            if (pipelineInfo[input->GetPipelineIndex()].current < 0)
                pipelineInfo[input->GetPipelineIndex()].current  = 0;
            int domain = list[pipelineInfo[input->GetPipelineIndex()].current];
            int sggDomain = avtStreamingGhostGenerator::LBGetNextDomain();
            if (sggDomain >= 0)
                domain = sggDomain;
            vector<int> domainList(1, domain);
            new_data->GetRestriction()
                                   ->RestrictDomainsForLoadBalance(domainList);
            UpdateProgress(pipelineInfo[input->GetPipelineIndex()].current,
                           (int)list.size());
            pipelineInfo[input->GetPipelineIndex()].current++;
            if (pipelineInfo[input->GetPipelineIndex()].current == (int)list.size())
                pipelineInfo[input->GetPipelineIndex()].complete = true;
            return new_data;
        }
    }

#ifdef PARALLEL

    avtSILRestriction_p orig_silr   = data->GetRestriction();
    avtSILRestriction_p silr        = new avtSILRestriction(orig_silr);
    avtDataRequest_p new_data = new avtDataRequest(data, silr);
    avtSILRestrictionTraverser trav(silr);

    // set up MPI message tags
    static int lastDomDoneMsg = GetUniqueMessageTag();
    static int newDomToDoMsg = GetUniqueMessageTag();

    // Make sure that we have domain to file mapping available.
    LBInfo &lbInfo(pipelineInfo[input->GetPipelineIndex()]);
    std::string meshName = GetMeshName(input, dbState[lbInfo.db]);
    GetIOInformation(lbInfo.db, dbState[lbInfo.db], meshName);

    if (scheme == LOAD_BALANCE_STREAM)
    {
        if (pipelineInfo[input->GetPipelineIndex()].current < 0)
        {
            pipelineInfo[input->GetPipelineIndex()].current = 0;

            //
            // We probably want to do something more sophisticated in the future 
            // (like walking through a SIL).  For now, just use the "chunks"
            // mechanism set up with convenience methods.
            //
            vector<int> list;
            trav.GetDomainList(list);

            int amountPer = list.size() / nProcs;
            int oneExtraUntil = list.size() % nProcs;
            int lastDomain = 0;
            for (int i = 0 ; i < nProcs ; i++)
            {
                if (i == rank)
                {
                    int amount = amountPer + (i < oneExtraUntil ? 1 : 0);
                    for (int j = 0 ; j < amount ; j++)
                    {
                        domainListForStreaming.push_back(list[j+lastDomain]);
                    }
                }
                lastDomain += amountPer + (i < oneExtraUntil ? 1 : 0);
            }
        }

        int domain = domainListForStreaming[pipelineInfo[input->GetPipelineIndex()].current];
        int sggDomain = avtStreamingGhostGenerator::LBGetNextDomain();
        if (sggDomain >= 0)
            domain = sggDomain;
        vector<int> domainList(1, domain);
        new_data->GetRestriction()
                               ->RestrictDomainsForLoadBalance(domainList);
        UpdateProgress(pipelineInfo[input->GetPipelineIndex()].current,
                       domainListForStreaming.size());
        pipelineInfo[input->GetPipelineIndex()].current++;
        if (pipelineInfo[input->GetPipelineIndex()].current == (int)domainListForStreaming.size())
        {
            pipelineInfo[input->GetPipelineIndex()].complete = true;
            domainListForStreaming.clear();
        }
    }
    // Can we do dynamic load balancing?
    else if (! CheckDynamicLoadBalancing(input))
    {
        //
        // We probably want to do something more sophisticated in the future 
        // (like walking through a SIL).  For now, just use the "chunks"
        // mechanism set up with convenience methods.
        //
        vector<int> list;
        vector<int> mylist;
        trav.GetDomainList(list);

        if (dataReplicationRequested && list.size() == 1)
        {
            silr->RestrictDomainsForLoadBalance(list);
            pipelineInfo[input->GetPipelineIndex()].complete = true;

            // Communicate back to the pipeline that we are replicating.
            input->SetReplicateSingleDomainOnAllProcessors(true);

            return data;
        }

        //
        // For variables (including meshes) that require specific types of
        // load balancing, we override the scheme here
        //
        LoadBalanceScheme theScheme = DetermineAppropriateScheme(input);

        if (theScheme == LOAD_BALANCE_CONTIGUOUS_BLOCKS_TOGETHER)
        {
            int amountPer = list.size() / nProcs;
            int oneExtraUntil = list.size() % nProcs;
            int lastDomain = 0;
            for (int i = 0 ; i < nProcs ; i++)
            {
                if (i == rank)
                {
                    int amount = amountPer + (i < oneExtraUntil ? 1 : 0);
                    for (int j = 0 ; j < amount ; j++)
                    {
                        mylist.push_back(list[j+lastDomain]);
                    }
                }
                lastDomain += amountPer + (i < oneExtraUntil ? 1 : 0);
            }
        }
        else if (theScheme == LOAD_BALANCE_STRIDE_ACROSS_BLOCKS)
        {
            for (size_t j = 0 ; j < list.size() ; j++)
            {
                if (j % nProcs == (size_t)rank)
                    mylist.push_back(list[j]);
            }
        }
        else if (theScheme == LOAD_BALANCE_ABSOLUTE)
        {
            for (size_t j = 0 ; j < list.size() ; j++)
            {
                if (list[j] % nProcs == rank)
                    mylist.push_back(list[j]);
            }
        }
        else if (theScheme == LOAD_BALANCE_RESTRICTED)
        {
            LBInfo &lbInfo(pipelineInfo[input->GetPipelineIndex()]);
            IOInfo &ioInfo(ioMap[lbInfo.db]);
            const HintList &hints(ioInfo.ioInfo.GetHints());

            for (size_t j = 0 ; j < list.size() ; j++)
            {
                if (hints.size() >= (size_t)rank)
                {
                    const vector<int> &doms = hints[rank];
                    int ndoms = doms.size();
                    for (int h=0; h<ndoms; h++)
                    {
                        if (doms[h] == list[j])
                        {
                            mylist.push_back(list[j]);
                            break;
                        }
                    }
                }
            }
        }
        else if (theScheme == LOAD_BALANCE_RANDOM_ASSIGNMENT)
        {
            // all procs randomly jumble the list of domain ids
            // all procs compute same jumbled list due to same seed
            // [ which won't be true on a heterogeneous platform ]
            size_t j;
            vector<int> jumbledList = list;
            srand(0xDeadBeef);
            for (j = 0 ; j < list.size() * 5; j++)
            {
               int i1 = rand() % list.size();
               int i2 = rand() % list.size();
               int tmp = jumbledList[i1];
               jumbledList[i1] = jumbledList[i2];
               jumbledList[i2] = tmp;
            }
            // now, do round-robin assignment from the jumbled list
            for (j = 0 ; j < list.size() ; j++)
            {
                if (j % nProcs == (size_t)rank)
                    mylist.push_back(jumbledList[j]);
            }
        }
        else if (theScheme == LOAD_BALANCE_DBPLUGIN_DYNAMIC)
        {
            // Every processor gets the complete list
            mylist = list;
        }

        silr->RestrictDomainsForLoadBalance(mylist);
        pipelineInfo[input->GetPipelineIndex()].complete = true;
    }
    else
    {
        // disable progress updates from the filters this time around
        avtDataObjectSource::RegisterProgressCallback(NULL,NULL);

        LBInfo &lbInfo(pipelineInfo[input->GetPipelineIndex()]);
        IOInfo &ioInfo(ioMap[lbInfo.db]);
        if (rank == 0)
        {
            // -------------------------------------
            //     MASTER LOADBALANCER PROCESSES
            // -------------------------------------

            // Allocate enough space to hold the completed domains
            ioInfo.domains.resize(nProcs);
            ioInfo.files.resize(nProcs);
            bool validFileMap = (ioInfo.fileMap.size() != 0);

            // Get the list of domains to process
            vector<int> domainList;
            trav.GetDomainList(domainList);

            // Make a work list and a completed list
            size_t         totaldomains = domainList.size();
            deque<int>  incomplete(domainList.begin(), domainList.end());
            vector<int> complete;

            debug5 << "LoadBalancer Master -- starting with " 
                   << incomplete.size() << " domains\n";

            // pull from the incomplete list and push onto the complete list
            // until all domains are complete
            bool abort = false;
            int domain;
            UpdateProgress(0,0);
            while (complete.size() < totaldomains)
            {
                // check for an abort
                if (!abort &&
                    CheckAbort(false))
                {
                    abort = true;
                    totaldomains -= incomplete.size();
                    incomplete.clear();
                }

                // update the progress
                UpdateProgress(complete.size() + (domainList.size() - incomplete.size()),
                               domainList.size()*2);


                // get the completed domain number
                MPI_Status stat;
                MPI_Recv(&domain, 1, MPI_INT, MPI_ANY_SOURCE,
                         lastDomDoneMsg, VISIT_MPI_COMM, &stat);
                int processor = stat.MPI_SOURCE;

                // -1 means the first pass by the slave; nothing completed yet
                if (domain != -1)
                {
                    // add it to the complete list
                    complete.push_back(domain);
                }

                // figure out what to tell this processor to do
                if (incomplete.empty())
                    continue;

                // find a cached domain for next processor
                deque<int>::iterator i;
                for (i = incomplete.begin(); i != incomplete.end(); i++)
                {
                    if (ioInfo.domains[processor].find(*i) != 
                        ioInfo.domains[processor].end())
                        break;
                }
                // if no match, try to find one that is in a file
                // already opened by this processor
                if (i == incomplete.end())
                {
                    for (i = incomplete.begin(); i != incomplete.end(); i++)
                    {
                        int fileno = 0;
                        if (validFileMap)
                            fileno = ioInfo.fileMap[*i];
                        if (ioInfo.files[processor].count(fileno) > 0)
                            break;
                    }
                }
                // if still no match, find one that is in a file
                // opened by the fewest number of processors
                if (i == incomplete.end())
                {
                    int mindomain = -1;
                    int minopen   = 999999999;
                    for (i = incomplete.begin(); i != incomplete.end(); i++)
                    {
                        int fileno = 0;
                        if (validFileMap)
                            fileno = ioInfo.fileMap[*i];
                        // count the number of processors which have
                        // this file opened
                        int nopen = 0;
                        for (size_t j=0; j<ioInfo.files.size(); j++)
                            if (ioInfo.files[j].count(fileno) > 0)
                                nopen++;
                        if (nopen < minopen)
                        {
                            mindomain = *i;
                            minopen   = nopen;
                        }
                    }
                    for (i = incomplete.begin(); i != incomplete.end(); i++)
                    {
                        if (*i == mindomain)
                            break;
                    }
                }                    

                // if no match, just take the next one in line
                if (i == incomplete.end())
                    i=incomplete.begin();

                domain = *i;
                incomplete.erase(i);

                ioInfo.domains[processor].insert(domain);
                if (validFileMap)
                    ioInfo.files[processor].insert(ioInfo.fileMap[domain]);
                else
                    ioInfo.files[processor].insert(0);

                // send the new domain number to that processor
                debug5 << "LoadBalancer Master: sending domain " 
                       << domain << " to processor "<<processor<<"\n";
                MPI_Send(&domain, 1, MPI_INT, processor, newDomToDoMsg, VISIT_MPI_COMM);
            }

            // we're all done -- -2 means to abort, -1 means to send results
            int status = abort ? -2 : -1;
            for (int i=1; i<nProcs; i++)
                MPI_Send(&status, 1, MPI_INT, i, newDomToDoMsg,VISIT_MPI_COMM);

            if (abort)
                EXCEPTION0(AbortException);

            // all work is done
            UpdateProgress(1,0);
            lbInfo.complete = true;
            new_data->GetRestriction()->TurnOffAll();
            MPI_Barrier(VISIT_MPI_COMM);
        }
        else
        {
            // -------------------------------------
            //            SLAVE PROCESSES
            // -------------------------------------

            // send our last completed domain to the master
            int domain = lbInfo.current;
            MPI_Send(&domain, 1, MPI_INT, 0, lastDomDoneMsg, VISIT_MPI_COMM);

            // get our new work unit
            MPI_Status stat;
            MPI_Recv(&domain, 1, MPI_INT, 0, newDomToDoMsg, VISIT_MPI_COMM, &stat);
            lbInfo.current = domain;

            if (domain == -2)
            {
                EXCEPTION0(AbortException);
            }
            else if (domain == -1)
            {
                //  -1 is a tag for "no work" -- we are all done
                lbInfo.complete = true;
                new_data->GetRestriction()->TurnOffAll();
                MPI_Barrier(VISIT_MPI_COMM);
            }
            else
            {
                vector<int> domainList(1, domain);
                new_data->GetRestriction()
                                   ->RestrictDomainsForLoadBalance(domainList);
            }
        }
    }

    // By intersecting with the original restriction, we will ensure that
    // we are catching restrictions beyond domains, like materials, etc.
    // See comments in SIL restriction code regarding 'FastIntersect'.
    new_data->GetRestriction()->FastIntersect(orig_silr);

    return new_data;
#else
    EXCEPTION1(VisItException, "nprocs was > 1 in a non-parallel code");
#endif

}
bool
LoadBalancer::CheckDynamicLoadBalancing(avtContract_p input)
{
    //
    // See if we have already have decided.  If so, just return our cached
    // decision.
    //
    int index = input->GetPipelineIndex();
    LBInfo &lbinfo = pipelineInfo[index];
    if (lbinfo.haveInitializedDLB)
        return lbinfo.doDLB;

    //
    // If the user has not explicitly asked for DLB, then don't do it.
    //
    if (!allowDynamic)
    {
        // Almost always false.
        lbinfo.doDLB = false || (scheme == LOAD_BALANCE_STREAM);
        lbinfo.haveInitializedDLB = true;
        return lbinfo.doDLB;
    }

    //
    // Some hard and fast rules:
    //
    // Pipeline index 0 is reserved for meta-data and inlined pipelines.  So
    // no DLB for those.
    //
    // Cannot dynamic load balance some pipelines because of the filters
    // in the pipeline.
    //
    // We cannot do dynamic load balancing if the database does not believe
    // we can do dynamic load balancing (for example because we need ghost
    // data communicated or materials reconstructed).
    //
    avtDataRequest_p data = input->GetDataRequest();
    std::string dbname = lbinfo.db;
    avtDatabase *db = dbMap[dbname];
    if (input->GetPipelineIndex() == 0 ||
        input->ShouldUseStreaming() == false || 
        db->CanDoStreaming(data) == false)
    {
        lbinfo.doDLB = false;
        lbinfo.haveInitializedDLB = true;
        return false;
    }

    //
    // Don't do DLB if we have 2 or 3 procs.  It's not worth it.
    //
    if (nProcs == 2 || nProcs == 3)
    {
        lbinfo.doDLB = false;
        lbinfo.haveInitializedDLB = true;
        return false;
    }

    //
    // The user has asked for DLB.  And nothing in the pipeline is prevent it.
    // Do it!
    //
    lbinfo.doDLB = true;
    lbinfo.haveInitializedDLB = true;
    return true;
}
avtContract_p
avtPseudocolorFilter::ModifyContract(avtContract_p contract)
{
    avtContract_p rv = contract;

    avtDataAttributes &data = GetInput()->GetInfo().GetAttributes();

    int topoDim = data.GetTopologicalDimension();

    std::string pointVar   = plotAtts.GetPointSizeVar();
    std::string radiusVar    = plotAtts.GetTubeRadiusVar();
    std::string opacityVar = plotAtts.GetOpacityVariable();

    avtDataRequest_p dataRequest = new avtDataRequest(
                                       contract->GetDataRequest());

    primaryVar = dataRequest->GetVariable();

    // ARS - FIX ME - Why AddSecondaryVariable here and not in
    // avtPseudocolorPlot::EnhanceSpecification

    //
    // Find out if we need to add a secondary variable.
    //
    if( (topoDim == 0 || (topoDim > 0 && plotAtts.GetRenderPoints())) &&
        plotAtts.GetPointType() != PseudocolorAttributes::Point &&
        plotAtts.GetPointType() != PseudocolorAttributes::Sphere &&
        plotAtts.GetPointSizeVarEnabled() && 
        pointVar != "default" &&
        pointVar != "\0" &&
        pointVar != primaryVar &&
        !dataRequest->HasSecondaryVariable(pointVar.c_str()))
    {
        rv->GetDataRequest()->AddSecondaryVariable(pointVar.c_str());
        rv->SetCalculateVariableExtents(pointVar, true);
    }

    if( (topoDim == 1 || (topoDim > 1 && plotAtts.GetRenderWireframe())) &&
        plotAtts.GetLineType() == PseudocolorAttributes::Tube && 
        plotAtts.GetTubeRadiusVarEnabled() &&
        radiusVar != "default" &&
        radiusVar != "\0" &&
        radiusVar != primaryVar &&
        !dataRequest->HasSecondaryVariable(radiusVar.c_str()))
    {
        rv->GetDataRequest()->AddSecondaryVariable(radiusVar.c_str());
        rv->SetCalculateVariableExtents(radiusVar, true);
    }

    if (plotAtts.GetOpacityType() == PseudocolorAttributes::VariableRange &&
        opacityVar != "default" &&
        opacityVar != "\0" &&
        opacityVar != primaryVar &&
        !dataRequest->HasSecondaryVariable(opacityVar.c_str()))
    {
        rv->GetDataRequest()->AddSecondaryVariable(opacityVar.c_str());
        rv->SetCalculateVariableExtents(opacityVar, true);
    }

    // Note the line type so that upstream operators can obtain the
    // needed data for displaying ribbons or tubes.
    std::string key =
      rv->SetAttribute( &plotAtts, PseudocolorAttributes::ID_lineType,
                        PseudocolorAttributes::LineType_ToString(plotAtts.GetLineType()) );

    if (contract->GetDataRequest()->MayRequireZones() ||
        contract->GetDataRequest()->MayRequireNodes())
    {
        keepNodeZone = true;

        if (data.ValidActiveVariable())
        {
            if (data.GetCentering() == AVT_NODECENT)
            {
                rv->GetDataRequest()->TurnNodeNumbersOn();
            }
            else if (data.GetCentering() == AVT_ZONECENT)
            {
                rv->GetDataRequest()->TurnZoneNumbersOn();
            }
        }
        else 
        {
            // canot determine variable centering, so turn on both
            // node numbers and zone numbers.
            rv->GetDataRequest()->TurnNodeNumbersOn();
            rv->GetDataRequest()->TurnZoneNumbersOn();
        }
    }
    else
    {
        keepNodeZone = false;
    }

    return rv;
}
示例#29
0
avtContract_p
avtDataBinningFilter::ModifyContract(avtContract_p inContract)
{
    bool defaultVarOK = true;
    if (strncmp(pipelineVariable, "operators/DataBinning", strlen("operators/DataBinning")) == 0)
    {
        defaultVarOK = false;
        varname = pipelineVariable;
    }

    const char *dim1Var = atts.GetDim1Var().c_str();
    if (atts.GetDim1BinBasedOn() == DataBinningAttributes::Variable)
    {
        if (strcmp(dim1Var, "default") == 0)
        {    
            if (defaultVarOK)
                dim1Var = pipelineVariable;
            else
            {
                EXCEPTION1(VisItException, "You specified the first dimension of the "
                                   "data binning as \"default\", but your plotting variable "
                                   "(which \"default\" resolves to) is of the output of the "
                                   "data binning.  This is a recursion definition.  Please "
                                   "change the first dimension of the data binning to be "
                                   "something besides \"default\".");
            }
        }
    }

    const char *dim2Var = atts.GetDim2Var().c_str();
    if (atts.GetDim2BinBasedOn() == DataBinningAttributes::Variable)
    {
        if (strcmp(dim2Var, "default") == 0 && 
            (atts.GetNumDimensions() == DataBinningAttributes::Two || 
             atts.GetNumDimensions() == DataBinningAttributes::Three))
        {    
            if (defaultVarOK)
                dim2Var = pipelineVariable;
            else
            {
                EXCEPTION1(VisItException, "You specified the second dimension of the "
                                   "data binning as \"default\", but your plotting variable "
                                   "(which \"default\" resolves to) is of the output of the "
                                   "data binning.  This is a recursion definition.  Please "
                                   "change the first dimension of the data binning to be "
                                   "something besides \"default\".");
            }
        }
    }

    const char *dim3Var = atts.GetDim3Var().c_str();
    if (atts.GetDim3BinBasedOn() == DataBinningAttributes::Variable)
    {
        if (strcmp(dim3Var, "default") == 0 && 
            atts.GetNumDimensions() == DataBinningAttributes::Three)
        {    
            if (defaultVarOK)
                dim3Var = pipelineVariable;
            else
            {
                EXCEPTION1(VisItException, "You specified the third dimension of the "
                                   "data binning as \"default\", but your plotting variable "
                                   "(which \"default\" resolves to) is of the output of the "
                                   "data binning.  This is a recursion definition.  Please "
                                   "change the first dimension of the data binning to be "
                                   "something besides \"default\".");
            }
        }
    }

    avtDataRequest_p in_dr  = inContract->GetDataRequest();
    avtDataRequest_p out_dr;
    avtDataAttributes &inAtts   = GetInput()->GetInfo().GetAttributes();
    if (strncmp(in_dr->GetVariable(), "operators/DataBinning", strlen("operators/DataBinning")) == 0)
        out_dr = new avtDataRequest(in_dr, inAtts.GetMeshname().c_str());
    else
        out_dr = new avtDataRequest(in_dr);
    std::vector<CharStrRef>   vars2nd = in_dr->GetSecondaryVariablesWithoutDuplicates();
    std::vector<std::string>  removeMe;
    int  i;
    for (i = 0 ; i < vars2nd.size() ; i++)
        if (strncmp(*(vars2nd[i]), "operators/DataBinning", strlen("operators/DataBinning")) == 0)
        {
            varname = *(vars2nd[i]);
            removeMe.push_back(*(vars2nd[i]));
        }
    for (i = 0 ; i < removeMe.size() ; i++)
        out_dr->RemoveSecondaryVariable(removeMe[i].c_str());

    if (atts.GetDim1BinBasedOn() == DataBinningAttributes::Variable)
        out_dr->AddSecondaryVariable(dim1Var);
    if ((atts.GetNumDimensions() == DataBinningAttributes::Two || 
        atts.GetNumDimensions() == DataBinningAttributes::Three)
        && (atts.GetDim2BinBasedOn() == DataBinningAttributes::Variable))
        out_dr->AddSecondaryVariable(dim2Var);
    if ((atts.GetNumDimensions() == DataBinningAttributes::Three)
        && (atts.GetDim3BinBasedOn() == DataBinningAttributes::Variable))
        out_dr->AddSecondaryVariable(dim3Var);
    if (atts.GetReductionOperator() != DataBinningAttributes::PDF && 
        atts.GetReductionOperator() != DataBinningAttributes::Count)
    {
        if (atts.GetVarForReduction() == "default")
        {
            if (defaultVarOK)
                out_dr->AddSecondaryVariable(pipelineVariable);
            else
            {
                EXCEPTION1(VisItException, "You specified the variable for the reduction operator of your "
                               "data binning as \"default\", but your plotting variable "
                               "(which \"default\" resolves to) is of the output of the "
                               "data binning.  This is a recursion definition.  Please "
                               "change the first dimension of the data binning to be "
                               "something besides \"default\".");
            }
        }
        else
            out_dr->AddSecondaryVariable(atts.GetVarForReduction().c_str());
    }

    //
    // Calculate the "original" extents.  If we clip away part of the volume, we don't
    // want the extents bouncing all around because certain regions aren't contributing.
    //
    avtContract_p rv = new avtContract(inContract, out_dr);
    if (! atts.GetDim1SpecifyRange() && dim1Var != pipelineVariable
        && atts.GetDim1BinBasedOn() == DataBinningAttributes::Variable)
        rv->SetCalculateVariableExtents(dim1Var, true);
    if ((! atts.GetDim2SpecifyRange()) && (atts.GetNumDimensions() == DataBinningAttributes::Two ||
                                         atts.GetNumDimensions() == DataBinningAttributes::Three)
         && (dim2Var != pipelineVariable)
         && (atts.GetDim2BinBasedOn() == DataBinningAttributes::Variable))
        rv->SetCalculateVariableExtents(dim2Var, true);
    if ((! atts.GetDim3SpecifyRange()) && atts.GetNumDimensions() == DataBinningAttributes::Three
         && (dim2Var != pipelineVariable)
         && (atts.GetDim3BinBasedOn() == DataBinningAttributes::Variable))
        rv->SetCalculateVariableExtents(dim3Var, true);

    int numSpatialDimensions = 0;
    if ((atts.GetDim1BinBasedOn() != DataBinningAttributes::Variable) &&
        (! atts.GetDim1SpecifyRange()))
        numSpatialDimensions++;
    if ((atts.GetDim2BinBasedOn() != DataBinningAttributes::Variable) 
        && (! atts.GetDim2SpecifyRange()) 
        && (atts.GetNumDimensions() == DataBinningAttributes::Two ||
            atts.GetNumDimensions() == DataBinningAttributes::Three))
        numSpatialDimensions++;
    if ((atts.GetDim3BinBasedOn() != DataBinningAttributes::Variable) 
        && (! atts.GetDim3SpecifyRange()) 
        && (atts.GetNumDimensions() == DataBinningAttributes::Three))
        numSpatialDimensions++;

    if (numSpatialDimensions > 0)
        rv->SetCalculateMeshExtents(true);
    
    lastContract = rv;

    return rv;
}
avtContract_p
avtVolumeFilter::ModifyContract(avtContract_p contract)
{
    avtContract_p newcontract = NULL;

    if (primaryVariable != NULL)
    {
        delete [] primaryVariable;
    }

    avtDataRequest_p ds = new avtDataRequest(contract->GetDataRequest());
    const char *var = ds->GetVariable();

    bool setupExpr = false;
    char exprDef[128];
    std::string exprName = (std::string)"_expr_" + (std::string)var;

    if (atts.GetScaling() == VolumeAttributes::Linear)
    {
#ifdef HAVE_LIBSLIVR
        if ((atts.GetRendererType() == VolumeAttributes::RayCastingSLIVR) ||
            ((atts.GetRendererType() == VolumeAttributes::RayCasting) && (atts.GetSampling() == VolumeAttributes::Trilinear)))
            ds->SetDesiredGhostDataType(GHOST_ZONE_DATA);
#endif
        newcontract = new avtContract(contract, ds);
        primaryVariable = new char[strlen(var)+1];
        strcpy(primaryVariable, var);
    }
    else if (atts.GetScaling() == VolumeAttributes::Log)
    {
        setupExpr = true;
        if (atts.GetUseColorVarMin())
        {
            char m[16];
            SNPRINTF(m, 16, "%f", atts.GetColorVarMin());
            SNPRINTF(exprDef, 128, "log10withmin(<%s>, %s)", var, m);
        }
        else
        {
            SNPRINTF(exprDef, 128, "log10(<%s>)", var);
        }
        avtDataRequest_p nds = new avtDataRequest(exprName.c_str(),
                               ds->GetTimestep(), ds->GetRestriction());
        nds->AddSecondaryVariable(var);
#ifdef HAVE_LIBSLIVR
        if ((atts.GetRendererType() == VolumeAttributes::RayCastingSLIVR) ||
            ((atts.GetRendererType() == VolumeAttributes::RayCasting) && (atts.GetSampling() == VolumeAttributes::Trilinear)))
            nds->SetDesiredGhostDataType(GHOST_ZONE_DATA);
#endif
        newcontract = new avtContract(contract, nds);
        primaryVariable = new char[exprName.size()+1];
        strcpy(primaryVariable, exprName.c_str());
    }
    else // VolumeAttributes::Skew)
    {
        setupExpr = true;
        SNPRINTF(exprDef, 128, "var_skew(<%s>, %f)", var,
                 atts.GetSkewFactor());
        avtDataRequest_p nds =
            new avtDataRequest(exprName.c_str(),
                               ds->GetTimestep(), ds->GetRestriction());
        nds->AddSecondaryVariable(var);
#ifdef HAVE_LIBSLIVR
        if ((atts.GetRendererType() == VolumeAttributes::RayCastingSLIVR) ||
            ((atts.GetRendererType() == VolumeAttributes::RayCasting) && (atts.GetSampling() == VolumeAttributes::Trilinear)))
            nds->SetDesiredGhostDataType(GHOST_ZONE_DATA);
#endif
        newcontract = new avtContract(contract, nds);
        primaryVariable = new char[strlen(exprName.c_str())+1];
        strcpy(primaryVariable, exprName.c_str());
    }

    if (setupExpr)
    {
        ExpressionList *elist = ParsingExprList::Instance()->GetList();
        Expression *e = NULL;
        for (int i = 0 ; i < elist->GetNumExpressions() ; i++)
        {
            if (elist->GetExpressions(i).GetName() == exprName)
            {
                e = &(elist->GetExpressions(i));
                break;
            }
        }
        bool shouldDelete = false;
        if (e == NULL)
        {
            e = new Expression();
            shouldDelete = true;
        }

        e->SetName(exprName.c_str());
        e->SetDefinition(exprDef);
        e->SetType(Expression::ScalarMeshVar);
        elist->AddExpressions(*e);
        if (shouldDelete)
            delete e;
    }

    newcontract->NoStreaming();
    newcontract->SetHaveRectilinearMeshOptimizations(true);
    return newcontract;
}