1 /****************************************************************************/
2 /* This file is part of FreeFEM.                                            */
3 /*                                                                          */
4 /* FreeFEM is free software: you can redistribute it and/or modify          */
5 /* it under the terms of the GNU Lesser General Public License as           */
6 /* published by the Free Software Foundation, either version 3 of           */
7 /* the License, or (at your option) any later version.                      */
8 /*                                                                          */
9 /* FreeFEM is distributed in the hope that it will be useful,               */
10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of           */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
12 /* GNU Lesser General Public License for more details.                      */
13 /*                                                                          */
14 /* You should have received a copy of the GNU Lesser General Public License */
15 /* along with FreeFEM. If not, see <http://www.gnu.org/licenses/>.          */
16 /****************************************************************************/
17 // SUMMARY : Add interface with partionning library scotch
18 // LICENSE : LGPLv3
19 // ORG     : LJLL Universite Pierre et Marie Curie, Paris, FRANCE
20 // AUTHORS : Mathieu Cloirec
21 // E-MAIL  : cloirec@cines.fr
22 
23 /* clang-format off */
24 //ff-c++-LIBRARY-dep: hdf5
25 //ff-c++-cpp-dep:
26 /* clang-format on */
27 
28 #include "ff++.hpp"
29 #include "write_xdmf.hpp"
30 #include "write_hdf5.hpp"
31 
32 #ifndef H5_NO_NAMESPACE
33 #ifndef H5_NO_STD
34 using std::cout;
35 using std::endl;
36 #endif    // H5_NO_STD
37 #endif
38 
39 #include "H5Cpp.h"
40 
41 #ifndef H5_NO_NAMESPACE
42 using namespace H5;
43 #endif
44 #ifdef DEBUG
45 int debug = 1;
46 #else
47 int debug = 0;
48 #endif
49 
50 using namespace std;
51 
52 class datasolHDF5Mesh2_Op : public E_F0mps {
53  public:
54   typedef long Result;
55   Expression eTh;
56   Expression filename;
57   struct Expression2 {
58     long what;       // 1 scalar, 2 vector, 3 symtensor
59     long nbfloat;    // 1 scalar, 2 vector (3D), 3 symtensor(3D)
60     Expression e[3];
61     Expression lename;
Expression2datasolHDF5Mesh2_Op::Expression262     Expression2( ) {
63       e[0] = 0;
64       e[1] = 0;
65       e[2] = 0;
66       what = 0;
67       nbfloat = 0;
68     };
operator []datasolHDF5Mesh2_Op::Expression269     Expression &operator[](int i) { return e[i]; }
70 
evaldatasolHDF5Mesh2_Op::Expression271     double eval(int i, Stack stack) const {
72       if (e[i]) {
73         return GetAny< double >((*e[i])(stack));
74       } else {
75         return 0;
76       }
77     }
78   };
79   vector< Expression2 > l;
80   static const int n_name_param = 1;
81   static basicAC_F0::name_and_type name_param[];
82   Expression nargs[n_name_param];
arg(int i,Stack stack,long a) const83   long arg(int i, Stack stack, long a) const {
84     return nargs[i] ? GetAny< long >((*nargs[i])(stack)) : a;
85   }
86 
87  public:
datasolHDF5Mesh2_Op(const basicAC_F0 & args)88   datasolHDF5Mesh2_Op(const basicAC_F0 &args) : l((args.size( ) - 2) / 2) {
89     int nbofsol;
90     int ddim = 2;
91     int stsize = 3;
92 
93     cout << " " << endl;
94 
95     if (debug == 1) {
96       cout << "construction data hdf5 solution avec datasolHDF5Mesh2_Op" << endl;
97       cout << "taille de args " << args.size( ) << endl;
98     }
99 
100     args.SetNameParam(n_name_param, name_param, nargs);
101 
102     if (BCastTo< string * >(args[0])) {
103       filename = CastTo< string * >(args[0]);
104     }
105 
106     if (BCastTo< pmesh >(args[1])) {
107       eTh = CastTo< pmesh >(args[1]);
108     }
109 
110     nbofsol = l.size( );
111     if (debug == 1) {
112       cout << "hdf5 solution 2d nb sol: " << nbofsol << endl;
113     }
114 
115     size_t kk = 0;
116 
117     for (size_t i = 2; i < (unsigned int)args.size( ); i = i + 2) {
118       size_t jj = i - 2 - kk;
119       if (BCastTo< double >(args[i])) {
120         l[jj].what = 1;
121         l[jj].nbfloat = 1;
122         l[jj][0] = to< double >(args[i]);
123         if (debug == 1) {
124           cout << "hdf5 solution 2d N° " << jj << " is scalar type " << endl;
125         }
126       } else if (args[i].left( ) == atype< E_Array >( )) {
127         const E_Array *a0 = dynamic_cast< const E_Array * >(args[i].LeftValue( ));
128         if (a0->size( ) != ddim && a0->size( ) != stsize) {
129           CompileError(
130             "savesol in 2D: vector solution is 2 composant, tensor solution is 3 composant");
131         }
132 
133         if (a0->size( ) == ddim) {
134           // vector solution
135           if (debug == 1) {
136             cout << "hdf5 solution 2d N° " << jj << " is vector type" << endl;
137           }
138 
139           l[jj].what = 2;
140           l[jj].nbfloat = ddim;
141 
142           for (int j = 0; j < ddim; j++) {
143             l[jj][j] = to< double >((*a0)[j]);
144           }
145         } else if (a0->size( ) == stsize) {
146           // symmetric tensor solution
147           if (debug == 1) {
148             cout << "hdf5 solution 2d N° " << jj << " is tensor type" << endl;
149           }
150 
151           l[jj].what = 3;
152           l[jj].nbfloat = stsize;
153 
154           for (int j = 0; j < stsize; j++) {
155             l[jj][j] = to< double >((*a0)[j]);
156           }
157         }
158       } else {
159         cout << " arg " << i << " " << args[i].left( ) << endl;
160         CompileError("savesol in 2D: Sorry no way to save this kind of data");
161       }
162 
163       if (BCastTo< string * >(args[i + 1])) {
164         l[jj].lename = CastTo< string * >(args[i + 1]);
165       }
166 
167       kk++;
168     }
169   }
170 
typeargs()171   static ArrayOfaType typeargs( ) {
172     return ArrayOfaType(atype< string * >( ), atype< pmesh >( ), true);
173   }
174 
f(const basicAC_F0 & args)175   static E_F0 *f(const basicAC_F0 &args) { return new datasolHDF5Mesh2_Op(args); }
176 
177   AnyType operator( )(Stack stack) const;
178 };
179 
180 basicAC_F0::name_and_type datasolHDF5Mesh2_Op::name_param[] = {{"order", &typeid(long)}};
operator ( )(Stack stack) const181 AnyType datasolHDF5Mesh2_Op::operator( )(Stack stack) const {
182   // Hyp A
183   // -----
184   // A priori, paraview - hdf5 -xdmf impose qu un vecteur possede 3 composantes.
185   // Donc, pour stocker la solution, on transforme le resultat produit par le
186   // code, i.e. vecteur 2D, en vecteur 3D en initialisant le vecteur 3D a zero.
187   //
188 
189   // Hyp B
190   // -----
191   // Etant donne que le tenseur est un tenseur 2d symetrique,
192   // on fait le choix, ici, pour paraview, de le representer sous forme
193   // d'un vecteur a 3 composantes Exx,Eyy,Exy=Eyx
194   // un autre choix possible serait de stocker les valeurs sous
195   // un tenseur 3x3 avec Ezz=Exz=Ezx=Eyz=Ezy=0
196 
197   // mp & mps set but not used
198   // MeshPoint *mp(MeshPointStack(stack)), mps=*mp;
199 
200   const Mesh *pTh = GetAny< const Mesh * >((*eTh)(stack));
201   string *ffname = GetAny< string * >((*filename)(stack));
202 
203   ffassert(pTh);
204   const Mesh &Th = *pTh;
205   int nt = Th.nt;
206   int nv = Th.nv;
207   int nbsol;
208   int solnbfloat;
209   int resultorder = arg(0, stack, 1L);
210   string *datafieldname;
211   long longdefault = 0;
212 
213   if (verbosity > 2) {
214     cout << "filename data hdf5 solution () : " << ffname << endl;
215     cout << "hdf5 solution () nb vertices: " << nv << endl;
216     cout << "hdf5 solution () nb triangles: " << nt << endl;
217     cout << "hdf5 solution () nb of fields: " << l.size( ) << endl;
218   }
219 
220   // write xdmf sol file
221   WriteXdmf *XdmfSolFile2D = new WriteXdmf(ffname->c_str( ), nt, nv);
222   XdmfSolFile2D->WriteXdmfSolFile2DInit( );
223 
224   for (size_t i = 0; i < l.size( ); i++) {
225     // Hyp A
226     int trans = -1;
227     if (l[i].nbfloat == 2) {
228       trans = 3;
229     } else {
230       trans = l[i].nbfloat;
231     }
232 
233     datafieldname = GetAny< string * >((*(l[i].lename))(stack));
234     XdmfSolFile2D->WriteXdmfSolFile2DAddField(datafieldname, (l[i].what - 1), resultorder, trans);
235   }
236 
237   XdmfSolFile2D->WriteXdmfSolFile2DFinalize( );
238   delete XdmfSolFile2D;
239 
240   // write hdf5 sol file
241   WriteHdf5 *Hdf5SolFile2D = new WriteHdf5(ffname->c_str( ), nt, nv);
242   Hdf5SolFile2D->WriteHdf5SolFile2DInit( );
243 
244   solnbfloat = 0;
245 
246   for (size_t ii = 0; ii < l.size( ); ii++) {
247     datafieldname = GetAny< string * >((*(l[ii].lename))(stack));
248 
249     if (resultorder == 0) {
250       // ordre 0
251       // a priori la solution est par triangle
252 
253       // Hyp A
254       int trans = -1;
255       if (l[ii].nbfloat == 2) {
256         trans = 3;
257       } else {
258         trans = l[ii].nbfloat;
259       }
260 
261       // initialisation a 0 du field tab
262       float *tab_vfield;
263       tab_vfield = new float[nt * trans];
264       memset(tab_vfield, 0, sizeof(float) * nt * trans);
265 
266       solnbfloat = l[ii].nbfloat;
267       nbsol = nt;
268       KN< double > valsol(solnbfloat * nbsol);
269       MeshPoint *mp3(MeshPointStack(stack));
270       R2 Cdg_hat = R2(1. / 3., 1. / 3.);
271 
272       // boucle sur les triangles
273       for (int it = 0; it < nt; it++) {
274         int h = 0;
275         const Mesh::Triangle &K(Th.t(it));
276         mp3->set(Th, K(Cdg_hat), Cdg_hat, K, K.lab);
277 
278         // boucle sur chaque champ des triangles
279         for (size_t i = 0; i < l.size( ); i++) {
280           // boucle sur les valeurs de chaque champ des triangles
281           for (size_t j = 0; j < (unsigned int)l[ii].nbfloat; j++) {
282             valsol[it * solnbfloat + h] = l[ii].eval(j, stack);
283             h = h + 1;
284           }
285         }
286 
287         assert(solnbfloat == h);
288       }
289 
290       // creation du tableau de valeur des champs par element (idem valsol mais pour le cas vecteur
291       // il faut 0 sur la troisieme composante : Hyp A
292       for (int i = 0; i < nt; i++) {
293         for (int h = 0; h < solnbfloat; h++) {
294           tab_vfield[i * trans + h] = valsol[i * solnbfloat + h];
295         }
296       }
297 
298       Hdf5SolFile2D->WriteHdf5SolFile2DAddField(datafieldname, resultorder, trans, (l[ii].what - 1),
299                                                 tab_vfield);
300       delete[] tab_vfield;
301     } else {
302       // Hyp A
303       int trans = -1;
304       if (l[ii].nbfloat == 2) {
305         trans = 3;
306       } else {
307         trans = l[ii].nbfloat;
308       }
309 
310       // initialisation a 0 du field tab
311       float *tab_vfield;
312       tab_vfield = new float[nv * trans];
313       memset(tab_vfield, 0, sizeof(float) * nv * trans);
314 
315       solnbfloat = l[ii].nbfloat;
316       nbsol = nv;
317       KN< double > valsol(solnbfloat * nbsol);
318       valsol = 0.;
319       KN< int > takemesh(nbsol);
320       MeshPoint *mp3(MeshPointStack(stack));
321       takemesh = 0;
322 
323       // boucle sur les triangles
324       for (int it = 0; it < nt; it++) {
325         // boucle sur les 3 noeuds du triangle
326         for (int iv = 0; iv < 3; iv++) {
327           // i = numéro du noeud
328           // ex : triangle 0 avec noeuds : 2 3 9
329           int i = Th(it, iv);
330           mp3->setP(&Th, it, iv);
331           int h = 0;
332 
333           for (size_t j = 0; j < (unsigned int)l[ii].nbfloat; j++) {
334             // calcul de la somme des valeurs du champ Ux (par exemple) sur un noeud
335             // appartenant à plusieurs triangles
336             // u_noeud_2_appartenant_au_triangle_0 + u_noeud_2_appartenant_au_triangle_23 + ...
337             valsol[i * solnbfloat + h] = valsol[i * solnbfloat + h] + l[ii].eval(j, stack);
338             h = h + 1;
339           }
340 
341           assert(solnbfloat == h);
342           takemesh[i] = takemesh[i] + 1;
343         }
344       }
345 
346       for (int i = 0; i < nv; i++) {
347         for (int h = 0; h < solnbfloat; h++) {
348           // calcul de la moyenne des valeurs du champ Ux (par exemple) sur un noeud
349           // appartenant à plusieurs triangles
350           valsol[i * solnbfloat + h] = valsol[i * solnbfloat + h] / takemesh[i];
351         }
352       }
353 
354       for (int i = 0; i < nv; i++) {
355         for (int h = 0; h < solnbfloat; h++) {
356           tab_vfield[i * trans + h] = valsol[i * solnbfloat + h];
357         }
358       }
359 
360       if (verbosity > 10) {
361         for (int m = 0; m < (solnbfloat * nbsol); m++) {
362           cout << "valsol[m] hdf5 solution : " << valsol[m] << " for lii : " << ii << endl;
363         }
364       }
365 
366       Hdf5SolFile2D->WriteHdf5SolFile2DAddField(datafieldname, resultorder, trans, (l[ii].what - 1),
367                                                 tab_vfield);
368       delete[] tab_vfield;
369     }
370   }
371 
372   Hdf5SolFile2D->WriteHdf5SolFile2DFinalize( );
373   delete Hdf5SolFile2D;
374   return longdefault;
375 };
376 
377 // datasolMesh3
378 template< class v_fes >
379 class datasolHDF5Mesh3_Op : public E_F0mps {
380  public:
381   typedef long Result;
382   Expression eTh;
383   Expression filename;
384   struct Expression2 {
385     long what;       // 1 scalar, 2 vector, 3 symtensor
386     long nbfloat;    // 1 scalar, 3 vector (3D), 6 symtensor(3D)
387     Expression e[6];
388     Expression lename;
Expression2datasolHDF5Mesh3_Op::Expression2389     Expression2( ) {
390       e[0] = 0;
391       e[1] = 0;
392       e[2] = 0;
393       e[3] = 0;
394       e[4] = 0;
395       e[5] = 0;
396       what = 0;
397       nbfloat = 0;
398     };
operator []datasolHDF5Mesh3_Op::Expression2399     Expression &operator[](int i) { return e[i]; }
400 
evaldatasolHDF5Mesh3_Op::Expression2401     double eval(int i, Stack stack) const {
402       if (e[i]) {
403         return GetAny< double >((*e[i])(stack));
404       } else {
405         return 0;
406       }
407     }
408   };
409   vector< Expression2 > l;
410   static const int n_name_param = 1;
411   static basicAC_F0::name_and_type name_param[];
412   Expression nargs[n_name_param];
arg(int i,Stack stack,long a) const413   long arg(int i, Stack stack, long a) const {
414     return nargs[i] ? GetAny< long >((*nargs[i])(stack)) : a;
415   }
416 
417  public:
datasolHDF5Mesh3_Op(const basicAC_F0 & args)418   datasolHDF5Mesh3_Op(const basicAC_F0 &args) : l((args.size( ) - 2) / 2) {
419     int nbofsol;
420     int ddim = 3;
421     int stsize = 6;
422 
423     cout << " " << endl;
424     if (debug == 1) {
425       cout << "construction data hdf5 solution avec datasolHDF5Mesh3_Op" << endl;
426       cout << "taille de args " << args.size( ) << endl;
427     }
428 
429     args.SetNameParam(n_name_param, name_param, nargs);
430     if (BCastTo< string * >(args[0])) {
431       filename = CastTo< string * >(args[0]);
432     }
433 
434     if (BCastTo< pmesh3 >(args[1])) {
435       eTh = CastTo< pmesh3 >(args[1]);
436     }
437 
438     nbofsol = l.size( );
439     if (verbosity > 1) {
440       cout << "hdf5 solution 3d nb sol: " << nbofsol << endl;
441     }
442 
443     size_t kk = 0;
444 
445     for (size_t i = 2; i < (unsigned int)args.size( ); i = i + 2) {
446       size_t jj = i - 2 - kk;
447       if (BCastTo< double >(args[i])) {
448         l[jj].what = 1;
449         l[jj].nbfloat = 1;
450         l[jj][0] = to< double >(args[i]);
451         if (verbosity > 9) {
452           cout << "hdf5 solution 3d N° " << jj << " is scalar type " << endl;
453         }
454       } else if (args[i].left( ) == atype< E_Array >( )) {
455         const E_Array *a0 = dynamic_cast< const E_Array * >(args[i].LeftValue( ));
456         if (a0->size( ) != ddim && a0->size( ) != stsize) {
457           CompileError(
458             "savesol in 3D: vector solution is 3 composant, tensor solution is 6 composant");
459         }
460 
461         if (a0->size( ) == ddim) {
462           // vector solution
463           if (verbosity > 9) {
464             cout << "hdf5 solution 3d N° " << jj << " is vector type" << endl;
465           }
466 
467           l[jj].what = 2;
468           l[jj].nbfloat = ddim;
469 
470           for (int j = 0; j < ddim; j++) {
471             l[jj][j] = to< double >((*a0)[j]);
472           }
473         } else if (a0->size( ) == stsize) {
474           // symmetric tensor solution
475           if (verbosity > 9) {
476             cout << "hdf5 solution 3d N° " << jj << " is tensor type" << endl;
477           }
478 
479           l[jj].what = 3;
480           l[jj].nbfloat = stsize;
481 
482           for (int j = 0; j < stsize; j++) {
483             l[jj][j] = to< double >((*a0)[j]);
484           }
485         }
486       } else {
487         CompileError("savesol in 3D: Sorry no way to save this kind of data");
488       }
489 
490       if (BCastTo< string * >(args[i + 1])) {
491         l[jj].lename = CastTo< string * >(args[i + 1]);
492       }
493 
494       kk++;
495     }
496   }
497 
typeargs()498   static ArrayOfaType typeargs( ) {
499     return ArrayOfaType(atype< string * >( ), atype< pmesh3 >( ), true);
500   }
501 
f(const basicAC_F0 & args)502   static E_F0 *f(const basicAC_F0 &args) { return new datasolHDF5Mesh3_Op(args); }
503 
504   AnyType operator( )(Stack stack) const;
505 };
506 
507 template< class v_fes >
508 basicAC_F0::name_and_type datasolHDF5Mesh3_Op< v_fes >::name_param[] = {{"order", &typeid(long)}};
509 
510 template< class v_fes >
operator ( )(Stack stack) const511 AnyType datasolHDF5Mesh3_Op< v_fes >::operator( )(Stack stack) const {
512   const Mesh3 *pTh = GetAny< const Mesh3 * >((*eTh)(stack));
513   string *ffname = GetAny< string * >((*filename)(stack));
514 
515   ffassert(pTh);
516   const Mesh3 &Th = *pTh;
517   int trans = -1;
518   int nt = Th.nt;
519   int nv = Th.nv;
520   int nbsol;
521   int solnbfloat;
522   int resultorder = arg(0, stack, 1);
523   long longdefault = 0;
524   string *datafieldname;
525 
526   if (verbosity > 2) {
527     cout << "filename data hdf5 solution () : " << ffname << endl;
528     cout << "hdf5 solution () nb vertices: " << nv << endl;
529     cout << "hdf5 solution () nb tetrahedrons: " << nt << endl;
530     cout << "hdf5 solution () nb of fields: " << l.size( ) << endl;
531   }
532 
533   // write xdmf sol file
534   WriteXdmf *XdmfSolFile3D = new WriteXdmf(ffname->c_str( ), nt, nv);
535   XdmfSolFile3D->WriteXdmfSolFile3DInit( );
536 
537   for (size_t i = 0; i < l.size( ); i++) {
538     // Hyp A
539     trans = l[i].nbfloat;
540     datafieldname = GetAny< string * >((*(l[i].lename))(stack));
541     XdmfSolFile3D->WriteXdmfSolFile3DAddField(datafieldname, (l[i].what - 1), resultorder, trans);
542   }
543 
544   XdmfSolFile3D->WriteXdmfSolFile3DFinalize( );
545   delete XdmfSolFile3D;
546 
547   // write hdf5 sol file
548   WriteHdf5 *Hdf5SolFile3D = new WriteHdf5(ffname->c_str( ), nt, nv);
549   Hdf5SolFile3D->WriteHdf5SolFile3DInit( );
550 
551   solnbfloat = 0;
552 
553   for (size_t ii = 0; ii < l.size( ); ii++) {
554     datafieldname = GetAny< string * >((*(l[ii].lename))(stack));
555     trans = l[ii].nbfloat;
556 
557     if (resultorder == 0) {
558       // Tetrahedra
559       // ordre 0
560       float *tab_vfield;
561       tab_vfield = new float[nt * trans];
562       memset(tab_vfield, 0, sizeof(float) * nt * trans);
563       solnbfloat = l[ii].nbfloat;
564 
565       nbsol = nt;
566       KN< double > valsol(solnbfloat * nbsol);
567       MeshPoint *mp3(MeshPointStack(stack));
568       R3 Cdg_hat = R3(1. / 4., 1. / 4., 1. / 4.);
569 
570       // boucle sur les tetrahedres
571       for (int it = 0; it < nt; it++) {
572         int h = 0;
573         const Tet &K(Th.elements[it]);
574         mp3->set(Th, K(Cdg_hat), Cdg_hat, K, K.lab);
575 
576         // boucle sur chaque champ des tetrahedres
577         for (size_t i = 0; i < l.size( ); i++) {
578           // boucle sur les valeurs de chaque champ des tetrahedres
579           for (size_t j = 0; j < (unsigned int)l[ii].nbfloat; j++) {
580             valsol[it * solnbfloat + h] = l[ii].eval(j, stack);
581             h = h + 1;
582           }
583         }
584 
585         assert(solnbfloat == h);
586       }
587 
588       // creation du tableau de valeur des champs par element
589       for (int i = 0; i < nt; i++) {
590         for (int h = 0; h < solnbfloat; h++) {
591           tab_vfield[i * trans + h] = valsol[i * solnbfloat + h];
592         }
593       }
594 
595       Hdf5SolFile3D->WriteHdf5SolFile3DAddField(datafieldname, resultorder, trans, (l[ii].what - 1),
596                                                 tab_vfield);
597       delete[] tab_vfield;
598     }
599 
600     if (resultorder == 1) {
601       // ordre 1
602       float *tab_vfield;
603       tab_vfield = new float[nv * trans];
604       memset(tab_vfield, 0, sizeof(float) * nv * trans);
605       solnbfloat = l[ii].nbfloat;
606       nbsol = nv;
607       KN< double > valsol(solnbfloat * nbsol);
608       KN< int > takemesh(nbsol);
609       MeshPoint *mp3(MeshPointStack(stack));
610       // R3 Cdg_hat = R3(1./4.,1./4.,1./4.);
611       takemesh = 0;
612 
613       // boucle sur les tetrahedres
614       for (int it = 0; it < nt; it++) {
615         // boucle sur les 4 noeuds du tetrahedre
616         for (int iv = 0; iv < 4; iv++) {
617           int i = Th(it, iv);
618           if (takemesh[i] == 0) {
619             mp3->setP(&Th, it, iv);
620             int h = 0;
621 
622             for (size_t j = 0; j < (unsigned int)l[ii].nbfloat; j++) {
623               valsol[i * solnbfloat + h] = l[ii].eval(j, stack);
624               h = h + 1;
625             }
626 
627             assert(solnbfloat == h);
628             takemesh[i] = takemesh[i] + 1;
629           }
630         }
631       }
632 
633       for (int i = 0; i < nv; i++) {
634         for (int h = 0; h < solnbfloat; h++) {
635           tab_vfield[i * trans + h] = valsol[i * solnbfloat + h];
636         }
637       }
638 
639       if (verbosity > 9) {
640         for (int m = 0; m < (solnbfloat * nbsol); m++) {
641           cout << "valsol[m] hdf5 solution : " << valsol[m] << " for lii : " << ii << endl;
642         }
643       }
644 
645       Hdf5SolFile3D->WriteHdf5SolFile3DAddField(datafieldname, resultorder, trans, (l[ii].what - 1),
646                                                 tab_vfield);
647       delete[] tab_vfield;
648     }
649   }
650 
651   Hdf5SolFile3D->WriteHdf5SolFile3DFinalize( );
652   delete Hdf5SolFile3D;
653   return longdefault;
654 }
655 
Load_Init()656 static void Load_Init( ) {
657   cout << " " << endl;
658   cout << " ---------------------- " << endl;
659 
660   typedef const Mesh *pmesh;
661   typedef const Mesh3 *pmesh3;
662 
663   if (verbosity > 2) {
664     cout << " load:popen.cpp  " << endl;
665   }
666 
667   // 2D
668   Global.Add("savehdf5sol", "(", new OneOperatorCode< datasolHDF5Mesh2_Op >);
669 
670   // 3D
671   Global.Add("savehdf5sol", "(", new OneOperatorCode< datasolHDF5Mesh3_Op< v_fes3 > >);
672 }
673 
674 LOADFUNC(Load_Init)
675