void
avtTimeIteratorDataTreeIteratorExpression::InternalProcessDataTree(
                                                    avtDataTree_p tree, int ts)
{
    if (*tree == NULL)
    {
        return;
    }

    int nc = tree->GetNChildren();

    if (nc <= 0 && !tree->HasData())
    {
        return;
    }

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = tree->GetDataRepresentation().GetDataVTK();
        PrepareAndExecuteDataset(in_ds, ts);
    }
    else
    {
        for (int j = 0; j < nc; j++)
            if (tree->ChildIsPresent(j))
                InternalProcessDataTree(tree->GetChild(j), ts);
    }
}
void
avtSIMODataTreeIterator::Execute(avtDataTree_p inDT, avtDataTree_p &outDT)
{
    CheckAbort();

    if (*inDT == NULL)
    {
        return;
    }

    int nc = inDT->GetNChildren();

    if (nc <= 0 && !inDT->HasData())
    {
        return;
    }

    if (nc == 0)
    {
        SIMOWorkItem *work = new SIMOWorkItem;
        work->This  = this;
        work->inDT  = inDT;
        work->outDT = outDT;
 
        if( *outDT )
        {
            // Schedule the work to be done.
            avtExecutionManagerScheduleWork(ExecuteDataTreeOnThread, (void *)work);
        }
        else
        {
            // There is only one dataset to process, so do it now.
            outDT = new avtDataTree();
            work->outDT = outDT;
            ExecuteDataTreeOnThread(work);
        }
    }
    else
    {
        //
        // there is more than one input dataset to process
        // and we need an output datatree for each
        //
        avtDataTree_p *localOutDT = new avtDataTree_p[nc];
        for (int j = 0; j < nc; j++)
        {
            if (inDT->ChildIsPresent(j))
            {
                localOutDT[j].SetReference( new avtDataTree );
                Execute(inDT->GetChild(j), localOutDT[j]);
            }
            else
            {
                localOutDT[j] = NULL;
            }
        }
        outDT = new avtDataTree(nc, localOutDT);
        delete [] localOutDT;
    }
}
void
avtSIMODataTreeIterator::UpdateExtents(avtDataTree_p tree)
{
    if (*tree == NULL)
    {
        return;
    }

    if (overrideOriginalSpatialExtents)
    {
        avtDataAttributes &outAtts = GetOutput()->GetInfo().GetAttributes();
        if (originalSpatialExtents == NULL)
        {
            avtDataAttributes &atts = GetInput()->GetInfo().GetAttributes();
            avtExtents        *exts = atts.GetThisProcsOriginalSpatialExtents();
            originalSpatialExtents = new avtExtents(exts->GetDimension());
        }
        double bounds[6];
        bool gotBounds = false;
        struct {double *se; const double *xform;} info = {bounds,NULL};
        tree->Traverse(CGetSpatialExtents, (void *)&info, gotBounds);
        if (gotBounds)
        {
            originalSpatialExtents->Merge(bounds);
            avtExtents *exts = outAtts.GetThisProcsOriginalSpatialExtents();
            *exts = *originalSpatialExtents;
        }
        outAtts.GetOriginalSpatialExtents()->Clear();
    }

    if (overrideOriginalDataExtents)
    {
        avtDataAttributes &outAtts = GetOutput()->GetInfo().GetAttributes();
        if (originalDataExtents == NULL)
        {
            originalDataExtents = new avtExtents(1);
        }
        double range[2];  // who has more than 25 vars?
        bool gotBounds = false;
        tree->Traverse(CGetDataExtents, (void *) range, gotBounds);
        if (gotBounds)
        {
            originalDataExtents->Merge(range);
            avtExtents *exts = outAtts.GetThisProcsOriginalDataExtents();
            *exts = *originalDataExtents;
        }
        outAtts.GetOriginalDataExtents()->Clear();
    }
}
avtDataTree_p
avtTimeIteratorDataTreeIteratorExpression::ConstructOutput(avtDataTree_p t)
{
    if (*t == NULL)
    {
        return NULL;
    }

    int nc = t->GetNChildren();

    if (nc <= 0 && !t->HasData())
    {
        return NULL;
    }

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = t->GetDataRepresentation().GetDataVTK();
        vtkDataSet *new_ds = in_ds->NewInstance();
        new_ds->ShallowCopy(in_ds);
        vtkDataArray *final_arr = 
                        ConvertIntermediateArrayToFinalArray(vars[arrayIndex]);
        vars[arrayIndex]->Delete();
        arrayIndex++;
        if (IsPointVariable())
            new_ds->GetPointData()->AddArray(final_arr);
        else
            new_ds->GetCellData()->AddArray(final_arr);
        final_arr->Delete();
        avtDataTree_p rv = new avtDataTree(new_ds,
                                   t->GetDataRepresentation().GetDomain(),
                                   t->GetDataRepresentation().GetLabel());
        new_ds->Delete();
        return rv;
    }
    else
    {
        // there is more than one input dataset to process
        // and we need an output datatree for each
        //
        avtDataTree_p *outDT = new avtDataTree_p[nc];
        for (int j = 0; j < nc; j++)
        {
            if (t->ChildIsPresent(j))
            {
                outDT[j] = ConstructOutput(t->GetChild(j));
            }
            else
            {
                outDT[j] = NULL;
            }
        }
        avtDataTree_p rv = new avtDataTree(nc, outDT);
        delete [] outDT;
        return (rv);
    }
}
bool
avtLCSFilter::MultiBlockIterativeCalc(avtDataTree_p inDT,
                                     std::vector<avtIntegralCurve*> &ics,
                                     int &offset)
{
    if (*inDT == NULL)
        return true;

    int nc = inDT->GetNChildren();

    if (nc < 0 && !inDT->HasData())
        return true;

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = inDT->GetDataRepresentation().GetDataVTK();

        return SingleBlockIterativeCalc( in_ds, ics, offset );
    }
    else
    {
      bool haveAllExponents = true;

      //
      // there is more than one input dataset to process
      // and we need an input datatree for each
      //
      for (int j = 0; j < nc; j++)
      {
        if (inDT->ChildIsPresent(j) )
        {
          if( MultiBlockIterativeCalc( inDT->GetChild(j), ics, offset ) == false )
            haveAllExponents = false;
        }
      }

      return haveAllExponents;
    }
}
avtDataTree_p
avtCurveCMFEExpression::ExecuteTree(avtDataTree_p tree1, avtDataTree_p tree2,
                                   const std::string &invar,
                                   const std::string &outvar)
{
   if (tree1->GetNumberOfLeaves() == 0)
        return tree1;
    else if (tree1->GetNumberOfLeaves() != 1)
        EXCEPTION0(ImproperUseException);

    if (tree2->GetNumberOfLeaves() == 0)
        return tree1;
    else if (tree2->GetNumberOfLeaves() != 1)
        EXCEPTION0(ImproperUseException);

    //
    // We know that there is only one leaf node.  It is the curve.
    //
    vtkRectilinearGrid *curve1 = 
        vtkRectilinearGrid::SafeDownCast(tree1->GetSingleLeaf());
    if (curve1 == NULL)
        EXCEPTION0(ImproperUseException);

    vtkRectilinearGrid *curve2 = 
        vtkRectilinearGrid::SafeDownCast(tree2->GetSingleLeaf());
    if (curve2 == NULL)
        EXCEPTION0(ImproperUseException);

    vtkRectilinearGrid *rg = 
        MergeCurvesToSameXIntervals(curve1, curve2, outvar);
    avtDataTree_p output = new avtDataTree(rg, 1);
    rg->Delete();
    return output;
}
void
avtLCSFilter::CreateMultiBlockIterativeCalcOutput( avtDataTree_p inDT,
                                                   avtDataTree_p outDT,
                                                   std::vector<avtIntegralCurve*> &ics,
                                                   int &offset,
                                                   double &minv, double &maxv,
                                                   int &count)
{
    if (*inDT == NULL || *outDT == NULL)
        return;

    int nc = inDT->GetNChildren();

    if (nc < 0 && !inDT->HasData())
        return;

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet  *in_ds =  inDT->GetDataRepresentation().GetDataVTK();
        vtkDataSet *out_ds = outDT->GetDataRepresentation().GetDataVTK();

        int dom = inDT->GetDataRepresentation().GetDomain();
        std::string label = inDT->GetDataRepresentation().GetLabel();

        CreateSingleBlockIterativeCalcOutput(in_ds, out_ds, ics,
                                             offset, dom, minv, maxv, count);
    }
    else
    {
      //
      // there is more than one input dataset to process
      // and we need an output datatree for each
      //
      for (int j = 0; j < nc; j++)
      {
          if (inDT->ChildIsPresent(j))
            CreateMultiBlockIterativeCalcOutput(inDT->GetChild(j),
                                                outDT->GetChild(j),
                                                ics, offset, minv, maxv, count);
      }
    }
}
// ****************************************************************************
//  Method: avtTwoPassDatasetQuery::Execute
//
//  Purpose:
//    Recursive method to traverse an avtDataTree, calling Execute on the leaf
//    nodes. 
//
//  Notes:  Started as a direct copy of Execute() method of
//          avtDatasetQuery, added extensions for two passes
//
//  Programmer: Jeremy Meredith
//  Creation:   April 16, 2003
//
//  Modifications:
//    Kathleen Bonnell, Wed May 17 15:22:06 PDT 2006
//    Remove call to SetSource(NULL) as it now removes information necessary
//    for the dataset.
//
// ****************************************************************************
void
avtTwoPassDatasetQuery::ExecuteNthPass(avtDataTree_p inDT, int pass)
{
    if (*inDT == NULL)
    {
        return;
    }
 
    int nc = inDT->GetNChildren();
 
    if (nc <= 0 && !inDT->HasData())
    {
        return;
    }
 
    if ( nc == 0 )
    {
        //
        // There is only one dataset to process.
        //
        vtkDataSet *in_ds = inDT->GetDataRepresentation().GetDataVTK();
        int dom = inDT->GetDataRepresentation().GetDomain();
 
        //
        // Setting the source to NULL for the input will break the
        // pipeline.
        //
        //in_ds->SetSource(NULL);

        if (pass==1)
            Execute1(in_ds, dom);
        if (pass==2)
            Execute2(in_ds, dom);

        currentNode++;
        UpdateProgress(currentNode, totalNodes);
    }
    else
    {
        //
        // There is more than one input dataset to process.
        // Recurse through the children.
        //
        for (int j = 0; j < nc; j++)
        {
            if (inDT->ChildIsPresent(j))
            {
                ExecuteNthPass(inDT->GetChild(j), pass);
            }
        }
    }
}
void
avtLineScanQuery::ExecuteTree(avtDataTree_p inDT)
{
    if (*inDT == NULL)
    {
        return;
    }

    int nc = inDT->GetNChildren();

    if (nc <= 0 && !inDT->HasData())
    {
        return;
    }

    if ( nc == 0 )
    {
        //
        // There is only one dataset to process.
        //
        vtkDataSet *in_ds = inDT->GetDataRepresentation().GetDataVTK();
        int dom = inDT->GetDataRepresentation().GetDomain();

        //
        // Setting the source to NULL for the input will break the
        // pipeline.
        //
        // NO LONGER A GOOD IDEA
        //in_ds->SetSource(NULL);
        Execute(in_ds, dom);
        if (!timeVarying)
        {
            currentNode++;
            UpdateProgress(currentNode, totalNodes);
        }
    }
    else
    {
        //
        // There is more than one input dataset to process.
        // Recurse through the children.
        //
        for (int j = 0; j < nc; j++)
        {
            if (inDT->ChildIsPresent(j))
            {
                Execute(inDT->GetChild(j));
            }
        }
    }
}
void
avtDataTreeIteratorPreprocessor::PreprocessTree(avtDataTree_p tree)
{
    if (*tree == NULL)
    {
        return;
    }

    int numChildren = tree->GetNChildren();

    if ( (numChildren <= 0) && (!(tree->HasData())) )
    {
        return;
    }

    if (numChildren == 0)
    {
        //
        // There is only one dataset to process (the leaf).
        //
        vtkDataSet *in_ds = tree->GetDataRepresentation().GetDataVTK();
        int dom = tree->GetDataRepresentation().GetDomain();

        //
        // Ensure that there is no funny business when we do an Update.
        //
        // NO LONGER A GOOD IDEA
        //in_ds->SetSource(NULL);

        ProcessDomain(in_ds, dom);
    }
    else
    {
        for (int i = 0 ; i < numChildren ; i++)
        {
            if (tree->ChildIsPresent(i))
            {
                PreprocessTree(tree->GetChild(i));
            }
        }
    }
}
Beispiel #11
0
avtDataTree_p
avtDataBinningFilter::CreateArrayFromDataBinning(avtDataTree_p tree, 
                                                 avtDataBinning *theDataBinning, 
                                                 double *extents, bool &hadError)
{
    if (*tree == NULL)
        return NULL;

    int nc = tree->GetNChildren();

    if (nc <= 0 && !tree->HasData())
        return NULL;

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = tree->GetDataRepresentation().GetDataVTK();
        vtkDataArray *res = theDataBinning->ApplyFunction(in_ds);
        if (res == NULL)
        {
            hadError = true;
            return NULL;
        }
        res->SetName(varname.c_str());
        if (res->GetNumberOfTuples() == in_ds->GetNumberOfCells())
        {
            in_ds->GetCellData()->AddArray(res);
            in_ds->GetCellData()->SetActiveScalars(varname.c_str());
        }
        if (res->GetNumberOfTuples() == in_ds->GetNumberOfPoints())
        {
            in_ds->GetPointData()->AddArray(res);
            in_ds->GetPointData()->SetActiveScalars(varname.c_str());
        }
        res->Delete();
        double range[2] = { FLT_MAX, -FLT_MAX };
        GetDataRange(in_ds, range, varname.c_str(), false);
        extents[0] = (extents[0] > range[0] ? range[0] : extents[0]);
        extents[1] = (extents[1] < range[1] ? range[1] : extents[1]);

        int dom = tree->GetDataRepresentation().GetDomain();
        std::string label = tree->GetDataRepresentation().GetLabel();
        avtDataTree_p rv = new avtDataTree(in_ds, dom, label);
        return rv;
    }
    else
    {
        avtDataTree_p *outDT = new avtDataTree_p[nc];
        for (int j = 0; j < nc; j++)
        {
            if (tree->ChildIsPresent(j))
                outDT[j] = CreateArrayFromDataBinning(tree->GetChild(j), 
                                theDataBinning, extents, hadError);
            else
                outDT[j] = NULL;
        }
        avtDataTree_p rv = new avtDataTree(nc, outDT);
        delete [] outDT;
        return (rv);
    }
}
avtDataTree_p
avtSIMODataTreeIterator::Execute(avtDataTree_p inDT)
{
    CheckAbort();

    if (*inDT == NULL)
    {
        return NULL;
    }

    int nc = inDT->GetNChildren();

    if (nc <= 0 && !inDT->HasData())
    {
        return NULL;
    }

    if ( nc == 0 )
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = inDT->GetDataRepresentation().GetDataVTK();
        int dom = inDT->GetDataRepresentation().GetDomain();
        std::string label = inDT->GetDataRepresentation().GetLabel();
  
        //
        // Setting the source to NULL for the input will break the 
        // pipeline.
        //
        // NO LONGER A GOOD IDEA
        //in_ds->SetSource(NULL);

        //
        // We own the returned dataset because you cannot delete it if
        // it only has one reference and you want to return it.
        //
        avtDataTree_p rv = ExecuteDataTree(in_ds, dom, label);
        UpdateExtents(rv);
        currentNode++;
        UpdateProgress(currentNode, totalNodes);
        return rv;
    }
    else
    {
        //
        // there is more than one input dataset to process
        // and we need an output datatree for each
        //
        avtDataTree_p *outDT = new avtDataTree_p[nc];
        for (int j = 0; j < nc; j++)
        {
            if (inDT->ChildIsPresent(j))
            {
                outDT[j] = Execute(inDT->GetChild(j));
            }
            else
            {
                outDT[j] = NULL;
            }
        }
        avtDataTree_p rv = new avtDataTree(nc, outDT);
        delete [] outDT;
        return (rv);
    }
}
void
avtDataSetWriter::WriteDataTree(avtDataTree_p tree, avtDataObjectString &str)
{
    if (*tree == NULL||(tree->GetNChildren() <= 0 && tree->HasData() == false))
    {
        WriteInt(str, -1);
        return;
    }

    // get & write the number of children 
    int nc = tree->GetNChildren();
    WriteInt(str, nc);

    if (nc > 0)
    {
        for (int i = 0; i < nc; ++i)
        {
            if ( tree->ChildIsPresent(i) )
            {
                // write 1 to indicate child tree is present
                WriteInt(str, 1);
                // now write out this child tree
                WriteDataTree(tree->GetChild(i), str);
            }
            else 
            {
                // write 0 to indicate child tree is absent
                WriteInt(str, 0);
            }
        }
    }
    else
    {
        int len;
        int lengthAndChunkAndDSTAndLabel[4];
        unsigned char * s;
        DataSetType dst;

        // get the domain string and its length
        if (useCompression)
            s = tree->GetDataRepresentation().GetCompressedDataString(len, dst);
        else
            s = tree->GetDataRepresentation().GetDataString(len, dst);

        lengthAndChunkAndDSTAndLabel[0] = len;
        // write out the length 

        // write out the chunk index
        int chunk = tree->GetDataRepresentation().GetDomain();
        lengthAndChunkAndDSTAndLabel[1] = chunk;

        // write out the dataset's type.
        lengthAndChunkAndDSTAndLabel[2] = dst;

        // write out the label
        string label = tree->GetDataRepresentation().GetLabel();
        lengthAndChunkAndDSTAndLabel[3] = label.size();

        WriteInt(str, lengthAndChunkAndDSTAndLabel, 4);

        if (label.size() > 0)
        {
            str.Append((char *) label.c_str(), label.size(), 
                  avtDataObjectString::DATA_OBJECT_STRING_SHOULD_MAKE_COPY);
        }

        // write out the string 
        if (len > 0)
        {
            str.Append((char*) s, len, 
               avtDataObjectString::DATA_OBJECT_STRING_DOES_NOT_OWN_REFERENCE);
        }
    }
}
avtDataTree_p
avtConnCMFEExpression::ExecuteTree(avtDataTree_p in1, avtDataTree_p in2,
                                   const std::string &invar,
                                   const std::string &outvar)
{
    int numNull = 0;
    if (*in1 == NULL)
        numNull++;
    if (*in2 == NULL)
        numNull++;
    if (numNull == 2)
        return NULL;

    debug5 << "avtConnCMFEExpression::ExecuteTree: numNull=" << numNull << std::endl;
    if (numNull == 1)
        EXCEPTION1(InvalidMergeException, "The databases cannot be compared "
                   "because they have a different number of domains.");

    int nc1 = in1->GetNChildren();
    int nc2 = in1->GetNChildren();

    debug5 << "avtConnCMFEExpression::ExecuteTree: nc1=" << nc1 << " nc2= " << nc2 << std::endl;
    if (nc1 != nc2)
        EXCEPTION1(InvalidMergeException, "The databases cannot be compared "
                   "because they have a different number of domains.");

    if (nc1 <= 0)
    {
        int numHaveData = 0;
        if (in1->HasData())
            numHaveData++;
        if (in2->HasData())
            numHaveData++;
        debug5 << "avtConnCMFEExpression::ExecuteTree: numHaveData " << numHaveData << std::endl;
        if (numHaveData == 1)
            EXCEPTION1(InvalidMergeException, "The databases cannot be "
                  "compared because they have a different number of domains.");
        if (numHaveData == 0)
            return NULL;

        // 
        // We finally get to get their VTK datasets and compare them.
        //
        vtkDataSet *in_ds1 = in1->GetDataRepresentation().GetDataVTK();
        vtkDataSet *in_ds2 = in2->GetDataRepresentation().GetDataVTK();

        //
        // Make some basic checks to make sure the connectivities really do
        // agree.
        //
        char msg[1024];
        if (in_ds1->GetNumberOfCells() != in_ds2->GetNumberOfCells())
        {
            avtSILRestrictionTraverser trav(firstDBSIL);
            if (trav.UsesAllMaterials())
            {
                SNPRINTF(msg, 1024,
                             "The databases cannot be compared because they "
                             "have a different number of cells for domain %d."
                             " The cell counts are %d and %d.",
                             in1->GetDataRepresentation().GetDomain(),
                             static_cast<int>(in_ds1->GetNumberOfCells()),
                             static_cast<int>(in_ds2->GetNumberOfCells()));
            }
            else
            {
                SNPRINTF(msg, 1024,
                             "The databases cannot be compared because they"
                             " have a different number of cells for domain %d."
                             " The cell counts are %d and %d.  It appears that"
                             " you have removed some materials.  Databases "
                             "cannot be compared in this manner when materials"
                             " have been removed (and the simulation is "
                             "Eulerian).",
                             in1->GetDataRepresentation().GetDomain(),
                             static_cast<int>(in_ds1->GetNumberOfCells()), 
                             static_cast<int>(in_ds2->GetNumberOfCells()));
            }
            EXCEPTION1(InvalidMergeException, msg);
        }
        if (in_ds1->GetNumberOfPoints() != in_ds2->GetNumberOfPoints())
        {
            avtSILRestrictionTraverser trav(firstDBSIL);
            if (trav.UsesAllMaterials())
            {
                SNPRINTF(msg, 1024,
                             "The databases cannot be compared because they "
                             "have a different number of points for domain %d."
                             "  The point counts are %d and %d.", 
                         in1->GetDataRepresentation().GetDomain(),
                         static_cast<int>(in_ds1->GetNumberOfPoints()), 
                         static_cast<int>(in_ds2->GetNumberOfPoints()));
            }
            else
            {
                SNPRINTF(msg, 1024,
                             "The databases cannot be compared because they "
                             "have a different number of points for domain %d."
                             "  The point counts are %d and %d.  It appears "
                             "that you have removed some materials.  Databases"
                             " cannot be compared in this manner when materials"
                             " have been removed (and the simulation is "
                             "Eulerian).",
                         in1->GetDataRepresentation().GetDomain(),
                         static_cast<int>(in_ds1->GetNumberOfPoints()), 
                         static_cast<int>(in_ds2->GetNumberOfPoints()));
            }
            EXCEPTION1(InvalidMergeException, msg);
        }

        bool isPoint      = true;
        vtkDataArray *arr = NULL;
        arr               = in_ds2->GetPointData()->GetArray(invar.c_str());
        if (arr == NULL)
        {
            arr     = in_ds2->GetCellData()->GetArray(invar.c_str());
            isPoint = false;
        }
        if (arr == NULL)
        {
            sprintf(msg, "The databases cannot be compared because variable "
                         " \"%s\" cannot be located.", invar.c_str());
            EXCEPTION1(InvalidMergeException, msg);
        }

        // 
        // At this point copy field data from the second data set to
        // the first data set. This is a backdoor method for time
        // varying fields and moving higher element data that is
        // stored in the field data.
        //
        vtkFieldData *fd1 = in_ds1->GetFieldData();
        vtkFieldData *fd2 = in_ds2->GetFieldData();

        if( fd1->GetNumberOfArrays() && fd2->GetNumberOfArrays() )
        {
          for( int i=0; i<fd1->GetNumberOfArrays(); ++i )
          {
            // Copy only arrays found in both datasets.
            const char *name1 = fd1->GetArrayName(i);
            vtkAbstractArray *fp2 = fd2->GetAbstractArray(name1);
        
            if( fp2 )
            {
              // Make a copy of the array found in dataset2
              vtkAbstractArray *fp = (vtkAbstractArray *) fp2->NewInstance();
              fp->DeepCopy( fp2 );

              // Append '2' to the name so not to have any name conflicts.
              char name[128];
              sprintf( name, "%s2", name1);

              fp->SetName(name);
              in_ds1->GetFieldData()->AddArray(fp);
              fp->Delete();
            }
          }
        }

        //
        // 
        //
        vtkDataArray *addvar = NULL;
        bool deleteAddvar = false;
        if (invar == outvar)
        {
            addvar       = arr;
            deleteAddvar = false;
        }
        else
        {
            addvar = arr->NewInstance();
            addvar->DeepCopy(arr);
            addvar->SetName(outvar.c_str());
            deleteAddvar = true;
        }
        
        vtkDataSet *new_obj = (vtkDataSet *) in_ds1->NewInstance();
        new_obj->ShallowCopy(in_ds1);
        if (isPoint)
            new_obj->GetPointData()->AddArray(addvar);
        else
            new_obj->GetCellData()->AddArray(addvar);
        if (deleteAddvar)
            addvar->Delete();
        avtDataTree_p rv = new avtDataTree(new_obj, 
                                      in1->GetDataRepresentation().GetDomain(),
                                      in1->GetDataRepresentation().GetLabel());
        new_obj->Delete();
        return rv;
    }
    else
    {
        //
        // There is more than one input dataset to process
        // and we need an output datatree for each.
        //
        avtDataTree_p *outDT = new avtDataTree_p[nc1];
        for (int j = 0; j < nc1; j++)
        {
            int numPresent = 0;
            if (in1->ChildIsPresent(j))
                numPresent++;
            if (in2->ChildIsPresent(j))
                numPresent++;
            if (numPresent == 0)
            {
                outDT[j] = NULL;
            }
            else if (numPresent == 2)
            {
                outDT[j] = ExecuteTree(in1->GetChild(j), in2->GetChild(j), 
                                       invar, outvar);
            }
            else
            {
                debug1 << "Number of children = " << nc1 << endl;
                debug1 << "In1(j) " << (int) in1->ChildIsPresent(j) << endl;
                debug1 << "In2(j) " << (int) in2->ChildIsPresent(j) << endl;
                EXCEPTION1(InvalidMergeException, "The databases cannot be "
                  "compared because they have a different number of domains.");
            }
        }
        avtDataTree_p rv = new avtDataTree(nc1, outDT);
        delete [] outDT;
        return (rv);
    }
}
avtDataTree_p
avtLCSFilter::CreateIterativeCalcDataTree(avtDataTree_p inDT)
{
    if (*inDT == NULL)
        return 0;
    
    int nc = inDT->GetNChildren();
    
    if (nc < 0 && !inDT->HasData())
    {
        return 0;
    }

    if (nc == 0)
    {
        //variable name.
        std::string var = outVarRoot + outVarName;

        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = inDT->GetDataRepresentation().GetDataVTK();

        //create new instance from old.
        vtkDataSet* out_ds = in_ds->NewInstance();
        out_ds->ShallowCopy(in_ds);
        int nTuples = in_ds->GetNumberOfPoints();

        // Create storage for the components that need to be used
        // for calculating the exponent. All arrays but the exponent
        // array will be deleted when done.
        vtkDoubleArray *exponents = vtkDoubleArray::New();
        exponents->SetName(var.c_str());
        exponents->SetNumberOfTuples(nTuples);
        out_ds->GetPointData()->AddArray(exponents);
        // Will set the exponents to be the active scalars when
        // finished. In the mean time the component is the working
        // active scalars.
//      out_ds->GetPointData()->SetActiveScalars(var.c_str());

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

        vtkDoubleArray *component = vtkDoubleArray::New();
        component->SetName("component");
        component->SetNumberOfTuples(nTuples);
        out_ds->GetPointData()->AddArray(component);
        out_ds->GetPointData()->SetActiveScalars("component");
        
        vtkDoubleArray *times = vtkDoubleArray::New();
        times->SetName("times");
        times->SetNumberOfTuples(nTuples);
        out_ds->GetPointData()->AddArray(times);

        //cleanup
        exponents->Delete();
        component->Delete();
        times->Delete();
        
        int dom = inDT->GetDataRepresentation().GetDomain();
        std::string label = inDT->GetDataRepresentation().GetLabel();
        avtDataTree_p rv = new avtDataTree(out_ds, dom, label);
        out_ds->Delete();
        return rv;
    }
    else
    {
      //
      // there is more than one input dataset to process
      // and we need an output datatree for each
      //
      avtDataTree_p *outDT = new avtDataTree_p[nc];
      for (int j = 0; j < nc; j++)
      {
          if (inDT->ChildIsPresent(j))
            outDT[j] = CreateIterativeCalcDataTree(inDT->GetChild(j));
          else
            outDT[j] = NULL;
      }
      avtDataTree_p rv = new avtDataTree(nc, outDT);
      delete [] outDT;
      return rv;
    }
}