1 /*  This file is part of MED.
2  *
3  *  COPYRIGHT (C) 1999 - 2019  EDF R&D, CEA/DEN
4  *  MED is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU Lesser General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  MED 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 MED.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 #include <med.h>
20 #include <med_config.h>
21 #include <med_outils.h>
22 #include <string.h>
23 #include <stdlib.h>
24 
25 /**\ingroup MEDmesh
26   \brief \MEDmeshComputationStepCrBrief
27   \param fid \fid
28   \param meshname \meshname
29   \param numdt1 \numdt1
30   \param numit1 \numit1
31   \param numdt2 \numdt2
32   \param numit2 \numit2
33   \param dt2 \dt2
34   \retval med_err \error
35   \details \MEDmeshComputationStepCrDetails
36 */
37 
38 
39 med_err
MEDmeshComputationStepCr(const med_idt fid,const char * const meshname,const med_int numdt1,const med_int numit1,const med_int numdt2,const med_int numit2,const med_float dt2)40 MEDmeshComputationStepCr(const med_idt fid,
41 			 const char * const meshname,
42 			 const med_int numdt1,
43 			 const med_int numit1,
44 			 const med_int numdt2,
45 			 const med_int numit2,
46 			 const med_float dt2 )
47 {
48 
49   med_access_mode _MED_ACCESS_MODE;
50   med_err  _ret=-1;
51   med_idt  _meshid=0,_datagroup1=0,_datagroup2=0,_datagroup3=0;
52   char     _meshpath [MED_MESH_SUPPORT_GRP_SIZE+MED_NAME_SIZE+1]="";
53   char     _datagroupname [2*MED_MAX_PARA+1]="";
54   char     _datagroupname2[2*MED_MAX_PARA+1]="";
55   char     _datagroupname1bis[2*MED_MAX_PARA+1]="";
56   char     _latestcpstname[2*MED_MAX_PARA+1]="";
57   char*    _datagroupname1=_datagroupname;
58   char     _datagroupname3[2*MED_MAX_PARA+1]="";
59   char     _prevcpstname[2*MED_MAX_PARA+1]="";
60   char     _pathsrc[MED_MESH_SUPPORT_GRP_SIZE+MED_NAME_SIZE+1+2*MED_MAX_PARA+1+1]="";
61   char     _pathdst[MED_MESH_SUPPORT_GRP_SIZE+MED_NAME_SIZE+1+2*MED_MAX_PARA+1+1]="";
62   med_bool _datagroup1exist = MED_TRUE;
63   med_bool _isasupportmesh = MED_FALSE;
64   med_int  _nextdt=MED_NO_DT, _nextit=MED_NO_IT,_pvdt=MED_NO_DT, _pvit=MED_NO_IT;
65   med_int  _lastnumdt=MED_NO_DT, _lastnumit=MED_NO_IT;
66   med_int  _numdt1=numdt1,_numit1=numit1;
67   med_int  _false = 0;
68   med_sorting_type _sortingtype;
69   med_int          _intsortingtype;
70   /*
71    * On inhibe le gestionnaire d'erreur
72    */
73   _MEDmodeErreurVerrouiller();
74  if (_MEDcheckVersion30(fid) < 0) goto ERROR;
75 
76   if ( (_MED_ACCESS_MODE = _MEDmodeAcces(fid) ) == MED_ACC_UNDEF ) {
77     MED_ERR_(_ret,MED_ERR_UNRECOGNIZED,MED_ERR_ACCESSMODE,MED_ERR_FILE_MSG);
78     goto ERROR;
79   }
80 
81   if ( _MED_ACCESS_MODE == MED_ACC_RDONLY) {
82     MED_ERR_(_ret,MED_ERR_INVALID,MED_ERR_ACCESSMODE,MED_ERR_FILE_MSG);
83     ISCRUTE_int(_MED_ACCESS_MODE);
84     goto ERROR;
85   }
86 
87 /*   strcat( _meshpath, meshname); */
88 /*   strcat( _pathsrc , meshname);strcat( _pathsrc , "/"); */
89 /*   strcat( _pathdst , meshname);strcat( _pathdst , "/"); */
90 /*   if ((_meshid = _MEDdatagroupOuvrir(fid,_meshpath)) < 0) { */
91 /*     MED_ERR_(_ret,MED_ERR_OPEN,MED_ERR_DATAGROUP,_meshpath); */
92 /*     SSCRUTE(_meshid);goto ERROR; */
93 /*   } */
94 
95   if ((_meshid=_MEDmeshDatagroupOpen(fid,meshname,_meshpath,&_isasupportmesh)) < 0) {
96     MED_ERR_(_ret,MED_ERR_OPEN,MED_ERR_DATAGROUP,MED_ERR_MESH_MSG);
97     SSCRUTE(_meshpath); goto ERROR;
98   }
99   strcat( _pathsrc , _meshpath);strcat( _pathsrc , "/");
100   strcat( _pathdst , _meshpath);strcat( _pathdst , "/");
101 
102   if ( _MEDattrEntierLire(_meshid,MED_NOM_NXT,&_lastnumdt) < 0) {
103 /*     MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG); */
104 /*     SSCRUTE(meshname);SSCRUTE(_meshpath);SSCRUTE(MED_NOM_NXT); */
105 /*     goto ERROR; */
106     _lastnumdt = MED_NO_DT;
107   }
108 
109   if ( _MEDattrEntierLire(_meshid,MED_NOM_NXI,&_lastnumit) < 0) {
110 /*     MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG); */
111 /*     SSCRUTE(meshname);SSCRUTE(_meshpath);SSCRUTE(MED_NOM_NXI); */
112 /*     goto ERROR; */
113     _lastnumit = MED_NO_IT;
114   }
115 
116  if ( _MEDattrEntierLire(_meshid,MED_NOM_SRT,&_intsortingtype) < 0) {
117    MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
118     SSCRUTE(meshname);SSCRUTE(MED_NOM_SRT);
119     ISCRUTE(_intsortingtype);goto ERROR;
120   }
121   _sortingtype = (med_sorting_type) (_intsortingtype);
122 
123   _MEDgetComputationStepName(_sortingtype,numdt1,numit1,_datagroupname);
124   _MEDgetComputationStepName(_sortingtype,numdt2,numit2,_datagroupname2);
125   _MEDgetComputationStepName(_sortingtype,_lastnumdt,_lastnumit,_latestcpstname);
126 
127   /*
128     L'utilisateur peut demander la création d'une nouvelle étape de calcul postérieure
129     à toutes les autres en indiquant (numdt1 == numdt2) && (numit1 == numit2)
130     Celà fonctionne aussi pour MED_NO_DT, NED_NO_IT
131   */
132 
133   if ( (numdt1 == numdt2) && (numit1 == numit2) ) {
134     _numdt1         = _lastnumdt;
135     _numit1         = _lastnumit;
136     _datagroupname1 = _latestcpstname;
137   }
138   /*Vérifie que le _datagroupname2 est bien postérieur ou égal au _datagroupname1
139    REM: _datagroupname1 peut être la première/dernière séquence de calcul
140    ou une séquence intermédiaire */
141   if ( strncmp(_datagroupname2,_datagroupname1,2*MED_MAX_PARA+2) < 0) {
142     MED_ERR_(_ret,MED_ERR_RANGE,MED_ERR_COMPUTINGSTEP,_datagroupname2);
143     SSCRUTE(meshname);SSCRUTE(_datagroupname1);goto ERROR;
144   }
145 
146   strcat( _pathsrc , _datagroupname1 );strcat( _pathsrc , "/");
147   strcat( _pathdst , _datagroupname2 );strcat( _pathdst , "/");
148 
149   /* On accepte l'absence de _datagroupname1 uniquement si
150      numdt2 == MED_NO_DT && numit2 == MED_NO_IT */
151   if ( (_datagroup1 = _MEDdatagroupOuvrir(_meshid,_datagroupname1)) < 0 ) {
152     if ( (numdt2 != MED_NO_DT ) || (numit2 != MED_NO_IT) ) {
153       MED_ERR_(_ret,MED_ERR_DOESNTEXIST,MED_ERR_COMPUTINGSTEP,_datagroupname1);
154       SSCRUTE(meshname);goto ERROR;
155       }
156   }
157 
158   /*L'étape de calcul à créer ne doit pas déjà exister*/
159   if ( (_datagroup2 = _MEDdatagroupOuvrir(_meshid,_datagroupname2)) >= 0 ) {
160     MED_ERR_(_ret,MED_ERR_EXIST,MED_ERR_COMPUTINGSTEP,_datagroupname2);
161     SSCRUTE(meshname);goto ERROR;
162   }
163 
164 
165   if ( _datagroup1 > 0 ) {
166 
167 
168     /*Lecture NEXT et PREV du datagroup1 */
169     if ( _MEDattrEntierLire(_datagroup1,MED_NOM_NXT,&_nextdt) < 0) {
170       MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
171       SSCRUTE(meshname);SSCRUTE(_datagroupname1);SSCRUTE(MED_NOM_NXT);
172       goto ERROR;
173     }
174 
175     if ( _MEDattrEntierLire(_datagroup1,MED_NOM_NXI,&_nextit) < 0) {
176       MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
177       SSCRUTE(meshname);SSCRUTE(_datagroupname1);SSCRUTE(MED_NOM_NXI);
178       goto ERROR;
179     }
180 
181     /* On vérifie que la nouvelle étape de calcul s'insère correctement :
182        < au next du datagroup1 */
183 /*     if ( !((_nextdt == MED_NO_DT) && (_nextit == MED_NO_IT) )) { */
184     if ( (_nextdt != MED_NO_DT) || (_nextit != MED_NO_IT) ) {
185       _MEDgetComputationStepName(_sortingtype,_nextdt,_nextit,_datagroupname3);
186 
187       if ( strncmp(_datagroupname3,_datagroupname2,2*MED_MAX_PARA+2) <= 0) {
188 	MED_ERR_(_ret,MED_ERR_RANGE,MED_ERR_COMPUTINGSTEP,_datagroupname2);
189 	SSCRUTE(meshname);SSCRUTE(_datagroupname3);goto ERROR;
190       }
191     }
192 
193     /*On crée la nouvelle étape de calcul (au plus tard, après vérifs...)*/
194     if ((_datagroup2 = _MEDdatagroupCreer(_meshid,_datagroupname2)) < 0 ) {
195       MED_ERR_(_ret,MED_ERR_CREATE,MED_ERR_DATAGROUP,_datagroupname2);
196       SSCRUTE(meshname);goto ERROR;
197     }
198 
199     /*On crée les datagroups, attributs et liens sur les datatsets et les liens symboliques
200       pour avoir une image de l'étape de calcul précedente.*/
201     if ( _MEDvisit(fid,_pathsrc,_pathdst,(medvisitorfunc) _MEDlinkobjs ) < 0 ) {
202       MED_ERR_(_ret,MED_ERR_VISIT,MED_ERR_DATAGROUP,MED_ERR_MESH_MSG);
203       SSCRUTE(meshname);SSCRUTE(_pathsrc);SSCRUTE(_pathdst);
204       goto ERROR;
205     }
206 
207     /*Ecriture NEXT et PREV du nouveau datagroup2 */
208     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NXT,&_nextdt) < 0) {
209       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
210       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXT);
211       goto ERROR;
212     }
213 
214     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NXI,&_nextit) < 0) {
215       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
216       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXI);
217       goto ERROR;
218     }
219 
220 
221     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_PVT,&_numdt1) < 0) {
222       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
223       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_PVT);
224       goto ERROR;
225     }
226 
227     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_PVI,&_numit1) < 0) {
228       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
229       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_PVI);
230       goto ERROR;
231     }
232 
233 
234     /*Modification du NEXT du datagroup1 */
235     if ( _MEDattributeIntWr(_datagroup1,MED_NOM_NXT,&numdt2) < 0) {
236       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
237       SSCRUTE(meshname);SSCRUTE(_datagroupname1);SSCRUTE(MED_NOM_NXT);
238       goto ERROR;
239     }
240 
241     if ( _MEDattributeIntWr(_datagroup1,MED_NOM_NXI,&numit2) < 0) {
242       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
243       SSCRUTE(meshname);SSCRUTE(_datagroupname1);SSCRUTE(MED_NOM_NXI);
244       goto ERROR;
245     }
246 
247     /*Modification de PREV du ( NEXT de datagroup1 ) s'il existe*/
248     if (strlen(_datagroupname3) ) {
249 
250       if ( (_datagroup3 = _MEDdatagroupOuvrir(_meshid,_datagroupname3)) < 0 ) {
251 	MED_ERR_(_ret,MED_ERR_OPEN,MED_ERR_COMPUTINGSTEP,_datagroupname3);
252 	SSCRUTE(meshname);goto ERROR;
253       }
254 
255       if ( _MEDattrEntierLire(_datagroup3,MED_NOM_PVT,&_pvdt) < 0) {
256 	MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
257 	SSCRUTE(meshname);SSCRUTE(_datagroupname3);SSCRUTE(MED_NOM_PVT);
258 	goto ERROR;
259       }
260 
261       if ( _MEDattrEntierLire(_datagroup3,MED_NOM_PVI,&_pvit) < 0) {
262 	MED_ERR_(_ret,MED_ERR_READ,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
263 	SSCRUTE(meshname);SSCRUTE(_datagroupname3);SSCRUTE(MED_NOM_PVI);
264 	goto ERROR;
265       }
266       _MEDgetComputationStepName(_sortingtype,_pvdt,_pvit,_datagroupname1bis);
267 
268       if ( strncmp(_datagroupname1,_datagroupname1bis,2*MED_MAX_PARA+2) != 0) {
269 	MED_ERR_(_ret,MED_ERR_NOTEQUAL,MED_ERR_COMPUTINGSTEP,_datagroupname1);
270 	SSCRUTE(meshname);SSCRUTE(_datagroupname1bis);goto ERROR;
271       }
272 
273       if ( _MEDattributeIntWr(_datagroup3,MED_NOM_PVT,&numdt2) < 0) {
274 	MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
275 	SSCRUTE(meshname);SSCRUTE(_datagroupname3);SSCRUTE(MED_NOM_PVT);
276 	goto ERROR;
277       }
278 
279       if ( _MEDattributeIntWr(_datagroup3,MED_NOM_PVI,&numit2) < 0) {
280 	MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
281 	SSCRUTE(meshname);SSCRUTE(_datagroupname3);SSCRUTE(MED_NOM_PVI);
282 	goto ERROR;
283       }
284 
285     }
286 
287   } else { /* Création de la première étape de calcul  */
288 
289     /*On crée la nouvelle étape de calcul (au plus tard, après vérifs...) */
290     if ((_datagroup2 = _MEDdatagroupCreer(_meshid,_datagroupname2)) < 0 ) {
291       MED_ERR_(_ret,MED_ERR_CREATE,MED_ERR_DATAGROUP,_datagroupname2);
292       SSCRUTE(meshname);goto ERROR;
293     }
294 
295     /* Ecriture de MED_NO_IT, MED_NO_DT pour NEXT et PREV de la première
296        étape de calcul */
297     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NXT,&numdt2) < 0) {
298       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
299       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXT);
300       goto ERROR;
301     }
302 
303     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NXI,&numit2) < 0) {
304       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
305       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXI);
306       goto ERROR;
307     }
308 
309     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_PVT,&numdt2) < 0) {
310       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
311       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_PVT);
312       goto ERROR;
313     }
314 
315     if ( _MEDattributeIntWr(_datagroup2,MED_NOM_PVI,&numit2) < 0) {
316       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
317       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_PVI);
318       goto ERROR;
319     }
320 
321   }
322 
323   /*Cree ou ouvre l'attribut MED_NOM_NDT pour écriture */
324   if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NDT,&numdt2) < 0) {
325     MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
326     SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NDT);
327     ISCRUTE(numdt2);goto ERROR;
328   }
329 
330   /*Cree ou ouvre l'attribut MED_NOM_PDT pour écriture */
331   if ( _MEDattrFloatEcrire(_datagroup2,MED_NOM_PDT,&dt2) < 0) {
332     MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
333     SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_PDT);
334     RSCRUTE(dt2);goto ERROR;
335   }
336 
337   /*Cree ou ouvre l'attribut MED_NOM_NOR pour écriture */
338   if ( _MEDattributeIntWr(_datagroup2,MED_NOM_NOR,&numit2) < 0) {
339     MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
340     SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NOR);
341     ISCRUTE(numit2); goto ERROR;
342   }
343 
344   /* Une nouvelle étape de calcul est vierge de toute modifiation*/
345   if ( _MEDattributeIntWr(_datagroup2,MED_NOM_CGT,&_false) < 0) {
346     MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
347     SSCRUTE(meshname);SSCRUTE(_datagroupname3);SSCRUTE(MED_NOM_CGT);
348     goto ERROR;
349   }
350 
351 
352   /* Ecriture de NEXT et PREV  au niveau meshid (dernière étape de calcul créée */
353   if ( strncmp(_datagroupname2,_latestcpstname,2*MED_MAX_PARA+2) >= 0) {
354 
355     if ( _MEDattributeIntWr(_meshid,MED_NOM_NXT,&numdt2) < 0) {
356       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
357       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXT);
358       goto ERROR;
359     }
360 
361     if ( _MEDattributeIntWr(_meshid,MED_NOM_NXI,&numit2) < 0) {
362       MED_ERR_(_ret,MED_ERR_WRITE,MED_ERR_ATTRIBUTE,MED_ERR_MESH_MSG);
363       SSCRUTE(meshname);SSCRUTE(_datagroupname2);SSCRUTE(MED_NOM_NXI);
364       goto ERROR;
365     }
366   }
367 
368   _ret = 0;
369  ERROR:
370 
371   if (_datagroup3>0)     if (_MEDdatagroupFermer(_datagroup3) < 0) {
372     MED_ERR_(_ret,MED_ERR_CLOSE,MED_ERR_DATAGROUP,_datagroupname3);
373     ISCRUTE_id(_datagroup3);
374   }
375 
376   if (_datagroup2>0)     if (_MEDdatagroupFermer(_datagroup2) < 0) {
377     MED_ERR_(_ret,MED_ERR_CLOSE,MED_ERR_DATAGROUP,_datagroupname2);
378     ISCRUTE_id(_datagroup2);
379   }
380 
381   if (_datagroup1>0)     if (_MEDdatagroupFermer(_datagroup1) < 0) {
382     MED_ERR_(_ret,MED_ERR_CLOSE,MED_ERR_DATAGROUP,_datagroupname1);
383     ISCRUTE_id(_datagroup1);
384   }
385 
386   if (_meshid>0)     if (_MEDdatagroupFermer(_meshid) < 0) {
387     MED_ERR_(_ret,MED_ERR_CLOSE,MED_ERR_DATAGROUP,_meshpath);
388     ISCRUTE_id(_meshid);
389   }
390 
391   return _ret;
392 }
393