Commit f5677470 authored by whitlocb's avatar whitlocb

Added better zero-copy support for Libsim.

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@26836 18c085ea-50e0-402c-830e-de6fd14e8384
parent 9d94a63b
......@@ -292,6 +292,9 @@ static void ConvertToType(oT *obuf, const iT* ibuf, size_t n)
// Gunther H. Weber, Thu Nov 8 10:20:32 PST 2012
// Use size_t instead of int
//
// Brad Whitlock, Thu Jul 23 16:01:46 PDT 2015
// Support for non-standard memory layout. Use vtkTemplateMacro.
//
// ****************************************************************************
static vtkDataArray *
......@@ -309,9 +312,6 @@ ConvertDataArrayToFloat(vtkDataArray *oldArr)
newArr->SetNumberOfComponents(numComponents);
newArr->SetNumberOfTuples(numTuples);
float *newBuf = (float*) newArr->GetVoidPointer(0);
void *oldBuf = oldArr->GetVoidPointer(0);
debug1 << "avtTransformManager: Converting vktDataArray, ";
if (oldArr->GetName() != NULL)
{
......@@ -322,52 +322,22 @@ ConvertDataArrayToFloat(vtkDataArray *oldArr)
<< DataArrayTypeName(oldArr) << "\" to \"float\"" << endl;
size_t numValues = numTuples * numComponents;
switch (oldArr->GetDataType())
if(oldArr->HasStandardMemoryLayout())
{
case VTK_CHAR:
ConvertToType(newBuf, (char*) oldBuf, numValues);
break;
case VTK_UNSIGNED_CHAR:
ConvertToType(newBuf, (unsigned char*) oldBuf, numValues);
break;
case VTK_SHORT:
ConvertToType(newBuf, (short*) oldBuf, numValues);
break;
case VTK_UNSIGNED_SHORT:
ConvertToType(newBuf, (unsigned short*) oldBuf, numValues);
break;
case VTK_INT:
ConvertToType(newBuf, (int*) oldBuf, numValues);
break;
case VTK_UNSIGNED_INT:
ConvertToType(newBuf, (unsigned int*) oldBuf, numValues);
break;
case VTK_LONG:
ConvertToType(newBuf, (long*) oldBuf, numValues);
break;
case VTK_LONG_LONG:
ConvertToType(newBuf, (long long*) oldBuf, numValues);
break;
case VTK_UNSIGNED_LONG:
ConvertToType(newBuf, (unsigned long*) oldBuf, numValues);
break;
case VTK_UNSIGNED_LONG_LONG:
ConvertToType(newBuf, (unsigned long long*) oldBuf, numValues);
break;
case VTK_DOUBLE:
ConvertToType(newBuf, (double*) oldBuf, numValues);
break;
case VTK_ID_TYPE:
ConvertToType(newBuf, (vtkIdType*) oldBuf, numValues);
break;
default:
{
char msg[256];
SNPRINTF(msg, sizeof(msg),
"Cannot convert from type \"%s\" to float",
DataArrayTypeName(oldArr));
EXCEPTION1(ImproperUseException, msg);
}
float *newBuf = (float*) newArr->GetVoidPointer(0);
void *oldBuf = oldArr->GetVoidPointer(0);
switch (oldArr->GetDataType())
{
vtkTemplateMacro(
ConvertToType(newBuf, (VTK_TT *) oldBuf, numValues);
);
}
}
else
{
vtkIdType nTuples = oldArr->GetNumberOfTuples();
for (vtkIdType i = 0; i < nTuples; i++)
newArr->SetTuple(i, oldArr->GetTuple(i));
}
}
......
......@@ -121,6 +121,9 @@ avtMagnitudeExpression::~avtMagnitudeExpression()
// Hank Childs, Mon Jan 14 17:58:58 PST 2008
// Clean up some wrapped lines.
//
// Brad Whitlock, Tue Jul 21 13:50:55 PDT 2015
// Support non-standard memory layout.
//
// ****************************************************************************
vtkDataArray *
......@@ -151,7 +154,7 @@ avtMagnitudeExpression::DeriveVariable(vtkDataSet *in_ds, int currentDomainsInde
EXCEPTION2(ExpressionException, outputVariableName,
"Can only take magnitude of vectors.");
}
int ntuples = vectorValues->GetNumberOfTuples();
vtkIdType ntuples = vectorValues->GetNumberOfTuples();
vtkDataArray *results = vectorValues->NewInstance();
results->SetNumberOfComponents(1);
......@@ -161,7 +164,7 @@ avtMagnitudeExpression::DeriveVariable(vtkDataSet *in_ds, int currentDomainsInde
{ \
dtype *x = (dtype*)vectorValues->GetVoidPointer(0); \
dtype *r = (dtype*)results->GetVoidPointer(0); \
for (int i = 0, idx = 0 ; i < ntuples ; i++, idx += 3) \
for (vtkIdType i = 0, idx = 0 ; i < ntuples ; i++, idx += 3) \
{ \
r[i] = sqrt((double)x[idx+0]*(double)x[idx+0]+\
(double)x[idx+1]*(double)x[idx+1]+\
......@@ -169,13 +172,20 @@ avtMagnitudeExpression::DeriveVariable(vtkDataSet *in_ds, int currentDomainsInde
} \
}
if (vectorValues->GetDataType() == VTK_FLOAT)
{
COMPUTE_MAG(float);
if(vectorValues->HasStandardMemoryLayout())
{
switch(vectorValues->GetDataType())
{
vtkTemplateMacro(COMPUTE_MAG(VTK_TT));
}
}
else // assuming double
{
COMPUTE_MAG(double);
else
{
for(vtkIdType i = 0; i < ntuples ; i++)
{
const double *x = vectorValues->GetTuple(i);
results->SetTuple1(i, sqrt(x[0]*x[0]+ x[1]*x[1]+ x[2]*x[2]));
}
}
return results;
......
This diff is collapsed.
......@@ -1041,9 +1041,7 @@ avtDataRepresentation::InitializeNullDatasets(void)
initializedNullDatasets = true;
#if defined(DEBUG_MEMORY_LEAKS)
atexit(DeleteNullDatasets);
#endif
}
// ****************************************************************************
......
This diff is collapsed.
#ifndef SIMV2_GET_MESH_H
#define SIMV2_GET_MESH_H
class avtPolyhedralSplit;
#define NOTHING(CODE)
#define simV2MemoryCopyMacro(FUNC, MEMORY, NTUPLES, OFFSET, STRIDE, CPPTYPE, DATA, ERROR) \
if(MEMORY == VISIT_MEMORY_CONTIGUOUS) \
{ \
CPPTYPE *src = reinterpret_cast<CPPTYPE*>(DATA); \
for(int _i = 0; _i < NTUPLES; ++_i) \
FUNC(_i, src[_i]); \
ERROR = false; \
} \
else if(MEMORY == VISIT_MEMORY_STRIDED) \
{ \
unsigned char *base = reinterpret_cast<unsigned char *>(DATA); \
unsigned char *ptr = base + OFFSET; \
for(int _i = 0; _i < NTUPLES; ++_i) \
{ \
const CPPTYPE *src = reinterpret_cast<const CPPTYPE *>(ptr); \
FUNC(_i, *src); \
ptr += STRIDE; \
} \
ERROR = false; \
}
#define simV2TemplateDataArrayIterateMacro(H, COMP, SETNTUPLES, FUNC, ERROR) \
{ \
ERROR = true; \
int _owner, _memory, _offset, _stride, _dataType, _nComps, _nTuples = 0; \
void *_data = 0; \
if(simv2_VariableData_getArrayData(H, COMP, _memory, _owner, _dataType, \
_nComps, _nTuples, _offset, _stride, _data)) \
{ \
switch (_dataType) \
{ \
simV2TemplateMacro( \
SETNTUPLES(_nTuples); \
simV2MemoryCopyMacro(FUNC, _memory, _nTuples, _offset, _stride, simV2_TT::cppType, _data, ERROR);\
); \
} \
} \
}
int SimV2_GetVTKType(int simv2type);
vtkDataSet *SimV2_GetMesh_Curvilinear(visit_handle h);
vtkDataSet *SimV2_GetMesh_Rectilinear(visit_handle h);
vtkDataSet *SimV2_GetMesh_Unstructured(int, visit_handle h, avtPolyhedralSplit **);
vtkDataSet *SimV2_GetMesh_Point(visit_handle h);
vtkDataSet *SimV2_GetMesh_CSG(visit_handle h);
#endif
This diff is collapsed.
#ifndef VTK_ARRAY_COMPONENT_H
#define VTK_ARRAY_COMPONENT_H
// ****************************************************************************
// Class: vtkArrayComponentStride
//
// Purpose:
// This array component object lets us iterate over blocks of memory using
// a stride and then we apply an offset to access parts within the block.
// This lets us access AOS data as though it was contiguous.
//
// Notes: For zero-copy access of SOA data. It can be used for AOS data too.
//
// Programmer: Brad Whitlock
// Creation: Fri Jun 19 11:52:42 PDT 2015
//
// Modifications:
//
// ****************************************************************************
class vtkArrayComponentStride
{
public:
vtkArrayComponentStride()
{
this->start = NULL;
this->offset = 0;
this->stride = 0;
this->type = 0;
this->owns = false;
}
vtkArrayComponentStride(void *start, size_t offset, size_t stride, int type, bool owns)
{
this->start = (unsigned char *)start;
this->offset = offset;
this->stride = stride;
this->type = type;
this->owns = owns;
}
~vtkArrayComponentStride()
{
}
void Delete()
{
if(this->owns && this->start != NULL)
{
free(start);
start = NULL;
}
}
template <typename DestinationType>
void GetValue(vtkIdType id, DestinationType &out) const
{
if(this->start != NULL)
{
unsigned char *addr = this->start + this->offset + id * this->stride;
switch(this->type)
{
vtkTemplateMacro(
VTK_TT *ptr = reinterpret_cast<VTK_TT *>(addr);
out = static_cast<DestinationType>(*ptr);
);
}
}
else
{
out = DestinationType();
}
}
protected:
// Memory traversal attributes.
unsigned char *start;
size_t offset;
size_t stride;
int type;
bool owns;
};
////////////////////////////////////////////////////////////////////////////////
// ****************************************************************************
// Class: vtkArrayComponentIJKSlice
//
// Purpose:
// This array component object lets us select an IJK volume of interest in a
// larger IJK block of memory. We can access the subvolume using normal
// vtkDataArray indexing and we handle the id translation here so we index
// into the original volume appropriately.
//
// Notes: For zero-copy access of subvolumes of structured data.
//
// Programmer: Brad Whitlock
// Creation: Fri Jun 19 11:52:42 PDT 2015
//
// Modifications:
//
// ****************************************************************************
class vtkArrayComponentIJKSlice
{
public:
vtkArrayComponentIJKSlice()
{
this->start = NULL;
this->offset = 0;
this->stride = 0;
this->type = 0;
for(int i = 0; i < 3; ++i)
{
this->whole_start_index[i] = 0;
this->whole_end_index[i] = 0;
this->slice_start_index[i] = 0;
this->slice_end_index[i] = 0;
this->slice_size[i] = 0;
this->whole_size[i] = 0;
}
this->sliceNXNY = 0;
this->wholeNXNY = 0;
}
vtkArrayComponentIJKSlice(void *start, size_t offset, size_t stride, int type,
const int whole_start_index[3], const int whole_end_index[3],
const int slice_start_index[3], const int slice_end_index[3])
{
this->start = (unsigned char *)start;
this->offset = offset;
this->stride = stride;
this->type = type;
for(int i = 0; i < 3; ++i)
{
this->whole_start_index[i] = whole_start_index[i];
this->whole_end_index[i] = whole_end_index[i];
this->slice_start_index[i] = slice_start_index[i];
this->slice_end_index[i] = slice_end_index[i];
this->slice_size[i] = slice_end_index[i] - slice_start_index[i] + 1;
this->whole_size[i] = whole_end_index[i] - whole_start_index[i] + 1;
}
this->sliceNXNY = slice_size[0] * slice_size[1];
this->wholeNXNY = whole_size[0] * whole_size[1];
}
void Delete()
{
}
template <typename DestinationType>
void GetValue(vtkIdType id, DestinationType &out) const
{
// id is the index in the smaller sliced volume. Figure out where that
// exists in the larger volume.
vtkIdType slice_K = id / this->sliceNXNY;
vtkIdType idInIJPlane = id % this->sliceNXNY;
vtkIdType slice_J = idInIJPlane / this->slice_size[0];
vtkIdType slice_I = idInIJPlane % this->slice_size[0];
vtkIdType whole_I = slice_I + this->slice_start_index[0] - this->whole_start_index[0];
vtkIdType whole_J = slice_J + this->slice_start_index[1] - this->whole_start_index[1];
vtkIdType whole_K = slice_K + this->slice_start_index[2] - this->whole_start_index[2];
vtkIdType wholeId = whole_K * this->wholeNXNY +
whole_J * whole_size[0] +
whole_I;
#if 0
cout << "GetValue: id=" << id
<< ", sliceIJK={" << slice_I << ", " << slice_J << ", " << slice_K
<< "}, wholeIJK={" << whole_I << ", " << whole_J << ", " << whole_K
<< "}, wholeId=" << wholeId << endl;
#endif
unsigned char *addr = this->start + this->offset + wholeId * this->stride;
switch(this->type)
{
vtkTemplateMacro(
VTK_TT *ptr = reinterpret_cast<VTK_TT *>(addr);
out = static_cast<DestinationType>(*ptr);
);
}
}
bool GetPrint() const { return false; }
private:
// Memory traversal attributes.
unsigned char *start;
size_t offset;
size_t stride;
int type;
// The IJK extents of the whole data array.
int whole_start_index[3];
int whole_end_index[3];
// The IJK extents of the volume of interest.
int slice_start_index[3];
int slice_end_index[3];
// Derived data
vtkIdType slice_size[3];
vtkIdType whole_size[3];
vtkIdType sliceNXNY;
vtkIdType wholeNXNY;
};
#endif
This diff is collapsed.
......@@ -1576,6 +1576,14 @@ avtScatterFilter::ModifyContract(avtContract_p spec)
else
keepNodeZone = false;
// Admit more VTK types.
std::vector<int> dataTypes;
dataTypes.push_back(VTK_CHAR);
dataTypes.push_back(VTK_INT);
dataTypes.push_back(VTK_LONG);
dataTypes.push_back(VTK_FLOAT);
dataTypes.push_back(VTK_DOUBLE);
rv->GetDataRequest()->UpdateAdmissibleDataTypes(dataTypes);
return rv;
}
......@@ -40,6 +40,58 @@ enhancements and bug-fixes that were added to this release.</p>
<a name="Advanced_Features"></a>
<p><b><font size="4">Advanced features added in version 2.10</font></b></p>
<ul>
<li>Libsim's VisIt_VariableData object was extended so you can optionally supply it with multiple data arrays, each representing a separate component of data. This enhancement permits VisIt to accept non-contiguous simulation data without transcribing that data to a contiguous representation. This is a particularly useful feature for array-of-structure data structures and will reduce Libsim's memory overhead.
Data arrays using the new <i>setArrayData</i> functions can have one or more components, which have their own base address and associated offset and stride. All of the previous <i>setData</i> functions continue to work and remain the preferred method for passing contiguous data to Libsim. The flexibility offered by the new <i>setDataArray</i> functions allows simulation data to be used directly (zero-copy) in situations that would previously have required a copy of the data.<br>
<p><b>Structure of Arrays Example:</b><br>
<font color="#6666dd"><code><pre>
#define MAX_PART 100
typedef struct
{
double x,y,z;
double mass;
} Particle;
Particle P[MAX_PART];
/* Expose Array of Structure x,y,z values as a single VariableData object. */
visit_handle coordinates = VISIT_INVALID_HANDLE;
VisIt_VariableData_alloc(&coordinates);
VisIt_VariableData_setArrayDataD(coordinates, 0, VISIT_OWNER_SIM, MAX_PART, 0, sizeof(Particle), (void *)&P[0].x);
VisIt_VariableData_setArrayDataD(coordinates, 1, VISIT_OWNER_SIM, MAX_PART, 0, sizeof(Particle), (void *)&P[0].y);
VisIt_VariableData_setArrayDataD(coordinates, 2, VISIT_OWNER_SIM, MAX_PART, 0, sizeof(Particle), (void *)&P[0].z);
/* Expose Array of Structures mass array as a single VariableData object. */
visit_handle mass = VISIT_INVALID_HANDLE;
VisIt_VariableData_alloc(&mass);
VisIt_VariableData_setArrayDataD(mass, 0, VISIT_OWNER_SIM, MAX_PART, 0, sizeof(Particle), (void *)&P[0].mass);
</pre></code></font>
In addition, this new functionality can be used to create the desired interleaved view of coordinates that are stored in separate arrays.
<br><br>
<b>Interleaved Coordinates Example:</b><br>
<font color="#6666dd"><code><pre>
#define NX 100
#define NY 100
#define NZ 100
int dims[] = {NX, NY, NZ};
double x[NZ][NY][NX], y[NZ][NY][NX], z[NZ][NY][NX];
/* Expose x,y,z values as a single VariableData object. */
visit_handle coordinates = VISIT_INVALID_HANDLE;
VisIt_VariableData_alloc(&coordinates);
VisIt_VariableData_setArrayDataD(coordinates, 0, VISIT_OWNER_SIM, NX*NY*NZ, 0, sizeof(double), (void *)x);
VisIt_VariableData_setArrayDataD(coordinates, 1, VISIT_OWNER_SIM, NX*NY*NZ, 0, sizeof(double), (void *)y);
VisIt_VariableData_setArrayDataD(coordinates, 2, VISIT_OWNER_SIM, NX*NY*NZ, 0, sizeof(double), (void *)z);
visit_handle mesh = VISIT_INVALID_HANDLE;
VisIt_CurvilinearMesh_alloc(&mesh);
VisIt_CurvilinearMesh_setCoords3(mesh, dims, coordinates);
</pre></code></font>
<br>
Data passed via the new <i>setDataArray</i> functions are supported for mesh coordinates and variables. Certain other use such as specifying unstructured mesh connectivity are not currently permitted.
</p>
</li>
<li>Libsim's Fortran bindings were enhanced so the <i>visitsetmpicommunicator</i> function passes an MPI communicator by its integer handle. Thank you to William T. Jones for this improvement.</li>
<li></li>
<li></li>
......
......@@ -109,6 +109,10 @@ typedef enum {
#define VISIT_OWNER_COPY 2
#define VISIT_OWNER_VISIT_EX 3
/* Array memory layout */
#define VISIT_MEMORY_CONTIGUOUS 0
#define VISIT_MEMORY_STRIDED 1
/* Cell Types */
#define VISIT_CELL_BEAM 0
#define VISIT_CELL_TRI 1
......
This diff is collapsed.
......@@ -46,21 +46,31 @@ extern "C"
int VisIt_VariableData_alloc(visit_handle*);
int VisIt_VariableData_free(visit_handle);
/* Pass data (contiguous version) */
int VisIt_VariableData_setDataC(visit_handle obj, int owner, int nComps, int nTuples, char *);
int VisIt_VariableData_setDataI(visit_handle obj, int owner, int nComps, int nTuples, int *);
int VisIt_VariableData_setDataL(visit_handle obj, int owner, int nComps, int nTuples, long *);
int VisIt_VariableData_setDataF(visit_handle obj, int owner, int nComps, int nTuples, float *);
int VisIt_VariableData_setDataD(visit_handle obj, int owner, int nComps, int nTuples, double *);
int VisIt_VariableData_setDataL(visit_handle obj, int owner, int nComps, int nTuples, long *);
int VisIt_VariableData_setData(visit_handle, int, int, int, int, void *);
int VisIt_VariableData_setDataEx(visit_handle, int, int, int, int, void *, void(*)(void*), void *);
/* Pass data on a per-component basis with strided access. */
int VisIt_VariableData_setArrayDataC(visit_handle obj, int arrIndex, int owner, int nTuples, int byteOffset, int byteStride, char *);
int VisIt_VariableData_setArrayDataI(visit_handle obj, int arrIndex, int owner, int nTuples, int byteOffset, int byteStride, int *);
int VisIt_VariableData_setArrayDataL(visit_handle obj, int arrIndex, int owner, int nTuples, int byteOffset, int byteStride, long *);
int VisIt_VariableData_setArrayDataF(visit_handle obj, int arrIndex, int owner, int nTuples, int byteOffset, int byteStride, float *);
int VisIt_VariableData_setArrayDataD(visit_handle obj, int arrIndex, int owner, int nTuples, int byteOffset, int byteStride, double *);
/* Get data (contiguous version) */
int VisIt_VariableData_getData(visit_handle obj, int *owner, int *dataType, int *nComps, int *nTuples, void **);
int VisIt_VariableData_getDataC(visit_handle obj, int *owner, int *nComps, int *nTuples, char **);
int VisIt_VariableData_getDataI(visit_handle obj, int *owner, int *nComps, int *nTuples, int **);
int VisIt_VariableData_getDataL(visit_handle obj, int *owner, int *nComps, int *nTuples, long **);
int VisIt_VariableData_getDataF(visit_handle obj, int *owner, int *nComps, int *nTuples, float **);
int VisIt_VariableData_getDataD(visit_handle obj, int *owner, int *nComps, int *nTuples, double **);
int VisIt_VariableData_getDataL(visit_handle obj, int *owner, int *nComps, int *nTuples, long **);
int VisIt_VariableData_setData(visit_handle, int, int, int, int, void *);
int VisIt_VariableData_setDataEx(visit_handle, int, int, int, int, void *, void(*)(void*), void *);
#ifdef __cplusplus
}
......
......@@ -162,12 +162,25 @@ simv2_CSGMesh_setRegions(visit_handle h, visit_handle typeflags,
cHandles[2] = rightids;
// Get the coordinates
int owner[3], dataType[3], nComps[3], nTuples[3];
int memory[3], owner[3], dataType[3], nComps[3], nTuples[3], offset[3], stride[3];
void *data[3] = {0,0,0};
for(int i = 0; i < 3; ++i)
{
if(simv2_VariableData_getData(cHandles[i], owner[i], dataType[i], nComps[i],
nTuples[i], data[i]) == VISIT_ERROR)
// How many arrays make up the variable.
int nArr = 1;
if(simv2_VariableData_getNumArrays(cHandles[i], &nArr) == VISIT_ERROR)
{
return VISIT_ERROR;
}
if(nArr != 1)
{
VisItError("Region arrays must have 1 component.");
return VISIT_ERROR;
}
if(simv2_VariableData_getArrayData(cHandles[i], 0, memory[i], owner[i],
dataType[i], nComps[i], nTuples[i], offset[i], stride[i], data[i]) == VISIT_ERROR)
{
return VISIT_ERROR;
}
......@@ -188,6 +201,11 @@ simv2_CSGMesh_setRegions(visit_handle h, visit_handle typeflags,
VisItError("Region arrays must contain integer data");
return VISIT_ERROR;
}
if(memory[i] != VISIT_MEMORY_CONTIGUOUS)
{
VisItError("Region arrays must be stored in contiguous memory locations.");
return VISIT_ERROR;
}
}
for(int i = 1; i < 3; ++i)
......@@ -219,10 +237,23 @@ simv2_CSGMesh_setZonelist(visit_handle h, visit_handle zonelist)
VisIt_CSGMesh *obj = GetObject(h);
if(obj != NULL)
{
int owner, dataType, nComps, nTuples;
// How many arrays make up the variable.
int nArr = 1;
if(simv2_VariableData_getNumArrays(zonelist, &nArr) == VISIT_ERROR)
{
return VISIT_ERROR;
}
if(nArr != 1)
{
VisItError("Zonelist array must have 1 component.");
return VISIT_ERROR;
}
int memory, owner, dataType, nComps, nTuples, offset, stride;
void *data = NULL;
if(simv2_VariableData_getData(zonelist, owner, dataType, nComps,
nTuples, data) == VISIT_ERROR)
if(simv2_VariableData_getArrayData(zonelist, 0, memory, owner, dataType, nComps,
nTuples, offset, stride, data) == VISIT_ERROR)
{
return VISIT_ERROR;
}
......@@ -242,7 +273,11 @@ simv2_CSGMesh_setZonelist(visit_handle h, visit_handle zonelist)
VisItError("Zonelist array must contain integer data");
return VISIT_ERROR;
}
if(memory != VISIT_MEMORY_CONTIGUOUS)
{
VisItError("Zonelist array must be stored in contiguous memory locations.");
return VISIT_ERROR;
}
obj->FreeZonelist();
obj->zonelist = zonelist;
......@@ -258,10 +293,23 @@ simv2_CSGMesh_setBoundaryTypes(visit_handle h, visit_handle boundaryTypes)
VisIt_CSGMesh *obj = GetObject(h);
if(obj != NULL)
{
int owner, dataType, nComps, nTuples;
// How many arrays make up the variable.
int nArr = 1;
if(simv2_VariableData_getNumArrays(boundaryTypes, &nArr) == VISIT_ERROR)
{
return VISIT_ERROR;
}
if(nArr != 1)
{
VisItError("CSGMesh's boundary types array must have 1 component.");
return VISIT_ERROR;
}
int memory, owner, dataType, nComps, nTuples, offset, stride;
void *data = NULL;
if(simv2_VariableData_getData(boundaryTypes, owner, dataType, nComps,
nTuples, data) == VISIT_ERROR)
if(simv2_VariableData_getArrayData(boundaryTypes, 0, memory, owner, dataType, nComps,
nTuples, offset, stride, data) == VISIT_ERROR)
{
return VISIT_ERROR;
}
......@@ -281,7 +329,11 @@ simv2_CSGMesh_setBoundaryTypes(visit_handle h, visit_handle boundaryTypes)
VisItError("CSGMesh's boundary types array must contain integer data");
return VISIT_ERROR;
}
if(memory != VISIT_MEMORY_CONTIGUOUS)
{
VisItError("CSGMesh's boundary types array must be stored in contiguous memory locations.");
return VISIT_ERROR;
}
obj->FreeBoundaryTypes();
obj->boundaryTypes = boundaryTypes;
......@@ -297,10 +349,23 @@ simv2_CSGMesh_setBoundaryCoeffs(visit_handle h, visit_handle boundaryCoeffs)
VisIt_CSGMesh *obj = GetObject(h);
if(obj != NULL)
{
int owner, dataType, nComps, nTuples;
// How many arrays make up the variable.
int nArr = 1;
if(simv2_VariableData_getNumArrays(boundaryCoeffs, &nArr) == VISIT_ERROR)
{
return VISIT_ERROR;
}
if(nArr != 1)
{
VisItError("CSGMesh's boundary Coeffs array must have 1 component.");
return VISIT_ERROR;
}
int memory, owner, dataType, nComps, nTuples, offset, stride;
void *data = NULL;
if(simv2_VariableData_getData(boundaryCoeffs, owner, dataType, nComps,
nTuples, data) == VISIT_ERROR)
if(simv2_VariableData_getArrayData(boundaryCoeffs, 0, memory, owner, dataType, nComps,
nTuples, offset, stride, data) == VISIT_ERROR)
{
return VISIT_ERROR;
}
......@@ -321,7 +386,11 @@ simv2_CSGMesh_setBoundaryCoeffs(visit_handle h, visit_handle boundaryCoeffs)
VisItError("CSGMesh's boundary Coeffs array must contain float or double data");
return VISIT_ERROR;
}
if(memory != VISIT_MEMORY_CONTIGUOUS)
{
VisItError("CSGMesh's boundary Coeffs array must be stored in contiguous memory locations.");
return VISIT_ERROR;
}
obj->FreeBoundaryCoeffs();
obj->boundaryCoeffs = boundaryCoeffs;</