libs/ck-libs/ParFUM/mesh.C

Go to the documentation of this file.
00001 /*
00002 Finite Element Method (FEM) Framework for Charm++
00003 Parallel Programming Lab, Univ. of Illinois 2002
00004 Orion Sky Lawlor, olawlor@acm.org, 12/20/2002
00005 
00006 FEM Implementation file: mesh creation and user-data manipulation.
00007 */
00008 
00009 #include "ParFUM.h"
00010 #include "ParFUM_internals.h"
00011 
00012 extern int femVersion;
00013 
00014 /*** IDXL Interface ****/
00015 FEM_Comm_Holder::FEM_Comm_Holder(FEM_Comm *sendComm, FEM_Comm *recvComm)
00016         :comm(sendComm,recvComm)
00017 {
00018         registered=false;
00019         idx=-1;
00020 }
00021 void FEM_Comm_Holder::registerIdx(IDXL_Chunk *c) {
00022         assert(!registered);
00023         IDXL_Chunk *owner=c;
00024         if (idx!=-1) // had an old index: try to get it back
00025                 idx=owner->addStatic(&comm,idx);
00026         else //No old index:
00027                 idx=owner->addStatic(&comm);
00028 }
00029 void FEM_Comm_Holder::pup(PUP::er &p) {
00030         p|idx;
00031         if (p.isUnpacking() && idx!=-1)
00032         { // Try to grab the same index we had on our old processor:
00033                 registerIdx(IDXL_Chunk::get("FEM_Comm_Holder::pup"));
00034         }
00035 }
00036 
00037 FEM_Comm_Holder::~FEM_Comm_Holder(void)
00038 {
00039         if (registered)
00040         { // Try to unregister from IDXL:
00041                 const char *caller="FEM_Comm_Holder::~FEM_Comm_Holder";
00042                 IDXL_Chunk *owner=IDXL_Chunk::getNULL();
00043                 if (owner) owner->destroy(idx,caller);
00044         }
00045 }
00046 
00047 /******* FEM_Mesh API ******/
00048 
00049 static void checkIsSet(int fem_mesh,bool wantSet,const char *caller) {
00050         if (FEM_Mesh_is_set(fem_mesh)!=wantSet) {
00051                 const char *msg=wantSet?"This mesh (%d) is not a setting mesh":
00052                         "This mesh (%d) is not a getting mesh";
00053                 FEM_Abort(caller,msg,fem_mesh);
00054         }
00055 }
00056 
00057 /* Connectivity: Map calls to appropriate version of FEM_Mesh_data */
00058 CDECL void
00059 FEM_Mesh_conn(int fem_mesh,int entity,
00060         int *conn, int firstItem, int length, int width)
00061 {
00062         FEM_Mesh_data(fem_mesh,entity,FEM_CONN, conn, firstItem,length, FEM_INDEX_0, width);
00063 }
00064 FDECL void
00065 FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(int *fem_mesh,int *entity,
00066         int *conn, int *firstItem,int *length, int *width)
00067 {
00068         //Can't just call the C version of this routine, because we use 1-based indices:
00069         FEM_Mesh_data(*fem_mesh,*entity,FEM_CONN, conn, *firstItem-1,*length, FEM_INDEX_1, *width);
00070 }
00071 
00072 CDECL void
00073 FEM_Mesh_set_conn(int fem_mesh,int entity,
00074         const int *conn, int firstItem,int length, int width)
00075 {
00076         checkIsSet(fem_mesh,true,"FEM_Mesh_set_conn");
00077         FEM_Mesh_conn(fem_mesh,entity,(int *)conn,firstItem,length,width);
00078 }
00079 FDECL void
00080 FTN_NAME(FEM_MESH_SET_CONN,fem_mesh_set_conn)(int *fem_mesh,int *entity,
00081         const int *conn, int *firstItem,int *length, int *width)
00082 {
00083         checkIsSet(*fem_mesh,true,"fem_mesh_set_conn");
00084         FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,(int *)conn,firstItem,length,width);
00085 }
00086 
00087 CDECL void
00088 FEM_Mesh_get_conn(int fem_mesh,int entity,
00089         int *conn, int firstItem,int length, int width)
00090 {
00091         checkIsSet(fem_mesh,false,"FEM_Mesh_get_conn");
00092         FEM_Mesh_conn(fem_mesh,entity,conn,firstItem,length,width);
00093 }
00094 FDECL void
00095 FTN_NAME(FEM_MESH_GET_CONN,fem_mesh_get_conn)(int *fem_mesh,int *entity,
00096         int *conn, int *firstItem,int *length, int *width)
00097 {
00098         checkIsSet(*fem_mesh,false,"fem_mesh_get_conn");
00099         FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,conn,firstItem,length,width);
00100 }
00101 
00102 
00103 /* Data: map to FEM_Mesh_offset */
00104 CDECL void
00105 FEM_Mesh_data(int fem_mesh,int entity,int attr,
00106         void *data, int firstItem,int length, int datatype,int width)
00107 {
00108         IDXL_Layout lo(datatype,width);
00109         FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,lo);
00110 }
00111 
00112 FORTRAN_AS_C(FEM_MESH_DATA,FEM_Mesh_data,fem_mesh_data,
00113         (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00114         (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00115 )
00116 
00117 
00118 CDECL void
00119 FEM_Mesh_set_data(int fem_mesh,int entity,int attr,
00120         const void *data, int firstItem,int length, int datatype,int width)
00121 {
00122         checkIsSet(fem_mesh,true,"FEM_Mesh_set_data");
00123         FEM_Mesh_data(fem_mesh,entity,attr,(void *)data,firstItem,length,datatype,width);
00124 }
00125 FORTRAN_AS_C(FEM_MESH_SET_DATA,FEM_Mesh_set_data,fem_mesh_set_data,
00126         (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00127         (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00128 )
00129 
00130 CDECL void
00131 FEM_Mesh_get_data(int fem_mesh,int entity,int attr,
00132         void *data, int firstItem,int length, int datatype,int width)
00133 {
00134         checkIsSet(fem_mesh,false,"FEM_Mesh_get_data");
00135         FEM_Mesh_data(fem_mesh,entity,attr,data,firstItem,length,datatype,width);
00136 }
00137 FORTRAN_AS_C(FEM_MESH_GET_DATA,FEM_Mesh_get_data,fem_mesh_get_data,
00138         (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00139         (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00140 )
00141 
00142 CDECL void
00143 FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
00144         void *data, int firstItem,int length, IDXL_Layout_t layout)
00145 {
00146         const char *caller="FEM_Mesh_data_layout";
00147         FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00148                 IDXL_Layout_List::get().get(layout,caller));
00149 }
00150 
00151 FORTRAN_AS_C(FEM_MESH_DATA_LAYOUT,FEM_Mesh_data_layout,fem_mesh_data_layout,
00152         (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *layout),
00153         (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*layout)
00154 )
00155 
00156 CDECL void
00157 FEM_Mesh_data_offset(int fem_mesh,int entity,int attr,
00158         void *data, int firstItem,int length,
00159         int type,int width, int offsetBytes,int distanceBytes,int skewBytes)
00160 {
00161         const char *caller="FEM_Mesh_data_offset";
00162         FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00163                 IDXL_Layout(type,width,offsetBytes,distanceBytes,skewBytes));
00164 }
00165 FORTRAN_AS_C(FEM_MESH_DATA_OFFSET,FEM_Mesh_data_offset,fem_mesh_data_offset,
00166         (int *fem_mesh,int *entity,int *attr,
00167          void *data,int *firstItem,int *length,
00168          int *type,int *width,int *offset,int *distance,int *skew),
00169         (*fem_mesh,*entity,*attr,
00170          data,*firstItem-1,*length,
00171          *type,*width,*offset,*distance,*skew)
00172 )
00173 
00174 
00175 void FEM_Register_array(int fem_mesh,int entity,int attr,
00176         void *data, int datatype,int width,int firstItem){
00177         IDXL_Layout lo(datatype,width);
00178 /*      if(attr == FEM_CONN){
00179                 printf("CONN width %d \n",width);
00180                 int len = FEM_Mesh_get_length(fem_mesh,entity);
00181                 int *connd = (int *)data;
00182                 for(int i=0;i<len;i++){
00183                         printf("%d -> (%d %d %d) \n",i+1,connd[3*i],connd[3*i+1],connd[3*i+2]);
00184                 }
00185         }
00186         printf("firstItem %d \n",firstItem);*/
00187         FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem,lo);
00188 }
00189 
00190 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,
00191         void *data, IDXL_Layout_t layout,int firstItem){
00192         const char *caller="FEM_Register_array_layout";
00193         FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem,
00194                 IDXL_Layout_List::get().get(layout,caller));
00195 
00196 }
00197 
00198 /*registration api */
00199 CDECL void
00200 FEM_Register_array(int fem_mesh,int entity,int attr,
00201         void *data, int datatype,int width)
00202 {
00203         FEM_Register_array(fem_mesh,entity,attr,data,datatype,width,0);
00204 }
00205 
00206 CDECL void
00207 FEM_Register_array_layout(int fem_mesh,int entity,int attr,
00208         void *data, IDXL_Layout_t layout){
00209         FEM_Register_array_layout(fem_mesh,entity,attr,data,layout,0);
00210 }
00211 
00212 
00213 CDECL void
00214 FEM_Register_entity(int fem_mesh,int entity,void *data,
00215                 int len,int max,FEM_Mesh_alloc_fn fn) {
00216                 FEM_Register_entity_impl(fem_mesh,entity,data,len,max,fn);
00217 }
00218 
00221 FORTRAN_AS_C(FEM_REGISTER_ARRAY,FEM_Register_array,fem_register_array,
00222         (int *fem_mesh,int *entity,int *attr,void *data,int *datatype,int *width),(*fem_mesh,*entity,*attr,data,*datatype,*width,0))
00223 
00224 
00225 FORTRAN_AS_C(FEM_REGISTER_ARRAY_LAYOUT,FEM_Register_array_layout,fem_register_array_layout,
00226         (int *fem_mesh,int *entity,int *attr,void *data,int *layout),(*fem_mesh,*entity,*attr,data,*layout,0))
00227 
00228 FORTRAN_AS_C(FEM_REGISTER_ENTITY,FEM_Register_entity,fem_register_entity,
00229         (int *fem_mesh,int *entity,void *data,int *len,int *max,FEM_Mesh_alloc_fn fn),(*fem_mesh,*entity,data,*len,*max,fn))
00230 
00231 
00232 // User data API:
00233 CDECL void
00234 FEM_Mesh_pup(int fem_mesh,int dataTag,FEM_Userdata_fn fn,void *data) {
00235         const char *caller="FEM_Mesh_pup"; FEMAPI(caller);
00236         FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00237         FEM_Userdata_item &i=m->udata.find(dataTag);
00238         FEM_Userdata_pupfn f(fn,data);
00239         if (m->isSetting()) i.store(f);
00240         else /* m->isGetting() */ {
00241                 if (!i.hasStored())
00242                         FEM_Abort(caller,"Never stored any user data at tag %d",dataTag);
00243                 i.restore(f);
00244         }
00245 }
00246 FORTRAN_AS_C(FEM_MESH_PUP,FEM_Mesh_pup,fem_mesh_pup,
00247         (int *m,int *t,FEM_Userdata_fn fn,void *data), (*m,*t,fn,data))
00248 
00249 // Accessor API:
00250 CDECL void
00251 FEM_Mesh_set_length(int fem_mesh,int entity,int newLength) {
00252         const char *caller="FEM_Mesh_set_length"; FEMAPI(caller);
00253         checkIsSet(fem_mesh,true,caller);
00254         FEM_Entity_lookup(fem_mesh,entity,caller)->setLength(newLength);
00255 }
00256 FORTRAN_AS_C(FEM_MESH_SET_LENGTH,FEM_Mesh_set_length,fem_mesh_set_length,
00257         (int *fem_mesh,int *entity,int *newLength),
00258         (*fem_mesh,*entity,*newLength)
00259 )
00260 
00261 
00262 CDECL int
00263 FEM_Mesh_get_length(int fem_mesh,int entity) {
00264         const char *caller="FEM_Mesh_get_length"; FEMAPI(caller);
00265         int len=FEM_Entity_lookup(fem_mesh,entity,caller)->size();
00266         return len;
00267 }
00268 FORTRAN_AS_C_RETURN(int,
00269         FEM_MESH_GET_LENGTH,FEM_Mesh_get_length,fem_mesh_get_length,
00270         (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00271 )
00272 
00273 
00274 CDECL void
00275 FEM_Mesh_set_width(int fem_mesh,int entity,int attr,int newWidth) {
00276         const char *caller="FEM_Mesh_set_width";
00277         FEMAPI(caller);
00278         checkIsSet(fem_mesh,true,caller);
00279         FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->setWidth(newWidth,caller);
00280 }
00281 FORTRAN_AS_C(FEM_MESH_SET_WIDTH,FEM_Mesh_set_width,fem_mesh_set_width,
00282         (int *fem_mesh,int *entity,int *attr,int *newWidth),
00283         (*fem_mesh,*entity,*attr,*newWidth)
00284 )
00285 
00286 CDECL int
00287 FEM_Mesh_get_width(int fem_mesh,int entity,int attr) {
00288         const char *caller="FEM_Mesh_get_width";
00289         FEMAPI(caller);
00290         return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getWidth();
00291 }
00292 FORTRAN_AS_C_RETURN(int,
00293         FEM_MESH_GET_WIDTH,FEM_Mesh_get_width,fem_mesh_get_width,
00294         (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00295 )
00296 
00297 CDECL int
00298 FEM_Mesh_get_datatype(int fem_mesh,int entity,int attr) {
00299         const char *caller="FEM_Mesh_get_datatype";
00300         FEMAPI(caller);
00301         return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getDatatype();
00302 }
00303 FORTRAN_AS_C_RETURN(int,
00304         FEM_MESH_GET_DATATYPE,FEM_Mesh_get_datatype,fem_mesh_get_datatype,
00305         (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00306 )
00307 
00308 CDECL int
00309 FEM_Mesh_is_set(int fem_mesh) /* return 1 if this is a writing mesh */
00310 {
00311         return (FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00312 }
00313 FORTRAN_AS_C_RETURN(int,
00314         FEM_MESH_IS_SET,FEM_Mesh_is_set,fem_mesh_is_set,
00315         (int *fem_mesh),(*fem_mesh)
00316 )
00317 
00318 CDECL int
00319 FEM_Mesh_is_get(int fem_mesh) /* return 1 if this is a readable mesh */
00320 {
00321         return (!FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00322 }
00323 FORTRAN_AS_C_RETURN(int,
00324         FEM_MESH_IS_GET,FEM_Mesh_is_get,fem_mesh_is_get,
00325         (int *fem_mesh),(*fem_mesh)
00326 )
00327 
00328 CDECL void
00329 FEM_Mesh_become_get(int fem_mesh) /* Make this a readable mesh */
00330 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeGetting(); }
00331 FORTRAN_AS_C(FEM_MESH_BECOME_GET,FEM_Mesh_become_get,fem_mesh_become_get, (int *m),(*m))
00332 
00333 CDECL void
00334 FEM_Mesh_become_set(int fem_mesh)
00335 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeSetting(); }
00336 FORTRAN_AS_C(FEM_MESH_BECOME_SET,FEM_Mesh_become_set,fem_mesh_become_set, (int *m),(*m))
00337 
00338 
00339 CDECL IDXL_t
00340 FEM_Comm_shared(int fem_mesh,int entity) {
00341         const char *caller="FEM_Comm_shared";
00342         FEMAPI(caller);
00343         if (entity!=FEM_NODE) FEM_Abort(caller,"Only shared nodes supported");
00344         return FEM_Mesh_lookup(fem_mesh,caller)->node.
00345                 sharedIDXL.getIndex(IDXL_Chunk::get(caller));
00346 }
00347 FORTRAN_AS_C_RETURN(int,
00348         FEM_COMM_SHARED,FEM_Comm_shared,fem_comm_shared,
00349         (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00350 )
00351 
00352 CDECL IDXL_t
00353 FEM_Comm_ghost(int fem_mesh,int entity) {
00354         const char *caller="FEM_Comm_ghost";
00355         FEMAPI(caller);
00356         FEM_Entity *e=FEM_Entity_lookup(fem_mesh,entity,caller);
00357         if (e->isGhost()) FEM_Abort(caller,"Can only call FEM_Comm_ghost on real entity type");
00358         return e->ghostIDXL.getIndex(IDXL_Chunk::get(caller));
00359 }
00360 FORTRAN_AS_C_RETURN(int,
00361         FEM_COMM_GHOST,FEM_Comm_ghost,fem_comm_ghost,
00362         (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00363 )
00364 
00365 
00366 // Internal API:
00367 void FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
00368         void *data, int firstItem,int length, const IDXL_Layout &layout)
00369 {
00370         if (femVersion == 0 && length==0) return;
00371         const char *caller="FEM_Mesh_data";
00372         FEMAPI(caller);
00373         FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00374         FEM_Attribute *a=m->lookup(entity,caller)->lookup(attr,caller);
00375 
00376         if (m->isSetting())
00377                 a->set(data,firstItem,length,layout,caller);
00378         else /* m->isGetting()*/
00379                 a->get(data,firstItem,length,layout,caller);
00380 }
00381 
00383 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,void *data,int firstItem,const IDXL_Layout &layout){
00384         const char *caller="FEM_Register_array";
00385         FEMAPI(caller);
00386         FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00387         FEM_Entity *e = m->lookup(entity,caller);
00388         int length = e->size();
00389         //should actually be a call on the entity
00390         int max = e->getMax();
00391         FEM_Attribute *a = e->lookup(attr,caller);
00392         if(a->getWidth() == 0){
00396         //      a->setDatatype(layout.type);
00397                 a->setWidth(layout.width);
00398         }
00399 
00400 
00401         if(m->isSetting()){
00402           a->register_data(data,length,max,layout,caller);
00403         }else{
00404           a->get(data,firstItem,length,layout,caller);
00405           //replace the attribute's data array with the user's data
00406           a->register_data(data,max/*length*/,max,layout,caller);
00407         }
00408 }
00409 void FEM_Register_entity_impl(int fem_mesh,int entity,void *args,int len,int max,FEM_Mesh_alloc_fn fn){
00410         char *caller = "FEM_Register_entity";
00411         FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00412 /*      if(!m->isSetting()){
00413                 CmiAbort("Register entity called on mesh that can't be written into");
00414         }
00415 */
00416         FEM_Entity *e = m->lookup(entity,caller);
00417         e->setMaxLength(len,max,args,fn);
00418 }
00419 
00420 FEM_Entity *FEM_Entity_lookup(int fem_mesh,int entity,const char *caller) {
00421         return FEM_Mesh_lookup(fem_mesh,caller)->lookup(entity,caller);
00422 }
00423 FEM_Attribute *FEM_Attribute_lookup(int fem_mesh,int entity,int attr,const char *caller) {
00424         return FEM_Entity_lookup(fem_mesh,entity,caller)->lookup(attr,caller);
00425 }
00426 
00427 CDECL int FEM_Mesh_get_entities(int fem_mesh, int *entities) {
00428         const char *caller="FEM_Mesh_get_entities";
00429         FEMAPI(caller);
00430         return FEM_Mesh_lookup(fem_mesh,caller)->getEntities(entities);
00431 }
00432 FORTRAN_AS_C_RETURN(int,
00433         FEM_MESH_GET_ENTITIES,FEM_Mesh_get_entities,fem_mesh_get_entities,
00434         (int *mesh,int *ent), (*mesh,ent)
00435 )
00436 
00437 CDECL int FEM_Mesh_get_attributes(int fem_mesh,int entity,int *attributes) {
00438         const char *caller="FEM_Mesh_get_attributes";
00439         FEMAPI(caller);
00440         return FEM_Entity_lookup(fem_mesh,entity,caller)->getAttrs(attributes);
00441 }
00442 FORTRAN_AS_C_RETURN(int,
00443         FEM_MESH_GET_ATTRIBUTES,FEM_Mesh_get_attributes,fem_mesh_get_attributes,
00444         (int *mesh,int *ent,int *attrs), (*mesh,*ent,attrs)
00445 )
00446 
00447 /************** FEM_Attribute ****************/
00448 
00449 CDECL const char *FEM_Get_datatype_name(int datatype,char *storage) {
00450         switch(datatype) {
00451         case FEM_BYTE: return "FEM_BYTE";
00452         case FEM_INT: return "FEM_INT";
00453         case FEM_FLOAT: return "FEM_FLOAT";
00454         case FEM_DOUBLE: return "FEM_DOUBLE";
00455         case FEM_INDEX_0: return "FEM_INDEX_0";
00456         case FEM_INDEX_1: return "FEM_INDEX_1";
00457         };
00458         sprintf(storage,"unknown datatype code (%d)",datatype);
00459         return storage;
00460 }
00461 
00464 CDECL const char *FEM_Get_attr_name(int attr,char *storage)
00465 {
00466         if (attr<FEM_ATTRIB_TAG_MAX)
00467         { //It's a user tag:
00468                 sprintf(storage,"FEM_DATA+%d",attr-FEM_DATA);
00469                 return storage;
00470         }
00471         switch(attr) {
00472         case FEM_CONN: return "FEM_CONN";
00473         case FEM_SPARSE_ELEM: return "FEM_SPARSE_ELEM";
00474         case FEM_COOR: return "FEM_COOR";
00475         case FEM_GLOBALNO: return "FEM_GLOBALNO";
00476         case FEM_PARTITION: return "FEM_PARTITION";
00477         case FEM_SYMMETRIES: return "FEM_SYMMETRIES";
00478         case FEM_NODE_PRIMARY: return "FEM_NODE_PRIMARY";
00479         case FEM_NODE_ELEM_ADJACENCY: return "FEM_NODE_ELEM_ADJACENCY";
00480         case FEM_NODE_NODE_ADJACENCY: return "FEM_NODE_NODE_ADJACENCY";
00481         case FEM_ELEM_ELEM_ADJACENCY: return "FEM_ELEM_ELEM_ADJACENCY";
00482         case FEM_ELEM_ELEM_ADJ_TYPES: return "FEM_ELEM_ELEM_ADJ_TYPES";
00483         case FEM_IS_VALID_ATTR: return "FEM_IS_VALID_ATTR";
00484         case FEM_MESH_SIZING: return "FEM_MESH_SIZING";
00485 
00486         default: break;
00487         };
00488         sprintf(storage,"unknown attribute code (%d)",attr);
00489         return storage;
00490 }
00491 
00492 //Abort with a nice error message saying:
00493 // Our <field> was previously set to <cur>; it cannot now be <operation> <next>
00494 void FEM_Attribute::bad(const char *field,bool forRead,int cur,int next,const char *caller) const
00495 {
00496         char nameStorage[256];
00497         const char *name=FEM_Get_attr_name(attr,nameStorage);
00498         char errBuf[1024];
00499         const char *cannotBe=NULL;
00500         if (forRead) {
00501                 if (cur==-1) {
00502                         sprintf(errBuf,"The %s %s %s was never set-- it cannot now be read",
00503                                 e->getName(),name,field);
00504                 }
00505                 else /* already had a value */
00506                         cannotBe="read as";
00507         }
00508         else /* for write */ {
00509                 cannotBe="set to";
00510         }
00511         if (cannotBe!=NULL) /* Use standard ... <something> cannot be <something>'d... error message */
00512                 sprintf(errBuf,"The %s %s %s was previously set to %d; it cannot now be %s %d",
00513                         e->getName(),name,field,cur,cannotBe,next);
00514 
00515         FEM_Abort(caller,errBuf);
00516 }
00517 
00518 
00519 FEM_Attribute::FEM_Attribute(FEM_Entity *e_,int attr_)
00520                 :e(e_),ghost(0),attr(attr_),width(0),datatype(-1), allocated(false)
00521 {
00522         tryAllocate();
00523         if (femVersion == 0) width=-1;
00524 }
00525 void FEM_Attribute::pup(PUP::er &p) {
00526         // e, attr, and ghost are always set by the constructor
00527         p|width;
00528         if (p.isUnpacking() && femVersion > 0 && width<0)  width=0;
00529         p|datatype;
00530         if (p.isUnpacking()) tryAllocate();
00531 }
00532 void FEM_Attribute::pupSingle(PUP::er &p, int pupindx) {
00533   return;
00534 }
00535 FEM_Attribute::~FEM_Attribute() {}
00536 
00537 void FEM_Attribute::setLength(int next,const char *caller) {
00538         int cur=getLength();
00539         if (next==cur) return; //Already set--nothing to do
00540         if (cur>0) bad("length",false,cur,next, caller);
00541         e->setLength(next);
00542         tryAllocate();
00543 }
00544 
00545 void FEM_Attribute::setWidth(int next,const char *caller) {
00546         int cur=getWidth();
00547         if (next==cur) return; //Already set--nothing to do
00548         if (cur>0) bad("width",false,cur,next, caller);
00549         width=next;
00550         tryAllocate();
00551         if (ghost) ghost->setWidth(width,caller);
00552 }
00553 
00554 void FEM_Attribute::setDatatype(int next,const char *caller) {
00555         int cur=getDatatype();
00556         if (next==cur) return; //Already set--nothing to do
00557         if (cur!=-1) bad("datatype",false,cur,next, caller);
00558         datatype=next;
00559         tryAllocate();
00560         if (ghost) ghost->setDatatype(datatype,caller);
00561 }
00562 
00563 void FEM_Attribute::copyShape(const FEM_Attribute &src) {
00564         setWidth(src.getWidth());
00565         if (src.getDatatype()!=-1)
00566           setDatatype(src.getDatatype()); //Automatically calls tryAllocate
00567 }
00568 void FEM_Attribute::set(const void *src, int firstItem,int length,
00569                 const IDXL_Layout &layout, const char *caller)
00570 {
00571         if (firstItem!=0) { /* If this isn't the start... */
00572                 if (length!=1) /* And we're not setting one at a time */
00573                         CmiAbort("FEM_Mesh_data: unexpected firstItem");
00574         }
00575 
00576         if (femVersion == 0 && getRealLength() == -1) setLength(length);
00577         else if (getLength()==0) setLength(length);
00578         else if (length!=1 && length!=getLength())
00579                 bad("length",false,getLength(),length, caller);
00580 
00581         int width=layout.width;
00582         if (femVersion==0 && getRealWidth()==-1) setWidth(width);
00583         else if (getWidth()==0) setWidth(width);
00584         else if (width!=getWidth())
00585                 bad("width",false,getWidth(),width, caller);
00586 
00587         int datatype=layout.type;
00588         if (getDatatype()==-1) setDatatype(datatype);
00589         else if (datatype!=getDatatype())
00590                 bad("datatype",false,getDatatype(),datatype, caller);
00591 
00592         /* Assert: our storage should be allocated now.
00593            Our subclass will actually copy user data */
00594 }
00595 
00596 void FEM_Attribute::get(void *dest, int firstItem,int length,
00597                 const IDXL_Layout &layout, const char *caller)  const
00598 {
00599         if (length==0) return; //Nothing to get
00600         if (length!=1 && length!=getLength())
00601                 bad("length",true,getLength(),length, caller);
00602 
00603         int width=layout.width;
00604         if (width!=getWidth())
00605                 bad("width",true,getWidth(),width, caller);
00606 
00607         int datatype=layout.type;
00608         if (datatype!=getDatatype())
00609                 bad("datatype",true,getDatatype(),datatype, caller);
00610 
00611         /* our subclass will actually copy into user data */
00612 }
00613 
00614 /*check if the layout is the same as earlier */
00615 
00616 void FEM_Attribute::register_data(void *user, int length,int max,
00617         const IDXL_Layout &layout, const char *caller){
00618 
00619                 int width=layout.width;
00620                 if (femVersion == 0 && getRealWidth()==-1) setWidth(width);
00621                 else if (getWidth()==0){
00622                         setWidth(width);
00623                 }else{
00624                         if (width!=getWidth()){
00625                                 bad("width",false,getWidth(),width, caller);
00626                         }
00627                 }
00628 
00629                 int datatype=layout.type;
00630                 if (getDatatype()==-1){
00631                         setDatatype(datatype);
00632                 }else{
00633                         if (datatype!=getDatatype()){
00634                                 bad("datatype",false,getDatatype(),datatype, caller);
00635                         }
00636                 }
00637 
00638 }
00639 
00640 //Check if all three of length, width, and datatype are set.
00641 // If so, call allocate.
00642 void FEM_Attribute::tryAllocate(void) {
00643         int lenNull, widthNull;
00644         if (femVersion == 0) {
00645           // version 0 takes -1 as empty
00646           lenNull = (getRealLength()==-1);
00647           widthNull = (getRealWidth()==-1);
00648         }
00649         else {
00650           lenNull = (getLength()==0);
00651           widthNull = (getWidth()==0);
00652         }
00653         if ((!allocated) && !lenNull && !widthNull && getDatatype()!=-1) {
00654           allocated=true;
00655                 allocate(getMax(),getWidth(),getDatatype());
00656         }
00657 }
00658 
00659 /*********************** DataAttribute *******************/
00660 FEM_DataAttribute::FEM_DataAttribute(FEM_Entity *e,int myAttr)
00661         :FEM_Attribute(e,myAttr),
00662          char_data(0),int_data(0),float_data(0),double_data(0)
00663 {
00664 }
00665 void FEM_DataAttribute::pup(PUP::er &p) {
00666         super::pup(p);
00667         switch(getDatatype()) {
00668         case -1: /* not allocated yet */ break;
00669         case FEM_BYTE:
00670           if (char_data) {
00671             /*if(p.isSizing()) {
00672               char_data->setRowLen(getEntity()->size());
00673               }*/
00674             char_data->pup(p);
00675           }
00676           break;
00677         case FEM_INT:
00678           if (int_data) {
00679             /*if(p.isSizing()) {
00680               int_data->setRowLen(getEntity()->size());
00681               }*/
00682             int_data->pup(p);
00683           }
00684           break;
00685         case FEM_FLOAT:
00686           if (float_data) {
00687             /*if(p.isSizing()) {
00688               float_data->setRowLen(getEntity()->size());
00689               }*/
00690             float_data->pup(p);
00691           }
00692           break;
00693         case FEM_DOUBLE:
00694           if (double_data) {
00695             /*if(p.isSizing()) {
00696               double_data->setRowLen(getEntity()->size());
00697               }*/
00698             double_data->pup(p);
00699           }
00700           break;
00701         default: CkAbort("Invalid datatype in FEM_DataAttribute::pup");
00702         }
00703 }
00704 void FEM_DataAttribute::pupSingle(PUP::er &p, int pupindx) {
00705         super::pupSingle(p,pupindx);
00706         switch(getDatatype()) {
00707         case -1: /* not allocated yet */ break;
00708         case FEM_BYTE:   if (char_data) char_data->pupSingle(p,pupindx); break;
00709         case FEM_INT:    if (int_data) int_data->pupSingle(p,pupindx); break;
00710         case FEM_FLOAT:  if (float_data) float_data->pupSingle(p,pupindx); break;
00711         case FEM_DOUBLE: if (double_data) double_data->pupSingle(p,pupindx); break;
00712         default: CkAbort("Invalid datatype in FEM_DataAttribute::pupSingle");
00713         }
00714 }
00715 FEM_DataAttribute::~FEM_DataAttribute() {
00716         if (char_data) delete char_data;
00717         if (int_data) delete int_data;
00718         if (float_data) delete float_data;
00719         if (double_data) delete double_data;
00720 
00721 }
00722 
00724 template <class T>
00725 inline void setTableData(const void *user, int firstItem, int length,
00726         IDXL_LAYOUT_PARAM, AllocTable2d<T> *table)
00727 {
00728         for (int r=0;r<length;r++) {
00729                 register T *tableRow=table->getRow(firstItem+r);
00730                 for (int c=0;c<width;c++)
00731                         tableRow[c]=IDXL_LAYOUT_DEREF(T,user,r,c);
00732         }
00733 }
00734 
00736 template <class T>
00737 inline void getTableData(void *user, int firstItem, int length,
00738         IDXL_LAYOUT_PARAM, const AllocTable2d<T> *table)
00739 {
00740         for (int r=0;r<length;r++) {
00741                 register const T *tableRow=table->getRow(firstItem+r);
00742                 for (int c=0;c<width;c++)
00743                         IDXL_LAYOUT_DEREF(T,user,r,c)=tableRow[c];
00744         }
00745 
00746 }
00747 
00748 void FEM_DataAttribute::set(const void *u, int f,int l,