#include "nq_basic.h"
#include "nq_structure.h"
#include <netcdf.h>
#include <math.h>
#include <visu_tools.h>
#include <visu_elements.h>
#include <visu_data.h>
#include <extraFunctions/scalarFields.h>
#include <coreTools/toolFileFormat.h>
#include <coreTools/toolMatrix.h>
/* Local methods */
static gboolean loadNQETSF(VisuData *data, const gchar* filename,
FileFormat *format, GError **error);
RenderingFormatLoad* nqStructuralInit()
{
char *type[] = {"*.nc", "*-etsf.nc", (char*)0};
char *descr = _("ETSF file format");
RenderingFormatLoad *meth;
meth = g_malloc(sizeof(RenderingFormatLoad));
meth->name = "ETSF (Nanoquanta) file format";
meth->fmt = fileFormatNew(descr, type);
if (!meth->fmt)
g_error("Can't initialize the Nanoquanta loading method, aborting...\n");
meth->priority = 5;
meth->load = loadNQETSF;
return meth;
}
static gboolean loadNQETSF(VisuData *data, const gchar* filename,
FileFormat *format, GError **error)
{
gboolean res;
int netcdfId, status, i, j, k, ret;
int varId;
size_t dimSize;
char* varNbElement = "number_of_atom_species";
int nbEle;
char* varNbNode = "number_of_atoms";
int nbNode;
char* varAtomsNames = "atom_species_names";
int varIdSymbols;
size_t dimsSymbols[2];
char* symbols;
char* varNodeToEle = "atom_species";
int varIdNodeToEle;
size_t dimsNodeToEle;
int *nodeToEle;
char* varCoord = "reduced_atom_positions";
int varIdCoord;
size_t dimsCoord[2];
double* coord;
char *varRprimd = "primitive_vectors";
int varIdRprimd;
size_t dimsRprimd[2];
double rprimd[3][3];
size_t start[] = {0, 0};
char *varTitle = "title";
size_t sizeTitle;
char title[256];
int *nbNodesPerEle;
VisuElement **visuEle;
float boxGeometry[6];
float vect[3], mat[3][3], vectB[3];
nc_type ncType;
gchar *infoUTF8, *name;
gboolean *flag;
g_return_val_if_fail(error && *error == (GError*)0, FALSE);
g_return_val_if_fail(data && filename, FALSE);
res = nqOpen_netcdfFile(filename, &netcdfId, error);
if (!res)
return FALSE;
/* From now on, the file is a NETCDF valid file, so
we return TRUE, but errrors can still occurs. */
/********************************/
/* Retrieve the numeral values. */
/********************************/
/* Grep the number of elements. */
if (!nqGetDim(netcdfId, error, varNbElement, &varId, &dimSize))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
nbEle = (int)dimSize;
/* Grep the number of nodes. */
if (!nqGetDim(netcdfId, error, varNbNode, &varId, &dimSize))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
nbNode = (int)dimSize;
/**************************************************************/
/* Check the conformance of the arrays to the specifications. */
/**************************************************************/
/* Check the names of elements. */
dimsSymbols[0] = nbEle;
dimsSymbols[1] = 80;
if (!nqCheckVar(netcdfId, error, varAtomsNames, &varIdSymbols,
NC_CHAR, 2, dimsSymbols))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
/* Check the 'node to element'array. */
dimsNodeToEle = nbNode;
if (!nqCheckVar(netcdfId, error, varNodeToEle, &varIdNodeToEle,
NC_INT, 1, &dimsNodeToEle))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
/* Check the reduce coordinates array. */
dimsCoord[0] = nbNode;
dimsCoord[1] = 3;
if (!nqCheckVar(netcdfId, error, varCoord, &varIdCoord,
NC_DOUBLE, 2, dimsCoord))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
/* Check the rprimd matrix. */
dimsRprimd[0] = 3;
dimsRprimd[1] = 3;
if (!nqCheckVar(netcdfId, error, varRprimd, &varIdRprimd,
NC_DOUBLE, 2, dimsRprimd))
{
nqClose_netcdfFile(netcdfId);
return TRUE;
}
/****************************/
/* Retrieve now the arrays. */
/****************************/
/* Grep the names of elements. */
symbols = g_malloc(sizeof(char) * 80 * nbEle);
status = nc_get_vara_text(netcdfId, varIdSymbols, start, dimsSymbols, symbols);
if (status != NC_NOERR)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("Retrieve value for variable '%s': %s."),
varAtomsNames, nc_strerror(status));
nqClose_netcdfFile(netcdfId);
g_free(symbols);
return TRUE;
}
for (i = 0; i < nbEle; i++)
symbols[(i + 1) * 80 - 1] = '\0';
/* Grep table from 'node to element'. */
nodeToEle = g_malloc(sizeof(int) * nbNode);
status = nc_get_vara_int(netcdfId, varIdNodeToEle, start, &dimsNodeToEle, nodeToEle);
if (status != NC_NOERR)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("Retrieve value for variable '%s': %s."),
varNodeToEle, nc_strerror(status));
nqClose_netcdfFile(netcdfId);
g_free(symbols);
g_free(nodeToEle);
return TRUE;
}
for (i = 0; i < nbNode; i++)
{
/* Specifications 1.3 says that the values range from 1.
So we remove 1 to be coherent with C numbering. */
nodeToEle[i] -= 1;
if (nodeToEle[i] < 0 || nodeToEle[i] >= nbEle)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("Error in indexing array '%s', index out of bounds."),
varNodeToEle);
nqClose_netcdfFile(netcdfId);
g_free(symbols);
g_free(nodeToEle);
return TRUE;
}
}
/* Grep the reduced coordinates. */
coord = g_malloc(sizeof(double) * 3 * nbNode);
status = nc_get_vara_double(netcdfId, varIdCoord, start, dimsCoord, coord);
if (status != NC_NOERR)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("Retrieve value for variable '%s': %s."),
varCoord, nc_strerror(status));
nqClose_netcdfFile(netcdfId);
g_free(symbols);
g_free(nodeToEle);
g_free(coord);
return TRUE;
}
/* Grep the box definition. */
status = nc_get_vara_double(netcdfId, varIdRprimd, start, dimsRprimd, &rprimd[0][0]);
if (status != NC_NOERR)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("Retrieve value for variable '%s': %s."),
varRprimd, nc_strerror(status));
nqClose_netcdfFile(netcdfId);
g_free(symbols);
g_free(nodeToEle);
g_free(coord);
return TRUE;
}
/* Prepare the arrays for memory allocation in the VisuData object. */
res = matrix_reducePrimitiveVectors(boxGeometry, rprimd);
if (!res)
{
*error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT,
_("The variable '%s' is not well formed (the basis is not 3D)."),
varRprimd);
nqClose_netcdfFile(netcdfId);
g_free(symbols);
g_free(nodeToEle);
g_free(coord);
return TRUE;
}
nbNodesPerEle = g_malloc(sizeof(int) * nbEle);
for (i = 0; i < nbEle; i++)
nbNodesPerEle[i] = 0;
for (i = 0; i < nbNode; i++)
nbNodesPerEle[nodeToEle[i]] += 1;
visuEle = g_malloc(sizeof(VisuElement*) * nbEle);
for (i = 0; i < nbEle; i++)
{
name = g_strstrip(symbols + i * 80);
visuEle[i] = visuElementGet_fromName(name);
if (!visuEle[i])
{
visuEle[i] = visuElementNewWithName(name);
visuElementAdd(visuEle[i]);
}
}
DBG_fprintf(stderr, "NQ structure : File '%s' parsed.\n", filename);
DBG_fprintf(stderr, " | box definition : ( %f %f %f )\n",
rprimd[0][0], rprimd[0][1], rprimd[0][2]);
DBG_fprintf(stderr, " | ( %f %f %f )\n",
rprimd[1][0], rprimd[1][1], rprimd[1][2]);
DBG_fprintf(stderr, " | ( %f %f %f )\n",
rprimd[2][0], rprimd[2][1], rprimd[2][2]);
DBG_fprintf(stderr, " | number of nodes per element (%d):\n", nbEle);
for (i = 0; i < nbEle ; i++)
DBG_fprintf(stderr, " | %d nodes for '%s' (%p)\n", nbNodesPerEle[i],
visuEle[i]->name, (gpointer)visuEle[i]);
g_free(symbols);
visuDataSet_boxGeometry(data, boxGeometry, TRUE);
k = 0;
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
{
if (i > j)
mat[i][j] = 0.;
else
mat[i][j] = boxGeometry[k++];
}
ret = visuDataSet_population(data, nbEle, nbNodesPerEle, visuEle);
if (!ret)
g_error("Can't store the nodes in the VisuData object.\n");
for (i = 0; i < nbNode; i++)
{
for (j = 0; j < 3; j++)
vectB[j] = (float)coord[3 * i + j];
matrix_productVector(vect, mat, vectB);
visuDataAdd_VisuElement(data, visuEle[nodeToEle[i]], vect[0], vect[1], vect[2], i);
}
g_free(nodeToEle);
g_free(coord);
g_free(nbNodesPerEle);
g_free(visuEle);
/**********************/
/* Optional elements. */
/**********************/
status = nc_inq_att(netcdfId, NC_GLOBAL, varTitle, &ncType, &sizeTitle);
if (status == NC_NOERR && ncType == NC_CHAR && sizeTitle < 255)
{
status = nc_get_att_text(netcdfId, NC_GLOBAL, varTitle, title);
if (status == NC_NOERR)
{
title[sizeTitle] = '\0';
infoUTF8 = getStringInUTF8(title);
visuDataSet_fileCommentary(data, infoUTF8);
g_free(infoUTF8);
}
}
nqClose_netcdfFile(netcdfId);
/******************************************/
/* Add some flags to the VisuData object. */
/******************************************/
flag = g_malloc(sizeof(gboolean));
*flag = TRUE;
visuDataSet_property(data, SCALAR_FIELD_DEFINED_IN_STRUCT_FILE, (gpointer)flag);
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1