1 /*******************************************************************/
2 /*                               XDMF                              */
3 /*                   eXtensible Data Model and Format              */
4 /*                                                                 */
5 /*  Id : Id  */
6 /*  Date : $Date$ */
7 /*  Version : $Revision$ */
8 /*                                                                 */
9 /*  Author:                                                        */
10 /*     Jerry A. Clarke                                             */
11 /*     clarke@arl.army.mil                                         */
12 /*     US Army Research Laboratory                                 */
13 /*     Aberdeen Proving Ground, MD                                 */
14 /*                                                                 */
15 /*     Copyright @ 2002 US Army Research Laboratory                */
16 /*     All Rights Reserved                                         */
17 /*     See Copyright.txt or http://www.arl.hpc.mil/ice for details */
18 /*                                                                 */
19 /*     This software is distributed WITHOUT ANY WARRANTY; without  */
20 /*     even the implied warranty of MERCHANTABILITY or FITNESS     */
21 /*     FOR A PARTICULAR PURPOSE.  See the above copyright notice   */
22 /*     for more information.                                       */
23 /*                                                                 */
24 /*******************************************************************/
25 #include "XdmfDataItem.h"
26 #include "XdmfDataDesc.h"
27 #include "XdmfExpression.h"
28 #include "XdmfArray.h"
29 #include "XdmfDOM.h"
30 #include "XdmfHDF.h"
31 
32 // Supported Xdmf Formats
33 #include "XdmfValuesXML.h"
34 #include "XdmfValuesHDF.h"
35 #ifdef XDMF_USE_MYSQL
36 #include "XdmfValuesMySQL.h"
37 #endif
38 #include "XdmfValuesBinary.h"
39 
40 #include <libxml/tree.h>
41 
42 namespace xdmf2
43 {
44 
XdmfDataItem()45 XdmfDataItem::XdmfDataItem() {
46     this->SetElementName("DataItem");
47     this->Values = NULL;
48     this->DataDesc = new XdmfDataDesc();
49     this->DataDescIsMine = 1;
50     this->Array = new XdmfArray();
51     this->ArrayIsMine = 1;
52     this->Array->SetNumberType(XDMF_FLOAT32_TYPE);
53     this->Array->SetNumberOfElements(3);
54     this->Format = XDMF_FORMAT_XML;
55     this->HeavyDataSetName = NULL;
56     this->ItemType = XDMF_ITEM_UNIFORM;
57     this->Function = NULL;
58     this->ColumnMajor = 0;
59     this->TransposeInMemory = 1;
60 }
61 
~XdmfDataItem()62 XdmfDataItem::~XdmfDataItem() {
63     XdmfDebug(".... Deleteing DataItem " << this);
64     if(this->Array && this->ArrayIsMine ){
65         XdmfDebug("Deleting array " << this->Array);
66         delete this->Array;
67         XdmfDebug("Done Deleteing array");
68     }
69     if(this->DataDesc && this->DataDescIsMine) delete this->DataDesc;
70     if(this->Values) delete this->Values;
71     delete [] this->HeavyDataSetName;
72 }
73 
74 XdmfInt32
Release()75 XdmfDataItem::Release(){
76     // Don't Delete it.
77     if(this->Array) this->Array->SetNumberOfElements(3);
78     return(XDMF_SUCCESS);
79 }
80 
81 XdmfInt32
Insert(XdmfElement * Child)82 XdmfDataItem::Insert( XdmfElement *Child){
83     if(Child && (
84         XDMF_WORD_CMP(Child->GetElementName(), "DataItem") ||
85         XDMF_WORD_CMP(Child->GetElementName(), "Information")
86         )){
87         return(XdmfElement::Insert(Child));
88     }else{
89         XdmfErrorMessage("DataItem can only Insert DataItem or Information elements");
90     }
91     return(XDMF_FAIL);
92 }
93 
94 XdmfArray *
GetArray(XdmfInt32 Create)95 XdmfDataItem::GetArray(XdmfInt32 Create){
96     if(!this->Array && Create){
97         this->Array = new XdmfArray;
98         this->ArrayIsMine = 1;
99     }
100     return(this->Array);
101 }
102 
103 XdmfInt32
SetArray(XdmfArray * anArray)104 XdmfDataItem::SetArray(XdmfArray *anArray){
105     if(this->Array && this->ArrayIsMine) delete this->Array;
106     this->ArrayIsMine = 0;
107     this->Array = anArray;
108     return(XDMF_SUCCESS);
109 }
110 
111 XdmfInt32
SetDataDesc(XdmfDataDesc * aDataDesc)112 XdmfDataItem::SetDataDesc(XdmfDataDesc *aDataDesc){
113     if(this->DataDesc && this->DataDescIsMine) delete this->DataDesc;
114     this->DataDescIsMine = 0;
115     this->DataDesc = aDataDesc;
116     return(XDMF_SUCCESS);
117 }
118 
119 // Derived version
120 XdmfInt32
Copy(XdmfElement * Source)121 XdmfDataItem::Copy(XdmfElement *Source){
122     XdmfDataItem *ds;
123 
124     XdmfDebug("XdmfDataItem::Copy(XdmfElement *Source)");
125     ds = (XdmfDataItem *)Source;
126     // this->SetDOM(ds->GetDOM());
127     this->SetFormat(ds->GetFormat());
128     this->SetHeavyDataSetName(ds->GetHeavyDataSetName());
129     this->SetDsmBuffer(ds->GetDsmBuffer());
130     this->DataDesc->CopyType(ds->GetDataDesc());
131     this->DataDesc->CopyShape(ds->GetDataDesc());
132     this->DataDesc->CopySelection(ds->GetDataDesc());
133     if(CopyReferenceData){
134         XdmfDebug("Copying Data From Array");
135         this->SetArray(ds->GetArray()->Clone());
136         if(!this->Array){
137             XdmfErrorMessage("Error Cloning Array");
138             return(XDMF_FAIL);
139         }
140         // Allow for future deletion
141         this->ArrayIsMine = 1;
142     }else{
143         XdmfDebug("Referenceing Data From Array");
144         // Problem if owner deletes
145         this->SetArray(ds->GetArray());
146     }
147     return(XDMF_SUCCESS);
148 }
149 
UpdateInformationFunction()150 XdmfInt32 XdmfDataItem::UpdateInformationFunction(){
151     switch(this->ItemType){
152         case XDMF_ITEM_FUNCTION :
153            XdmfConstString Value;
154            Value = this->Get("Function");
155            this->SetFunction(Value);
156            delete Value;
157            break;
158         case XDMF_ITEM_HYPERSLAB :
159             break;
160         case XDMF_ITEM_COORDINATES :
161             break;
162     }
163     return(XDMF_SUCCESS);
164 }
165 
UpdateInformationCollection()166 XdmfInt32 XdmfDataItem::UpdateInformationCollection(){
167     return(XDMF_SUCCESS);
168 }
169 
UpdateInformationTree()170 XdmfInt32 XdmfDataItem::UpdateInformationTree(){
171     return(XDMF_SUCCESS);
172 }
173 
UpdateInformationUniform()174 XdmfInt32 XdmfDataItem::UpdateInformationUniform(){
175     XdmfConstString Value = 0;
176     XdmfInt32   Precision = 4;
177 
178     Value = this->Get("Precision");
179     if(Value) Precision = atoi(Value);
180     free((void*)Value);
181     Value = this->Get("NumberType");
182     // Try DataType
183     if(!Value) Value = this->Get("DataType");
184     //! Try Old Style
185     if(!Value) Value = this->Get("Type");
186     // Only allow Simple for now.
187     if(XDMF_WORD_CMP(Value, "Char")){
188         this->DataDesc->SetNumberType(XDMF_INT8_TYPE);
189     } else if(XDMF_WORD_CMP(Value, "UChar")){
190         this->DataDesc->SetNumberType(XDMF_UINT8_TYPE);
191     } else if(XDMF_WORD_CMP(Value, "Short")){
192         this->DataDesc->SetNumberType(XDMF_INT16_TYPE);
193     } else if(XDMF_WORD_CMP(Value, "UShort")){
194         this->DataDesc->SetNumberType(XDMF_UINT16_TYPE);
195     } else if(XDMF_WORD_CMP(Value, "Int")){
196         if(Precision == 8){
197             this->DataDesc->SetNumberType(XDMF_INT64_TYPE);
198         }else{
199             this->DataDesc->SetNumberType(XDMF_INT32_TYPE);
200         }
201     } else if(XDMF_WORD_CMP(Value, "UInt")){
202         this->DataDesc->SetNumberType(XDMF_UINT32_TYPE);
203     } else {
204         if(Precision == 8){
205             this->DataDesc->SetNumberType(XDMF_FLOAT64_TYPE);
206         }else{
207             this->DataDesc->SetNumberType(XDMF_FLOAT32_TYPE);
208         }
209     }
210     free((void*)Value);;
211     Value = this->Get("Format");
212     // Currently XML or HDF5
213     if(XDMF_WORD_CMP(Value, "HDF")){
214         this->SetFormat(XDMF_FORMAT_HDF);
215     } else if(XDMF_WORD_CMP(Value, "HDF5")){
216         this->SetFormat(XDMF_FORMAT_HDF);
217     } else if(XDMF_WORD_CMP(Value, "H5")){
218         this->SetFormat(XDMF_FORMAT_HDF);
219     } else if(XDMF_WORD_CMP(Value, "XML")){
220         this->SetFormat(XDMF_FORMAT_XML);
221     } else if(XDMF_WORD_CMP(Value, "MYSQL")){
222         this->SetFormat(XDMF_FORMAT_MYSQL);
223     } else if(XDMF_WORD_CMP(Value, "BINARY")){
224         this->SetFormat(XDMF_FORMAT_BINARY);
225     }else if(Value){
226         XdmfErrorMessage("Unsupported DataItem Format :" << Value);
227         free((void*)Value);
228         return(XDMF_FAIL);
229     }
230     free((void*)Value);
231     return(XDMF_SUCCESS);
232 }
233 
UpdateInformation()234 XdmfInt32 XdmfDataItem::UpdateInformation(){
235     XdmfConstString Value;
236 
237   Value = this->Get("Major");
238   if(Value)
239   {
240     if(XDMF_WORD_CMP(Value,"Column"))
241       this->ColumnMajor = 1;
242     else if(XDMF_WORD_CMP(Value,"Row"))
243       this->ColumnMajor = 0;
244     else
245     {
246         XdmfErrorMessage("invalid major");
247         free((void*)Value);
248         return(XDMF_FAIL);
249     }
250   }
251   free((void*)Value);
252   XdmfDebug("Major = " << this->ColumnMajor);
253 
254     XdmfDebug("XdmfDataItem::UpdateInformation()");
255     if(XdmfElement::UpdateInformation() != XDMF_SUCCESS) return(XDMF_FAIL);
256     // If this is a Reference, this->Element now points to the end of the chain. Continue?
257     XdmfDebug("Back from XdmfElement::UpdateInformation() IsReference = " << this->GetIsReference());
258     // XdmfDebug("o = " << this->GetReferenceObject(this->Element) << " this = " << this);
259     // XdmfDebug("r = " << this->ReferenceElement << " e = " << this->Element);
260     // XdmfDebug(this->DOM->Serialize(this->ReferenceElement));
261     // Dtetermine type : Uniform, Collection, or Tree
262     Value = this->Get("ItemType");
263     if(!Value){
264         // Try Old "Type=XX" Style from Xdmf Version 1.0
265         Value = this->Get("Type");
266     }
267     if(!Value){
268         this->SetItemType(XDMF_ITEM_UNIFORM);
269     }else{
270         // Allow for "break";
271         do {
272             if(XDMF_WORD_CMP(Value, "Uniform")){
273                 this->SetItemType(XDMF_ITEM_UNIFORM);
274                 break;
275             }
276             if(XDMF_WORD_CMP(Value, "Collection")){
277                 this->SetItemType(XDMF_ITEM_COLLECTION);
278                 break;
279             }
280             if(XDMF_WORD_CMP(Value, "Tree")){
281                 this->SetItemType(XDMF_ITEM_TREE);
282                 break;
283             }
284             if(XDMF_WORD_CMP(Value, "HyperSlab")){
285                 this->SetItemType(XDMF_ITEM_HYPERSLAB);
286                 break;
287             }
288             if(XDMF_WORD_CMP(Value, "Coordinates")){
289                 this->SetItemType(XDMF_ITEM_COORDINATES);
290                 break;
291             }
292             if(XDMF_WORD_CMP(Value, "Function")){
293                 this->SetItemType(XDMF_ITEM_FUNCTION);
294                 break;
295             }
296             XdmfErrorMessage("Unknown DataItem Type = " << Value);
297             free((void*)Value);
298             return(XDMF_FAIL);
299         } while(0);
300     }
301     free((void*)Value);
302     if(this->GetIsReference() &&
303         (this->ReferenceElement != this->Element) &&
304         (this->GetReferenceObject(this->Element) != this)){
305         XdmfDebug("Reference DataItem Copied Info from another ReferenceObject");
306         return(XDMF_SUCCESS);
307     }
308     Value = this->Get("Dimensions");
309     if(!Value) {
310         XdmfErrorMessage("Dimensions are not set in XML Element");
311         XdmfErrorMessage(this->DOM->Serialize(this->Element));
312         return(XDMF_FAIL);
313     }
314     if(!this->DataDesc) this->DataDesc = new XdmfDataDesc();
315     this->DataDesc->SetShapeFromString(Value);
316     free((void*)Value);;
317     switch(this->ItemType){
318         case XDMF_ITEM_UNIFORM :
319             return(this->UpdateInformationUniform());
320             break;
321         case XDMF_ITEM_COLLECTION:
322             return(this->UpdateInformationCollection());
323             break;
324         case XDMF_ITEM_TREE:
325             return(this->UpdateInformationTree());
326             break;
327         case XDMF_ITEM_HYPERSLAB :
328         case XDMF_ITEM_COORDINATES :
329         case XDMF_ITEM_FUNCTION :
330             return(this->UpdateInformationFunction());
331             break;
332         default :
333             // Should Never get Here
334             XdmfErrorMessage("Unknown ItemType");
335             return(XDMF_FAIL);
336             break;
337     }
338     // Should Never get Here
339     return(XDMF_SUCCESS);
340 }
341 
UpdateFunction()342 XdmfInt32 XdmfDataItem::UpdateFunction(){
343         XdmfConstString  Value;
344         XdmfArray  *ReturnArray;
345         XdmfDataItem *ItemToDelete[100];
346         XdmfInt32  Id, NTmp = 0;
347 
348     if(this->ItemType == XDMF_ITEM_COORDINATES){
349         // $0 is Selection $1 is Data Source
350             XdmfXmlNode  Argument;
351             XdmfArray  *TmpArray;
352             XdmfDataItem *TmpItem, *SrcItem;
353             XdmfInt64   NCoordinates, *Coordinates;
354 
355             XdmfDebug("Updating Coordinate Selection");
356             Argument = this->DOM->FindDataElement(0, this->Element);
357             TmpItem = new XdmfDataItem();
358             TmpItem->SetDOM(this->DOM);
359             TmpItem->SetElement(Argument);
360             TmpItem->UpdateInformation();
361             TmpItem->Update();
362             TmpArray = TmpItem->GetArray();
363             NCoordinates = TmpArray->GetNumberOfElements();
364             Coordinates = new XdmfInt64[NCoordinates];
365             TmpArray->GetValues( 0, Coordinates, NCoordinates );
366             // Now Access the Source Data
367             SrcItem = new XdmfDataItem();
368             Argument = this->DOM->FindDataElement(1, this->Element);
369             SrcItem->SetDOM(this->DOM);
370             SrcItem->SetElement(Argument);
371             SrcItem->UpdateInformation();
372             NCoordinates /= SrcItem->GetRank();
373             SrcItem->GetDataDesc()->SelectCoordinates(NCoordinates, Coordinates);
374             SrcItem->Update();
375             // Steal The Array
376             ReturnArray = SrcItem->GetArray();
377             SrcItem->SetArrayIsMine(0);
378             ItemToDelete[ NTmp++ ] = TmpItem;
379             ItemToDelete[ NTmp++ ] = SrcItem;
380             delete Coordinates;
381     }
382     if(this->ItemType == XDMF_ITEM_HYPERSLAB){
383         // $0 is Selection $1 is Data Source
384             XdmfXmlNode  Argument;
385             XdmfArray  *TmpArray;
386             XdmfDataItem *TmpItem, *SrcItem;
387             XdmfInt64   Rank;
388             XdmfInt64   Start[ XDMF_MAX_DIMENSION ];
389             XdmfInt64   Stride[ XDMF_MAX_DIMENSION ];
390             XdmfInt64   Count[ XDMF_MAX_DIMENSION ];
391 
392             XdmfDebug("Updating HyperSlab");
393             Argument = this->DOM->FindDataElement(0, this->Element);
394             TmpItem = new XdmfDataItem();
395             TmpItem->SetDOM(this->DOM);
396             TmpItem->SetElement(Argument);
397             TmpItem->UpdateInformation();
398             TmpItem->Update();
399             TmpArray = TmpItem->GetArray();
400             Rank = TmpArray->GetNumberOfElements() / 3; // Start, Stride, Count for each Source Dim
401             TmpArray->GetValues(0, Start, Rank);
402             TmpArray->GetValues(Rank, Stride, Rank);
403             TmpArray->GetValues(2 * Rank, Count, Rank);
404             XdmfDebug("Selection is " << TmpArray->GetValues());
405             // Now Access the Source Data
406             SrcItem = new XdmfDataItem();
407             Argument = this->DOM->FindDataElement(1, this->Element);
408             SrcItem->SetDOM(this->DOM);
409             SrcItem->SetElement(Argument);
410             SrcItem->UpdateInformation();
411             SrcItem->GetDataDesc()->SelectHyperSlab( Start, Stride, Count );
412             SrcItem->Update();
413             // Steal The Array
414             ReturnArray = SrcItem->GetArray();
415             SrcItem->SetArrayIsMine(0);
416             ItemToDelete[ NTmp++ ] = TmpItem;
417             ItemToDelete[ NTmp++ ] = SrcItem;
418 
419     }
420     if(this->ItemType == XDMF_ITEM_FUNCTION){
421         ostrstream  FunctionToEval;
422         char    c, *StreamString, *scdata;
423 
424 
425         if(!this->Function){
426                 XdmfErrorMessage("Function is NULL");
427                 return(XDMF_FAIL);
428         }
429         XDMF_STRING_DUPLICATE(scdata, this->Function);
430         XdmfDebug("Transform Function = " << scdata);
431         XdmfConstString ch = scdata;
432         while( (c = *ch++) ) {
433             if( c == '$' ) {
434                 XdmfXmlNode  Argument;
435                 XdmfArray  *TmpArray;
436                 XdmfDataItem *TmpItem;
437                 Id = atoi(ch);
438                 while( (c = *ch++) ) {
439                     if( c > ' ') break;
440                 }
441                 Argument = this->DOM->FindDataElement(Id, this->Element );
442                 TmpItem = new XdmfDataItem();
443                 TmpItem->SetDOM(this->DOM);
444                 TmpItem->SetElement(Argument);
445                 TmpItem->UpdateInformation();
446                 TmpItem->Update();
447                 TmpArray = TmpItem->GetArray();
448                 if( TmpArray->GetNumberOfElements() == 1 ){
449                     XdmfDebug("Using Scalar = " << TmpArray->GetValueAsFloat64( 0 ) );
450                     FunctionToEval << " " << TmpArray->GetValueAsFloat64( 0 ) << " ";
451                     delete TmpArray;
452                 } else {
453                     ItemToDelete[ NTmp++ ] = TmpItem;
454                     FunctionToEval << " " << TmpArray->GetTagName() << " ";
455                 }
456             } else {
457                 FunctionToEval << c;
458             }
459         }
460         delete [] scdata;
461         FunctionToEval << ends;
462         StreamString = FunctionToEval.str();
463         XdmfDebug("Function Translation = " << StreamString );
464         ReturnArray = XdmfExpr(StreamString);
465         delete [] StreamString;
466     }
467     // Reform and Cleanup
468     Value = this->DOM->Get( Element, "Dimensions" );
469     if(Value && ReturnArray){
470         ReturnArray->ReformFromString(Value);
471     }
472     free((void*)Value);;
473     // If only a portion of the DataItem was requested
474     // the XdmfValues did not reflect this selection since
475     // DataDesc was used to select HyperSlad | Coordinates | Function
476     if(this->DataDesc->GetSelectionType() != XDMF_SELECTALL){
477             XdmfArray   *Portion;
478             XdmfInt64  SelectionSize = this->DataDesc->GetSelectionSize();
479 
480             Portion = ReturnArray->Clone();
481             ReturnArray->SetShape(1, &SelectionSize);
482             ReturnArray->SelectAll();
483             Portion->CopySelection(this->DataDesc);
484             CopyArray(Portion, ReturnArray);
485             delete Portion;
486     }
487     while( NTmp ){
488         NTmp--;
489         XdmfDebug("Deleteing DataItem #" << NTmp );
490         delete ItemToDelete[ NTmp ];
491     }
492     this->SetArray(ReturnArray);
493     // We'll need to delete this
494     this->ArrayIsMine = 1;
495     return( XDMF_SUCCESS);
496 }
497 
Update()498 XdmfInt32 XdmfDataItem::Update(){
499     if(XdmfElement::Update() != XDMF_SUCCESS) return(XDMF_FAIL);
500     if(this->IsReference){
501         XdmfDebug("This is a Reference");
502     }else{
503         XdmfDebug("This is not a Reference");
504     }
505     if(this->GetIsReference() && (this->GetReferenceObject(this->Element) != this)){
506         XdmfDebug("Reference DataItem Copied Info from another ReferenceObject");
507         return(XDMF_SUCCESS);
508     }
509     if(this->GetIsMultiple()){
510         XdmfDebug("Item Type does not evaluate to a single array. Done");
511         return(XDMF_SUCCESS);
512     }
513     if(this->ItemType != XDMF_ITEM_UNIFORM){
514         return(this->UpdateFunction());
515     }
516     if(this->Array->CopyType(this->DataDesc) != XDMF_SUCCESS) return(XDMF_FAIL);
517     // if(this->Array->CopyShape(this->DataDesc) != XDMF_SUCCESS) return(XDMF_FAIL);
518     // if(this->Array->CopySelection(this->DataDesc) != XDMF_SUCCESS) return(XDMF_FAIL);
519     if(this->CheckValues(this->Format) != XDMF_SUCCESS){
520         XdmfErrorMessage("Error Accessing Internal XdmfValues");
521         return(XDMF_FAIL);
522     }
523     if(this->Values->GetDataDesc()->CopySelection(this->DataDesc) != XDMF_SUCCESS) return(XDMF_FAIL);
524     XdmfDebug("Resize Array");
525     if(this->Array->SetShapeFromSelection(this->DataDesc) != XDMF_SUCCESS) return(XDMF_FAIL);
526     switch (this->Format) {
527         case XDMF_FORMAT_HDF :
528             this->Values->SetDebug(this->GetDebug());
529             // this->SetDsmBuffer(this->Values->GetDsmBuffer());
530             // cout << "Setting Values Dsm to " << this->DsmBuffer << endl;
531             this->Values->SetDsmBuffer(this->DsmBuffer);
532             XdmfDebug("Reading Data");
533             if(!((XdmfValuesHDF *)this->Values)->Read(this->Array)){
534                 XdmfErrorMessage("Reading Values Failed");
535                 return(XDMF_FAIL);
536             }
537             this->SetHeavyDataSetName(this->Values->GetHeavyDataSetName());
538             this->Array->SetHeavyDataSetName(this->Values->GetHeavyDataSetName());
539             break;
540         case XDMF_FORMAT_XML :
541             this->Values->SetDebug(this->GetDebug());
542             if(!((XdmfValuesXML *)this->Values)->Read(this->Array)){
543                 XdmfErrorMessage("Reading Values Failed");
544                 return(XDMF_FAIL);
545             }
546             break;
547         case XDMF_FORMAT_MYSQL :
548             this->Values->SetDebug(this->GetDebug());
549 #ifdef XDMF_USE_MYSQL
550             if(!((XdmfValuesMySQL *)this->Values)->Read(this->Array)){
551                 XdmfErrorMessage("Reading Values Failed");
552                 return(XDMF_FAIL);
553             }
554 #else
555             XdmfErrorMessage("XdmfValuesMySQL not enabled in this Xdmf");
556             return(XDMF_FAIL);
557 #endif
558 
559             break;
560         case XDMF_FORMAT_BINARY :
561             this->Values->SetDebug(this->GetDebug());
562             if(!((XdmfValuesBinary *)this->Values)->Read(this->Array)){
563                 XdmfErrorMessage("Reading Values Failed");
564                 return(XDMF_FAIL);
565             }
566             break;
567         default :
568             XdmfErrorMessage("Unsupported Data Format");
569             return(XDMF_FAIL);
570     }
571 
572   // Support for Fortran matrices (2D arrays) added by Dominik Szczerba, June 2009.
573   // Can be further optimized by e.g. in situ transpose methods
574   // discussed on http://en.wikipedia.org/wiki/In-place_matrix_transposition
575   if(ColumnMajor)
576   {
577     if(TransposeInMemory)
578     {
579       XdmfDebug("Transposing Array " << this->GetHeavyDataSetName());
580       XdmfInt32 rank = 0;
581       XdmfInt64 dims[XDMF_MAX_DIMENSION];
582       rank = GetShape(dims);
583       XdmfDebug("rank = " << rank);
584       if(rank!=2)
585       {
586         XdmfErrorMessage("transpose is only implemented for rank 2 arrays");
587         return(XDMF_FAIL);
588       }
589       // for(int i=0; i<rank; i++)
590         // cerr << "DEBUG: dims[" << i << "] = " << dims[i] << endl;
591 
592       const int NI = dims[0], NJ = dims[1];
593 
594       void* ArrayT;
595       switch(this->Array->GetNumberType())
596       {
597         case XDMF_FLOAT64_TYPE:
598           ArrayT = (XdmfFloat64*)new XdmfFloat64[NI*NJ];
599           break;
600         case XDMF_INT32_TYPE:
601           ArrayT = (XdmfInt32*)new XdmfInt32[NI*NJ];
602           break;
603         // TODO implement the other types
604         default:
605           XdmfErrorMessage("unknown data type");
606           return(XDMF_FAIL);
607       }
608 
609       // XdmfPointer ArrayPointer, ArrayPointerT;
610       XdmfPointer ArrayPointer;
611 
612       for(int j=0; j<NJ; j++)
613       {
614         for(int i=0; i<NI; i++)
615         {
616           const int idx  = NI*j+i;
617           const int idxT = NJ*i+j;
618           // cerr << "DEBUG: idx/idxT = " << idx << " " << idxT << endl;
619           switch(this->Array->GetNumberType())
620           {
621             case XDMF_FLOAT64_TYPE:
622               ArrayPointer = (XdmfFloat64*)this->Array->GetDataPointer(idxT);
623               ((XdmfFloat64*)ArrayT)[idx] = *(XdmfFloat64*)ArrayPointer;
624               break;
625             case XDMF_INT32_TYPE:
626               ArrayPointer = (XdmfInt32*)this->Array->GetDataPointer(idxT);
627               ((XdmfInt32*)ArrayT)[idx] = *(XdmfInt32*)ArrayPointer;
628               break;
629             // TODO implement the other types
630             default:
631               XdmfErrorMessage("unknown data type");
632               return(XDMF_FAIL);
633           }
634         }
635       }
636 
637       std::swap(dims[0], dims[1]);
638       Array->Reform(rank,dims);
639 
640       for(int l=0; l<NI*NJ; l++)
641       {
642         switch(this->Array->GetNumberType())
643         {
644           case XDMF_FLOAT64_TYPE:
645             // cerr << "DEBUG: l = " << l  << " " << ((XdmfFloat64*)ArrayT)[l] << endl;
646             this->Array->SetValue(l,((XdmfFloat64*)ArrayT)[l]);
647             break;
648           case XDMF_INT32_TYPE:
649             // cerr << "DEBUG: l = " << l << " " << ((XdmfInt32*)ArrayT)[l] << endl;
650             this->Array->SetValue(l,((XdmfInt32*)ArrayT)[l]);
651             break;
652           // TODO implement the other types
653           default:
654             XdmfErrorMessage("unknown data type");
655             return(XDMF_FAIL);
656         }
657       }
658 
659       // delete [] ArrayT;
660       switch(this->Array->GetNumberType())
661       {
662         case XDMF_FLOAT64_TYPE:
663           delete [] (XdmfFloat64*)ArrayT;
664           break;
665         case XDMF_INT32_TYPE:
666           delete [] (XdmfInt32*)ArrayT;
667           break;
668         // TODO implement the other types
669         default:
670           XdmfErrorMessage("unknown data type");
671           return(XDMF_FAIL);
672       }
673 
674       XdmfDebug("done transpose");
675 
676     }
677     else
678     {
679       XdmfErrorMessage("out-of-core transpose not implemented yet");
680       return(XDMF_FAIL);
681     }
682 
683 
684   }
685 
686     return(XDMF_SUCCESS);
687 }
688 
GetDataValues(XdmfInt64 Index,XdmfInt64 NumberOfValues,XdmfInt64 ArrayStride)689 XdmfString XdmfDataItem::GetDataValues(XdmfInt64 Index, XdmfInt64 NumberOfValues, XdmfInt64 ArrayStride){
690     if(!this->Array) return(NULL);
691     return(this->Array->GetValues(Index, NumberOfValues, ArrayStride));
692 }
693 
SetDataValues(XdmfInt64 Index,XdmfConstString someValues,XdmfInt64 ArrayStride,XdmfInt64 ValuesStride)694 XdmfInt32 XdmfDataItem::SetDataValues(XdmfInt64 Index, XdmfConstString someValues, XdmfInt64 ArrayStride, XdmfInt64 ValuesStride){
695     if(!this->Array){
696         XdmfErrorMessage("DataItem has no XdmfArray");
697         return(XDMF_FAIL);
698     }
699     return(this->Array->SetValues(Index, someValues, ArrayStride, ValuesStride));
700 }
701 
GetRank()702 XdmfInt32   XdmfDataItem::GetRank() {
703     if(!this->DataDesc){
704         XdmfErrorMessage("There is no XdmfDataDesc");
705         return(XDMF_FAIL);
706     }
707     return(this->DataDesc->GetRank());
708 }
709 
SetShape(XdmfInt32 Rank,XdmfInt64 * Dimensions)710 XdmfInt32 XdmfDataItem::SetShape(XdmfInt32 Rank, XdmfInt64 *Dimensions){
711     if(!this->DataDesc){
712         XdmfErrorMessage("There is no XdmfDataDesc");
713         return(XDMF_FAIL);
714     }
715     return(this->DataDesc->SetShape(Rank, Dimensions));
716 }
717 
GetShape(XdmfInt64 * Dimensions)718 XdmfInt32 XdmfDataItem::GetShape(XdmfInt64 *Dimensions){
719     if(!this->DataDesc){
720         XdmfErrorMessage("There is no XdmfDataDesc");
721         return(XDMF_FAIL);
722     }
723     return(this->DataDesc->GetShape(Dimensions));
724 }
725 
SetDimensionsFromString(XdmfConstString Dimensions)726 XdmfInt32 XdmfDataItem::SetDimensionsFromString(XdmfConstString Dimensions){
727     if(!this->DataDesc){
728         XdmfErrorMessage("There is no XdmfDataDesc");
729         return(XDMF_FAIL);
730     }
731     return(this->DataDesc->SetShapeFromString(Dimensions));
732 }
733 
GetShapeAsString()734 XdmfConstString XdmfDataItem::GetShapeAsString(){
735     if(!this->DataDesc){
736         XdmfErrorMessage("There is no XdmfDataDesc");
737         return(NULL);
738     }
739     return(this->DataDesc->GetShapeAsString());
740 }
741 
Build()742 XdmfInt32 XdmfDataItem::Build(){
743     XdmfDataDesc *aDataDesc = this->DataDesc;
744     if(XdmfElement::Build() != XDMF_SUCCESS) return(XDMF_FAIL);
745     if(this->Array) aDataDesc = this->Array;
746     this->Set("Dimensions", aDataDesc->GetShapeAsString());
747     this->Set("NumberType", XdmfTypeToClassString(aDataDesc->GetNumberType()));
748     switch (aDataDesc->GetElementSize()) {
749         case 8 :
750             this->Set("Precision", "8");
751             break;
752         case 4 :
753             this->Set("Precision", "4");
754             break;
755   case 2 :
756       this->Set("Precision", "2");
757       break;
758         case 1 :
759             this->Set("Precision", "1");
760             break;
761         default :
762             break;
763     }
764     switch (this->Format) {
765         case XDMF_FORMAT_HDF :
766             this->Set("Format", "HDF");
767             break;
768         case XDMF_FORMAT_XML :
769             this->Set("Format", "XML");
770             break;
771         case XDMF_FORMAT_MYSQL :
772             this->Set("Format", "MYSQL");
773             break;
774         case XDMF_FORMAT_BINARY :
775             this->Set("Format", "BINARY");
776             break;
777         default :
778             XdmfErrorMessage("Unsupported Data Format");
779             return(XDMF_FAIL);
780     }
781     if(this->BuildFromDataXml(1) == XDMF_SUCCESS) return(XDMF_SUCCESS);
782     if(this->CheckValues(this->Format) != XDMF_SUCCESS){
783         XdmfErrorMessage("Error Accessing Internal XdmfValues");
784         return(XDMF_FAIL);
785     }
786     this->Values->SetDataDesc(aDataDesc);
787     switch (this->Format) {
788         case XDMF_FORMAT_HDF :
789             XdmfDebug("Writing Values in HDF Format");
790             Values->SetHeavyDataSetName(this->GetHeavyDataSetName());
791             Values->SetDsmBuffer(this->GetDsmBuffer());
792             if(((XdmfValuesHDF *)Values)->Write(this->Array) != XDMF_SUCCESS){
793                 XdmfErrorMessage("Writing Values Failed");
794                 return(XDMF_FAIL);
795             }
796             this->Set("Format", "HDF");
797             break;
798         case XDMF_FORMAT_XML :
799             XdmfDebug("Writing Values in XML Format");
800             if(((XdmfValuesXML *)Values)->Write(this->Array) != XDMF_SUCCESS){
801                 XdmfErrorMessage("Writing Values Failed");
802                 return(XDMF_FAIL);
803             }
804             this->Set("Format", "XML");
805             break;
806         default :
807             XdmfErrorMessage("Unsupported Data Format");
808             return(XDMF_FAIL);
809     }
810     return(XDMF_SUCCESS);
811 }
812 
813 XdmfInt32
CheckValues(XdmfInt32 aFormat)814 XdmfDataItem::CheckValues(XdmfInt32 aFormat){
815     if(this->Values){
816         // Exists
817         if(this->Values->Format != aFormat){
818             // Wrong Format
819             XdmfDebug("CheckValues Changing Format");
820             delete this->Values;
821             this->Values = NULL;
822         }
823     }
824     if(!this->Values){
825         // Create One of the Proper Format
826         switch (this->Format) {
827             case XDMF_FORMAT_HDF :
828                 this->Values = (XdmfValues *)new XdmfValuesHDF();
829                 break;
830             case XDMF_FORMAT_XML :
831                 this->Values = (XdmfValues *)new XdmfValuesXML();
832                 break;
833             case XDMF_FORMAT_MYSQL :
834 #ifdef XDMF_USE_MYSQL
835                 this->Values = (XdmfValues *)new XdmfValuesMySQL();
836 #else
837                 XdmfErrorMessage("MySQL not supported in this Xdmf");
838                 return(XDMF_FAIL);
839 #endif
840                 break;
841             case XDMF_FORMAT_BINARY :
842                 this->Values = (XdmfValues *)new XdmfValuesBinary();
843                 break;
844             default :
845                 XdmfErrorMessage("Unsupported Data Format");
846                 return(XDMF_FAIL);
847         }
848     }
849     if(!this->Values){
850         XdmfErrorMessage("Error Creating new XdmfValues");
851         return(XDMF_FAIL);
852     }
853     if(this->Values->Inherit(this) != XDMF_SUCCESS){
854         XdmfErrorMessage("Error Inheriting DOM, Element, and DataDesc");
855         return(XDMF_FAIL);
856     }
857     return(XDMF_SUCCESS);
858 }
859 
860 }
861