1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Luc BILLARD et Damien
3 	CALISTE, laboratoire L_Sim, (2001-2005)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Luc BILLARD et Damien
25 	CALISTE, laboratoire L_Sim, (2001-2005)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 #include "atomic_xyz.h"
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 #include "atomic_yaml.h"
51 
52 #include <visu_dataloadable.h>
53 #include <visu_dataatomic.h>
54 #include <coreTools/toolPhysic.h>
55 #include <coreTools/toolFiles.h>
56 #include <extraFunctions/vibration.h>
57 
58 /*#define TESTNEW*/
59 
60 /**
61  * SECTION:atomic_xyz
62  * @short_description: Method to load xyz position file.
63  *
64  * <para>XYZ formats are plain text format to store atomic
65  * positions. This format is quite simple, first line must contain the
66  * number of element, then
67  * the second usually store a commentary (but this is not required),
68  * then all lines that are not beginning with a '#' are tried to match
69  * "label x y z":. If succeed a node is added, if not, the next line
70  * is read as much time as specified on first line. This scheme can be
71  * repeated as much time as required to store animation for instance.</para>
72  */
73 
74 static VisuDataLoader *xyzLoader = NULL;
75 
76 static gboolean loadXyz(VisuDataLoader *self, VisuDataLoadable *data,
proto_register_dap(void)77                         guint type, guint nSet,
78                         GCancellable *cancel, GError **error);
79 static int read_Xyz_File(VisuDataLoadable *data, guint iType,
80                          guint nSet, GError **error);
81 
82 #ifdef TESTNEW
83 static gboolean test_Routine(float* coords, float* dcoord, VisuElement **nodeTypes);
84 #endif
85 
86 /******************************************************************************/
87 /**
88  * visu_data_loader_xyz_getStatic:
89  *
90  * Retrieve the instance of the atomic loader used to parse XYZ files.
91  *
92  * Since: 3.8
93  *
94  * Returns: (transfer none): a #VisuDataLoader owned by V_Sim.
95  **/
96 VisuDataLoader* visu_data_loader_xyz_getStatic(void)
97 {
98   const gchar *typeXYZ[] = {"*.xyz", (char*)0};
99 
100   if (xyzLoader)
101     return xyzLoader;
102 
103   return xyzLoader = visu_data_loader_new(_("'Element x y z' format"), typeXYZ,
104                                           FALSE, loadXyz, 100);
105 }
106 
107 static gboolean loadXyz(VisuDataLoader *self _U_, VisuDataLoadable *data,
108                         guint type, guint nSet,
109                         GCancellable *cancel _U_, GError **error)
110 {
111   int res;
112 
113   g_return_val_if_fail(error && *error == (GError*)0, FALSE);
114 
115   res = read_Xyz_File(data, type, nSet, error);
116 
117   if (res < 0)
118     {
119       g_clear_error(error);
proto_reg_handoff_dap(void)120       /* The file is not a XYZ file. */
121       return FALSE;
122     }
123   else if (res > 0)
124     /* The file is a XYZ file but some errors occured. */
125     return TRUE;
126   /* Everything is OK. */
127   *error = (GError*)0;
128   return TRUE;
129 }
130 
131 static gboolean readNextLine(ToolFiles *flux, gboolean mandatory,
132                              GString *line, GIOStatus *status, GError **error)
133 {
134   /*if there are commentaries */
135   do
136     {
137       *status = tool_files_read_line_string(flux, line, NULL, error);
138       if (*status != G_IO_STATUS_NORMAL)
139         {
140           if (*status == G_IO_STATUS_EOF)
141             {
142               if (*error)
143                 g_error_free(*error);
144               *error = (GError*)0;
145               return !mandatory;
146             }
147           return FALSE;
148         };
149       g_strstrip(line->str);
150     }
151   while (line->str[0] == '#' || line->str[0] == '!' || line->str[0] == '\0');
152 
153   return TRUE;
154 }
155 
156 static ToolUnits readUnit(const gchar *line)
157 {
158   ToolUnits unit;
159   gchar *tmpStr;
160   guint nNodes;
161 
162   unit = TOOL_UNITS_UNDEFINED;
163 
164   tmpStr = g_strdup(line);
165   if (sscanf(line, "%u %s", &nNodes, tmpStr) == 2)
166     unit = tool_physic_getUnitFromName(g_strstrip(tmpStr));
167   DBG_fprintf(stderr, " | units for the set is '%s' -> %d.\n",
168               tmpStr, unit);
169   g_free(tmpStr);
170 
171   return unit;
172 }
173 static gboolean readReduced(const gchar *line)
174 {
175   gboolean reduced;
176   gchar *tmpStr;
177   guint nNodes;
178 
179   reduced = FALSE;
180   tmpStr = g_strdup(line);
181   if (sscanf(line, "%u %s", &nNodes, tmpStr) == 2)
182     reduced = (!g_ascii_strcasecmp(tmpStr, "reduced"));
183   DBG_fprintf(stderr, " | coordinates are reduced %d.\n", reduced);
184   g_free(tmpStr);
185 
186   return reduced;
187 }
188 
189 static float readEnergy(const gchar *line)
190 {
191   gchar *tmpStr;
192   guint nNodes;
193   float ene;
194 
195   tmpStr = g_strdup(line);
196   if (sscanf(line, "%u %s %f", &nNodes, tmpStr, &ene) != 3)
197     ene = G_MAXFLOAT;
198   else
199     ene *= 27.21138386;
200   g_free(tmpStr);
201 
202   DBG_fprintf(stderr, " | total energy for the set is %geV.\n", ene);
203   return ene;
204 }
205 
206 static VisuBoxBoundaries readBoundary(const gchar *line, const gchar *keyword,
207                                       VisuBoxBoundaries bc, gdouble box[3])
208 {
209   gchar *kwd;
210 
211   kwd = strstr(line, keyword);
212   if (kwd && sscanf(kwd + 8, "%lf %lf %lf",
213                     box, box + 1, box + 2) == 3)
214     return bc;
215   return VISU_BOX_FREE;
216 }
217 
218 static void readFree(ToolFiles *flux, GList *lst, VisuDataLoaderIter *iter, GString *line,
219                      VisuElement **nodeTypes, float *coords,
220                      GArray *dcoord, GArray *forces, GList *labels)
221 {
222   GList *tmpLst;
223 
224   if (flux) g_object_unref(flux);
225   if (line) g_string_free(line, TRUE);
226   visu_data_loader_iter_unref(iter);
227   for (tmpLst = lst; tmpLst; tmpLst = g_list_next(tmpLst))
228     g_free(tmpLst->data);
229   if (lst) g_list_free(lst);
230   if (nodeTypes) g_free(nodeTypes);
231   if (coords) g_free(coords);
232   if (dcoord) g_array_free(dcoord, TRUE);
233   if (forces) g_array_free(forces, TRUE);
234   for (tmpLst = labels; tmpLst; tmpLst = g_list_next(tmpLst))
235     {
236       tmpLst = g_list_next(tmpLst);
237       g_free(tmpLst->data);
238     }
239   if (labels) g_list_free(labels);
240 }
241 
242 static void readCoord(const gchar *line, guint iNodes, guint nNodes,
243                       float *xyz, GArray **dxyz, VisuDataLoaderIter *iter,
244                       VisuElement **nodeTypes, gchar **label, GError **error)
245 {
246   guint nbcolumn;
247   float dxyz_[3];
248   gchar nomloc[TOOL_MAX_LINE_LENGTH];
249   VisuElement *type;
250   int pos;
251 
252   *label = (gchar*)0;
253   nbcolumn = sscanf(line, "%s %f %f %f %f %f %f",
254                     nomloc,  xyz + 3 * iNodes + 0, xyz + 3 * iNodes + 1,
255                     xyz + 3 * iNodes + 2, dxyz_ + 0, dxyz_ + 1, dxyz_ + 2);
256   if (nbcolumn < 4)
257     {
258       DBG_fprintf(stderr, "Atomic XYZ: can't read line values.\n");
259       *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
260                            _("Wrong XYZ format, 'Atom X Y Z' awaited."));
261     }
262   else if (((*dxyz) && nbcolumn != 7) ||
263            (!(*dxyz) && iNodes > 0 && nbcolumn == 7))
264     {
265       DBG_fprintf(stderr, "Atomic XYZ: can't read vibration values.\n");
266       *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
267                            _("Wrong XYZ + vibration format,"
268                              " 'Atom X Y Z vx vy vz' awaited."));
269     }
270   if (nbcolumn == 7)
271     {
272       if (!(*dxyz))
273         *dxyz = g_array_sized_new(FALSE, FALSE, sizeof(float), 3 * nNodes);
274       g_array_append_vals(*dxyz, dxyz_, 3);
275     }
276   if (*error)
277     return;
278 
279   nomloc[8] = '\0';
280   type = visu_element_retrieveFromName(nomloc, (gboolean*)0);
281   nodeTypes[iNodes] = type;
282   visu_data_loader_iter_addNode(iter, type);
283 
284   /* Store a possible comment. */
285   pos = 0;
286   if (nbcolumn == 4)
287     sscanf(line, "%s %f %f %f %n", nomloc, xyz + 3 * iNodes + 0,
288            xyz + 3 * iNodes + 1, xyz + 3 * iNodes + 2, &pos);
289   else
290     sscanf(line, "%s %f %f %f %f %f %f %n",
291            nomloc, xyz + 3 * iNodes + 0, xyz + 3 * iNodes + 1,
292            xyz + 3 * iNodes + 2, dxyz_ + 0, dxyz_ + 1, dxyz_ + 2, &pos);
293   if (line[pos] != '\0')
294     {
295       *label = g_strdup(line + pos + ((line[pos] == '#')?1:0));
296       g_strstrip(*label);
297       if ((*label)[0] == '\0')
298         {
299           g_free(*label);
300           *label = (gchar*)0;
301         }
302     }
303 }
304 
305 static void readForces(ToolFiles *flux, GString *line, guint nNodes,
306                        GArray **forces, GIOStatus *status, GError **error)
307 {
308   gfloat fxyz[3];
309   guint iNodes;
310   gchar nomloc[TOOL_MAX_LINE_LENGTH];
311 #define FORCES_TAG "forces"
312 
313   if (!g_ascii_strncasecmp(g_strchug(line->str), FORCES_TAG, sizeof(FORCES_TAG) - 1))
314     {
315       DBG_fprintf(stderr, "Atomic XYZ: found a forces tag.\n");
316       if (forces)
317         *forces = g_array_sized_new(FALSE, FALSE, sizeof(float), nNodes * 3);
318       for (iNodes = 0; iNodes < nNodes && *status == G_IO_STATUS_NORMAL; iNodes++)
319 	{
320           if (!readNextLine(flux, TRUE, line, status, error))
321             {
322               *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
323                                    DATA_LOADABLE_ERROR_FORMAT,
324                                    _("Missing forces (%d read but"
325                                      " %d declared).\n"), iNodes, nNodes);
326               return;
327             }
328           if (forces && sscanf(line->str, "%s %f %f %f",
329                                nomloc, fxyz + 0, fxyz + 1, fxyz + 2) != 4)
330             {
331               *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
332                                    DATA_LOADABLE_ERROR_FORMAT,
333                                    _("Cannot read forces in '%s'.\n"), line->str);
334               return;
335             }
336           if (forces)
337             g_array_append_vals(*forces, fxyz, 3);
338 	}
339       /* Eat blank or commentary lines between Sets */
340       readNextLine(flux, FALSE, line, status, error);
341     }
342 }
343 
344 /******************************************************************************/
345 static int read_Xyz_File(VisuDataLoadable *data, guint iType,
346                          guint nSet, GError **error)
347 {
348   GIOStatus status;
349   ToolFiles *flux;
350   GString *line;
351   guint i;
352   int res, nNodes, iNodes, nNodesSet;
353   guint nSets;
354   float *coords;
355   GArray *forces, *dcoord;
356   gchar *infoUTF8;
357   GList *lst, *tmpLst;
358   VisuDataLoaderIter *iter;
359   float qpt[3], omega, totalEnergy;
360   double box[3], boxGeometry[6];
361   ToolUnits unit;
362   VisuElement **nodeTypes;
363   guint natom;
364   gchar *pt, *label;
365   VisuBoxBoundaries bc;
366   gboolean reduced;
367   GList *nodeComments;
368   VisuBox *boxObj;
369   VisuVibration *vib;
370   VisuNodeValuesString *labels;
371   VisuNode *node;
372 
373 #if DEBUG == 1
374   GTimer *timer, *readTimer, *internalTimer;
375   gulong fractionTimer;
376   float time1, time2, time3;
377 #endif
378 
379   flux = tool_files_new();
380 
381   DBG_fprintf(stderr, "Atomic xyz: reading file as an xyz file.\n");
382   if (!tool_files_open(flux, visu_data_loadable_getFilename(data, iType), error))
383     {
384       g_object_unref(flux);
385       return -1;
386     }
387 
388   line = g_string_new("");
389   unit = TOOL_UNITS_UNDEFINED;
390   reduced = FALSE;
391 
392   /* Storage of number of elements per types. */
393   iter = visu_data_loader_iter_new();
394 
395   /* We read the file completely to find the number of sets of points
396      and we store only the one corresponding to @nSet. */
397 #if DEBUG == 1
398   timer = g_timer_new();
399   readTimer = g_timer_new();
400   internalTimer = g_timer_new();
401   g_timer_start(timer);
402   g_timer_start(internalTimer);
403   g_timer_stop(internalTimer);
404   time3 = 0.f;
405 #endif
406 
407   nSets        = 0;
408   nNodesSet    = 0;
409   nodeTypes    = (VisuElement**)0;
410   coords       = (float*)0;
411   dcoord       = (GArray*)0;
412   forces       = (GArray*)0;
413   lst          = (GList*)0;
414   nodeComments = (GList*)0;
415   totalEnergy  = G_MAXFLOAT;
416   status = tool_files_read_line_string(flux, line, NULL, error);
417 
418   if ( status != G_IO_STATUS_NORMAL )
419     {
420       readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
421       return -1;
422     }
423 
424   while( status != ( G_IO_STATUS_EOF ) )
425     {
426       DBG_fprintf(stderr, "Atomic xyz: read node set number %d (%d).\n", nSets, nSet);
427 
428       /*The Number Of Nodes*/
429       nNodes=0;
430       DBG_fprintf(stderr, "Atomic xyz: get n atoms from '%s'.\n", line->str);
431       res = sscanf(line->str, "%d", &nNodes);
432       if ( res != 1 )
433 	{
434 	  *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
435 			       _("Wrong XYZ format, no number of atoms on line.\n  '%s'"), line->str);
436           readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
437 	  return (nSets > 0)?1:-1;
438 	}
439       DBG_fprintf(stderr, " | number of declared nodes is %d.\n", nNodes);
440 #if DEBUG == 1
441       if (nSets == nSet)
442         g_timer_start(readTimer);
443       else
444 	g_timer_continue(internalTimer);
445 #endif
446       if (nSets == nSet)
447         {
448           unit = readUnit(line->str);
449           reduced = readReduced(line->str);
450           totalEnergy = readEnergy(line->str);
451         }
452 
453       /*The Commentary line */
454       if ( tool_files_read_line_string(flux, line, NULL, error) !=
455 	   G_IO_STATUS_NORMAL )
456 	{
457           readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
458 	  return -2;
459 	}
460       g_strstrip(line->str);
461       DBG_fprintf(stderr, " | set the commentary to '%s'.\n", line->str);
462       if (line->str[0] == '#')
463 	infoUTF8 = g_locale_to_utf8(line->str + 1, -1, NULL, NULL, NULL);
464       else
465 	infoUTF8 = g_locale_to_utf8(line->str,     -1, NULL, NULL, NULL);
466       if (infoUTF8)
467 	lst = g_list_append(lst, infoUTF8);
468       else
469 	g_warning("Can't convert '%s' to UTF8.\n", line->str);
470 
471       /* The Data Lines.*/
472       if (nSets == nSet)
473 	{
474 	  nNodesSet = nNodes;
475 	  nodeTypes = g_malloc(sizeof(VisuElement*) * nNodes);
476 	  coords    = g_malloc(sizeof(float) * 3 * nNodes);
477 	  dcoord    = (GArray*)0;
478           forces    = (GArray*)0;
479 	  qpt[0] = 0.f;
480 	  qpt[1] = 0.f;
481 	  qpt[2] = 0.f;
482 	}
483       status = G_IO_STATUS_NORMAL;
484       DBG_fprintf(stderr, " | read node coordinates.\n");
485       for (iNodes = 0; iNodes < nNodes && status == G_IO_STATUS_NORMAL; iNodes++)
486 	{
487           if (!readNextLine(flux, TRUE, line, &status, error))
488             {
489               *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
490                                    DATA_LOADABLE_ERROR_FORMAT,
491                                    _("Missing coordinates (%d read but"
492                                      " %d declared).\n"), iNodes, nNodes);
493               readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
494               return 1;
495             }
496 
497           /* if Reading the nSets, parse the data */
498           if (nSets == nSet)
499             {
500               /* Read the coordinates. */
501               readCoord(line->str, iNodes, nNodes, coords, &dcoord,
502                         iter, nodeTypes, &label, error);
503 	      if (*error)
504 		{
505                   readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
506 		  return 1;
507 		}
508               if (label)
509                 {
510                   nodeComments = g_list_prepend(nodeComments, label);
511                   nodeComments = g_list_prepend(nodeComments,
512                                                 GINT_TO_POINTER(iNodes));
513                 }
514 	    }
515 #if DEBUG == 1
516 	  if (nSets == nSet)
517 	    g_timer_stop(readTimer);
518 	  else
519 	    g_timer_stop(internalTimer);
520 #endif
521 	}
522 #if DEBUG == 1
523       g_timer_stop(timer);
524 #endif
525       /* Eat blank or commentary lines after coordinates. */
526       if (!readNextLine(flux, FALSE, line, &status, error))
527         {
528           readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
529           return 1;
530         }
531       /* Maybe read forces (BigDFT addition). */
532       readForces(flux, line, nNodes, (nSets == nSet)?&forces:(GArray**)0, &status, error);
533       if (*error)
534         {
535           readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
536           return 1;
537         }
538       /* OK, one set of nodes have been read. */
539       nSets++;
540       DBG_fprintf(stderr, " | read OK %d %d.\n", status, G_IO_STATUS_EOF);
541     }
542   g_object_unref(flux);
543   DBG_fprintf(stderr, " | finish to read the file.\n");
544 #if DEBUG == 1
545   g_timer_stop(timer);
546   time1 = g_timer_elapsed(timer, &fractionTimer)/1e-6;
547   time2 = g_timer_elapsed(readTimer, &fractionTimer)/1e-6;
548   time3 = g_timer_elapsed(internalTimer, &fractionTimer)/1e-6;
549   g_timer_destroy(readTimer);
550 #endif
551 
552 #if DEBUG == 1
553   g_timer_start(timer);
554 #endif
555   /* Allocate the space for the nodes. */
556   natom = visu_data_loader_iter_allocate(iter, VISU_NODE_ARRAY(data));
557   if (natom <= 0)
558     {
559       readFree(NULL, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
560       *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
561 			   _("The file contains no atom coordinates.\n"));
562       return 1;
563     }
564   visu_data_loader_iter_unref(iter);
565 
566   g_string_free(line, TRUE);
567 
568   /* Begin the storage into VisuData. */
569   visu_data_loadable_setNSets(data, nSets);
570 
571   /* Set the commentary. */
572   bc = VISU_BOX_FREE;
573   for (i = 0, tmpLst = lst; i < nSets; i++, tmpLst = g_list_next(tmpLst))
574     {
575       /* Try to see if the commentary contains some keywords. */
576       if (i == nSet)
577 	{
578           if (bc == VISU_BOX_FREE)
579             bc = readBoundary(tmpLst->data, "periodic", VISU_BOX_PERIODIC, box);
580           if (bc == VISU_BOX_FREE)
581             bc = readBoundary(tmpLst->data, "surface", VISU_BOX_SURFACE_ZX, box);
582           DBG_fprintf(stderr, " | periodicity is %d (%g %g %g).\n",
583                       bc, box[0], box[1], box[2]);
584 	}
585 
586       visu_data_loadable_setSetLabel(data, (const gchar*)tmpLst->data, i);
587       g_free(tmpLst->data);
588     }
589   g_list_free(lst);
590 
591   boxObj = (VisuBox*)0;
592   if (bc != VISU_BOX_FREE)
593     {
594       DBG_fprintf(stderr, "Atomic xyz: the elements are in %fx%fx%f.\n",
595 		  box[0], box[1], box[2]);
596       boxGeometry[0] = box[0];
597       boxGeometry[1] = 0.;
598       boxGeometry[2] = box[1];
599       boxGeometry[3] = 0.;
600       boxGeometry[4] = 0.;
601       boxGeometry[5] = box[2];
602       boxObj = visu_box_new(boxGeometry, bc);
603       visu_boxed_setBox(VISU_BOXED(data), VISU_BOXED(boxObj));
604       g_object_unref(boxObj);
605     }
606   else
607     {
608       boxObj = visu_boxed_getBox(VISU_BOXED(data));
609       if (boxObj)
610         visu_box_setBoundary(boxObj, bc);
611     }
612 
613   /* Store the coordinates */
614   for(iNodes = 0; iNodes < nNodesSet; iNodes++)
615     visu_data_addNodeFromElement(VISU_DATA(data), nodeTypes[iNodes],
616                                  coords + 3 * iNodes, reduced);
617 
618 #ifdef TESTNEW
619   if ( test_Routine(coords, dcoord, nodeTypes) == FALSE )
620     return -1;
621 #endif
622 
623   g_free(nodeTypes);
624   g_free(coords);
625 
626   if (bc != VISU_BOX_PERIODIC)
627     boxObj = visu_data_setTightBox(VISU_DATA(data));
628 
629   /* create the structure for phonons */
630   if (dcoord)
631     {
632       vib = visu_data_getVibration(VISU_DATA(data), nSets);
633       for (i = 0; i < nSets; i++)
634 	{
635 	  omega = 1.f;
636 	  pt = strstr(visu_data_getDescription(VISU_DATA(data)), "freq=");
637 	  if (pt)
638 	    sscanf(pt + 5, "%f", &omega);
639 	  if (omega < 0.)
640 	    g_warning("Negative phonon frequency (%f).", omega);
641 	  visu_vibration_setCharacteristic(vib, i, qpt, 0.f, omega);
642 	}
643       visu_vibration_setDisplacements(vib, nSet, dcoord, FALSE);
644       g_array_free(dcoord, TRUE);
645     }
646 
647   /* Store the forces, if any. */
648   if (forces)
649     {
650       visu_node_values_vector_set
651         (visu_data_atomic_getForces(VISU_DATA_ATOMIC(data), TRUE), forces);
652       g_array_free(forces, TRUE);
653     }
654   /* We apply the comments, if any. */
655   labels = visu_data_getNodeLabels(VISU_DATA(data));
656   if (nodeComments)
657     {
658       for (tmpLst = nodeComments; tmpLst; tmpLst = g_list_next(g_list_next(tmpLst)))
659         {
660           node = visu_node_array_getFromId(VISU_NODE_ARRAY(data),
661                                            GPOINTER_TO_INT(tmpLst->data));
662           label = (gchar*)tmpLst->next->data;
663           if (label[0] == '{' && label[strlen(label) - 1] == '}')
664             visu_data_loader_yaml_setNodeProp(VISU_DATA(data), node, label);
665           else
666             visu_node_values_string_setAt(labels, node, tmpLst->next->data);
667           g_free(tmpLst->next->data);
668         }
669       g_list_free(nodeComments);
670     }
671   /* Add some other meta data. */
672   if (totalEnergy != G_MAXFLOAT)
673     g_object_set(G_OBJECT(data), "totalEnergy", totalEnergy, NULL);
674 
675   DBG_fprintf(stderr, "Atomic XYZ: apply the box geometry and set the unit.\n");
676   visu_box_setUnit(boxObj, unit);
677 
678 #if DEBUG == 1
679   g_timer_stop(timer);
680   fprintf(stderr, "Atomic XYZ: parse all file    in %g micro-s.\n", time1);
681   fprintf(stderr, "Atomic XYZ: parse coordinates in %g micro-s.\n", time2);
682   fprintf(stderr, "Atomic XYZ: header parse      in %g micro-s.\n", time3);
683   fprintf(stderr, "Atomic XYZ: set all data      in %g micro-s.\n",
684 	  g_timer_elapsed(timer, &fractionTimer)/1e-6);
685   g_timer_destroy(timer);
686 #endif
687 
688   return 0;
689 }
690 
691 /******************************************************************************/
692 #ifdef TESTNEW
693 static gboolean test_Routine(float* coords, float* dcoord, VisuElement **nodeTypes) {
694 
695   float xyz[15] = {-0.440035, -0.000385, 2.123698,
696     -1.765945, 0.000399, 2.377542,
697     -2.249233, -0.001453, 3.679971,
698     -1.338875, -0.004508, 4.739569,
699     0.024627, -0.005918, 4.466144};
700   float dxyz[15] = {0.001000, -0.151000, -0.002000,
701     0.001000, -0.175000, 0.000000,
702     0.003000, -0.198000, 0.001000,
703     0.005000, -0.183000, -0.000000,
704     0.005000, -0.146000, -0.003000};
705   char* waitedType[5]={ "N", "C", "C", "Co", "C"};
706   int i=0, j=0;
707 
708 /* Checking coordonates values and type values*/
709   DBG_fprintf(stderr, "+---------------------------------------------------------------+\n");
710  /* for each node : checking names and coordonates values using a difference.*/
711   while( (i<15) && (strcmp(nodeTypes[j]->name,waitedType[j])==0) && (ABS(coords[i]-xyz[i])<1e-6) && (ABS(dcoord[i]-dxyz[i])<1e-6)  )
712    {
713     if (i%3==0) {
714       DBG_fprintf(stderr, "xyz parser : expected element: %s, found: %s \n", waitedType[j], nodeTypes[j]->name);
715       DBG_fprintf(stderr, "xyz parser : expected x: %f, found: %f \t", xyz[i], coords[i]);
716       DBG_fprintf(stderr, "xyz parser : expected dx: %f, found: %f \n", dxyz[i], dcoord[i]);
717     }
718     if (i%3==1) {
719       DBG_fprintf(stderr, "xyz parser : expected y: %f, found: %f \t", xyz[i], coords[i]);
720       DBG_fprintf(stderr, "xyz parser : expected dy: %f, found: %f \n", dxyz[i], dcoord[i]);
721     }
722     if (i%3==2) {
723       DBG_fprintf(stderr, "xyz parser : expected z: %f, found: %f \t", xyz[i], coords[i]);
724       DBG_fprintf(stderr, "xyz parser : expected dz: %f, found: %f \n", dxyz[i], dcoord[i]);
725       j++;
726       DBG_fprintf(stderr, "+---------------------------------------------------------------+\n");
727     }
728     i++;
729    }
730 
731   if (i!=15)
732    {
733     DBG_fprintf(stderr, "xyz parser : An error occured while reading the test file : node number %d encoutred an error \n", j+1);
734     return FALSE;
735    }
736   else
737    {
738    DBG_fprintf(stderr, "xyz parser : parser ok ! \n");
739     return TRUE;
740    }
741 }
742 #endif
743