MFEMSidreDataCollection does not like to read a field.
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 196
- Forks
- 34
- Avg merge
- 4d 1h
- Merged PRs (30d)
- 11
Description
When writing a CI test for IntersectionShaper replacement rules, I had been trying to save an MFEMSidreDataCollection that included volume fraction arrays. These were mfem::GridFunctions allocated using code that I don't recall modifying other than splitting it out into a method. The following program makes a MFEMSidreDataCollection like what might be seen as output from the IntersectionShaper and writes it out and then reads it back in. On readback, sidre claims that the fields do not meet Blueprint standards. So, is the data wrong before writing it out? There was no apparent failure during Save(). Or, is there a problem in Load() that messes up these fields?
This code was built using an Axom on rzgenie that used the rzgenie-toss_3_x86_64_ib-gcc@8.3.1.cmake host config.
Running "sidredebug > output.txt" works fine as there are no fields.
Running "sidredebug -fields > output.txt" produces the errors below.
```
#include
#include
#include
#define PARALLEL
#ifdef PARALLEL
#include
#endif
#include
#define USE_PREFIX
#include
using std::cout;
using std::endl;
namespace sidre = axom::sidre;
// Is there something wrong with this MFEM grid function? It is
// borrowed from IntersectionShaper.
mfem::GridFunction *
newGridFunction(mfem::Mesh *mesh)
{
const int vfOrder = 0;
const int dim = mesh->Dimension();
mfem::L2_FECollection* coll =
new mfem::L2_FECollection(vfOrder, dim, mfem::BasisType::Positive);
mfem::FiniteElementSpace* fes = new mfem::FiniteElementSpace(mesh, coll);
mfem::GridFunction* gf = new mfem::GridFunction(fes);
gf->MakeOwner(coll);
memset(gf->GetData(), 0, gf->Size() * sizeof(double));
return gf;
}
void
makeTestMesh(sidre::MFEMSidreDataCollection &dc, bool addFields)
{
int polynomialOrder = 1;
double lo[] = {0., 0., -0.25};
double hi[] = {1., 1., 0.};
int celldims[] = {20, 20, 1};
auto mesh = new mfem::Mesh(mfem::Mesh::MakeCartesian3D(celldims[0],
celldims[1],
celldims[2],
mfem::Element::HEXAHEDRON,
hi[0] - lo[0],
hi[1] - lo[1],
hi[2] - lo[2],
false));
mesh->SetCurvature(polynomialOrder);
dc.SetMeshNodesName("positions");
dc.SetMesh(mesh);
if(addFields)
{
// This mode will make 2 clean materials in the mesh.
mfem::GridFunction *mata = newGridFunction(mesh);
mfem::GridFunction *matb = newGridFunction(mesh);
for(int k = 0; k < celldims[2]; k++)
{
for(int j = 0; j < celldims[1]; j++)
{
for(int i = 0; i < celldims[0]; i++)
{
int id = k*celldims[1]*celldims[0] + j*celldims[0] + i;
(*mata)(id) = (j < celldims[1]/2);
(*matb)(id) = (j >= celldims[1]/2);
}
}
}
dc.RegisterField("vol_frac_a", mata);
dc.RegisterField("vol_frac_b", matb);
}
}
int
main(int argc, char *argv[])
{
#ifdef PARALLEL
MPI_Init(&argc, &argv);
#endif
bool addFields = false;
for(int i = 1; i < argc; i++)
{
if(strcmp(argv[i],"-fields") == 0)
addFields = true;
}
cout << "Making mesh" << endl;
std::string baseName("foo");
sidre::MFEMSidreDataCollection dc(baseName, nullptr, true);
makeTestMesh(dc, addFields);
// We have to set this to make it work.
dc.SetComm(MPI_COMM_WORLD);
#ifdef USE_PREFIX
mkdir("baselines", 0750);
dc.SetPrefixPath("baselines");
#endif
// Save the data
cout << "Saving mesh" << endl;
dc.SetCycle(0);
dc.Save();
cout << "Loading mesh" << endl;
sidre::MFEMSidreDataCollection fromFileDC(baseName, nullptr, true);
fromFileDC.SetCycle(0);
// We have to set this to make it work.
fromFileDC.SetComm(MPI_COMM_WORLD);
#ifdef USE_PREFIX
fromFileDC.SetPrefixPath("baselines");
#endif
fromFileDC.Load(0);
#ifdef PARALLEL
MPI_Finalize();
#endif
return 0;
}
```
CMake
```
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_COMPILER /usr/tce/packages/gcc/gcc-8.3.1/bin/g++)
set(CMAKE_C_COMPILER /usr/tce/packages/gcc/gcc-8.3.1/bin/gcc)
set(CMAKE_BUILD_TYPE Debug)
project(sidrebug)
add_compile_options("-std=c++14")
set(axom_DIR /usr/WS2/whitlocb/Axom/axom/install-rzgenie/lib/cmake)
find_package(axom)
add_executable(sidredebug main.cpp)
target_link_libraries(sidredebug axom)
```
Program output
```
Making mesh
gf->GetData=0x1b814d0, gf->Size=400
gf->GetData=0x1ba9760, gf->Size=400
Saving mesh
Loading mesh
***********************************
LEVEL=WARNING
MESSAGE=MFEMSidreDataCollection blueprint verification failed:
coordsets:
valid: "true"
coords:
type:
valid: "true"
info:
- "mesh::coordset::explicit: 'type' has valid value 'explicit'"
- "mesh::coordset::explicit: 'values' is an mcarray"
values:
valid: "true"
valid: "true"
topologies:
valid: "true"
mesh:
coordset:
valid: "true"
type:
valid: "true"
info:
- "mesh::topology::unstructured: 'type' has valid value 'unstructured'"
elements:
valid: "true"
shape:
valid: "true"
info:
- "mesh::topology::shape: has valid value 'hex'"
connectivity:
valid: "true"
valid: "true"
optional:
- "mesh::topology: includes grid_function"
grid_function:
valid: "true"
boundary:
coordset:
valid: "true"
type:
valid: "true"
info:
- "mesh::topology::unstructured: 'type' has valid value 'unstructured'"
elements:
valid: "true"
shape:
valid: "true"
info:
- "mesh::topology::shape: has valid value 'quad'"
connectivity:
valid: "true"
valid: "true"
fields:
valid: "false"
mesh_material_attribute:
association:
valid: "true"
info:
- "mesh::association: has valid value 'element'"
topology:
valid: "true"
values:
valid: "true"
info:
- "mesh::field: 'values' is an mlarray"
valid: "true"
boundary_material_attribute:
association:
valid: "true"
info:
- "mesh::association: has valid value 'element'"
topology:
valid: "true"
values:
valid: "true"
info:
- "mesh::field: 'values' is an mlarray"
valid: "true"
positions:
basis:
valid: "true"
topology:
valid: "true"
values:
valid: "true"
info:
- "mesh::field: 'values' is an mlarray"
valid: "true"
vol_frac_a:
basis:
valid: "true"
topology:
valid: "true"
values:
errors:
- "mlarray: mlarray is empty"
valid: "false"
errors:
- "mesh::field: 'values' is not an mlarray"
valid: "false"
vol_frac_b:
basis:
valid: "true"
topology:
valid: "true"
values:
errors:
- "mlarray: mlarray is empty"
valid: "false"
errors:
- "mesh::field: 'values' is not an mlarray"
valid: "false"
valid: "false"
FILE=/usr/WS2/whitlocb/Axom/axom/src/axom/sidre/core/MFEMSidreDataCollection.cpp
LINE=723
***********************************
***********************************
LEVEL=ERROR
MESSAGE=Cannot reconstruct mesh, data does not satisfy Conduit Blueprint
** StackTrace of 8 frames **
Frame 1: axom::slic::logErrorMessage(std::string const&, std::string const&, int)
Frame 2: axom::sidre::MFEMSidreDataCollection::reconstructMesh()
Frame 3: axom::sidre::MFEMSidreDataCollection::UpdateMeshAndFieldsFromDS()
Frame 4: axom::sidre::MFEMSidreDataCollection::Load(std::string const&, std::string const&)
Frame 5: axom::sidre::MFEMSidreDataCollection::Load(int)
Frame 6: main
Frame 7: __libc_start_main
Frame 8: ./sidredebug() [0x6b0cd4]
=====
FILE=/usr/WS2/whitlocb/Axom/axom/src/axom/sidre/core/MFEMSidreDataCollection.cpp
LINE=2398
***********************************
```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer in main.cpp and run sidredebug -fields to reproduce the Blueprint errors for vol_frac_a and vol_frac_b. Then inspect MFEMSidreDataCollection.cpp at reconstructMesh() and UpdateMeshAndFieldsFromDS(); done means the saved fields remain valid on Load() and mesh reconstruction completes without Blueprint errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, hpc
- Domain
- data-engineering
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100