00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <assert.h>
00010 #include "fem.h"
00011 #include "fem_impl.h"
00012 #include "charm-api.h" 
00013 #include "fem_mesh_modify.h"
00014 
00015 extern int femVersion;
00016 
00017 
00018 FEM_Comm_Holder::FEM_Comm_Holder(FEM_Comm *sendComm, FEM_Comm *recvComm)
00019     :comm(sendComm,recvComm)
00020 {
00021     registered=false;
00022     idx=-1; 
00023 }
00024 void FEM_Comm_Holder::registerIdx(IDXL_Chunk *c) {
00025     assert(!registered);
00026     IDXL_Chunk *owner=c;
00027     if (idx!=-1) 
00028         idx=owner->addStatic(&comm,idx);
00029     else 
00030         idx=owner->addStatic(&comm);
00031 }
00032 void FEM_Comm_Holder::pup(PUP::er &p) {
00033     p|idx;
00034     if (p.isUnpacking() && idx!=-1) 
00035     { 
00036         registerIdx(IDXL_Chunk::get("FEM_Comm_Holder::pup"));
00037     }
00038 }
00039 
00040 FEM_Comm_Holder::~FEM_Comm_Holder(void)
00041 {
00042     if (registered) 
00043     { 
00044         const char *caller="FEM_Comm_Holder::~FEM_Comm_Holder";
00045         IDXL_Chunk *owner=IDXL_Chunk::getNULL();
00046         if (owner) owner->destroy(idx,caller); 
00047     }
00048 }
00049 
00050 
00051 
00052 static void checkIsSet(int fem_mesh,bool wantSet,const char *caller) {
00053     if (FEM_Mesh_is_set(fem_mesh)!=wantSet) {
00054         const char *msg=wantSet?"This mesh (%d) is not a setting mesh":
00055             "This mesh (%d) is not a getting mesh";
00056         FEM_Abort(caller,msg,fem_mesh);
00057     }
00058 }
00059 
00060 
00061 CLINKAGE void
00062 FEM_Mesh_conn(int fem_mesh,int entity,
00063     int *conn, int firstItem, int length, int width) 
00064 {
00065     FEM_Mesh_data(fem_mesh,entity,FEM_CONN, conn, firstItem,length, FEM_INDEX_0, width);
00066 }
00067 FLINKAGE void
00068 FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(int *fem_mesh,int *entity,
00069     int *conn, int *firstItem,int *length, int *width)
00070 {
00071     
00072     FEM_Mesh_data(*fem_mesh,*entity,FEM_CONN, conn, *firstItem-1,*length, FEM_INDEX_1, *width);
00073 }
00074 
00075 CLINKAGE void
00076 FEM_Mesh_set_conn(int fem_mesh,int entity,
00077     const int *conn, int firstItem,int length, int width)
00078 {
00079     checkIsSet(fem_mesh,true,"FEM_Mesh_set_conn");
00080     FEM_Mesh_conn(fem_mesh,entity,(int *)conn,firstItem,length,width);
00081 }
00082 FLINKAGE void
00083 FTN_NAME(FEM_MESH_SET_CONN,fem_mesh_set_conn)(int *fem_mesh,int *entity,
00084     const int *conn, int *firstItem,int *length, int *width)
00085 {
00086     checkIsSet(*fem_mesh,true,"fem_mesh_set_conn");
00087     FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,(int *)conn,firstItem,length,width);
00088 }
00089 
00090 CLINKAGE void
00091 FEM_Mesh_get_conn(int fem_mesh,int entity,
00092     int *conn, int firstItem,int length, int width)
00093 {
00094     checkIsSet(fem_mesh,false,"FEM_Mesh_get_conn");
00095     FEM_Mesh_conn(fem_mesh,entity,conn,firstItem,length,width);
00096 }
00097 FLINKAGE void
00098 FTN_NAME(FEM_MESH_GET_CONN,fem_mesh_get_conn)(int *fem_mesh,int *entity,
00099     int *conn, int *firstItem,int *length, int *width)
00100 {
00101     checkIsSet(*fem_mesh,false,"fem_mesh_get_conn");
00102     FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,conn,firstItem,length,width);
00103 }
00104 
00105 
00106 
00107 CLINKAGE void
00108 FEM_Mesh_data(int fem_mesh,int entity,int attr,     
00109     void *data, int firstItem,int length, int datatype,int width)
00110 {
00111     IDXL_Layout lo(datatype,width);
00112     FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,lo);
00113 }
00114 
00115 FORTRAN_AS_C(FEM_MESH_DATA,FEM_Mesh_data,fem_mesh_data,
00116     (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00117     (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00118 )
00119 
00120 
00121 CLINKAGE void
00122 FEM_Mesh_set_data(int fem_mesh,int entity,int attr,     
00123     const void *data, int firstItem,int length, int datatype,int width)
00124 {
00125     checkIsSet(fem_mesh,true,"FEM_Mesh_set_data");
00126     FEM_Mesh_data(fem_mesh,entity,attr,(void *)data,firstItem,length,datatype,width);
00127 }
00128 FORTRAN_AS_C(FEM_MESH_SET_DATA,FEM_Mesh_set_data,fem_mesh_set_data,
00129     (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00130     (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00131 )
00132 
00133 CLINKAGE void
00134 FEM_Mesh_get_data(int fem_mesh,int entity,int attr,     
00135     void *data, int firstItem,int length, int datatype,int width)
00136 {
00137     checkIsSet(fem_mesh,false,"FEM_Mesh_get_data");
00138     FEM_Mesh_data(fem_mesh,entity,attr,data,firstItem,length,datatype,width);
00139 }
00140 FORTRAN_AS_C(FEM_MESH_GET_DATA,FEM_Mesh_get_data,fem_mesh_get_data,
00141     (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00142     (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00143 )
00144 
00145 CLINKAGE void
00146 FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,  
00147     void *data, int firstItem,int length, IDXL_Layout_t layout)
00148 {
00149     const char *caller="FEM_Mesh_data_layout";
00150     FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00151         IDXL_Layout_List::get().get(layout,caller));
00152 }
00153 
00154 FORTRAN_AS_C(FEM_MESH_DATA_LAYOUT,FEM_Mesh_data_layout,fem_mesh_data_layout,
00155     (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *layout),
00156     (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*layout)
00157 )
00158 
00159 CLINKAGE void
00160 FEM_Mesh_data_offset(int fem_mesh,int entity,int attr,  
00161     void *data, int firstItem,int length,
00162     int type,int width, int offsetBytes,int distanceBytes,int skewBytes)
00163 {
00164     const char *caller="FEM_Mesh_data_offset";
00165     FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00166         IDXL_Layout(type,width,offsetBytes,distanceBytes,skewBytes));
00167 }
00168 FORTRAN_AS_C(FEM_MESH_DATA_OFFSET,FEM_Mesh_data_offset,fem_mesh_data_offset,
00169     (int *fem_mesh,int *entity,int *attr,
00170      void *data,int *firstItem,int *length,
00171      int *type,int *width,int *offset,int *distance,int *skew),
00172     (*fem_mesh,*entity,*attr,
00173      data,*firstItem-1,*length,
00174      *type,*width,*offset,*distance,*skew)
00175 )
00176 
00177 
00178 void FEM_Register_array(int fem_mesh,int entity,int attr,
00179     void *data, int datatype,int width,int firstItem){
00180     IDXL_Layout lo(datatype,width);
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190     FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem,lo);
00191 }
00192 
00193 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,    
00194     void *data, IDXL_Layout_t layout,int firstItem){
00195     const char *caller="FEM_Register_array_layout";
00196     FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem, 
00197         IDXL_Layout_List::get().get(layout,caller));
00198 
00199 }
00200 
00201 
00202 CLINKAGE void
00203 FEM_Register_array(int fem_mesh,int entity,int attr,
00204     void *data, int datatype,int width)
00205 {   
00206     FEM_Register_array(fem_mesh,entity,attr,data,datatype,width,0);
00207 }
00208 
00209 CLINKAGE void
00210 FEM_Register_array_layout(int fem_mesh,int entity,int attr,     
00211     void *data, IDXL_Layout_t layout){
00212     FEM_Register_array_layout(fem_mesh,entity,attr,data,layout,0);
00213 }
00214 
00215 
00216 CLINKAGE void
00217 FEM_Register_entity(int fem_mesh,int entity,void *data,
00218         int len,int max,FEM_Mesh_alloc_fn fn) {
00219         FEM_Register_entity_impl(fem_mesh,entity,data,len,max,fn);
00220 }
00221 
00224 FORTRAN_AS_C(FEM_REGISTER_ARRAY,FEM_Register_array,fem_register_array,
00225     (int *fem_mesh,int *entity,int *attr,void *data,int *datatype,int *width),(*fem_mesh,*entity,*attr,data,*datatype,*width,0))
00226 
00227 
00228 FORTRAN_AS_C(FEM_REGISTER_ARRAY_LAYOUT,FEM_Register_array_layout,fem_register_array_layout,
00229     (int *fem_mesh,int *entity,int *attr,void *data,int *layout),(*fem_mesh,*entity,*attr,data,*layout,0))
00230 
00231 FORTRAN_AS_C(FEM_REGISTER_ENTITY,FEM_Register_entity,fem_register_entity,
00232     (int *fem_mesh,int *entity,void *data,int *len,int *max,FEM_Mesh_alloc_fn fn),(*fem_mesh,*entity,data,*len,*max,fn))
00233 
00234 
00235 
00236 CLINKAGE void
00237 FEM_Mesh_pup(int fem_mesh,int dataTag,FEM_Userdata_fn fn,void *data) {
00238     const char *caller="FEM_Mesh_pup"; FEMAPI(caller);
00239     FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00240     FEM_Userdata_item &i=m->udata.find(dataTag);
00241     FEM_Userdata_pupfn f(fn,data);
00242     if (m->isSetting()) i.store(f);
00243     else  {
00244         if (!i.hasStored())
00245             FEM_Abort(caller,"Never stored any user data at tag %d",dataTag);
00246         i.restore(f);
00247     }
00248 }
00249 FORTRAN_AS_C(FEM_MESH_PUP,FEM_Mesh_pup,fem_mesh_pup,
00250     (int *m,int *t,FEM_Userdata_fn fn,void *data), (*m,*t,fn,data))
00251 
00252 
00253 CLINKAGE void
00254 FEM_Mesh_set_length(int fem_mesh,int entity,int newLength) {
00255     const char *caller="FEM_Mesh_set_length"; FEMAPI(caller);
00256     checkIsSet(fem_mesh,true,caller);
00257     FEM_Entity_lookup(fem_mesh,entity,caller)->setLength(newLength);
00258 }
00259 FORTRAN_AS_C(FEM_MESH_SET_LENGTH,FEM_Mesh_set_length,fem_mesh_set_length,
00260     (int *fem_mesh,int *entity,int *newLength),
00261     (*fem_mesh,*entity,*newLength)
00262 )
00263 
00264 
00265 CLINKAGE int
00266 FEM_Mesh_get_length(int fem_mesh,int entity) {
00267     const char *caller="FEM_Mesh_get_length"; FEMAPI(caller);
00268     int len=FEM_Entity_lookup(fem_mesh,entity,caller)->size();
00269     return len;
00270 }
00271 FORTRAN_AS_C_RETURN(int,
00272     FEM_MESH_GET_LENGTH,FEM_Mesh_get_length,fem_mesh_get_length,
00273     (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00274 )
00275 
00276 
00277 CLINKAGE void
00278 FEM_Mesh_set_width(int fem_mesh,int entity,int attr,int newWidth) {
00279     const char *caller="FEM_Mesh_set_width";
00280     FEMAPI(caller);
00281     checkIsSet(fem_mesh,true,caller);
00282     FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->setWidth(newWidth,caller);
00283 }
00284 FORTRAN_AS_C(FEM_MESH_SET_WIDTH,FEM_Mesh_set_width,fem_mesh_set_width,
00285     (int *fem_mesh,int *entity,int *attr,int *newWidth),
00286     (*fem_mesh,*entity,*attr,*newWidth)
00287 )
00288 
00289 CLINKAGE int
00290 FEM_Mesh_get_width(int fem_mesh,int entity,int attr) {
00291     const char *caller="FEM_Mesh_get_width";
00292     FEMAPI(caller);
00293     return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getWidth();
00294 }
00295 FORTRAN_AS_C_RETURN(int,
00296     FEM_MESH_GET_WIDTH,FEM_Mesh_get_width,fem_mesh_get_width,
00297     (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00298 )
00299 
00300 CLINKAGE int
00301 FEM_Mesh_get_datatype(int fem_mesh,int entity,int attr) {
00302     const char *caller="FEM_Mesh_get_datatype";
00303     FEMAPI(caller);
00304     return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getDatatype();
00305 }
00306 FORTRAN_AS_C_RETURN(int,
00307     FEM_MESH_GET_DATATYPE,FEM_Mesh_get_datatype,fem_mesh_get_datatype,
00308     (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00309 )
00310 
00311 CLINKAGE int
00312 FEM_Mesh_is_set(int fem_mesh) 
00313 {
00314     return (FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00315 }
00316 FORTRAN_AS_C_RETURN(int,
00317     FEM_MESH_IS_SET,FEM_Mesh_is_set,fem_mesh_is_set,
00318     (int *fem_mesh),(*fem_mesh)
00319 )
00320 
00321 CLINKAGE int
00322 FEM_Mesh_is_get(int fem_mesh) 
00323 {
00324     return (!FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00325 }
00326 FORTRAN_AS_C_RETURN(int,
00327     FEM_MESH_IS_GET,FEM_Mesh_is_get,fem_mesh_is_get,
00328     (int *fem_mesh),(*fem_mesh)
00329 )
00330 
00331 CLINKAGE void
00332 FEM_Mesh_become_get(int fem_mesh) 
00333 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeGetting(); }
00334 FORTRAN_AS_C(FEM_MESH_BECOME_GET,FEM_Mesh_become_get,fem_mesh_become_get, (int *m),(*m))
00335 
00336 CLINKAGE void
00337 FEM_Mesh_become_set(int fem_mesh)
00338 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeSetting(); }
00339 FORTRAN_AS_C(FEM_MESH_BECOME_SET,FEM_Mesh_become_set,fem_mesh_become_set, (int *m),(*m))
00340 
00341 
00342 CLINKAGE IDXL_t
00343 FEM_Comm_shared(int fem_mesh,int entity) {
00344     const char *caller="FEM_Comm_shared";
00345     FEMAPI(caller); 
00346     if (entity!=FEM_NODE) FEM_Abort(caller,"Only shared nodes supported");
00347     return FEM_Mesh_lookup(fem_mesh,caller)->node.
00348         sharedIDXL.getIndex(IDXL_Chunk::get(caller));
00349 }
00350 FORTRAN_AS_C_RETURN(int,
00351     FEM_COMM_SHARED,FEM_Comm_shared,fem_comm_shared,
00352     (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00353 )
00354 
00355 CLINKAGE IDXL_t
00356 FEM_Comm_ghost(int fem_mesh,int entity) {
00357     const char *caller="FEM_Comm_ghost";
00358     FEMAPI(caller);
00359     FEM_Entity *e=FEM_Entity_lookup(fem_mesh,entity,caller);
00360     if (e->isGhost()) FEM_Abort(caller,"Can only call FEM_Comm_ghost on real entity type");
00361     return e->ghostIDXL.getIndex(IDXL_Chunk::get(caller));
00362 }
00363 FORTRAN_AS_C_RETURN(int,
00364     FEM_COMM_GHOST,FEM_Comm_ghost,fem_comm_ghost,
00365     (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00366 )
00367 
00368 
00369 
00370 void FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,     
00371     void *data, int firstItem,int length, const IDXL_Layout &layout) 
00372 {
00373     if (femVersion == 0 && length==0) return;
00374     const char *caller="FEM_Mesh_data";
00375     FEMAPI(caller);
00376     FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00377     FEM_Attribute *a=m->lookup(entity,caller)->lookup(attr,caller);
00378     
00379     if (m->isSetting()) 
00380         a->set(data,firstItem,length,layout,caller);
00381     else 
00382         a->get(data,firstItem,length,layout,caller);
00383 }
00384 
00386 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,void *data,int firstItem,const IDXL_Layout &layout){
00387     const char *caller="FEM_Register_array";
00388     FEMAPI(caller);
00389     FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00390     FEM_Entity *e = m->lookup(entity,caller);
00391     int length = e->size();
00392     
00393     int max = e->getMax();
00394     FEM_Attribute *a = e->lookup(attr,caller);
00395     
00396     
00397     if(m->isSetting()){
00398     }else{
00399         a->get(data,firstItem,length,layout,caller);
00400     }
00401     
00402     a->register_data(data,length,max,layout,caller);
00403 }
00404 void FEM_Register_entity_impl(int fem_mesh,int entity,void *args,int len,int max,FEM_Mesh_alloc_fn fn){
00405     const char *caller = "FEM_Register_entity";
00406     FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00407 
00408 
00409 
00410 
00411     FEM_Entity *e = m->lookup(entity,caller);
00412     e->setMaxLength(len,max,args,fn);
00413 }
00414 
00415 FEM_Entity *FEM_Entity_lookup(int fem_mesh,int entity,const char *caller) {
00416     return FEM_Mesh_lookup(fem_mesh,caller)->lookup(entity,caller);
00417 }
00418 FEM_Attribute *FEM_Attribute_lookup(int fem_mesh,int entity,int attr,const char *caller) {
00419     return FEM_Entity_lookup(fem_mesh,entity,caller)->lookup(attr,caller);
00420 }
00421 
00422 CLINKAGE int FEM_Mesh_get_entities(int fem_mesh, int *entities) {
00423     const char *caller="FEM_Mesh_get_entities";
00424     FEMAPI(caller); 
00425     return FEM_Mesh_lookup(fem_mesh,caller)->getEntities(entities);
00426 }
00427 FORTRAN_AS_C_RETURN(int,
00428     FEM_MESH_GET_ENTITIES,FEM_Mesh_get_entities,fem_mesh_get_entities,
00429     (int *mesh,int *ent), (*mesh,ent)
00430 )
00431 
00432 CLINKAGE int FEM_Mesh_get_attributes(int fem_mesh,int entity,int *attributes) {
00433     const char *caller="FEM_Mesh_get_attributes";
00434     FEMAPI(caller);
00435     return FEM_Entity_lookup(fem_mesh,entity,caller)->getAttrs(attributes);
00436 }
00437 FORTRAN_AS_C_RETURN(int,
00438     FEM_MESH_GET_ATTRIBUTES,FEM_Mesh_get_attributes,fem_mesh_get_attributes,
00439     (int *mesh,int *ent,int *attrs), (*mesh,*ent,attrs)
00440 )
00441 
00442 
00443 
00444 CLINKAGE const char *FEM_Get_datatype_name(int datatype,char *storage) {
00445     switch(datatype) {
00446     case FEM_BYTE: return "FEM_BYTE";
00447     case FEM_INT: return "FEM_INT";
00448     case FEM_FLOAT: return "FEM_FLOAT";
00449     case FEM_DOUBLE: return "FEM_DOUBLE";
00450     case FEM_INDEX_0: return "FEM_INDEX_0";
00451     case FEM_INDEX_1: return "FEM_INDEX_1";
00452     };
00453     sprintf(storage,"unknown datatype code (%d)",datatype);
00454     return storage;
00455 }
00456 
00459 CLINKAGE const char *FEM_Get_attr_name(int attr,char *storage)
00460 {
00461     if (attr<FEM_ATTRIB_TAG_MAX) 
00462     { 
00463         sprintf(storage,"FEM_DATA+%d",attr-FEM_DATA);
00464         return storage;
00465     }
00466     switch(attr) {
00467     case FEM_CONN: return "FEM_CONN"; 
00468     case FEM_SPARSE_ELEM: return "FEM_SPARSE_ELEM";
00469     case FEM_COOR: return "FEM_COOR";
00470     case FEM_GLOBALNO: return "FEM_GLOBALNO";
00471     case FEM_PARTITION: return "FEM_PARTITION";
00472     case FEM_SYMMETRIES: return "FEM_SYMMETRIES";
00473     case FEM_NODE_PRIMARY: return "FEM_NODE_PRIMARY";
00474     case FEM_NODE_ELEM_ADJACENCY: return "FEM_NODE_ELEM_ADJACENCY";
00475     case FEM_NODE_NODE_ADJACENCY: return "FEM_NODE_NODE_ADJACENCY";
00476     case FEM_ELEM_ELEM_ADJACENCY: return "FEM_ELEM_ELEM_ADJACENCY";
00477     case FEM_ELEM_ELEM_ADJ_TYPES: return "FEM_ELEM_ELEM_ADJ_TYPES";
00478     case FEM_IS_VALID_ATTR: return "FEM_IS_VALID_ATTR";
00479     case FEM_MESH_SIZING: return "FEM_MESH_SIZING";
00480 
00481     default: break;
00482     };
00483     sprintf(storage,"unknown attribute code (%d)",attr);
00484     return storage;
00485 }
00486 
00487 
00488 
00489 void FEM_Attribute::bad(const char *field,bool forRead,int cur,int next,const char *caller) const
00490 {
00491     char nameStorage[256];
00492     const char *name=FEM_Get_attr_name(attr,nameStorage);
00493     char errBuf[1024];
00494     const char *cannotBe=NULL;
00495     if (forRead) {
00496         if (cur==-1) {
00497             sprintf(errBuf,"The %s %s %s was never set-- it cannot now be read",
00498                 e->getName(),name,field);
00499         }
00500         else 
00501             cannotBe="read as";
00502     }
00503     else  {
00504         cannotBe="set to";
00505     }
00506     if (cannotBe!=NULL) 
00507         sprintf(errBuf,"The %s %s %s was previously set to %d; it cannot now be %s %d",
00508             e->getName(),name,field,cur,cannotBe,next);
00509     
00510     FEM_Abort(caller,errBuf);
00511 }
00512 
00513 
00514 FEM_Attribute::FEM_Attribute(FEM_Entity *e_,int attr_)
00515         :e(e_),ghost(0),attr(attr_),width(0),datatype(-1), allocated(false)
00516 {
00517     tryAllocate();
00518     if (femVersion == 0) width=-1;
00519 }
00520 void FEM_Attribute::pup(PUP::er &p) {
00521     
00522     p|width;
00523     if (p.isUnpacking() && femVersion > 0 && width<0)  width=0;
00524     p|datatype;
00525     if (p.isUnpacking()) tryAllocate();
00526 }
00527 void FEM_Attribute::pupSingle(PUP::er &p, int pupindx) {
00528     
00529     p|width;
00530     if (p.isUnpacking() && femVersion > 0 && width<0)  width=0;
00531     p|datatype;
00532     if (p.isUnpacking()) tryAllocate();
00533 }
00534 FEM_Attribute::~FEM_Attribute() {}
00535 
00536 void FEM_Attribute::setLength(int next,const char *caller) {
00537     int cur=getLength();
00538     if (next==cur) return; 
00539     if (cur>0) bad("length",false,cur,next, caller);
00540     e->setLength(next);
00541     tryAllocate();
00542 }
00543     
00544 void FEM_Attribute::setWidth(int next,const char *caller) {
00545     int cur=getWidth();
00546     if (next==cur) return; 
00547     if (cur>0) bad("width",false,cur,next, caller);
00548     width=next;
00549     tryAllocate();
00550     if (ghost) ghost->setWidth(width,caller);
00551 }
00552 
00553 void FEM_Attribute::setDatatype(int next,const char *caller) {
00554     int cur=getDatatype();
00555     if (next==cur) return; 
00556     if (cur!=-1) bad("datatype",false,cur,next, caller);
00557     datatype=next;
00558     tryAllocate();
00559     if (ghost) ghost->setDatatype(datatype,caller);
00560 }
00561 
00562 void FEM_Attribute::copyShape(const FEM_Attribute &src) {
00563     setWidth(src.getWidth());
00564     if (src.getDatatype()!=-1)
00565       setDatatype(src.getDatatype()); 
00566 }
00567 void FEM_Attribute::set(const void *src, int firstItem,int length, 
00568         const IDXL_Layout &layout, const char *caller) 
00569 {
00570     if (firstItem!=0) { 
00571         if (length!=1) 
00572             CmiAbort("FEM_Mesh_data: unexpected firstItem");
00573     }
00574 
00575     if (femVersion == 0 && getRealLength() == -1) setLength(length);
00576     else if (getLength()==0) setLength(length);
00577     else if (length!=1 && length!=getLength()) 
00578         bad("length",false,getLength(),length, caller);
00579     
00580     int width=layout.width;
00581     if (femVersion==0 && getRealWidth()==-1) setWidth(width);
00582     else if (getWidth()==0) setWidth(width);
00583     else if (width!=getWidth()) 
00584         bad("width",false,getWidth(),width, caller);
00585     
00586     int datatype=layout.type;
00587     if (getDatatype()==-1) setDatatype(datatype);
00588     else if (datatype!=getDatatype()) 
00589         bad("datatype",false,getDatatype(),datatype, caller);
00590     
00591     
00592 
00593 }
00594 
00595 void FEM_Attribute::get(void *dest, int firstItem,int length, 
00596         const IDXL_Layout &layout, const char *caller)  const
00597 {
00598     if (length==0) return; 
00599     if (length!=1 && length!=getLength()) 
00600         bad("length",true,getLength(),length, caller);
00601     
00602     int width=layout.width;
00603     if (width!=getWidth()) 
00604         bad("width",true,getWidth(),width, caller);
00605     
00606     int datatype=layout.type;
00607     if (datatype!=getDatatype()) 
00608         bad("datatype",true,getDatatype(),datatype, caller);
00609     
00610     
00611 }
00612 
00613 
00614 
00615 void FEM_Attribute::register_data(void *user, int length,int max,
00616     const IDXL_Layout &layout, const char *caller){
00617     
00618         int width=layout.width;
00619         if (femVersion == 0 && getRealWidth()==-1) setWidth(width);
00620         else if (getWidth()==0){
00621             setWidth(width);
00622         }else{
00623             if (width!=getWidth()){
00624                 bad("width",false,getWidth(),width, caller);
00625             }
00626         }   
00627     
00628         int datatype=layout.type;
00629         if (getDatatype()==-1){
00630             setDatatype(datatype);
00631         }else{
00632             if (datatype!=getDatatype()){ 
00633                 bad("datatype",false,getDatatype(),datatype, caller);
00634             }
00635         }   
00636         
00637 }
00638 
00639 
00640 
00641 void FEM_Attribute::tryAllocate(void) {
00642     int lenNull, widthNull;
00643         if (femVersion == 0) {
00644       
00645       lenNull = (getRealLength()==-1);
00646       widthNull = (getRealWidth()==-1);
00647     }
00648     else {
00649       lenNull = (getLength()==0);
00650       widthNull = (getWidth()==0);
00651     }
00652     if ((!allocated) && !lenNull && !widthNull && getDatatype()!=-1) {
00653       allocated=true;
00654         allocate(getMax(),getWidth(),getDatatype());
00655     }
00656 }
00657 
00658 
00659 FEM_DataAttribute::FEM_DataAttribute(FEM_Entity *e,int myAttr)
00660     :FEM_Attribute(e,myAttr), 
00661      char_data(0),int_data(0),float_data(0),double_data(0)
00662 {
00663 }
00664 void FEM_DataAttribute::pup(PUP::er &p) {
00665     super::pup(p);
00666     switch(getDatatype()) {
00667     case -1:  break;
00668     case FEM_BYTE:   if (char_data) char_data->pup(p); break;
00669     case FEM_INT:    if (int_data) int_data->pup(p); break;
00670     case FEM_FLOAT:  if (float_data) float_data->pup(p); break;
00671     case FEM_DOUBLE: if (double_data) double_data->pup(p); break;
00672     default: CkAbort("Invalid datatype in FEM_DataAttribute::pup");
00673     }
00674 }
00675 void FEM_DataAttribute::pupSingle(PUP::er &p, int pupindx) {
00676     super::pupSingle(p,pupindx);
00677     switch(getDatatype()) {
00678     case -1:  break;
00679     case FEM_BYTE:   if (char_data) char_data->pupSingle(p,pupindx); break;
00680     case FEM_INT:    if (int_data) int_data->pupSingle(p,pupindx); break;
00681     case FEM_FLOAT:  if (float_data) float_data->pupSingle(p,pupindx); break;
00682     case FEM_DOUBLE: if (double_data) double_data->pupSingle(p,pupindx); break;
00683     default: CkAbort("Invalid datatype in FEM_DataAttribute::pupSingle");
00684     }
00685 }
00686 FEM_DataAttribute::~FEM_DataAttribute() {
00687     if (char_data) delete char_data;
00688     if (int_data) delete int_data;
00689     if (float_data) delete float_data;
00690     if (double_data) delete double_data;
00691     
00692 }
00693 
00695 template <class T>
00696 inline void setTableData(const void *user, int firstItem, int length, 
00697     IDXL_LAYOUT_PARAM, AllocTable2d<T> *table) 
00698 {
00699     for (int r=0;r<length;r++) {
00700         T *tableRow=table->getRow(firstItem+r);
00701         for (int c=0;c<width;c++)
00702             tableRow[c]=IDXL_LAYOUT_DEREF(T,user,r,c);
00703     }
00704 }
00705 
00707 template <class T>
00708 inline void getTableData(void *user, int firstItem, int length, 
00709     IDXL_LAYOUT_PARAM, const AllocTable2d<T> *table) 
00710 {
00711     for (int r=0;r<length;r++) {
00712         const T *tableRow=table->getRow(firstItem+r);
00713         for (int c=0;c<width;c++)
00714             IDXL_LAYOUT_DEREF(T,user,r,c)=tableRow[c];
00715     }
00716 
00717 }
00718 
00719 void FEM_DataAttribute::set(const void *u, int f,int l, 
00720         const IDXL_Layout &layout, const char *caller)
00721 {
00722     super::set(u,f,l,layout,caller);
00723     switch(getDatatype()) {
00724     case FEM_BYTE:  setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),char_data); break;
00725     case FEM_INT: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),int_data); break;
00726     case FEM_FLOAT: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),float_data); break;
00727     case FEM_DOUBLE: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),double_data); break;
00728     }
00729 }
00730     
00731 void FEM_DataAttribute::get(void *u, int f,int l,
00732         const IDXL_Layout &layout, const char *caller) const
00733 {
00734     super::get(u,f,l,layout,caller);
00735     switch(getDatatype()) {
00736     case FEM_BYTE:  getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),char_data); break;
00737     case FEM_INT: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),int_data); break;
00738     case FEM_FLOAT: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),float_data); break;
00739     case FEM_DOUBLE: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),double_data); break;
00740     }
00741 }
00742 
00743 void FEM_DataAttribute::register_data(void *u,int l,int max,
00744         const IDXL_Layout &layout, const char *caller)
00745 {
00746     super::register_data(u,l,max,layout,caller);
00747     switch(getDatatype()){
00748         case FEM_BYTE: char_data->register_data((unsigned char *)u,l,max); break;
00749         case FEM_INT:    int_data->register_data((int *)u,l,max); break;
00750         case FEM_FLOAT: float_data->register_data((float *)u,l,max);break;
00751         case FEM_DOUBLE: double_data->register_data((double *)u,l,max);break;
00752     }
00753 }
00754 
00755 template<class T>
00756 inline AllocTable2d<T> *allocTablePtr(AllocTable2d<T> *src,int len,int wid) {
00757     if (src==NULL) src=new AllocTable2d<T>;
00758     src->allocate(wid,len);
00759     return src;
00760 }
00761 void FEM_DataAttribute::allocate(int l,int w,int datatype)
00762 {
00763     switch(datatype) {
00764     case FEM_BYTE:  char_data=allocTablePtr(char_data,l,w); break;
00765     case FEM_INT: int_data=allocTablePtr(int_data,l,w); break;
00766     case FEM_FLOAT: float_data=allocTablePtr(float_data,l,w); break;
00767     case FEM_DOUBLE: double_data=allocTablePtr(double_data,l,w); break;
00768     default: CkAbort("Invalid datatype in FEM_DataAttribute::allocate");
00769     };
00770 }
00771 void FEM_DataAttribute::copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity)
00772 {
00773     const FEM_DataAttribute *dsrc=(const FEM_DataAttribute *)&src;
00774     switch(getDatatype()) {
00775     case FEM_BYTE:  char_data->setRow(dstEntity,dsrc->char_data->getRow(srcEntity)); break;
00776     case FEM_INT: 
00777             int_data->setRow(dstEntity,dsrc->int_data->getRow(srcEntity)); break;
00778     case FEM_FLOAT: float_data->setRow(dstEntity,dsrc->float_data->getRow(srcEntity)); break;
00779     case FEM_DOUBLE: double_data->setRow(dstEntity,dsrc->double_data->getRow(srcEntity)); break;
00780     }
00781 }
00782 
00783 template<class T>
00784 inline void interpolateAttrs(AllocTable2d<T> *data,int A,int B,int D,double frac,int width){
00785   T *rowA = data->getRow(A);
00786   T *rowB = data->getRow(B);
00787   T *rowD = data->getRow(D);
00788   for(int i=0;i<width;i++){
00789     double val = (double )rowA[i];
00790     val *= (frac);
00791     val += (1-frac) *((double )rowB[i]);
00792     rowD[i] = (T )val;
00793   }
00794 }
00795 
00796 template<class T>
00797 inline void interpolateAttrs(AllocTable2d<T> *data,int *iNodes,int rNode,int k,int width){
00798   T *row[8];
00799   for (int i=0; i<k; i++) {
00800     row[i] = data->getRow(iNodes[i]);
00801   }
00802   T *rowR = data->getRow(rNode);
00803   for(int i=0;i<width;i++){
00804     double val = 0.0;
00805     for (int j=0; j<k; j++) {
00806       val += (double)row[j][i];
00807     }
00808     val = val/k;
00809     rowR[i] = (T )val;
00810   }
00811 }
00812 
00813 template<class T>
00814 inline void minAttrs(AllocTable2d<T> *data,int A,int B,int D,double frac,int width){
00815   T *rowA = data->getRow(A);
00816   T *rowB = data->getRow(B);
00817   T *rowD = data->getRow(D);
00818   for(int i=0;i<width;i++){
00819     if(rowA[i] < rowB[i]){
00820       rowD[i] = rowA[i];
00821     }else{
00822       rowD[i] = rowB[i];
00823     }
00824   }
00825 }
00826 
00827 template<class T>
00828 inline void minAttrs(AllocTable2d<T> *data,int *iNodes,int rNode,int k,int width){
00829   T *row[8];
00830   for (int i=0; i<k; i++) {
00831     row[i] = data->getRow(iNodes[i]);
00832   }
00833   T *rowR = data->getRow(rNode);
00834   for(int i=0;i<width;i++){
00835     rowR[i] = row[0][i]; 
00836     for (int j=1; j<k; j++) {
00837       if (row[j][i] < rowR[i]) {
00838     rowR[i] = row[j][i];
00839       }
00840     }
00841   }
00842 }
00843 
00844 void FEM_DataAttribute::interpolate(int A,int B,int D,double frac){
00845   switch(getDatatype()){
00846   case FEM_BYTE:
00847     minAttrs(char_data,A,B,D,frac,getWidth());      
00848     break;
00849   case FEM_INT:
00850     minAttrs(int_data,A,B,D,frac,getWidth());       
00851     break;
00852   case FEM_FLOAT:
00853     interpolateAttrs(float_data,A,B,D,frac,getWidth());     
00854     break;
00855   case FEM_DOUBLE:
00856     interpolateAttrs(double_data,A,B,D,frac,getWidth());        
00857     break;
00858   }
00859 }
00860 
00861 void FEM_DataAttribute::interpolate(int *iNodes,int rNode,int k){
00862   switch(getDatatype()){
00863   case FEM_BYTE:
00864     minAttrs(char_data,iNodes,rNode,k,getWidth());      
00865     break;
00866   case FEM_INT:
00867     minAttrs(int_data,iNodes,rNode,k,getWidth());       
00868     break;
00869   case FEM_FLOAT:
00870     interpolateAttrs(float_data,iNodes,rNode,k,getWidth());     
00871     break;
00872   case FEM_DOUBLE:
00873     interpolateAttrs(double_data,iNodes,rNode,k,getWidth());        
00874     break;
00875   }
00876 }
00877 
00878 
00879 FEM_IndexAttribute::Checker::~Checker() {}
00880 
00881 FEM_IndexAttribute::FEM_IndexAttribute(FEM_Entity *e,int myAttr,FEM_IndexAttribute::Checker *checker_)
00882     :FEM_Attribute(e,myAttr), idx(0,0,-1), checker(checker_)
00883 {
00884     setDatatype(FEM_INT);
00885 }
00886 void FEM_IndexAttribute::pup(PUP::er &p) {
00887     super::pup(p);
00888     p|idx;
00889 }
00890 void FEM_IndexAttribute::pupSingle(PUP::er &p, int pupindx) {
00891     super::pupSingle(p,pupindx);
00892     idx.pupSingle(p,pupindx);
00893 }
00894 FEM_IndexAttribute::~FEM_IndexAttribute() {
00895     if (checker) delete checker;
00896 }
00897 
00898 void FEM_IndexAttribute::allocate(int length,int width,int datatype)
00899 {
00900     idx.allocate(width,length);
00901 }
00902 
00908 static int type2base(int base_type,const char *caller) {
00909     if (base_type==FEM_INDEX_0) return 0;
00910     if (base_type==FEM_INDEX_1) return 1;
00911     FEM_Abort(caller,"You must use the datatype FEM_INDEX_0 or FEM_INDEX_1 with FEM_CONN, not %d",
00912         base_type);
00913     return 0; 
00914 }
00915 
00917 void setIndexTableData(const void *user, int firstItem, int length, 
00918     IDXL_LAYOUT_PARAM, AllocTable2d<int> *table,int indexBase) 
00919 {
00920     for (int r=0;r<length;r++) {
00921         int *tableRow=table->getRow(firstItem+r);
00922         for (int c=0;c<width;c++)
00923             tableRow[c]=IDXL_LAYOUT_DEREF(int,user,r,c)-indexBase;
00924     }
00925 }
00926 
00928 void getIndexTableData(void *user, int firstItem, int length, 
00929     IDXL_LAYOUT_PARAM, const AllocTable2d<int> *table,int indexBase) 
00930 {
00931     for (int r=0;r<length;r++) {
00932         const int *tableRow=table->getRow(firstItem+r);
00933         for (int c=0;c<width;c++)
00934             IDXL_LAYOUT_DEREF(int,user,r,c)=tableRow[c]+indexBase;
00935     }
00936 }
00937 
00938 void FEM_IndexAttribute::set(const void *src, int firstItem,int length,
00939         const IDXL_Layout &layout,const char *caller)
00940 {
00941     IDXL_Layout lo=layout; lo.type=FEM_INT; 
00942     super::set(src,firstItem,length,lo,caller);
00943     
00944     int indexBase=type2base(layout.type,caller);
00945     setIndexTableData(src,firstItem,length,IDXL_LAYOUT_CALL(layout),&idx,indexBase);
00946     
00947     if (checker) 
00948         for (int r=0;r<length;r++)
00949             checker->check(firstItem+r,idx,caller);
00950 }
00951 
00952 void FEM_IndexAttribute::get(void *dest, int firstItem,int length, 
00953         const IDXL_Layout &layout,const char *caller) const
00954 {
00955     IDXL_Layout lo=layout; lo.type=FEM_INT; 
00956     super::get(dest,firstItem,length,lo,caller);
00957     
00958     int indexBase=type2base(layout.type,caller);
00959     getIndexTableData(dest,firstItem,length,IDXL_LAYOUT_CALL(layout),&idx,indexBase);
00960 }
00961 
00962 void FEM_IndexAttribute::register_data(void *user, int length,int max,
00963         const IDXL_Layout &layout, const char *caller){
00964     IDXL_Layout lo=layout; lo.type=FEM_INT; 
00965     super::register_data(user,length,max,lo,caller);
00966 
00967     idx.register_data((int *)user,length,max);
00968 }
00969 
00970 void FEM_IndexAttribute::copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity)
00971 {
00972     const FEM_IndexAttribute *csrc=(const FEM_IndexAttribute *)&src;
00973     idx.setRow(dstEntity,csrc->idx.getRow(srcEntity));
00974 }
00975 
00976 
00977 
00978 FEM_VarIndexAttribute::FEM_VarIndexAttribute(FEM_Entity *e,int myAttr)
00979     :FEM_Attribute(e,myAttr)
00980 {
00981   oldlength = 0;
00982     allocate(getMax(),getWidth(),getDatatype());
00983     setDatatype(FEM_INT);
00984 }
00985 
00986 void FEM_VarIndexAttribute::pup(PUP::er &p){
00987     super::pup(p);
00988     p | idx;
00989 }
00990 
00991 void FEM_VarIndexAttribute::pupSingle(PUP::er &p, int pupindx){
00992     super::pupSingle(p,pupindx);
00993     p|idx[pupindx];
00994 }
00995 
00996 void FEM_VarIndexAttribute::set(const void *src,int firstItem,int length,
00997         const IDXL_Layout &layout,const char *caller){
00998         printf("set not yet implemented for FEM_VarIndexAttribute \n");
00999 }
01000 
01001 void FEM_VarIndexAttribute::get(void *dest, int firstItem,int length,
01002         const IDXL_Layout &layout, const char *caller) const{
01003      printf("get not yet implemented for FEM_VarIndexAttribute \n");
01004             
01005 }
01006 
01007 void FEM_VarIndexAttribute::copyEntity(int dstEntity,const FEM_Attribute &_src,int srcEntity){
01008     FEM_VarIndexAttribute &src = (FEM_VarIndexAttribute &)_src;
01009     const CkVec<CkVec<ID> > &srcTable = src.get();
01010     idx.insert(dstEntity,srcTable[srcEntity]);
01011 }
01012 
01013 void FEM_VarIndexAttribute::print(){
01014     for(int i=0;i<idx.size();i++){
01015         printf("%d -> ",i);
01016         for(int j=0;j<idx[i].size();j++){
01017             printf("(%d %d) ",((idx[i])[j]).type,((idx[i])[j]).id);
01018         }
01019         printf("\n");
01020     }
01021 }
01022 
01023 int FEM_VarIndexAttribute::findInRow(int row,const ID &data){
01024     if(row >= idx.length()){
01025         return -1;
01026     }
01027     CkVec<ID> &rowVec = idx[row];
01028     for(int i=0;i<rowVec.length();i++){
01029         if(data == rowVec[i]){
01030             return i;
01031         }
01032     }
01033     return -1;
01034 }
01035 
01036 
01037 
01039 CLINKAGE const char *FEM_Get_entity_name(int entity,char *storage)
01040 {
01041     char *dest=storage;
01042     if (entity<FEM_ENTITY_FIRST || entity>=FEM_ENTITY_LAST) {
01043         sprintf(dest,"unknown entity code (%d)",entity);
01044     }
01045     else {
01046         if (entity>FEM_ENTITY_FIRST+FEM_GHOST) {
01047             sprintf(dest,"FEM_GHOST+");
01048             dest+=strlen(dest); 
01049             entity-=FEM_GHOST;
01050         }
01051         if (entity==FEM_NODE)
01052             sprintf(dest,"FEM_NODE");
01053         else if (entity>=FEM_SPARSE)
01054             sprintf(dest,"FEM_SPARSE+%d",entity-FEM_SPARSE);
01055         else 
01056             sprintf(dest,"FEM_ELEM+%d",entity-FEM_ELEM);
01057     }
01058     return storage;
01059 }
01060 
01061 FEM_Entity::FEM_Entity(FEM_Entity *ghost_) 
01062   :length(0), max(0),ghost(ghost_), coord(0), sym(0), globalno(0), valid(0), meshSizing(0),
01063      ghostIDXL(ghost?&ghostSend:NULL, ghost?&ghost->ghostRecv:NULL),resize(NULL)
01064 {
01065     
01066     if (femVersion == 0) {
01067         length=-1;
01068         max=-1;
01069     }
01070 } 
01071 void FEM_Entity::pup(PUP::er &p) {
01072     p|length;
01073     if (p.isUnpacking() && femVersion > 0 && length<0)  length=0;
01074     p.comment(" Ghosts to send out: ");
01075     ghostSend.pup(p);
01076     p.comment(" Ghosts to recv: ");
01077     ghostRecv.pup(p);
01078     p.comment(" Ghost IDXL tag: ");
01079     ghostIDXL.pup(p);
01080     
01081     int nAttributes=attributes.size();
01082     p|nAttributes;
01083     for (int a=0;a<nAttributes;a++) 
01084     {
01085     
01086 
01087 
01088 
01089 
01090 
01091 
01092         int attr=0; 
01093         FEM_Attribute *r=NULL;
01094         if (!p.isUnpacking()) { 
01095             r=attributes[a];
01096             attr=r->getAttr();
01097         }
01098         p|attr;
01099         if (p.isUnpacking()) { 
01100             r=lookup(attr,"FEM_Entity::pup");
01101         }
01102         
01103         { 
01104             char attrNameStorage[256];
01105             p.comment(FEM_Get_attr_name(attr,attrNameStorage));
01106         }
01107         
01108         r->pup(p);
01109     }
01110     
01111     if (ghost!=NULL) {
01112         p.comment(" ---- Ghost attributes ---- ");
01113         ghost->pup(p);
01114     }
01115 }
01116 FEM_Entity::~FEM_Entity() 
01117 {
01118     delete ghost;
01119     for (int a=0;a<attributes.size();a++)
01120         delete attributes[a];
01121 }
01122 
01124 void FEM_Entity::copyShape(const FEM_Entity &src) {
01125     for (int a=0;a<src.attributes.size();a++) 
01126     { 
01127         const FEM_Attribute *Asrc=src.attributes[a];
01128         FEM_Attribute *Adst=lookup(Asrc->getAttr(),"FEM_Entity::copyShape");
01129         Adst->copyShape(*Asrc);
01130     }
01131     if (ghost) ghost->copyShape(*src.ghost);
01132 }
01133 
01134 void FEM_Entity::setLength(int newlen) 
01135 {
01136   if (!resize) {
01137     if (size() != newlen) {
01138       length = newlen;
01139       
01140       for (int a=0; a<attributes.size(); a++) {
01141     CkAssert(attributes[a]->getWidth() < 1000);
01142     attributes[a]->reallocate();
01143       }
01144     }
01145   }
01146   else {
01147     length = newlen;
01148     if (length > max) {
01149       if (max > 4) {
01150     max = max + (max >> 2);
01151       }
01152       else {
01153     max = max + 10;
01154       }
01155       for (int a=0;a<attributes.size();a++){
01156     int code = attributes[a]->getAttr();
01157     if(!(code <= FEM_ATTRIB_TAG_MAX || code == FEM_CONN || code == FEM_BOUNDARY)){
01158       attributes[a]->reallocate();
01159     }
01160       } 
01161       
01162       CkPrintf("Resize called \n");
01163       resize(args,&length,&max);
01164     }
01165   }
01166 }
01167 
01168 void FEM_Entity::allocateValid(void) {
01169   if (!valid){
01170     valid=new FEM_DataAttribute(this,FEM_IS_VALID_ATTR);
01171     add(valid);
01172     valid->setWidth(1); 
01173     valid->setLength(size());
01174     valid->setDatatype(FEM_BYTE);
01175     valid->reallocate();
01176     
01177     
01178     for(int i=0;i<size();i++)
01179       valid->getChar()(i,0)=1;
01180   first_invalid = last_invalid = 0;
01181   }
01182 
01183 }
01184 
01185 void FEM_Entity::set_valid(unsigned int idx, bool isNode){
01186   if(false) {
01187     CkAssert(idx < size() && idx >=0);
01188     valid->getChar()(idx,0)=1;
01189   }
01190   else {
01191     CkAssert(idx < size() && idx >=0 && first_invalid<=last_invalid);
01192     valid->getChar()(idx,0)=1;
01193     
01194     if(idx == first_invalid)
01195       
01196       while((first_invalid<last_invalid) && is_valid(first_invalid)){
01197     first_invalid++;
01198       }
01199     else if(idx == last_invalid)
01200       
01201       while((first_invalid<last_invalid) && is_valid(last_invalid))
01202     last_invalid--;
01203     
01204     
01205     if( first_invalid == last_invalid && is_valid(first_invalid) )
01206       first_invalid = last_invalid = 0;
01207   }
01208 }
01209 
01210 void FEM_Entity::set_invalid(unsigned int idx, bool isNode){
01211   if(false) {
01212     CkAssert(idx < size() && idx >=0);
01213     valid->getChar()(idx,0)=0;
01214   }
01215   else {
01216     CkAssert(idx < size() && idx >=0 && first_invalid<=last_invalid);
01217     valid->getChar()(idx,0)=0;
01218     
01219     
01220     if(first_invalid==0 && last_invalid==0 && is_valid(0)){
01221       first_invalid = last_invalid = idx;
01222       return;
01223     }
01224     
01225     if(idx < first_invalid){
01226       first_invalid = idx;
01227     }
01228     
01229     if(idx > last_invalid){
01230       last_invalid = idx;
01231     }
01232     
01233     
01234     
01235     
01236     
01237     
01238     
01239     
01240     
01241     
01242   }
01243 }
01244 
01245 int FEM_Entity::is_valid(unsigned int idx){
01246   if(false) {
01247     CkAssert(idx < size() && idx >=0);
01248     return valid->getChar()(idx,0);
01249   } else {
01250     CkAssert(idx < size() && idx >=0 && first_invalid<=last_invalid);
01251     return valid->getChar()(idx,0);
01252   }
01253 }
01254 
01255 unsigned int FEM_Entity::count_valid(){
01256   CkAssert(first_invalid<=last_invalid);
01257   unsigned int count=0;
01258   for(int i=0;i<size();i++)
01259     if(is_valid(i)) count++;
01260   return count;
01261 }
01262 
01267 unsigned int FEM_Entity::get_next_invalid(FEM_Mesh *m, bool isNode, bool isGhost){
01268   unsigned int retval;
01269   if(false) {
01270     retval = size();
01271     setLength(retval+1);  
01272   }
01273   else {
01274     CkAssert(!is_valid(first_invalid) || first_invalid==0);
01275     
01276     
01277     bool flag1 = false;
01278     if(!is_valid(first_invalid)){
01279       retval = first_invalid;
01280       if(isNode && !isGhost) { 
01281     while(retval <= last_invalid) {
01282       if(!is_valid(retval)) {
01283         if(m->getfmMM()->fmLockN[retval]->haslocks()) {
01284           retval++;
01285         }
01286         else if(hasConn(retval)) { 
01287           retval++;
01288         }
01289         else {
01290           flag1 = true;
01291           break;
01292         }
01293       }
01294       else retval++;
01295     }
01296       }
01297       else if(isNode) {
01298     while(retval <= last_invalid) {
01299       if(!is_valid(retval)) {
01300         if(hasConn(retval)) { 
01301           retval++;
01302         }
01303         else {
01304           flag1 = true;
01305           break;
01306         }
01307       }
01308       else retval++;
01309     }
01310       }      
01311       else{
01312     
01313     flag1 = true;
01314       }
01315     }
01316     if(!flag1) {
01317       retval = size();
01318       setLength(retval+1);
01319     }
01320   }
01321   set_valid(retval,isNode);
01322   return retval;
01323 }
01324 
01325 void FEM_Entity::setMaxLength(int newLen,int newMaxLen,void *pargs,FEM_Mesh_alloc_fn fn){
01326         CkPrintf("resize fn %p \n",fn);
01327     max = newMaxLen;
01328     resize = fn;
01329     args = pargs;
01330     setLength(newLen);
01331 }
01332 
01333 
01335 void FEM_Entity::copyEntity(int dstEntity,const FEM_Entity &src,int srcEntity) {
01336     FEM_Entity *dp=this; 
01337     const FEM_Entity *sp=&src;
01338     for (int a=0;a<sp->attributes.size();a++) 
01339     { 
01340         const FEM_Attribute *Asrc=sp->attributes[a];
01341         FEM_Attribute *Adst=dp->lookup(Asrc->getAttr(),"FEM_Entity::copyEntity");
01342         Adst->copyEntity(dstEntity,*Asrc,srcEntity);
01343     }
01344 }
01345 
01348 int FEM_Entity::push_back(const FEM_Entity &src,int srcEntity) {
01349     int dstEntity=size();
01350     setLength(dstEntity+1);
01351     copyEntity(dstEntity,src,srcEntity);
01352     return dstEntity;
01353 }
01354 
01357 void FEM_Entity::add(FEM_Attribute *attribute) {
01358     if (ghost!=NULL) 
01359     { 
01360         attribute->setGhost(ghost->lookup(attribute->getAttr(),"FEM_Entity::add"));
01361     }
01362     attributes.push_back(attribute);
01363 }
01364 
01370 FEM_Attribute *FEM_Entity::lookup(int attr,const char *caller) {
01371     
01372     for (int a=0;a<attributes.size();a++) {
01373         if (attributes[a]->getAttr()==attr)
01374             return attributes[a];
01375     }
01376     
01377     
01378     create(attr,caller);
01379     
01380     
01381     return lookup(attr,caller);
01382 }
01383 
01390 void FEM_Entity::create(int attr,const char *caller) {
01391   if (attr<=FEM_ATTRIB_TAG_MAX) 
01392     add(new FEM_DataAttribute(this,attr));
01393   else if (attr==FEM_COORD) 
01394     allocateCoord();
01395   else if (attr==FEM_SYMMETRIES) 
01396     allocateSym();
01397   else if (attr==FEM_GLOBALNO) 
01398     allocateGlobalno();
01399   else if (attr==FEM_IS_VALID_ATTR)
01400     allocateValid();
01401   else if (attr==FEM_MESH_SIZING) 
01402     allocateMeshSizing();
01403   else if(attr == FEM_CHUNK){
01404     FEM_IndexAttribute *chunkNo= new FEM_IndexAttribute(this,FEM_CHUNK,NULL);
01405     add(chunkNo);
01406     chunkNo->setWidth(1);
01407   } else if(attr == FEM_BOUNDARY){
01408     
01409     allocateBoundary();
01410   } else {
01411     
01412     char attrNameStorage[256], msg[1024];
01413     sprintf(msg,"Could not locate the attribute %s for entity %s",
01414             FEM_Get_attr_name(attr,attrNameStorage), getName());
01415     FEM_Abort(caller,msg);
01416   }
01417 }
01418 
01419 void FEM_Entity::allocateCoord(void) {
01420     if (coord) CkAbort("FEM_Entity::allocateCoord called, but already allocated");
01421     coord=new FEM_DataAttribute(this,FEM_COORD);
01422     add(coord); 
01423     coord->setDatatype(FEM_DOUBLE);
01424 }
01425 
01426 void FEM_Entity::allocateSym(void) {
01427     if (sym) CkAbort("FEM_Entity::allocateSym called, but already allocated");
01428     sym=new FEM_DataAttribute(this,FEM_SYMMETRIES);
01429     add(sym); 
01430     sym->setWidth(1);
01431     sym->setDatatype(FEM_BYTE); 
01432 }
01433 
01434 void FEM_Entity::setSymmetries(int r,FEM_Symmetries_t s)
01435 {
01436     if (!sym) {
01437         if (s==0) return; 
01438         allocateSym();
01439     }
01440     sym->getChar()(r,0)=s;
01441 }
01442 
01443 
01444 
01445 
01446 
01447 
01448 
01449 
01450 
01451 
01452 
01453 inline void FEM_Entity::set_coord(int idx, double x, double y){
01454   if(coord){
01455     coord->getDouble()(idx,0)=x;
01456     coord->getDouble()(idx,1)=y;
01457   }
01458   else {
01459     FEM_DataAttribute* attr =   (FEM_DataAttribute*)lookup(FEM_DATA,"set_coord");
01460     attr->getDouble()(idx,0)=x;
01461     attr->getDouble()(idx,1)=y;
01462   }
01463 }
01464 
01465 inline void FEM_Entity::set_coord(int idx, double x, double y, double z){
01466   if(coord){
01467     coord->getDouble()(idx,0)=x;
01468     coord->getDouble()(idx,1)=y;
01469     coord->getDouble()(idx,2)=z;
01470   }
01471   else {
01472     FEM_DataAttribute* attr =   (FEM_DataAttribute*)lookup(FEM_DATA,"set_coord");
01473     attr->getDouble()(idx,0)=x;
01474     attr->getDouble()(idx,1)=y;
01475     attr->getDouble()(idx,2)=z;
01476   }
01477 }
01478 
01479 
01480 void FEM_Entity::allocateGlobalno(void) {
01481     if (globalno) CkAbort("FEM_Entity::allocateGlobalno called, but already allocated");
01482     globalno=new FEM_IndexAttribute(this,FEM_GLOBALNO,NULL);
01483     add(globalno); 
01484     globalno->setWidth(1);
01485 }
01486 
01487 void FEM_Entity::allocateMeshSizing(void) {
01488   if (meshSizing) 
01489     CkAbort("FEM_Entity::allocateMeshSizing called, but already allocated");
01490   meshSizing=new FEM_DataAttribute(this,FEM_MESH_SIZING);
01491   add(meshSizing); 
01492   meshSizing->setWidth(1);
01493   meshSizing->setDatatype(FEM_DOUBLE);
01494 }
01495 
01496 double FEM_Entity::getMeshSizing(int r) {
01497   if (!meshSizing) {
01498     allocateMeshSizing();
01499     return -1.0;
01500   }
01501   if (r >= 0)  return meshSizing->getDouble()(r,0);
01502   else  return ghost->meshSizing->getDouble()(FEM_To_ghost_index(r),0);
01503 }
01504 
01505 void FEM_Entity::setMeshSizing(int r,double s)
01506 {
01507   if (!meshSizing) allocateMeshSizing();
01508   if (s <= 0.0) return;
01509   if (r >= 0)  meshSizing->getDouble()(r,0)=s;
01510   else ghost->meshSizing->getDouble()(FEM_To_ghost_index(r),0)=s;
01511 }
01512 
01513 void FEM_Entity::setMeshSizing(double *sf)
01514 {
01515   if (!meshSizing) allocateMeshSizing();
01516   int len = size();
01517   for (int i=0; i<len; i++)
01518     meshSizing->getDouble()(i,0)=sf[i];
01519 }
01520 
01521 void FEM_Entity::allocateBoundary(){
01522     FEM_DataAttribute *bound = new FEM_DataAttribute(this,FEM_BOUNDARY);
01523     add(bound);
01524     bound->setWidth(1);
01525     bound->setDatatype(FEM_INT);
01526 }
01527 
01528 void FEM_Entity::setGlobalno(int r,int g) {
01529     if (!globalno) allocateGlobalno();
01530     globalno->get()(r,0)=g;
01531 }
01532 void FEM_Entity::setAscendingGlobalno(void) {
01533     if (!globalno) {
01534         allocateGlobalno();
01535         int len=size();
01536         for (int i=0;i<len;i++) globalno->get()(i,0)=i;
01537     }
01538 }
01539 void FEM_Entity::setAscendingGlobalno(int base) {
01540     if (!globalno) {
01541         allocateGlobalno();
01542         int len=size();
01543         for (int i=0;i<len;i++) globalno->get()(i,0)=i+base;
01544     }
01545 }
01546 void FEM_Entity::copyOldGlobalno(const FEM_Entity &e) {
01547     if ((!hasGlobalno()) && e.hasGlobalno() && size()>=e.size()) {
01548         for (int i=0;i<size();i++) 
01549             setGlobalno(i,e.getGlobalno(i));
01550     }
01551 }
01552 
01553 
01554 FEM_Node::FEM_Node(FEM_Node *ghost_) 
01555   :FEM_Entity(ghost_), primary(0), sharedIDXL(&shared,&shared),
01556    elemAdjacency(0),nodeAdjacency(0)
01557 {}
01558 
01559 void FEM_Node::allocatePrimary(void) {
01560   if (primary) CkAbort("FEM_Node::allocatePrimary called, but already allocated");
01561   primary=new FEM_DataAttribute(this,FEM_NODE_PRIMARY);
01562   add(primary); 
01563   primary->setWidth(1); 
01564   primary->setDatatype(FEM_BYTE);
01565 }
01566 
01567 bool FEM_Node::hasConn(unsigned int idx) {
01568   if((elemAdjacency->get()[idx].length() > 0)||(nodeAdjacency->get()[idx].length() > 0))
01569     return true;
01570   else return false;
01571 }
01572 
01573 void FEM_Node::pup(PUP::er &p) {
01574     p.comment(" ---------------- Nodes ------------------ ");   
01575     super::pup(p);
01576     p.comment(" ---- Shared nodes ----- "); 
01577     shared.pup(p);
01578     p.comment(" shared nodes IDXL ");
01579     sharedIDXL.pup(p);
01580 }
01581 FEM_Node::~FEM_Node() {
01582 }
01583 
01584 
01585 const char *FEM_Node::getName(void) const {return "FEM_NODE";}
01586 
01587 void FEM_Node::create(int attr,const char *caller) {
01588   if (attr==FEM_NODE_PRIMARY)
01589     allocatePrimary();
01590   else if(attr == FEM_NODE_ELEM_ADJACENCY)
01591     allocateElemAdjacency();
01592   else if(attr == FEM_NODE_NODE_ADJACENCY)
01593     allocateNodeAdjacency();
01594   else
01595     super::create(attr,caller);
01596 }
01597 
01598 
01599 
01601 class FEM_Elem_Conn_Checker : public FEM_IndexAttribute::Checker {
01602     const FEM_Entity &sizeSrc;
01603     const FEM_Entity *sizeSrc2;
01604 public:
01605     FEM_Elem_Conn_Checker(const FEM_Entity &sizeSrc_,const FEM_Entity *sizeSrc2_) 
01606         :sizeSrc(sizeSrc_), sizeSrc2(sizeSrc2_) {}
01607     
01608     void check(int row,const BasicTable2d<int> &table,const char *caller) const {
01609         const int *idx=table.getRow(row);
01610         int n=table.width();
01611         int max=sizeSrc.size();
01612         if (sizeSrc2) max+=sizeSrc2->size();
01613         for (int i=0;i<n;i++) 
01614             if ((idx[i]<0) || (idx[i]>=max))
01615             { 
01616                 if (idx[i]<0)
01617                     FEM_Abort(caller,"Connectivity entry %d's value, %d, is negative",row,idx[i]);
01618                 else 
01619                     FEM_Abort(caller,
01620                         "Connectivity entry %d's value, %d, should be less than the number of nodes, %d",
01621                         row,idx[i],max);
01622             }
01623     }
01624 };
01625 
01626 FEM_Elem::FEM_Elem(const FEM_Mesh &mesh, FEM_Elem *ghost_) 
01627   :FEM_Entity(ghost_), elemAdjacency(0), elemAdjacencyTypes(0)
01628 {
01629     FEM_IndexAttribute::Checker *c;
01630     if (isGhost()) 
01631         c=new FEM_Elem_Conn_Checker(mesh.node, mesh.node.getGhost());
01632     else  
01633         c=new FEM_Elem_Conn_Checker(mesh.node, NULL);
01634     conn=new FEM_IndexAttribute(this,FEM_CONN,c);
01635     add(conn); 
01636 }
01637 void FEM_Elem::pup(PUP::er &p) {
01638     p.comment(" ------------- Element data ---------- ");
01639     FEM_Entity::pup(p);
01640 }
01641 FEM_Elem::~FEM_Elem() {
01642 }
01643 
01644 
01645 void FEM_Elem::create(int attr,const char *caller) {
01646   
01647   
01648   
01649   
01650   
01651   
01652   
01653   if(attr == FEM_ELEM_ELEM_ADJACENCY)
01654     allocateElemAdjacency();
01655   else if(attr == FEM_ELEM_ELEM_ADJ_TYPES)
01656     allocateElemAdjacency();
01657   else
01658     super::create(attr,caller);
01659 }
01660 
01661 
01662 const char *FEM_Elem::getName(void) const {
01663     return "FEM_ELEM";
01664 }
01665 
01666 bool FEM_Elem::hasConn(unsigned int idx) {
01667   return false;
01668 }
01669 
01670 
01675 class FEM_Sparse_Elem_Checker : public FEM_IndexAttribute::Checker {
01676     const FEM_Mesh &mesh;
01677 public:
01678     FEM_Sparse_Elem_Checker(const FEM_Mesh &mesh_) :mesh(mesh_) {}
01679     
01680     void check(int row,const BasicTable2d<int> &table,const char *caller) const {
01681         
01682         const int *elem=table.getRow(row);
01683         int maxT=mesh.elem.size();
01684         if ((elem[0]<0) || (elem[1]<0))
01685             FEM_Abort(caller,"Sparse element entry %d's values, %d and %d, are negative",
01686                 row,elem[0],elem[1]);
01687         int t=elem[0];
01688         if (t>=maxT)
01689             FEM_Abort(caller,"Sparse element entry %d's element type, %d, is too big",
01690                 row,elem[0]);
01691         if (elem[1]>=mesh.elem[t].size())
01692             FEM_Abort(caller,"Sparse element entry %d's element index, %d, is too big",
01693                 row,elem[1]);
01694     }
01695 };
01696 
01697 FEM_Sparse::FEM_Sparse(const FEM_Mesh &mesh_,FEM_Sparse *ghost_) 
01698     :FEM_Elem(mesh_,ghost_), elem(0), mesh(mesh_)
01699 {
01700 }
01701 void FEM_Sparse::allocateElem(void) {
01702     if (elem) CkAbort("FEM_Sparse::allocateElem called, but already allocated");
01703     FEM_IndexAttribute::Checker *checker=new FEM_Sparse_Elem_Checker(mesh);
01704     elem=new FEM_IndexAttribute(this,FEM_SPARSE_ELEM,checker);
01705     add(elem); 
01706     elem->setWidth(2); 
01707 }
01708 void FEM_Sparse::pup(PUP::er &p) {
01709     p.comment(" ------------- Sparse Element ---------- ");
01710     super::pup(p);
01711 }
01712 FEM_Sparse::~FEM_Sparse() {
01713 }
01714 
01715 const char *FEM_Sparse::getName(void) const { return "FEM_SPARSE"; }
01716 
01717 void FEM_Sparse::create(int attr,const char *caller) {
01718     if (attr==FEM_SPARSE_ELEM)
01719         allocateElem();
01720     else  FEM_Entity::create(attr,caller);
01721 }
01722 
01723 
01724 
01725 FEM_Mesh::FEM_Mesh() 
01726     :node(new FEM_Node(NULL)),
01727      elem(*this,"FEM_ELEM"),
01728      sparse(*this,"FEM_SPARSE"),
01729      lastElemAdjLayer(NULL)
01730 {
01731     m_isSetting=true; 
01732     lastElemAdjLayer=NULL; 
01733 }
01734 FEM_Mesh::~FEM_Mesh() {
01735 }
01736 
01737 FEM_Entity *FEM_Mesh::lookup(int entity,const char *caller) {
01738     FEM_Entity *e=NULL;
01739     if (entity>=FEM_ENTITY_FIRST && entity<FEM_ENTITY_LAST) 
01740     { 
01741         bool isGhost=false;
01742         if (entity-FEM_ENTITY_FIRST>=FEM_GHOST) {
01743             entity-=FEM_GHOST;
01744             isGhost=true;
01745         }
01746         if (entity==FEM_NODE)
01747             e=&node;
01748         else if (entity>=FEM_ELEM && entity<FEM_ELEM+100) 
01749         { 
01750             int elType=entity-FEM_ELEM;
01751             e=&elem.set(elType);
01752         }
01753         else if (entity>=FEM_SPARSE && entity<FEM_SPARSE+100) 
01754         { 
01755             int sID=entity-FEM_SPARSE;
01756             e=&sparse.set(sID);
01757         }
01758         
01759         if (isGhost) 
01760             e=e->getGhost();
01761     }
01762     
01763     if (e==NULL) 
01764         FEM_Abort(caller,"Expected an entity type (FEM_NODE, FEM_ELEM, etc.) but got %d",entity);
01765     return e;
01766 }
01767 const FEM_Entity *FEM_Mesh::lookup(int entity,const char *caller) const {
01770     return ((FEM_Mesh *)this)->lookup(entity,caller);
01771 }
01772 
01773 void FEM_Mesh::setFemMeshModify(femMeshModify *m){
01774   fmMM = m;
01775 }
01776 
01777 
01778 femMeshModify *FEM_Mesh::getfmMM(){
01779   return fmMM;
01780 }
01781 
01782 void FEM_Mesh::pup(PUP::er &p)  
01783 {
01784     p.comment(" ------------- Node Data ---------- ");
01785     node.pup(p);
01786 
01787     p.comment(" ------------- Element Types ---------- ");
01788     elem.pup(p);
01789     
01790     p.comment("-------------- Sparse Types ------------");
01791     sparse.pup(p);
01792     
01793     p.comment("-------------- Symmetries ------------");
01794     symList.pup(p);
01795     
01796     p|m_isSetting;
01797 
01798     p.comment("-------------- Mesh data --------------");
01799     udata.pup(p);
01800 
01801 
01802 
01803 
01804 }
01805 
01806 int FEM_Mesh::chkET(int elType) const {
01807     if ((elType<0)||(elType>=elem.size())) {
01808         CkError("FEM Error! Bad element type %d!\n",elType);
01809         CkAbort("FEM Error! Bad element type used!\n");
01810     }
01811     return elType;
01812 }
01813 
01814 int FEM_Mesh::nElems(int t_max) const 
01815 {
01816 #if CMK_ERROR_CHECKING
01817     if (t_max<0 || t_max>elem.size()) {
01818         CkPrintf("FEM> Invalid element type %d used!\n");
01819         CkAbort("FEM> Invalid element type");
01820     }
01821 #endif
01822     int ret=0;
01823     for (int t=0;t<t_max;t++){ 
01824         if (elem.has(t)){
01825             ret+=elem.get(t).size();
01826         }
01827     }   
01828     return ret;
01829 }
01830 
01831 int FEM_Mesh::getGlobalElem(int elType,int elNo) const
01832 {
01833     int base=nElems(elType); 
01834 #if CMK_ERROR_CHECKING
01835     if (elNo<0 || elNo>=elem[elType].size()) {
01836         CkPrintf("FEM> Element number %d is invalid-- element type %d has only %d elements\n",
01837             elNo,elType,elem[elType].size());
01838         CkAbort("FEM> Invalid element number, probably passed via FEM_Set_Sparse_elem");
01839     }
01840 #endif
01841     return base+elNo;
01842 }
01843 
01845 void FEM_Mesh::setAscendingGlobalno(void) {
01846     node.setAscendingGlobalno();
01847     for (int e=0;e<elem.size();e++)
01848         if (elem.has(e)) elem[e].setAscendingGlobalno();
01849     for (int s=0;s<sparse.size();s++)
01850         if (sparse.has(s)) sparse[s].setAscendingGlobalno();
01851 }
01852 void FEM_Mesh::setAbsoluteGlobalno(){
01853     node.setAscendingGlobalno();
01854     for (int e=0;e<elem.size();e++){
01855         if (elem.has(e)) elem[e].setAscendingGlobalno(nElems(e));
01856     }   
01857 }
01858 
01859 void FEM_Mesh::copyOldGlobalno(const FEM_Mesh &m) {
01860     node.copyOldGlobalno(m.node);
01861     for (int e=0;e<m.elem.size();e++)
01862         if (m.elem.has(e) && e<elem.size() && elem.has(e)) 
01863             elem[e].copyOldGlobalno(m.elem[e]);
01864     for (int s=0;s<m.sparse.size();s++)
01865         if (m.sparse.has(s) && s<sparse.size() && sparse.has(s)) 
01866             sparse[s].copyOldGlobalno(m.sparse[s]);
01867 }
01868 
01869 void FEM_Index_Check(const char *caller,const char *entityType,int type,int maxType) {
01870     if (type<0 || type>maxType) {
01871         char msg[1024];
01872         sprintf(msg,"%s %d is not a valid entity type (it must be between %d and %d)",
01873             entityType,type, 0, maxType-1);
01874         FEM_Abort(caller,msg);
01875     }
01876 }
01877 void FEM_Is_NULL(const char *caller,const char *entityType,int type) {
01878     char msg[1024];
01879     sprintf(msg,"%s %d was never set--it cannot now be read",entityType,type);
01880     FEM_Abort(caller,msg);
01881 }
01882 
01883 void FEM_Mesh::copyShape(const FEM_Mesh &src)
01884 {
01885     node.copyShape(src.node);
01886     for (int t=0;t<src.elem.size();t++) 
01887         if (src.elem.has(t)) elem.set(t).copyShape(src.elem.get(t));
01888     
01889     for (int s=0;s<src.sparse.size();s++)
01890         if (src.sparse.has(s)) sparse.set(s).copyShape(src.sparse.get(s));
01891     
01892     setSymList(src.getSymList());
01893 }
01894 
01896 int FEM_Mesh::getEntities(int *entities) {
01897     int len=0;
01898     entities[len++]=FEM_NODE;
01899     for (int t=0;t<elem.size();t++) 
01900         if (elem.has(t)) entities[len++]=FEM_ELEM+t;
01901     for (int s=0;s<sparse.size();s++)
01902         if (sparse.has(s)) entities[len++]=FEM_SPARSE+s;
01903     return len;
01904 }
01905 
01906 
01907 FILE *FEM_openMeshFile(const char *prefix,int chunkNo,int nchunks,bool forRead)
01908 {
01909     char fname[256];
01910     static const char *meshFileNames="%s_vp%d_%d.dat";
01911     sprintf(fname, meshFileNames, prefix, nchunks, chunkNo);
01912     FILE *fp = fopen(fname, forRead?"r":"w");
01913     CkPrintf("FEM> %s %s...\n",forRead?"Reading":"Writing",fname);  
01914     if(fp==0) {
01915       FEM_Abort(forRead?"FEM: unable to open input file"
01916         :"FEM: unable to create output file.\n");
01917     }
01918     return fp;
01919 }
01920 
01921 static inline void read_version()
01922 {
01923     FILE *f = fopen("FEMVERSION", "r");
01924     if (f!=NULL)  {
01925     fscanf(f, "%d", &femVersion);
01926     if (CkMyPe()==0) CkPrintf("FEM> femVersion detected: %d\n", femVersion);
01927     fclose(f);
01928     }
01929 }
01930 
01931 static inline void write_version()
01932 {
01933     FILE *f = fopen("FEMVERSION", "w");
01934     if (f!=NULL)  {
01935         fprintf(f, "%d", femVersion);
01936         fclose(f);
01937     }
01938 }
01939 
01940 FEM_Mesh *FEM_readMesh(const char *prefix,int chunkNo,int nChunks)
01941 {
01942     
01943     static int version_checked = 0;
01944     if (!version_checked) {
01945         version_checked=1;
01946         read_version();
01947     }
01948 
01949     FEM_Mesh *ret=new FEM_Mesh;
01950     ret->becomeGetting();
01951         FILE *fp = FEM_openMeshFile(prefix,chunkNo,nChunks,true);
01952     PUP::fromTextFile p(fp);
01953     ret->pup(p);
01954     fclose(fp);
01955 
01956 #ifdef PRINT_SHARED_NODE_INFO
01957         FEM_Comm &shared = ret->node.shared;
01958         int numNeighborVPs = shared.size();
01959         CkPrintf("COMM DATA %d %d ", chunkNo, numNeighborVPs);
01960         
01961         for(int i=0;i<numNeighborVPs;i++) {
01962       IDXL_List list = shared.getLocalList(i);
01963           CkPrintf("%d %d ", list.getDest(), list.size()); 
01964         }
01965     CkPrintf("\n");
01966 #endif
01967 
01968     return ret;
01969 }
01970 
01971 void FEM_writeMesh(FEM_Mesh *m,const char *prefix,int chunkNo,int nChunks)
01972 {
01973     if (chunkNo == 0) {
01974        write_version();
01975     }
01976         FILE *fp = FEM_openMeshFile(prefix,chunkNo,nChunks,false);
01977     PUP::toTextFile p(fp);
01978     m->pup(p);
01979     fclose(fp);
01980 }
01981 
01982 
01983 
01984 CLINKAGE void FEM_Mesh_allocate_valid_attr(int fem_mesh, int entity_type){
01985   FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_create_valid_elem");
01986   FEM_Entity *entity = m->lookup(entity_type,"FEM_Mesh_allocate_valid_attr");
01987   entity->allocateValid();
01988 }
01989 FORTRAN_AS_C(FEM_MESH_ALLOCATE_VALID_ATTR,
01990              FEM_Mesh_allocate_valid_attr,
01991              fem_mesh_allocate_valid_attr, 
01992              (int *fem_mesh, int *entity_type),  (*fem_mesh, *entity_type) )
01993 
01994 
01995 
01996 CLINKAGE void FEM_set_entity_valid(int mesh, int entityType, int entityIdx){
01997   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_");
01998   FEM_Entity *entity = m->lookup(entityType,"FEM_");
01999   entity->set_valid(entityIdx,true);
02000 }
02001 FORTRAN_AS_C(FEM_SET_ENTITY_VALID, 
02002              FEM_set_entity_valid, 
02003              fem_set_entity_valid,  
02004              (int *fem_mesh, int *entity_type, int *entityIdx),  (*fem_mesh, *entity_type, *entityIdx) ) 
02005 
02006 
02007 
02008 CLINKAGE void FEM_set_entity_invalid(int mesh, int entityType, int entityIdx){
02009   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02010   FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02011   return entity->set_invalid(entityIdx,true);
02012 }
02013 FORTRAN_AS_C(FEM_SET_ENTITY_INVALID,  
02014              FEM_set_entity_invalid,  
02015              fem_set_entity_invalid,   
02016              (int *fem_mesh, int *entity_type, int *entityIdx),  (*fem_mesh, *entity_type, *entityIdx) )  
02017 
02018 
02019 
02020 CLINKAGE int FEM_is_valid(int mesh, int entityType, int entityIdx){
02021   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02022   FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02023   return (entity->is_valid(entityIdx) != 0);
02024 }
02025 FORTRAN_AS_C(FEM_IS_VALID,   
02026              FEM_is_valid,   
02027              fem_is_valid,    
02028              (int *fem_mesh, int *entity_type, int *entityIdx),  (*fem_mesh, *entity_type, *entityIdx) )   
02029 
02030 
02031 
02032 CLINKAGE unsigned int FEM_count_valid(int mesh, int entityType){
02033   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02034   FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02035   return entity->count_valid();
02036 }
02037 FORTRAN_AS_C(FEM_COUNT_VALID,    
02038              FEM_count_valid,    
02039              fem_count_valid,     
02040              (int *fem_mesh, int *entity_type),  (*fem_mesh, *entity_type) )    
02041  
02042 
02043 
02044 void FEM_set_entity_coord2(int mesh, int entityType, int idx, double x, double y){
02045   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02046   FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02047   entity->set_coord(idx,x,y);
02048 }
02049 void FEM_set_entity_coord3(int mesh, int entityType, int idx, double x, double y, double z){
02050   FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02051   FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02052   entity->set_coord(idx,x,y,z);
02053 }