1 /*--------------------------------------------------------------------------*/
2 /* ALBERTA:  an Adaptive multi Level finite element toolbox using           */
3 /*           Bisectioning refinement and Error control by Residual          */
4 /*           Techniques for scientific Applications                         */
5 /*                                                                          */
6 /* file:     read_mesh.c                                                    */
7 /*                                                                          */
8 /* description:  reading data of mesh and vectors in machine-dependent      */
9 /*               binary format                                              */
10 /*                                                                          */
11 /*--------------------------------------------------------------------------*/
12 /*                                                                          */
13 /*  authors:   Alfred Schmidt                                               */
14 /*             Zentrum fuer Technomathematik                                */
15 /*             Fachbereich 3 Mathematik/Informatik                          */
16 /*             Universitaet Bremen                                          */
17 /*             Bibliothekstr. 2                                             */
18 /*             D-28359 Bremen, Germany                                      */
19 /*                                                                          */
20 /*             Kunibert G. Siebert                                          */
21 /*             Institut fuer Mathematik                                     */
22 /*             Universitaet Augsburg                                        */
23 /*             Universitaetsstr. 14                                         */
24 /*             D-86159 Augsburg, Germany                                    */
25 /*                                                                          */
26 /*  http://www.alberta-fem.de/                                              */
27 /*                                                                          */
28 /*--------------------------------------------------------------------------*/
29 /*  (c) by A. Schmidt and K.G. Siebert (1996-2004)                          */
30 /*                                                                          */
31 /*     This program is free software; you can redistribute it and/or modify */
32 /*     it under the terms of the GNU General Public License as published by */
33 /*     the Free Software Foundation; either version 2 of the License, or    */
34 /*     any later version.                                                   */
35 /*                                                                          */
36 /*     This program is distributed in the hope that it will be useful,      */
37 /*     but WITHOUT ANY WARRANTY; without even the implied warranty of       */
38 /*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
39 /*     GNU General Public License for more details.                         */
40 /*--------------------------------------------------------------------------*/
41 
42 /*--------------------------------------------------------------------------*/
43 /* to_do :  number of dofs depending on node                                */
44 /* nach read_macro, damit dort pointer auf mel, v vorhanden sind!!!         */
45 /*    (fuers naechste Schreiben)                                            */
46 /*  error handling is terrible                                              */
47 /*--------------------------------------------------------------------------*/
48 
49 #include <string.h>
50 #include "alberta.h"
51 
52 static FILE       *file = nil;
53 static DOF_ADMIN  *admin = nil;
54 static MESH       *mesh = nil;
55 static U_CHAR     preserve_coarse_dofs;
56 
57 static int        n_vert_dofs = 0;
58 static DOF        **vert_dofs = nil;
59 
60 #if DIM > 1
61 static int        n_edge_dofs = 0;
62 static DOF        **edge_dofs = nil;
63 #endif
64 
65 #if DIM == 3
66 static int        n_face_dofs = 0;
67 static DOF        **face_dofs = nil;
68 #endif
69 
70 static EL *read_el_recursive(EL *parent);
71 
72 extern DOF_ADMIN *get_dof_admin(MESH *mesh, const char *name,
73 				      const int n_dof[DIM+1]);
74 
75 /*--------------------------------------------------------------------------*/
76 
read_dof_admins(MESH * mesh)77 static void read_dof_admins(MESH *mesh)
78 {
79   FUNCNAME("read_dof_admins");
80   int      i, n_dof_admin, iadmin, used_count;
81   int      n_dof_el, n_dof[DIM+1], n_node_el, node[DIM+1];
82   int      a_n_dof[DIM+1];
83   char     *name;
84 
85   fread(&n_dof_el, sizeof(int), 1, file);
86   fread(n_dof, sizeof(int), DIM+1, file);
87   fread(&n_node_el, sizeof(int), 1, file);
88   fread(node, sizeof(int), DIM+1, file);
89   /* use data later for check */
90 
91   fread(&n_dof_admin, sizeof(int), 1, file);
92   for (iadmin = 0; iadmin < n_dof_admin; iadmin++)
93   {
94     fread(a_n_dof, sizeof(int), DIM+1, file);
95     fread(&used_count, sizeof(int), 1, file);
96 
97     fread(&i, sizeof(int), 1, file);     /* length without terminating \0 */
98     name = MEM_ALLOC(i+1, char);
99     fread(name, sizeof(char), i, file);      /* admin->name */
100     name[i] = 0;
101 
102     admin = get_dof_admin(mesh, name, a_n_dof);
103     MEM_FREE(name, i+1, char);
104 
105     if (used_count > 0)
106       enlarge_dof_lists(admin, used_count);
107 
108   } /* end for (iadmin) */
109 
110   TEST(mesh->n_dof_el == n_dof_el)("wrong n_dof_el: %d %d\n",
111 				   mesh->n_dof_el, n_dof_el);
112   for (i=0; i<=DIM; i++)
113     TEST(mesh->n_dof[i] == n_dof[i])("wrong n_dof[%d]: %d %d\n",
114 				     i, mesh->n_dof[i], n_dof[i]);
115   TEST(mesh->n_node_el == n_node_el)("wrong n_node_el: %d %d\n",
116 				     mesh->n_node_el, n_node_el);
117   for (i=0; i<=DIM; i++)
118     TEST(mesh->node[i] == node[i])("wrong node[%d]: %d %d\n",
119 				     i, mesh->node[i], node[i]);
120   return;
121 }
122 
123 /*--------------------------------------------------------------------------*/
124 
read_mesh(const char * filename,REAL * timeptr,void (* init_leaf_data)(LEAF_DATA_INFO *),const BOUNDARY * (* init_boundary)(MESH * mesh,int ibdry))125 MESH *read_mesh(const char *filename, REAL *timeptr,
126 		void (*init_leaf_data)(LEAF_DATA_INFO *),
127 		const BOUNDARY *(*init_boundary)(MESH *mesh, int ibdry))
128 {
129   FUNCNAME("read_mesh");
130   MACRO_EL   *mel;
131   int        i, j, n;
132   REAL_D     *v, x_min, x_max;
133   int        neigh_i[N_NEIGH];
134   char       c99[99], *name;
135   int        size_REAL, iDIM, iDIM_OF_WORLD, ne, nv;
136   REAL       time, diam[DIM_OF_WORLD];
137   int        vert_i[N_VERTICES];
138   static int funccount=0;
139 #if DIM==3
140   S_CHAR     edge_sc[N_EDGES];
141 #endif
142 
143 #if DIM > 1
144   S_CHAR     bound_sc[N_NEIGH];
145   const BOUNDARY *(*init_bdry)(MESH *, int);
146 
147   init_bdry  = (init_boundary) ? init_boundary : default_boundary;
148 #endif
149 
150   TEST_EXIT(file=fopen(filename,"rb"))("cannot open file %s\n",filename);
151 
152   for (i=0; i < 98; i++) {
153     fread(c99+i, sizeof(char), 1, file);
154     if (c99[i] == 0) break;
155   }
156   if (i >= 98)
157   {
158     ERROR("problem reading id. abort.\n");
159     goto error_exit;
160   }
161   if (strncmp(c99, "ALBERTA", 6))
162   {
163     c99[98] = 0;
164     ERROR("unknown file id: \"%s\"\n",c99);
165     goto error_exit;
166   }
167 
168 
169   fread(&size_REAL, sizeof(int), 1, file);
170   if (size_REAL != sizeof(REAL))
171   {
172     ERROR("wrong sizeof(REAL) %d. abort.\n", size_REAL);
173     goto error_exit;
174   }
175 
176   fread(&iDIM, sizeof(int), 1, file);
177   if (iDIM != DIM)
178   {
179     ERROR("wrong DIM %d. abort.\n", iDIM);
180     goto error_exit;
181   }
182 
183   fread(&iDIM_OF_WORLD, sizeof(int), 1, file);
184   if (iDIM_OF_WORLD != DIM_OF_WORLD)
185   {
186     ERROR("wrong DIM_OF_WORLD %d. abort.\n", iDIM_OF_WORLD);
187     goto error_exit;
188   }
189 
190   fread(&time, sizeof(REAL), 1, file);
191   if (timeptr) *timeptr = time;
192 
193   fread(&i, sizeof(int), 1, file);     /* length without terminating \0 */
194 
195   if(i) {
196     name = MEM_ALLOC(i+1, char);
197     fread(name, sizeof(char), i, file);
198     name[i] = 0;
199   }
200   else {
201     funccount++;
202     i=100;
203     name = MEM_ALLOC(i+1, char);
204     sprintf(name, "READ_MESH%d", funccount);
205   }
206 
207 
208   fread(diam, sizeof(REAL), DIM_OF_WORLD, file);
209   fread(&preserve_coarse_dofs, sizeof(U_CHAR), 1, file);
210 
211 
212   mesh = GET_MESH(name, read_dof_admins, init_leaf_data);
213 
214 
215   MEM_FREE(name, i+1, char);
216   for (i=0; i<DIM_OF_WORLD; i++) mesh->diam[i] = diam[i];
217   mesh->preserve_coarse_dofs = preserve_coarse_dofs;
218   /* mesh->parametric = nil;     */
219 
220 
221   fread(&n_vert_dofs, sizeof(int), 1, file);
222   if (n_vert_dofs > 0) {
223     vert_dofs = MEM_ALLOC(n_vert_dofs, DOF *);
224     n = mesh->n_dof[VERTEX];
225     for (i = 0; i < n_vert_dofs; i++) {
226       vert_dofs[i] = get_dof(mesh, VERTEX);
227       fread(vert_dofs[i], sizeof(DOF), n, file);
228     }
229   }
230 #if DIM > 1
231   fread(&n_edge_dofs, sizeof(int), 1, file);
232   if (n_edge_dofs > 0)
233   {
234     edge_dofs = MEM_ALLOC(n_edge_dofs, DOF *);
235     n = mesh->n_dof[EDGE];
236     for (i = 0; i < n_edge_dofs; i++) {
237       edge_dofs[i] = get_dof(mesh, EDGE);
238       fread(edge_dofs[i], sizeof(DOF), n, file);
239     }
240   }
241 #endif
242 #if DIM==3
243   fread(&n_face_dofs, sizeof(int), 1, file);
244   if (n_face_dofs > 0) {
245     face_dofs = MEM_ALLOC(n_face_dofs, DOF *);
246     n = mesh->n_dof[FACE];
247     for (i = 0; i < n_face_dofs; i++) {
248       face_dofs[i] = get_dof(mesh, FACE);
249       fread(face_dofs[i], sizeof(DOF), n, file);
250     }
251   }
252 #endif
253 
254 
255   fread(&ne, sizeof(int), 1, file);
256   fread(&nv, sizeof(int), 1, file);
257 
258   ((MESH_MEM_INFO *)mesh->mem_info)->count = nv;
259   v = ((MESH_MEM_INFO *)mesh->mem_info)->coords = MEM_ALLOC(nv, REAL_D);
260   fread(v, sizeof(REAL_D), nv, file);
261 
262   for (j = 0; j < DIM_OF_WORLD; j++)
263   {
264     x_min[j] =  1.E30;
265     x_max[j] = -1.E30;
266   }
267 
268   for (i = 0; i < nv; i++)
269     for (j = 0; j < DIM_OF_WORLD; j++)
270     {
271       x_min[j] = MIN(x_min[j], v[i][j]);
272       x_max[j] = MAX(x_max[j], v[i][j]);
273     }
274 
275   for (j = 0; j < DIM_OF_WORLD; j++)
276     mesh->diam[j] = x_max[j] - x_min[j];
277 
278 
279   mel  = MEM_ALLOC(ne, MACRO_EL);
280 
281   for (i = 0; i < ne-1; i++) mel[i].next = mel+(i+1);
282   for (i = 1; i < ne; i++)   mel[i].last = mel+(i-1);
283   mel[0].last = mel[ne-1].next = nil;
284 
285   mesh->n_macro_el = ne;
286   mesh->first_macro_el = mel;
287 
288 
289   for (n = 0; n < ne; n++)
290   {
291     mel[n].index = n;
292 
293     fread(vert_i, sizeof(int), N_VERTICES, file);
294     for (i = 0; i < N_VERTICES; i++)
295     {
296       if ((vert_i[i] >= 0) && (vert_i[i] < nv))
297 	mel[n].coord[i] = (REAL *)(v + (vert_i[i]));
298       else
299 	mel[n].coord[i] = nil;
300     }
301 
302     fread(mel[n].bound, sizeof(S_CHAR), N_VERTICES, file);
303 
304 #if DIM > 1
305     fread(bound_sc, sizeof(S_CHAR), N_NEIGH, file);
306     for (i = 0; i < N_NEIGH; i++)
307     {
308       if (bound_sc[i])
309 	mel[n].boundary[i] = init_bdry(mesh, bound_sc[i]);
310       else
311 	mel[n].boundary[i] = nil;
312     }
313 #endif
314 
315     fread(neigh_i, sizeof(int), N_NEIGH, file);
316     for (i = 0; i < N_NEIGH; i++)
317     {
318       if ((neigh_i[i] >= 0) && (neigh_i[i] < ne))
319 	mel[n].neigh[i] = mel + (neigh_i[i]);
320       else
321 	mel[n].neigh[i] = nil;
322     }
323 
324     fread(mel[n].opp_vertex, sizeof(U_CHAR), N_NEIGH, file);
325 
326 #if DIM==3
327     fread(edge_sc, sizeof(S_CHAR), N_EDGES, file);
328     for (i = 0; i < N_EDGES; i++)
329     {
330 #if 1
331       if (edge_sc[i])
332 	mel[n].boundary[N_FACES+i] = init_bdry(mesh, edge_sc[i]);
333       else
334 	mel[n].boundary[N_FACES+i] = nil;
335 #else
336       if (edge_sc[i] > 0)
337 	mel[n].boundary[N_FACES+i] = bound+1;
338       else if (edge_sc[i] < 0)
339 	mel[n].boundary[N_FACES+i] = bound+2;
340       else
341 	mel[n].boundary[N_FACES+i] = nil;
342 #endif
343     }
344 
345     fread(&(mel[n].el_type), sizeof(U_CHAR), 1, file);    /* read el_type */
346 
347     {
348       extern S_CHAR get_orientation(MACRO_EL *mel);
349       mel[n].orientation = get_orientation(&mel[n]);
350     }
351 #endif
352 
353     mel[n].el = read_el_recursive(nil);
354   }
355 
356   fread(&mesh->n_vertices, sizeof(int), 1, file);
357   if (!strncmp((char *)(&mesh->n_vertices), "EOF.", 4)) /* file end marker ? */
358   {
359     MSG("Warning: old mesh file format.\n");
360     mesh->n_vertices = n_vert_dofs;
361     goto error_exit;
362   }
363 
364   if (mesh->n_vertices != n_vert_dofs)
365   {
366     ERROR("n_vertices != n_vert_dofs.\n");
367     mesh->n_vertices = n_vert_dofs;
368     goto error_exit;
369   }
370 #if DIM > 1
371   fread(&mesh->n_edges, sizeof(int), 1, file);
372 #endif
373   fread(&mesh->n_elements, sizeof(int), 1, file);
374   fread(&mesh->n_hier_elements, sizeof(int), 1, file);
375 #if DIM == 3
376   fread(&mesh->n_faces, sizeof(int), 1, file);
377   fread(&mesh->max_edge_neigh, sizeof(int), 1, file);
378 #endif
379 
380   if (fread(c99, sizeof(char), 4, file) != 4)
381   {
382     ERROR("problem reading FILE END MARK.\n");
383     goto error_exit;
384   }
385   if (strncmp(c99, "EOF.", 4))                     /* file end marker */
386   {
387     ERROR("no FILE END MARK.\n");
388     goto error_exit;
389   }
390 
391 
392 #if NEIGH_IN_EL
393   ERROR_EXIT("read_mesh for NEIGH_IN_EL=1 not implemented yet!!!\n");
394 #endif
395 
396  error_exit:
397 
398   fclose(file);
399   file = nil;
400 
401 #if DIM == 3
402   if(n_face_dofs) MEM_FREE(face_dofs, n_face_dofs, DOF *);
403 #endif
404 #if DIM > 1
405   if(n_edge_dofs) MEM_FREE(edge_dofs, n_edge_dofs, DOF *);
406 #endif
407   if(n_vert_dofs) MEM_FREE(vert_dofs, n_vert_dofs, DOF *);
408 
409   return(mesh);
410 }
411 
412 /*--------------------------------------------------------------------------*/
413 
read_el_recursive(EL * parent)414 static EL *read_el_recursive(EL *parent)
415 {
416   FUNCNAME("read_el_recursive");
417   int    i, j, n, node0;
418   EL     *el;
419   U_CHAR uc;
420 #if DIM > 1
421   U_CHAR nc;
422 #endif
423 
424   el = get_element(mesh);
425   mesh->n_hier_elements++;
426 
427 #if EL_INDEX
428   el->index = mesh->n_hier_elements;
429 #endif
430 
431   fread(&uc, sizeof(U_CHAR), 1, file);
432 
433 #if DIM > 1
434   fread(&nc, sizeof(U_CHAR), 1, file);
435   if (nc)
436   {
437     el->new_coord = get_real_d(mesh);
438     fread(el->new_coord, sizeof(REAL_D), 1, file);
439   }
440   else
441   {
442     el->new_coord = nil;
443   }
444 #endif
445 
446   if (mesh->n_dof[VERTEX] > 0)
447   {
448     node0 = mesh->node[VERTEX];
449     for (i = 0; i < N_VERTICES; i++)
450     {
451       fread(&j, sizeof(int), 1, file);
452       TEST_EXIT(j < n_vert_dofs)
453 	("vert_dofs index too large: %d >= %d\n", j, n_vert_dofs);
454       el->dof[node0 + i] = vert_dofs[j];
455     }
456   }
457 
458   if ((!uc) || preserve_coarse_dofs)
459   {
460 #if DIM > 1
461     if (mesh->n_dof[EDGE] > 0)
462     {
463       node0 = mesh->node[EDGE];
464       for (i = 0; i < N_EDGES; i++)
465       {
466 	fread(&j, sizeof(int), 1, file);
467 	TEST_EXIT(j < n_edge_dofs)
468 	  ("edge_dofs index too large: %d >= %d\n", j, n_edge_dofs);
469 	el->dof[node0 + i] = edge_dofs[j];
470       }
471     }
472 #endif
473 
474 #if DIM==3
475     if ((n = mesh->n_dof[FACE]) > 0)
476     {
477       node0 = mesh->node[FACE];
478       for (i = 0; i < N_FACES; i++)
479       {
480 	fread(&j, sizeof(int), 1, file);
481 	TEST_EXIT(j < n_face_dofs)
482 	  ("face_dofs index too large: %d >= %d\n", j, n_face_dofs);
483 	el->dof[node0 + i] = face_dofs[j];
484       }
485     }
486 #endif
487 
488     if ((n = mesh->n_dof[CENTER]) > 0)
489     {
490       node0 = mesh->node[CENTER];
491       el->dof[node0] = get_dof(mesh, CENTER);
492       fread(el->dof[node0], sizeof(DOF), n, file);
493     }
494   }
495 
496 #if NEIGH_IN_EL
497   for (i = 0; i < N_NEIGH; i++)
498   {
499     el->neigh[i] = nil;
500     el->opp_vertex[i] = 0;
501   }
502 #endif
503 
504   if (uc)
505   {
506     el->child[0] = read_el_recursive(el);
507     el->child[1] = read_el_recursive(el);
508   }
509   else
510     mesh->n_elements++;
511 
512   return(el);
513 }
514 
515 #if 0
516 
517 /*--------------------------------------------------------------------------*/
518 /* read DOF vectors of various types                                        */
519 /*--------------------------------------------------------------------------*/
520 
521 typedef DOF_REAL_VEC DOF_VEC;
522 
523 static const DOF_ADMIN *read_dof_vec(const char *filename, DOF_VEC *dv,
524 				     int unit_size, const char dofvectype[16],
525 				     MESH *mesh, FE_SPACE *fe_space)
526 {
527   FUNCNAME("read_dof_vec");
528   int             i, last;
529   int             n_dof[DIM+1];
530   const DOF_ADMIN *admin = nil;
531   const BAS_FCTS  *bas_fcts = nil;
532   char            c20[20], *name;
533 
534   TEST_EXIT(mesh)("no mesh given\n");
535 
536   TEST_EXIT(file=fopen(filename,"rb"))("cannot open file %s\n",filename);
537 
538   if (fread(c20, sizeof(char), 16, file) != 16)
539   {
540     ERROR("cannot read file id\n");
541     goto error_exit;
542   }
543   if (strncmp(c20, dofvectype, 12))
544   {
545     c20[16] = 0;
546     ERROR("invalid file id; %s\n", c20);
547     goto error_exit;
548   }
549 
550   fread(&last, sizeof(int), 1, file);      /* length of DOF_VEC name */
551   if (last)
552   {
553     name = MEM_ALLOC(last+1, char);
554     fread(name, sizeof(char), last, file);
555     name[last] = 0;
556   }
557   else
558     name = strdup(filename);
559 
560   dv->name = name;
561 
562   fread(n_dof, sizeof(int), DIM+1, file);  /* for DOF_ADMIN selection */
563 
564   fread(&last, sizeof(int), 1, file);      /* length of BAS_FCTS name */
565   if (last)
566   {
567     name = MEM_ALLOC(last+1, char);
568     fread(name, sizeof(char), last, file);
569     name[last] = 0;
570 
571     if (fe_space && (bas_fcts = fe_space->bas_fcts)) {
572       if (strcmp(bas_fcts->name, name)) {
573 	ERROR("invalid name %s is not given fe_space->bas_fcts->name %s\n",
574 	    name, bas_fcts->name);
575       }
576     }
577     else { /* no given fe_space or no bas_fcts in given fe_space */
578       TEST_EXIT(bas_fcts = get_bas_fcts(name))
579 	("cannot get bas_fcts <%s>\n", name);
580 
581       if (fe_space) {                             /* use given fe_space */
582 	fe_space->bas_fcts = bas_fcts;
583       }
584       else {                                     /* create new fe_space */
585 	TEST_EXIT(fe_space =
586 		  (FE_SPACE *)get_fe_space(mesh, name, n_dof, bas_fcts))
587 	  ("cannot get fe_space for bas_fcts <%s>\n", name);
588       }
589     }
590 
591     for (i=0; i<=DIM; i++) {
592       TEST_EXIT(n_dof[i] == bas_fcts->n_dof[i])
593 	("wrong n_dof in bas_fcts <%s>", name);
594     }
595   }
596   else {  /* no bas_fcts.name in file */
597     if (fe_space) {                               /* use given fe_space */
598       TEST_EXIT(admin = fe_space->admin)("no fe_space->admin");
599       for (i=0; i<=DIM; i++) {
600 	TEST_EXIT(n_dof[i] == admin->n_dof[i])
601 	  ("wrong n_dof in admin <%s>", NAME(admin));
602       }
603     }
604     else {                                       /* create new fe_space */
605       TEST_EXIT(fe_space =
606 		(FE_SPACE *) get_fe_space(mesh, nil, n_dof, nil))
607 	("cannot get fe_space for given n_dof\n");
608       TEST_EXIT(admin = fe_space->admin)("no admin in new fe_space\n");
609       for (i=0; i<=DIM; i++) {
610 	TEST_EXIT(n_dof[i] == admin->n_dof[i])
611 	  ("wrong n_dof in admin <%s>", NAME(admin));
612       }
613     }
614 
615     MEM_FREE(name, last+1, char);
616   }
617   TEST_EXIT(fe_space)("still no fe_space\n");
618   dv->fe_space = fe_space;
619   TEST_EXIT(admin = fe_space->admin)("still no admin\n");
620 
621   dof_compress(mesh);
622 
623   fread(&last, sizeof(int), 1, file);
624   if (last != admin->size_used)
625   {
626     ERROR("size of dof vector `%s' does not fit to size_used in admin `%s'\n",
627 	  dv->name, admin->name);
628     ERROR_EXIT("can not read incompatible data\n");
629   }
630 
631   if (last)
632   {
633     dv->size = last;
634     dv->vec = ((REAL *) alberta_alloc((size_t)(last*unit_size), funcName,
635 				     __FILE__, __LINE__));
636     fread(dv->vec, unit_size, last, file);
637   }
638   else
639   {
640     ERROR("empty dof vector\n");
641     dv->size = 0;
642     dv->vec = nil;
643   }
644 
645   if (fread(c20, sizeof(char), 4, file) != 4)
646   {
647     print_error_msg("ERROR: problem reading file end mark.\n");
648     goto error_exit;
649   }
650   if (strncmp(c20, "EOF.", 4))                     /* file end marker */
651   {
652     print_error_msg("ERROR: no file end mark.\n");
653     goto error_exit;
654   }
655 
656  error_exit:
657   fclose(file);
658   file = nil;
659   return(admin);
660 }
661 /*--------------------------------------------------------------------------*/
662 
663 DOF_REAL_VEC *read_dof_real_vec(const char *filename,
664 				MESH *mesh, FE_SPACE *fe_space)
665 {
666   DOF_REAL_VEC    *dv;
667   const DOF_ADMIN *admin;
668   void add_dof_real_vec_to_admin(DOF_REAL_VEC *dv, DOF_ADMIN *admin);
669 
670   dv = get_dof_real_vec(filename, nil);
671   admin = read_dof_vec(filename, (DOF_VEC *)dv,
672 		       sizeof(REAL), "DOF_REAL_VEC    ", mesh, fe_space);
673 
674   if (admin) add_dof_real_vec_to_admin(dv, (DOF_ADMIN *)admin);
675   return(dv);
676 }
677 
678 /*--------------------------------------------------------------------------*/
679 
680 DOF_REAL_D_VEC *read_dof_real_d_vec(const char *filename,
681 				    MESH *mesh, FE_SPACE *fe_space)
682 {
683   DOF_REAL_D_VEC  *dv;
684   const DOF_ADMIN *admin;
685   void add_dof_real_d_vec_to_admin(DOF_REAL_D_VEC *dv, DOF_ADMIN *admin);
686 
687   dv = get_dof_real_d_vec(filename, nil);
688   admin = read_dof_vec(filename, (DOF_VEC *)dv,
689 		       sizeof(REAL_D), "DOF_REAL_D_VEC  ", mesh, fe_space);
690 
691   if (admin) add_dof_real_d_vec_to_admin(dv, (DOF_ADMIN *)admin);
692   return(dv);
693 }
694 
695 /*--------------------------------------------------------------------------*/
696 
697 DOF_INT_VEC *read_dof_int_vec(const char *filename,
698 			      MESH *mesh, FE_SPACE *fe_space)
699 {
700   DOF_INT_VEC     *dv;
701   const DOF_ADMIN *admin;
702   void add_dof_int_vec_to_admin(DOF_INT_VEC *dv, DOF_ADMIN *admin);
703 
704   dv = get_dof_int_vec(filename, nil);
705   admin = read_dof_vec(filename, (DOF_VEC *)dv,
706 		       sizeof(int), "DOF_INT_VEC     ", mesh, fe_space);
707 
708   if (admin) add_dof_int_vec_to_admin(dv, (DOF_ADMIN *)admin);
709   return(dv);
710 }
711 
712 /*--------------------------------------------------------------------------*/
713 
714 DOF_SCHAR_VEC *read_dof_schar_vec(const char *filename,
715 				  MESH *mesh, FE_SPACE *fe_space)
716 {
717   DOF_SCHAR_VEC   *dv;
718   const DOF_ADMIN *admin;
719   void add_dof_schar_vec_to_admin(DOF_SCHAR_VEC *dv, DOF_ADMIN *admin);
720 
721   dv = get_dof_schar_vec(filename, nil);
722   admin = read_dof_vec(filename, (DOF_VEC *)dv,
723 		       sizeof(S_CHAR), "DOF_SCHAR_VEC   ", mesh, fe_space);
724 
725   if (admin) add_dof_schar_vec_to_admin(dv, (DOF_ADMIN *)admin);
726   return(dv);
727 }
728 
729 /*--------------------------------------------------------------------------*/
730 
731 DOF_UCHAR_VEC *read_dof_uchar_vec(const char *filename,
732 				  MESH *mesh, FE_SPACE *fe_space)
733 {
734   DOF_UCHAR_VEC   *dv;
735   const DOF_ADMIN *admin;
736   void add_dof_uchar_vec_to_admin(DOF_UCHAR_VEC *dv, DOF_ADMIN *admin);
737 
738   dv = get_dof_uchar_vec(filename, nil);
739   admin = read_dof_vec(filename, (DOF_VEC *)dv,
740 		       sizeof(U_CHAR), "DOF_UCHAR_VEC   ", mesh, fe_space);
741 
742   if (admin) add_dof_uchar_vec_to_admin(dv, (DOF_ADMIN *)admin);
743   return(dv);
744 }
745 
746 /*--------------------------------------------------------------------------*/
747 #endif
748