1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //============================================================================
10 
11 #include <fides/FidesTypes.h>
12 #include <fides/predefined/DataModelFactory.h>
13 #include <fides/predefined/DataModelHelperFunctions.h>
14 #include <fides/predefined/InternalMetadataSource.h>
15 #include <fides/predefined/PredefinedDataModel.h>
16 #include <fides/predefined/SupportedDataModels.h>
17 
18 #include <fides_rapidjson.h>
19 // clang-format off
20 #include FIDES_RAPIDJSON(rapidjson/document.h)
21 #include FIDES_RAPIDJSON(rapidjson/prettywriter.h)
22 #include FIDES_RAPIDJSON(rapidjson/stringbuffer.h)
23 // clang-format on
24 
25 #include <iostream>
26 
27 namespace fides
28 {
29 namespace predefined
30 {
31 
32 namespace
33 {
34 
35 // Registration callbacks for DataModelFactory
CreateUniform(std::shared_ptr<InternalMetadataSource> source)36 std::shared_ptr<PredefinedDataModel> CreateUniform(std::shared_ptr<InternalMetadataSource> source)
37 {
38   return std::shared_ptr<PredefinedDataModel>(new UniformDataModel(source));
39 }
40 
CreateUniformFromDataSet(const vtkm::cont::DataSet & dataSet)41 std::shared_ptr<PredefinedDataModel> CreateUniformFromDataSet(const vtkm::cont::DataSet& dataSet)
42 {
43   return std::shared_ptr<PredefinedDataModel>(new UniformDataModel(dataSet));
44 }
45 
CreateRectilinearFromDataSet(const vtkm::cont::DataSet & dataSet)46 std::shared_ptr<PredefinedDataModel> CreateRectilinearFromDataSet(
47   const vtkm::cont::DataSet& dataSet)
48 {
49   return std::shared_ptr<PredefinedDataModel>(new RectilinearDataModel(dataSet));
50 }
51 
CreateUnstructuredSingleTypeFromDataSet(const vtkm::cont::DataSet & dataSet)52 std::shared_ptr<PredefinedDataModel> CreateUnstructuredSingleTypeFromDataSet(
53   const vtkm::cont::DataSet& dataSet)
54 {
55   return std::shared_ptr<PredefinedDataModel>(new UnstructuredSingleTypeDataModel(dataSet));
56 }
57 
CreateUnstructuredFromDataSet(const vtkm::cont::DataSet & dataSet)58 std::shared_ptr<PredefinedDataModel> CreateUnstructuredFromDataSet(
59   const vtkm::cont::DataSet& dataSet)
60 {
61   return std::shared_ptr<PredefinedDataModel>(new UnstructuredDataModel(dataSet));
62 }
63 
64 
CreateRectilinear(std::shared_ptr<InternalMetadataSource> source)65 std::shared_ptr<PredefinedDataModel> CreateRectilinear(
66   std::shared_ptr<InternalMetadataSource> source)
67 {
68   return std::shared_ptr<PredefinedDataModel>(new RectilinearDataModel(source));
69 }
70 
CreateUnstructured(std::shared_ptr<InternalMetadataSource> source)71 std::shared_ptr<PredefinedDataModel> CreateUnstructured(
72   std::shared_ptr<InternalMetadataSource> source)
73 {
74   return std::shared_ptr<PredefinedDataModel>(new UnstructuredDataModel(source));
75 }
76 
CreateUnstructuredSingleType(std::shared_ptr<InternalMetadataSource> source)77 std::shared_ptr<PredefinedDataModel> CreateUnstructuredSingleType(
78   std::shared_ptr<InternalMetadataSource> source)
79 {
80   return std::shared_ptr<PredefinedDataModel>(new UnstructuredSingleTypeDataModel(source));
81 }
82 
CreateXGC(std::shared_ptr<InternalMetadataSource> source)83 std::shared_ptr<PredefinedDataModel> CreateXGC(std::shared_ptr<InternalMetadataSource> source)
84 {
85   return std::shared_ptr<PredefinedDataModel>(new XGCDataModel(source));
86 }
87 
88 // registering data models with the factory
89 const bool uniformRegistered =
90   DataModelFactory::GetInstance().RegisterDataModel(DataModelTypes::UNIFORM, CreateUniform);
91 const bool rectilinearRegistered =
92   DataModelFactory::GetInstance().RegisterDataModel(DataModelTypes::RECTILINEAR, CreateRectilinear);
93 const bool unstructuredRegistered =
94   DataModelFactory::GetInstance().RegisterDataModel(DataModelTypes::UNSTRUCTURED,
95                                                     CreateUnstructured);
96 const bool unstructuredSingleRegistered =
97   DataModelFactory::GetInstance().RegisterDataModel(DataModelTypes::UNSTRUCTURED_SINGLE,
98                                                     CreateUnstructuredSingleType);
99 const bool xgcRegistered =
100   DataModelFactory::GetInstance().RegisterDataModel(DataModelTypes::XGC, CreateXGC);
101 
102 const bool uniformDSRegistered =
103   DataModelFactory::GetInstance().RegisterDataModelFromDS(DataModelTypes::UNIFORM,
104                                                           CreateUniformFromDataSet);
105 const bool rectilinearDSRegistered =
106   DataModelFactory::GetInstance().RegisterDataModelFromDS(DataModelTypes::RECTILINEAR,
107                                                           CreateRectilinearFromDataSet);
108 const bool unstructuredSingleDSRegistered =
109   DataModelFactory::GetInstance().RegisterDataModelFromDS(DataModelTypes::UNSTRUCTURED_SINGLE,
110                                                           CreateUnstructuredSingleTypeFromDataSet);
111 const bool unstructuredDSRegistered =
112   DataModelFactory::GetInstance().RegisterDataModelFromDS(DataModelTypes::UNSTRUCTURED,
113                                                           CreateUnstructuredFromDataSet);
114 
115 // some helper functions that are used by different data model classes
116 
GetOptionalVariableName(std::shared_ptr<InternalMetadataSource> source,const std::string & attrName,const std::string & defaultValue)117 std::string GetOptionalVariableName(std::shared_ptr<InternalMetadataSource> source,
118                                     const std::string& attrName,
119                                     const std::string& defaultValue)
120 {
121   if (!source)
122   {
123     return defaultValue;
124   }
125 
126   auto vec = source->GetAttribute<std::string>(attrName);
127   if (vec.empty())
128   {
129     return defaultValue;
130   }
131   return vec[0];
132 }
133 
GetOptionalVariableName(std::shared_ptr<InternalMetadataSource> source,const std::string & attrName)134 std::pair<bool, std::string> GetOptionalVariableName(std::shared_ptr<InternalMetadataSource> source,
135                                                      const std::string& attrName)
136 {
137   if (!source)
138   {
139     return std::make_pair(false, "");
140   }
141 
142   auto vec = source->GetAttribute<std::string>(attrName);
143   if (vec.empty())
144   {
145     return std::make_pair(false, "");
146   }
147   return std::make_pair(true, vec[0]);
148 }
149 
GetRequiredVariableName(std::shared_ptr<InternalMetadataSource> source,const std::string & attrName)150 std::string GetRequiredVariableName(std::shared_ptr<InternalMetadataSource> source,
151                                     const std::string& attrName)
152 {
153   auto dimVarName = source->GetAttribute<std::string>(attrName);
154   if (dimVarName.empty())
155   {
156     throw std::runtime_error(attrName + " must be set for this data model");
157   }
158   return dimVarName[0];
159 }
160 
161 const std::string DataModelAttrName = "Fides_Data_Model";
162 const std::string OriginAttrName = "Fides_Origin";
163 const std::string SpacingAttrName = "Fides_Spacing";
164 const std::string DimensionsAttrName = "Fides_Dimensions";
165 const std::string DimensionsVarAttrName = "Fides_Dimension_Variable";
166 const std::string XVarAttrName = "Fides_X_Variable";
167 const std::string YVarAttrName = "Fides_Y_Variable";
168 const std::string ZVarAttrName = "Fides_Z_Variable";
169 const std::string CoordinatesAttrName = "Fides_Coordinates_Variable";
170 const std::string ConnectivityAttrName = "Fides_Connectivity_Variable";
171 const std::string CellTypesAttrName = "Fides_Cell_Types_Variable";
172 const std::string CellTypeAttrName = "Fides_Cell_Type";
173 const std::string NumVertsAttrName = "Fides_Num_Vertices_Variable";
174 
175 const std::string VarListAttrName = "Fides_Variable_List";
176 const std::string AssocListAttrName = "Fides_Variable_Associations";
177 const std::string VectorListAttrName = "Fides_Variable_Vectors";
178 const std::string VarSourcesAttrName = "Fides_Variable_Sources";
179 const std::string VarArrayTypesAttrName = "Fides_Variable_Array_Types";
180 
181 const std::string XGCNumPlanesAttrName = "Fides_Number_Of_Planes_Variable";
182 const std::string XGCMeshAttrName = "Fides_XGC_Mesh_Filename";
183 const std::string XGC3dAttrName = "Fides_XGC_3d_Filename";
184 const std::string XGCDiagAttrName = "Fides_XGC_Diag_Filename";
185 const std::string XGCTriConnAttrName = "Fides_Triangle_Connectivity_Variable";
186 const std::string XGCPlaneConnAttrName = "Fides_Plane_Connectivity_Variable";
187 
createDimensionsJSON(std::shared_ptr<InternalMetadataSource> mdSource,rapidjson::Document::AllocatorType & allocator,rapidjson::Value & arrObj,const std::string & dataSourceName)188 void createDimensionsJSON(std::shared_ptr<InternalMetadataSource> mdSource,
189                           rapidjson::Document::AllocatorType& allocator,
190                           rapidjson::Value& arrObj,
191                           const std::string& dataSourceName)
192 {
193   auto retVal = GetOptionalVariableName(mdSource, DimensionsVarAttrName);
194   std::string dimVarName;
195   if (retVal.first)
196   {
197     dimVarName = retVal.second;
198     CreateValueVariableDimensions(
199       allocator, arrObj, "variable_dimensions", dataSourceName, dimVarName);
200   }
201   else
202   {
203     retVal = GetOptionalVariableName(mdSource, DimensionsAttrName);
204     if (!retVal.first)
205     {
206       throw std::runtime_error(DimensionsAttrName + " or " + DimensionsVarAttrName + " required");
207     }
208     CreateValueArrayVariable(allocator, arrObj, retVal.second, dataSourceName, "dimensions");
209   }
210 }
211 
212 } // end anonymous namespace
213 
214 //-----------------------------------------------------------------------------
PredefinedDataModel(std::shared_ptr<InternalMetadataSource> source)215 PredefinedDataModel::PredefinedDataModel(std::shared_ptr<InternalMetadataSource> source)
216   : MetadataSource(source)
217   , FieldsToWriteSet(false)
218 {
219 }
220 
PredefinedDataModel(const vtkm::cont::DataSet & dataSet)221 PredefinedDataModel::PredefinedDataModel(const vtkm::cont::DataSet& dataSet)
222   : MetadataSource(nullptr)
223   , DataSetSource(dataSet)
224   , FieldsToWriteSet(false)
225 {
226 }
227 
GetDOM(bool print)228 rapidjson::Document& PredefinedDataModel::GetDOM(bool print /* = false*/)
229 {
230   this->Doc.SetObject();
231   rapidjson::Value root(rapidjson::kObjectType);
232   this->CreateDataSources(root);
233   this->CreateCoordinateSystem(root);
234   this->CreateCellSet(root);
235   this->CreateFields(root);
236   this->AddStepInformation(root);
237   this->AddRootToDocument(root);
238 
239   if (print)
240   {
241     this->PrintJSON();
242   }
243 
244   return this->Doc;
245 }
246 
CreateDataSources(rapidjson::Value & parent)247 void PredefinedDataModel::CreateDataSources(rapidjson::Value& parent)
248 {
249   rapidjson::Value allSources(rapidjson::kArrayType);
250   this->CreateDataSource(allSources, this->DataSourceName, "input");
251   parent.AddMember("data_sources", allSources, this->Doc.GetAllocator());
252 }
253 
CreateDataSource(rapidjson::Value & parent,const std::string & name,const std::string & mode,const std::string & filename)254 void PredefinedDataModel::CreateDataSource(rapidjson::Value& parent,
255                                            const std::string& name,
256                                            const std::string& mode,
257                                            const std::string& filename /*=""*/)
258 {
259   rapidjson::Value source(rapidjson::kObjectType);
260   rapidjson::Value n = SetString(this->Doc.GetAllocator(), name);
261   source.AddMember("name", n, this->Doc.GetAllocator());
262 
263   rapidjson::Value m = SetString(this->Doc.GetAllocator(), mode);
264   source.AddMember("filename_mode", m, this->Doc.GetAllocator());
265 
266   if (mode == "relative")
267   {
268     rapidjson::Value fn = SetString(this->Doc.GetAllocator(), filename);
269     source.AddMember("filename", fn, this->Doc.GetAllocator());
270   }
271   parent.PushBack(source, this->Doc.GetAllocator());
272 }
273 
AddStepInformation(rapidjson::Value & parent)274 void PredefinedDataModel::AddStepInformation(rapidjson::Value& parent)
275 {
276   rapidjson::Value stepInfo(rapidjson::kObjectType);
277   auto srcName = SetString(this->Doc.GetAllocator(), this->DataSourceName);
278   stepInfo.AddMember("data_source", srcName, this->Doc.GetAllocator());
279   parent.AddMember("step_information", stepInfo, this->Doc.GetAllocator());
280 }
281 
AddFieldAttributes(std::unordered_map<std::string,std::vector<std::string>> & attrMap)282 void PredefinedDataModel::AddFieldAttributes(
283   std::unordered_map<std::string, std::vector<std::string>>& attrMap)
284 {
285   vtkm::Id numFields = this->DataSetSource.GetNumberOfFields();
286   attrMap[VarListAttrName] = std::vector<std::string>();
287   attrMap[AssocListAttrName] = std::vector<std::string>();
288   attrMap[VectorListAttrName] = std::vector<std::string>();
289   for (vtkm::Id i = 0; i < numFields; i++)
290   {
291     auto field = this->DataSetSource.GetField(i);
292     //If field restriction is turned on, then skip those fields.
293     if (this->FieldsToWriteSet &&
294         this->FieldsToWrite.find(field.GetName()) == this->FieldsToWrite.end())
295     {
296       continue;
297     }
298 
299     std::string assoc;
300     if (field.IsFieldCell())
301     {
302       assoc = "cell_set";
303     }
304     else if (field.IsFieldPoint())
305     {
306       assoc = "points";
307     }
308     else
309     {
310       throw std::runtime_error("Unsupported field association");
311     }
312 
313     // we handle isVector as string instead of bool, because there's also a
314     // case where it could be "auto", but in this case it's always true or false
315     std::string isVector = "false";
316     if (field.GetData().GetNumberOfComponents() > 1)
317       isVector = "true";
318 
319     attrMap[VarListAttrName].push_back(field.GetName());
320     attrMap[AssocListAttrName].push_back(assoc);
321     attrMap[VectorListAttrName].push_back(isVector);
322   }
323 }
324 
CreateFields(rapidjson::Value & parent)325 void PredefinedDataModel::CreateFields(rapidjson::Value& parent)
326 {
327   if (this->MetadataSource == nullptr)
328   {
329     vtkm::Id numFields = this->DataSetSource.GetNumberOfFields();
330     rapidjson::Value fieldArr(rapidjson::kArrayType);
331     for (vtkm::Id i = 0; i < numFields; i++)
332     {
333       auto field = this->DataSetSource.GetField(i);
334       //If field restriction is turned on, then skip those fields.
335       if (this->FieldsToWriteSet &&
336           this->FieldsToWrite.find(field.GetName()) == this->FieldsToWrite.end())
337       {
338         continue;
339       }
340 
341       rapidjson::Value fieldObj(rapidjson::kObjectType);
342       auto fieldName = SetString(this->Doc.GetAllocator(), field.GetName());
343       fieldObj.AddMember("name", fieldName, this->Doc.GetAllocator());
344       std::string assoc = "unknown";
345       if (field.IsFieldCell())
346         assoc = "cell_set";
347       else if (field.IsFieldPoint())
348         assoc = "points";
349       else
350         throw std::runtime_error("Unsupported field association");
351 
352       bool isVector = false;
353       if (field.GetData().GetNumberOfComponents() > 1)
354         isVector = true;
355 
356       auto assocStr = SetString(this->Doc.GetAllocator(), assoc);
357       fieldObj.AddMember("association", assocStr, this->Doc.GetAllocator());
358 
359       rapidjson::Value arrObj(rapidjson::kObjectType);
360       arrObj.AddMember("array_type", "basic", this->Doc.GetAllocator());
361       auto srcName = SetString(this->Doc.GetAllocator(), this->DataSourceName);
362       arrObj.AddMember("data_source", srcName, this->Doc.GetAllocator());
363       if (isVector)
364         arrObj.AddMember("is_vector", "true", this->Doc.GetAllocator());
365       else
366         arrObj.AddMember("is_vector", "false", this->Doc.GetAllocator());
367 
368       arrObj.AddMember(
369         "variable", SetString(this->Doc.GetAllocator(), field.GetName()), this->Doc.GetAllocator());
370       fieldObj.AddMember("array", arrObj, this->Doc.GetAllocator());
371 
372       fieldArr.PushBack(fieldObj, this->Doc.GetAllocator());
373     }
374 
375     parent.AddMember("fields", fieldArr, this->Doc.GetAllocator());
376     return;
377   }
378 
379   auto varList = this->MetadataSource->GetAttribute<std::string>(VarListAttrName);
380   if (varList.empty())
381   {
382     // In this case there are no fields specified in an ADIOS attribute
383     return;
384   }
385   rapidjson::Value fields(rapidjson::kArrayType);
386   rapidjson::Value field(rapidjson::kObjectType);
387   auto varListName = SetString(this->Doc.GetAllocator(), VarListAttrName);
388   field.AddMember("variable_list_attribute_name", varListName, this->Doc.GetAllocator());
389   auto assocListName = SetString(this->Doc.GetAllocator(), AssocListAttrName);
390   field.AddMember("variable_association_attribute_name", assocListName, this->Doc.GetAllocator());
391   auto vecListName = SetString(this->Doc.GetAllocator(), VectorListAttrName);
392   field.AddMember("variable_vector_attribute_name", vecListName, this->Doc.GetAllocator());
393   rapidjson::Value arrObj(rapidjson::kObjectType);
394   CreateArrayBasic(this->Doc.GetAllocator(), arrObj, this->DataSourceName, "");
395   field.AddMember("array", arrObj, this->Doc.GetAllocator());
396   fields.PushBack(field, this->Doc.GetAllocator());
397   parent.AddMember("fields", fields, this->Doc.GetAllocator());
398 }
399 
PrintJSON()400 void PredefinedDataModel::PrintJSON()
401 {
402   rapidjson::StringBuffer buf;
403   rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
404   this->Doc.Accept(writer);
405   std::cout << buf.GetString() << std::endl;
406 }
407 
408 //-----------------------------------------------------------------------------
UniformDataModel(std::shared_ptr<InternalMetadataSource> source)409 UniformDataModel::UniformDataModel(std::shared_ptr<InternalMetadataSource> source)
410   : PredefinedDataModel(source)
411 {
412 }
413 
UniformDataModel(const vtkm::cont::DataSet & dataSet)414 UniformDataModel::UniformDataModel(const vtkm::cont::DataSet& dataSet)
415   : PredefinedDataModel(dataSet)
416 {
417 }
418 
GetAttributes()419 std::unordered_map<std::string, std::vector<std::string>> UniformDataModel::GetAttributes()
420 {
421   std::unordered_map<std::string, std::vector<std::string>> attrMap;
422   attrMap[DataModelAttrName] = std::vector<std::string>(1, "uniform");
423   attrMap[OriginAttrName] = std::vector<std::string>(1, "origin");
424   attrMap[SpacingAttrName] = std::vector<std::string>(1, "spacing");
425   attrMap[DimensionsAttrName] = std::vector<std::string>(1, "dims");
426   this->AddFieldAttributes(attrMap);
427   return attrMap;
428 }
429 
CreateCoordinateSystem(rapidjson::Value & parent)430 void UniformDataModel::CreateCoordinateSystem(rapidjson::Value& parent)
431 {
432   if (this->MetadataSource == nullptr)
433   {
434     auto dcellSet = this->DataSetSource.GetCellSet();
435     if (!dcellSet.IsType<StructuredCell3DType>())
436     {
437       throw "Cellset not uniform 3D.";
438     }
439 
440     CreateArrayUniformPointCoordinates(
441       this->Doc.GetAllocator(), parent, "dims", "origin", "spacing");
442     return;
443   }
444 
445   rapidjson::Value coordSys(rapidjson::kObjectType);
446   rapidjson::Value arrObj(rapidjson::kObjectType);
447   arrObj.AddMember("array_type", "uniform_point_coordinates", this->Doc.GetAllocator());
448   createDimensionsJSON(
449     this->MetadataSource, this->Doc.GetAllocator(), arrObj, this->DataSourceName);
450 
451   CreateValueArray(this->Doc.GetAllocator(),
452                    arrObj,
453                    this->MetadataSource,
454                    OriginAttrName,
455                    "origin",
456                    this->DataSourceName);
457   CreateValueArray(this->Doc.GetAllocator(),
458                    arrObj,
459                    this->MetadataSource,
460                    SpacingAttrName,
461                    "spacing",
462                    this->DataSourceName);
463 
464   coordSys.AddMember("array", arrObj, this->Doc.GetAllocator());
465   parent.AddMember("coordinate_system", coordSys, this->Doc.GetAllocator());
466 }
467 
CreateCellSet(rapidjson::Value & parent)468 void UniformDataModel::CreateCellSet(rapidjson::Value& parent)
469 {
470   if (this->MetadataSource == nullptr)
471   {
472     CreateStructuredCellset(this->Doc.GetAllocator(), parent, "dims");
473     return;
474   }
475   rapidjson::Value cellSet(rapidjson::kObjectType);
476   cellSet.AddMember("cell_set_type", "structured", this->Doc.GetAllocator());
477   createDimensionsJSON(
478     this->MetadataSource, this->Doc.GetAllocator(), cellSet, this->DataSourceName);
479   parent.AddMember("cell_set", cellSet, this->Doc.GetAllocator());
480 }
481 
AddRootToDocument(rapidjson::Value & root)482 void UniformDataModel::AddRootToDocument(rapidjson::Value& root)
483 {
484   this->Doc.AddMember("uniform_grid", root, this->Doc.GetAllocator());
485 }
486 
487 //-----------------------------------------------------------------------------
RectilinearDataModel(std::shared_ptr<InternalMetadataSource> source)488 RectilinearDataModel::RectilinearDataModel(std::shared_ptr<InternalMetadataSource> source)
489   : PredefinedDataModel(source)
490 {
491 }
492 
RectilinearDataModel(const vtkm::cont::DataSet & dataSet)493 RectilinearDataModel::RectilinearDataModel(const vtkm::cont::DataSet& dataSet)
494   : PredefinedDataModel(dataSet)
495 {
496 }
497 
GetAttributes()498 std::unordered_map<std::string, std::vector<std::string>> RectilinearDataModel::GetAttributes()
499 {
500   std::unordered_map<std::string, std::vector<std::string>> attrMap;
501   attrMap[DataModelAttrName] = std::vector<std::string>(1, "rectilinear");
502   attrMap[XVarAttrName] = std::vector<std::string>(1, "x_array");
503   attrMap[YVarAttrName] = std::vector<std::string>(1, "y_array");
504   attrMap[ZVarAttrName] = std::vector<std::string>(1, "z_array");
505   attrMap[DimensionsAttrName] = std::vector<std::string>(1, "dims");
506   this->AddFieldAttributes(attrMap);
507   return attrMap;
508 }
509 
CreateCoordinateSystem(rapidjson::Value & parent)510 void RectilinearDataModel::CreateCoordinateSystem(rapidjson::Value& parent)
511 {
512   if (this->MetadataSource == nullptr)
513   {
514     auto dcellSet = this->DataSetSource.GetCellSet();
515     if (!dcellSet.IsType<StructuredCell3DType>())
516     {
517       throw "Cellset not structured 3D.";
518     }
519 
520     CreateArrayRectilinearPointCoordinates(
521       this->Doc.GetAllocator(), parent, "x_array", "y_array", "z_array");
522     return;
523   }
524 
525   rapidjson::Value coordSys(rapidjson::kObjectType);
526   rapidjson::Value arrObj(rapidjson::kObjectType);
527   CreateArrayCartesianProduct(
528     this->Doc.GetAllocator(), arrObj, this->MetadataSource, this->DataSourceName);
529   coordSys.AddMember("array", arrObj, this->Doc.GetAllocator());
530   parent.AddMember("coordinate_system", coordSys, this->Doc.GetAllocator());
531 }
532 
CreateCellSet(rapidjson::Value & parent)533 void RectilinearDataModel::CreateCellSet(rapidjson::Value& parent)
534 {
535   if (this->MetadataSource == nullptr)
536   {
537     CreateStructuredCellset(this->Doc.GetAllocator(), parent, "dims");
538     return;
539   }
540 
541   rapidjson::Value cellSet(rapidjson::kObjectType);
542   cellSet.AddMember("cell_set_type", "structured", this->Doc.GetAllocator());
543   createDimensionsJSON(
544     this->MetadataSource, this->Doc.GetAllocator(), cellSet, this->DataSourceName);
545   parent.AddMember("cell_set", cellSet, this->Doc.GetAllocator());
546 }
547 
AddRootToDocument(rapidjson::Value & root)548 void RectilinearDataModel::AddRootToDocument(rapidjson::Value& root)
549 {
550   this->Doc.AddMember("rectilinear_grid", root, this->Doc.GetAllocator());
551 }
552 
553 //-----------------------------------------------------------------------------
UnstructuredDataModel(std::shared_ptr<InternalMetadataSource> source)554 UnstructuredDataModel::UnstructuredDataModel(std::shared_ptr<InternalMetadataSource> source)
555   : PredefinedDataModel(source)
556 {
557 }
558 
UnstructuredDataModel(const vtkm::cont::DataSet & dataSet)559 UnstructuredDataModel::UnstructuredDataModel(const vtkm::cont::DataSet& dataSet)
560   : PredefinedDataModel(dataSet)
561 {
562 }
563 
GetAttributes()564 std::unordered_map<std::string, std::vector<std::string>> UnstructuredDataModel::GetAttributes()
565 {
566   std::unordered_map<std::string, std::vector<std::string>> attrMap;
567   attrMap[DataModelAttrName] = std::vector<std::string>(1, "unstructured");
568   attrMap[CoordinatesAttrName] = std::vector<std::string>(1, "coordinates");
569   attrMap[ConnectivityAttrName] = std::vector<std::string>(1, "connectivity");
570   attrMap[CellTypesAttrName] = std::vector<std::string>(1, "cell_types");
571   attrMap[NumVertsAttrName] = std::vector<std::string>(1, "num_verts");
572   this->AddFieldAttributes(attrMap);
573   return attrMap;
574 }
575 
CreateCoordinateSystem(rapidjson::Value & parent)576 void UnstructuredDataModel::CreateCoordinateSystem(rapidjson::Value& parent)
577 {
578   if (this->MetadataSource == nullptr)
579   {
580     auto dcellSet = this->DataSetSource.GetCellSet();
581     if (!dcellSet.IsType<UnstructuredSingleType>() && !dcellSet.IsType<UnstructuredType>())
582     {
583       throw std::runtime_error("Cellset is not UnstructuredSingleType.");
584     }
585 
586     CreateArrayUnstructuredPointCoordinates(this->Doc.GetAllocator(), parent, "coordinates");
587     return;
588   }
589 
590   rapidjson::Value coordSys(rapidjson::kObjectType);
591   rapidjson::Value arrObj(rapidjson::kObjectType);
592   auto varName = GetOptionalVariableName(this->MetadataSource, CoordinatesAttrName, "points");
593   CreateArrayBasic(this->Doc.GetAllocator(), arrObj, this->DataSourceName, varName, false);
594   coordSys.AddMember("array", arrObj, this->Doc.GetAllocator());
595   parent.AddMember("coordinate_system", coordSys, this->Doc.GetAllocator());
596 }
597 
CreateCellSet(rapidjson::Value & parent)598 void UnstructuredDataModel::CreateCellSet(rapidjson::Value& parent)
599 {
600   rapidjson::Value cellSet(rapidjson::kObjectType);
601   cellSet.AddMember("cell_set_type", "explicit", this->Doc.GetAllocator());
602 
603   rapidjson::Value connectivity(rapidjson::kObjectType);
604   std::string connName =
605     GetOptionalVariableName(this->MetadataSource, ConnectivityAttrName, "connectivity");
606   CreateArrayBasic(this->Doc.GetAllocator(), connectivity, this->DataSourceName, connName);
607   cellSet.AddMember("connectivity", connectivity, this->Doc.GetAllocator());
608 
609   rapidjson::Value cellTypes(rapidjson::kObjectType);
610   std::string ctName =
611     GetOptionalVariableName(this->MetadataSource, CellTypesAttrName, "cell_types");
612   CreateArrayBasic(this->Doc.GetAllocator(), cellTypes, this->DataSourceName, ctName);
613   cellSet.AddMember("cell_types", cellTypes, this->Doc.GetAllocator());
614 
615   rapidjson::Value numVertices(rapidjson::kObjectType);
616   std::string vertName =
617     GetOptionalVariableName(this->MetadataSource, NumVertsAttrName, "num_verts");
618   CreateArrayBasic(this->Doc.GetAllocator(), numVertices, this->DataSourceName, vertName);
619   cellSet.AddMember("number_of_vertices", numVertices, this->Doc.GetAllocator());
620 
621   parent.AddMember("cell_set", cellSet, this->Doc.GetAllocator());
622 }
623 
AddRootToDocument(rapidjson::Value & root)624 void UnstructuredDataModel::AddRootToDocument(rapidjson::Value& root)
625 {
626   this->Doc.AddMember("unstructured_grid", root, this->Doc.GetAllocator());
627 }
628 
629 //-----------------------------------------------------------------------------
UnstructuredSingleTypeDataModel(std::shared_ptr<InternalMetadataSource> source)630 UnstructuredSingleTypeDataModel::UnstructuredSingleTypeDataModel(
631   std::shared_ptr<InternalMetadataSource> source)
632   : UnstructuredDataModel(source)
633 {
634 }
635 
UnstructuredSingleTypeDataModel(const vtkm::cont::DataSet & dataSet)636 UnstructuredSingleTypeDataModel::UnstructuredSingleTypeDataModel(const vtkm::cont::DataSet& dataSet)
637   : UnstructuredDataModel(dataSet)
638 {
639 }
640 
641 std::unordered_map<std::string, std::vector<std::string>>
GetAttributes()642 UnstructuredSingleTypeDataModel::GetAttributes()
643 {
644   std::unordered_map<std::string, std::vector<std::string>> attrMap;
645   attrMap[DataModelAttrName] = std::vector<std::string>(1, "unstructured_single");
646   attrMap[CoordinatesAttrName] = std::vector<std::string>(1, "coordinates");
647   attrMap[ConnectivityAttrName] = std::vector<std::string>(1, "connectivity");
648 
649   const auto& cellSet = this->DataSetSource.GetCellSet().Cast<UnstructuredSingleType>();
650   vtkm::UInt8 shapeId = cellSet.GetCellShape(0);
651   std::string cellType = fides::ConvertVTKmCellTypeToFides(shapeId);
652   attrMap[CellTypeAttrName] = std::vector<std::string>(1, cellType);
653   this->AddFieldAttributes(attrMap);
654   return attrMap;
655 }
656 
CreateCellSet(rapidjson::Value & parent)657 void UnstructuredSingleTypeDataModel::CreateCellSet(rapidjson::Value& parent)
658 {
659   if (this->MetadataSource == nullptr)
660   {
661     auto dcellSet = this->DataSetSource.GetCellSet();
662     if (!dcellSet.IsType<UnstructuredSingleType>())
663     {
664       throw std::runtime_error("Cellset is not UnstructuredSingleType");
665     }
666     const auto& cellSet = this->DataSetSource.GetCellSet().Cast<UnstructuredSingleType>();
667     vtkm::UInt8 shapeId = cellSet.GetCellShape(0);
668     std::string cellType = fides::ConvertVTKmCellTypeToFides(shapeId);
669 
670     CreateUnstructuredSingleTypeCellset(this->Doc.GetAllocator(), parent, "connectivity", cellType);
671     return;
672   }
673 
674   // structured
675   rapidjson::Value cellSet(rapidjson::kObjectType);
676   cellSet.AddMember("cell_set_type", "single_type", this->Doc.GetAllocator());
677 
678   std::string cellType = this->MetadataSource->GetDataModelCellType();
679   rapidjson::Value ct = SetString(this->Doc.GetAllocator(), cellType);
680   cellSet.AddMember("cell_type", ct, this->Doc.GetAllocator());
681   auto srcName = SetString(this->Doc.GetAllocator(), this->DataSourceName);
682   cellSet.AddMember("data_source", srcName, this->Doc.GetAllocator());
683 
684   auto connName =
685     GetOptionalVariableName(this->MetadataSource, ConnectivityAttrName, "connectivity");
686   auto conn = SetString(this->Doc.GetAllocator(), connName);
687   cellSet.AddMember("variable", conn, this->Doc.GetAllocator());
688 
689   parent.AddMember("cell_set", cellSet, this->Doc.GetAllocator());
690 }
691 
AddRootToDocument(rapidjson::Value & root)692 void UnstructuredSingleTypeDataModel::AddRootToDocument(rapidjson::Value& root)
693 {
694   this->Doc.AddMember("unstructured_grid_single_cell_type", root, this->Doc.GetAllocator());
695 }
696 
697 //-----------------------------------------------------------------------------
XGCDataModel(std::shared_ptr<InternalMetadataSource> source)698 XGCDataModel::XGCDataModel(std::shared_ptr<InternalMetadataSource> source)
699   : PredefinedDataModel(source)
700 {
701 }
702 
GetAttributes()703 std::unordered_map<std::string, std::vector<std::string>> XGCDataModel::GetAttributes()
704 {
705   std::unordered_map<std::string, std::vector<std::string>> attrMap;
706   attrMap[DataModelAttrName] = std::vector<std::string>(1, "xgc");
707   this->AddFieldAttributes(attrMap);
708   return attrMap;
709 }
710 
GetDOM(bool print)711 rapidjson::Document& XGCDataModel::GetDOM(bool print /* = false*/)
712 {
713   PredefinedDataModel::GetDOM();
714   if (!this->Doc.HasMember("xgc"))
715   {
716     throw std::runtime_error("doc doesn't have xgc member");
717   }
718   auto& root = this->Doc["xgc"];
719   auto nplanes = GetOptionalVariableName(this->MetadataSource, XGCNumPlanesAttrName, "nphi");
720   CreateValueScalar(this->Doc.GetAllocator(), root, "number_of_planes", "scalar", "3d", "nphi");
721 
722   if (print)
723   {
724     this->PrintJSON();
725   }
726 
727   return this->Doc;
728 }
729 
CreateDataSources(rapidjson::Value & parent)730 void XGCDataModel::CreateDataSources(rapidjson::Value& parent)
731 {
732   rapidjson::Value allSources(rapidjson::kArrayType);
733   auto meshFilename = GetOptionalVariableName(this->MetadataSource, XGCMeshAttrName, "xgc.mesh.bp");
734   this->CreateDataSource(allSources, "mesh", "relative", meshFilename);
735   auto dFilename = GetOptionalVariableName(this->MetadataSource, XGC3dAttrName, "xgc.3d.bp");
736   this->CreateDataSource(allSources, "3d", "relative", dFilename);
737   auto diagFilename =
738     GetOptionalVariableName(this->MetadataSource, XGCDiagAttrName, "xgc.oneddiag.bp");
739   this->CreateDataSource(allSources, "diag", "relative", diagFilename);
740   parent.AddMember("data_sources", allSources, this->Doc.GetAllocator());
741 }
742 
AddStepInformation(rapidjson::Value & parent)743 void XGCDataModel::AddStepInformation(rapidjson::Value& parent)
744 {
745   rapidjson::Value stepInfo(rapidjson::kObjectType);
746   stepInfo.AddMember("data_source", "3d", this->Doc.GetAllocator());
747   parent.AddMember("step_information", stepInfo, this->Doc.GetAllocator());
748 }
749 
CreateCoordinateSystem(rapidjson::Value & parent)750 void XGCDataModel::CreateCoordinateSystem(rapidjson::Value& parent)
751 {
752   rapidjson::Value coordSys(rapidjson::kObjectType);
753   rapidjson::Value arrObj(rapidjson::kObjectType);
754   auto coords = GetOptionalVariableName(this->MetadataSource, CoordinatesAttrName, "rz");
755   CreateArrayXGCCoordinates(this->Doc.GetAllocator(), arrObj, "mesh", coords);
756   coordSys.AddMember("array", arrObj, this->Doc.GetAllocator());
757   parent.AddMember("coordinate_system", coordSys, this->Doc.GetAllocator());
758 }
759 
CreateCellSet(rapidjson::Value & parent)760 void XGCDataModel::CreateCellSet(rapidjson::Value& parent)
761 {
762   rapidjson::Value cellSet(rapidjson::kObjectType);
763   cellSet.AddMember("cell_set_type", "xgc", this->Doc.GetAllocator());
764   cellSet.AddMember("periodic", true, this->Doc.GetAllocator());
765 
766   auto triConn =
767     GetOptionalVariableName(this->MetadataSource, XGCTriConnAttrName, "nd_connect_list");
768   rapidjson::Value cells(rapidjson::kObjectType);
769   CreateArrayBasic(this->Doc.GetAllocator(), cells, "mesh", triConn);
770   cells.AddMember("static", true, this->Doc.GetAllocator());
771   cells.AddMember("is_vector", "false", this->Doc.GetAllocator());
772   cellSet.AddMember("cells", cells, this->Doc.GetAllocator());
773 
774   auto planeConn = GetOptionalVariableName(this->MetadataSource, XGCPlaneConnAttrName, "nextnode");
775   rapidjson::Value conn(rapidjson::kObjectType);
776   CreateArrayBasic(this->Doc.GetAllocator(), conn, "mesh", planeConn);
777   conn.AddMember("static", true, this->Doc.GetAllocator());
778   conn.AddMember("is_vector", "false", this->Doc.GetAllocator());
779   cellSet.AddMember("plane_connectivity", conn, this->Doc.GetAllocator());
780 
781   parent.AddMember("cell_set", cellSet, this->Doc.GetAllocator());
782 }
783 
CreateFields(rapidjson::Value & parent)784 void XGCDataModel::CreateFields(rapidjson::Value& parent)
785 {
786   rapidjson::Value fields(rapidjson::kArrayType);
787   rapidjson::Value field(rapidjson::kObjectType);
788   auto varListName = SetString(this->Doc.GetAllocator(), VarListAttrName);
789   field.AddMember("variable_list_attribute_name", varListName, this->Doc.GetAllocator());
790   auto assocListName = SetString(this->Doc.GetAllocator(), AssocListAttrName);
791   field.AddMember("variable_association_attribute_name", assocListName, this->Doc.GetAllocator());
792   auto varSourcesName = SetString(this->Doc.GetAllocator(), VarSourcesAttrName);
793   field.AddMember("variable_sources_attribute_name", varSourcesName, this->Doc.GetAllocator());
794   auto varArrayTypesName = SetString(this->Doc.GetAllocator(), VarArrayTypesAttrName);
795   field.AddMember("variable_arrays_attribute_name", varArrayTypesName, this->Doc.GetAllocator());
796 
797   rapidjson::Value arrObj(rapidjson::kObjectType);
798   CreateArrayBasic(this->Doc.GetAllocator(), arrObj, "", "", false, "");
799   field.AddMember("array", arrObj, this->Doc.GetAllocator());
800 
801   fields.PushBack(field, this->Doc.GetAllocator());
802   parent.AddMember("fields", fields, this->Doc.GetAllocator());
803 }
804 
AddRootToDocument(rapidjson::Value & root)805 void XGCDataModel::AddRootToDocument(rapidjson::Value& root)
806 {
807   this->Doc.AddMember("xgc", root, this->Doc.GetAllocator());
808 }
809 
810 }
811 }
812