/*******************************************************************/ /* XDMF */ /* eXtensible Data Model and Format */ /* */ /* Id : Id */ /* Date : $Date$ */ /* Version : $Revision$ */ /* */ /* Author: */ /* Jerry A. Clarke */ /* clarke@arl.army.mil */ /* US Army Research Laboratory */ /* Aberdeen Proving Ground, MD */ /* */ /* Copyright @ 2002 US Army Research Laboratory */ /* All Rights Reserved */ /* See Copyright.txt or http://www.arl.hpc.mil/ice for details */ /* */ /* This software is distributed WITHOUT ANY WARRANTY; without */ /* even the implied warranty of MERCHANTABILITY or FITNESS */ /* FOR A PARTICULAR PURPOSE. See the above copyright notice */ /* for more information. */ /* */ /*******************************************************************/ #include "XdmfTime.h" #include "XdmfDOM.h" #include "XdmfArray.h" #include "XdmfDataItem.h" #include "XdmfGrid.h" namespace xdmf2 { XdmfTime::XdmfTime() { this->SetElementName("Time"); this->Value = 0.0; this->Array = NULL; this->Epsilon = 1e-7; this->DataItem = new XdmfDataItem; this->TimeType = XDMF_TIME_UNSET; this->Function = NULL; } XdmfTime::~XdmfTime() { if(this->DataItem) delete this->DataItem; } XdmfInt32 XdmfTime::Insert( XdmfElement *Child){ if(Child && XDMF_WORD_CMP(Child->GetElementName(), "Time")){ return(XdmfElement::Insert(Child)); }else{ XdmfErrorMessage("Time can only Insert Time elements"); } return(XDMF_FAIL); } XdmfInt32 XdmfTime::UpdateInformation(){ XdmfConstString attribute; XdmfFloat64 dValue; if(XdmfElement::UpdateInformation() != XDMF_SUCCESS) return(XDMF_FAIL); attribute = this->Get("TimeType"); if(!attribute) attribute = this->Get("Type"); if( XDMF_WORD_CMP(attribute, "Single") ){ this->TimeType = XDMF_TIME_SINGLE; }else if( XDMF_WORD_CMP(attribute, "List") ){ this->TimeType = XDMF_TIME_LIST; }else if( XDMF_WORD_CMP(attribute, "Range") ){ this->TimeType = XDMF_TIME_RANGE; }else if( XDMF_WORD_CMP(attribute, "HyperSlab") ){ this->TimeType = XDMF_TIME_HYPERSLAB; }else if( XDMF_WORD_CMP(attribute, "Function") ){ this->TimeType = XDMF_TIME_FUNCTION; }else{ if(attribute){ XdmfErrorMessage("Unknown Time Type : " << attribute); free((void*)attribute); return(XDMF_FAIL); } // Default this->TimeType = XDMF_TIME_SINGLE; } if(attribute){ free((void*)attribute); } // Type == Function ? attribute = this->Get("Function"); if(attribute){ this->TimeType = XDMF_TIME_FUNCTION; this->SetFunction(attribute); free((void*)attribute); return(XDMF_SUCCESS); } attribute = this->Get("Value"); if(attribute){ istrstream Value_ist(const_cast(attribute), strlen(attribute) ); Value_ist >> dValue; this->SetValue(dValue); free((void*)attribute); }else{ XdmfXmlNode node; if(this->TimeType == XDMF_TIME_SINGLE){ XdmfErrorMessage("TimeType is Single but there is no Value Attribute"); return(XDMF_FAIL); } node = this->DOM->FindDataElement(0, this->GetElement()); if(!node){ XdmfErrorMessage("No Time Value is set and there is no DataItem"); return(XDMF_FAIL); } if(this->DataItem->SetDOM(this->DOM) == XDMF_FAIL) return(XDMF_FAIL); if(this->DataItem->SetElement(node) == XDMF_FAIL) return(XDMF_FAIL); if(this->DataItem->UpdateInformation() == XDMF_FAIL) return(XDMF_FAIL); if(this->DataItem->Update() == XDMF_FAIL) return(XDMF_FAIL); this->Array = this->DataItem->GetArray(); } return(XDMF_SUCCESS); } XdmfInt32 XdmfTime::Build(){ if(this->TimeType == XDMF_TIME_UNSET) return(XDMF_SUCCESS); if(XdmfElement::Build() != XDMF_SUCCESS) return(XDMF_FAIL); this->Set("TimeType", this->GetTimeTypeAsString()); if(this->TimeType == XDMF_TIME_FUNCTION){ this->Set("Function", this->Function); return(XDMF_SUCCESS); } if(this->Array){ XdmfDataItem *di = NULL; XdmfXmlNode node; XdmfDebug("Build for XdmfTime = " << this); //! Is there already a DataItem node = this->DOM->FindDataElement(0, this->GetElement()); if(node) { di = (XdmfDataItem *)this->GetCurrentXdmfElement(node); XdmfDebug("DataItem = " << di); } if(!di){ di = new XdmfDataItem; node = this->DOM->InsertNew(this->GetElement(), "DataItem"); di->SetDOM(this->DOM); di->SetElement(node); if(this->Array->GetNumberOfElements() > 100) di->SetFormat(XDMF_FORMAT_HDF); } if(this->Array != di->GetArray()){ XdmfDebug("Setting Array since " << this->Array << " != " << di->GetArray()); di->SetArray(this->Array); } XdmfDebug("Building DataItem"); di->Build(); this->SetCurrentXdmfElement(di->GetElement(), NULL); delete di; }else{ ostrstream StringOutput; StringOutput << this->Value << ends; this->Set("Value", StringOutput.str()); StringOutput.rdbuf()->freeze(0); } return(XDMF_SUCCESS); } XdmfInt32 XdmfTime::Evaluate(XdmfGrid *Grid, XdmfArray *ArrayToFill, XdmfInt32 Descend, XdmfInt32 Append){ XdmfInt64 i, n, nelements; XdmfTime *gt; if(!ArrayToFill){ XdmfErrorMessage("Array to fill is NULL"); return(XDMF_FAIL); } if(Append){ nelements = ArrayToFill->GetNumberOfElements(); }else{ ArrayToFill->SetNumberType(XDMF_FLOAT64_TYPE); nelements = 0; } gt = Grid->GetTime(); if(gt){ switch(gt->GetTimeType()){ case XDMF_TIME_SINGLE : nelements += 1; ArrayToFill->SetNumberOfElements(nelements); ArrayToFill->SetValueFromFloat64(nelements - 1, gt->GetValue()); break; case XDMF_TIME_RANGE : case XDMF_TIME_LIST : // cout << "Adding " << gt->GetArray()->GetValues() << endl; n = gt->GetArray()->GetNumberOfElements(); nelements += n; ArrayToFill->SetNumberOfElements(nelements); for(i=0 ; i < n ; i++){ ArrayToFill->SetValueFromFloat64(nelements - n + i, gt->GetArray()->GetValueAsFloat64(i)); } // cout << "Array = " << ArrayToFill->GetValues() << endl; break; case XDMF_TIME_HYPERSLAB : n = gt->GetArray()->GetValueAsInt64(2); nelements += n; ArrayToFill->SetNumberOfElements(nelements); for(i=0 ; i < n ; i++){ ArrayToFill->SetValueFromFloat64(nelements - n + i, gt->GetArray()->GetValueAsFloat64(0) + (gt->GetArray()->GetValueAsFloat64(1) * i)); } // cout << "Array = " << ArrayToFill->GetValues() << endl; break; default : if(!Descend) return(XDMF_FAIL); break; } }else{ XdmfErrorMessage("Grid has no XdmfTime"); } if(Descend){ for(i=0 ; i < Grid->GetNumberOfChildren() ; i++){ // Append children's times if(this->Evaluate(Grid->GetChild(i), ArrayToFill, Descend, 1) != XDMF_SUCCESS) return(XDMF_FAIL); } } if(this->TimeType == XDMF_TIME_RANGE) { XdmfFloat64 minval, maxval; minval = ArrayToFill->GetMinAsFloat64(); maxval = ArrayToFill->GetMaxAsFloat64(); ArrayToFill->SetNumberOfElements(2); ArrayToFill->SetValueFromFloat64(0, minval); ArrayToFill->SetValueFromFloat64(1, maxval); } return(XDMF_SUCCESS); } XdmfInt32 XdmfTime::SetTimeFromParent(XdmfTime *ParentTime, XdmfInt64 Index){ XdmfArray *TimeArray; if(!ParentTime || (Index < 0)) return(XDMF_FAIL); // this->DebugOn(); XdmfDebug("Setting Time from Type " << ParentTime->GetTimeTypeAsString() << " Index = " << Index); switch(ParentTime->GetTimeType()){ case XDMF_TIME_SINGLE: this->TimeType = XDMF_TIME_SINGLE; this->Value = ParentTime->GetValue(); XdmfDebug("Setting Time Value to " << this->Value); break; case XDMF_TIME_HYPERSLAB : TimeArray = ParentTime->GetArray(); if(!TimeArray){ XdmfErrorMessage("TimeType is HyperSlab but there is no array"); return(XDMF_FAIL); } this->TimeType = XDMF_TIME_SINGLE; this->Value = TimeArray->GetValueAsFloat64(0) + (TimeArray->GetValueAsFloat64(1) * Index); XdmfDebug("Setting Time Value to " << this->Value); break; case XDMF_TIME_LIST : TimeArray = ParentTime->GetArray(); if(!TimeArray){ XdmfErrorMessage("TimeType is List but there is no array"); return(XDMF_FAIL); } this->TimeType = XDMF_TIME_SINGLE; this->SetValue(TimeArray->GetValueAsFloat64(Index)); XdmfDebug("Setting Time Value to " << this->GetValue()); break; case XDMF_TIME_RANGE : this->TimeType = XDMF_TIME_RANGE; this->Array = ParentTime->GetArray(); break; default : XdmfErrorMessage("Unknown or Invalid TimeType"); return(XDMF_FAIL); } return(XDMF_SUCCESS); } XdmfConstString XdmfTime::GetTimeTypeAsString(void){ switch(this->TimeType){ case XDMF_TIME_UNSET: return("Unset"); case XDMF_TIME_LIST: return("List"); case XDMF_TIME_RANGE: return("Range"); case XDMF_TIME_HYPERSLAB: return("HyperSlab"); case XDMF_TIME_FUNCTION: return("Function"); default : return("Single"); } } XdmfInt32 XdmfTime::IsValid(XdmfTime *TimeSpec){ XdmfFloat64 minval, maxval; // cout << "this->TimeType = " << this->GetTimeTypeAsString() << endl; // cout << "TimeSpec->TimeType = " << TimeSpec->GetTimeTypeAsString() << endl; switch(TimeSpec->TimeType){ case XDMF_TIME_SINGLE : minval = TimeSpec->GetValue(); maxval = TimeSpec->GetValue(); break; case XDMF_TIME_LIST : if(!TimeSpec->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } minval = TimeSpec->Array->GetMinAsFloat64(); maxval = TimeSpec->Array->GetMaxAsFloat64(); break; case XDMF_TIME_RANGE : if(!TimeSpec->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } minval = TimeSpec->Array->GetValueAsFloat64(0); maxval = TimeSpec->Array->GetValueAsFloat64(1); break; case XDMF_TIME_HYPERSLAB : if(!TimeSpec->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } minval = TimeSpec->Array->GetValueAsFloat64(0); maxval = (TimeSpec->Array->GetValueAsFloat64(1) * (TimeSpec->Array->GetValueAsFloat64(2) - 1)); break; default : return(XDMF_FALSE); } return(this->IsValid(minval, maxval)); } XdmfInt32 XdmfTime::IsValid(XdmfFloat64 TimeMin, XdmfFloat64 TimeMax){ TimeMin -= this->Epsilon; TimeMax += this->Epsilon; switch(this->TimeType){ case XDMF_TIME_SINGLE : // cout << "TimeMin, TimeMax, this->GetValue() = " << TimeMin << "," << TimeMax << "," << this->GetValue() << endl; if((this->GetValue() >= TimeMin) && (this->GetValue() <= TimeMax)){ // cout << "Time Test Passed" << endl; return(XDMF_TRUE); }else{ // cout << "Time Test Failed" << endl; } break; case XDMF_TIME_LIST : if(!this->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } if((this->Array->GetMinAsFloat64() >= TimeMin) && (this->Array->GetMaxAsFloat64() <= TimeMax)) return(XDMF_TRUE); break; case XDMF_TIME_RANGE : // cout << "TimeMin, TimeMax, minmaxrange = " << TimeMin << "," << TimeMax << // "," << this->Array->GetValueAsFloat64(0) << // "," << this->Array->GetValueAsFloat64(1) << // endl; if(!this->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } if((this->Array->GetValueAsFloat64(0) >= TimeMin) && (this->Array->GetValueAsFloat64(1) <= TimeMax)) return(XDMF_TRUE); break; case XDMF_TIME_HYPERSLAB : if(!this->Array){ XdmfErrorMessage("XdmfTime has no Array"); return(XDMF_FALSE); } if((this->Array->GetValueAsFloat64(0) >= TimeMin) && ((this->Array->GetValueAsFloat64(1) * (this->Array->GetValueAsFloat64(2) - 1)) <= TimeMax)) return(XDMF_TRUE); break; default : return(XDMF_FALSE); } return(XDMF_FALSE); } }