00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "ParFUM_internals.h"
00010
00011 extern int femVersion;
00012
00013
00014 FEM_Comm_Holder::FEM_Comm_Holder(FEM_Comm *sendComm, FEM_Comm *recvComm)
00015 :comm(sendComm,recvComm)
00016 {
00017 registered=false;
00018 idx=-1;
00019 }
00020 void FEM_Comm_Holder::registerIdx(IDXL_Chunk *c) {
00021 assert(!registered);
00022 IDXL_Chunk *owner=c;
00023 if (idx!=-1)
00024 idx=owner->addStatic(&comm,idx);
00025 else
00026 idx=owner->addStatic(&comm);
00027 }
00028 void FEM_Comm_Holder::pup(PUP::er &p) {
00029 p|idx;
00030 if (p.isUnpacking() && idx!=-1)
00031 {
00032 registerIdx(IDXL_Chunk::get("FEM_Comm_Holder::pup"));
00033 }
00034 }
00035
00036 FEM_Comm_Holder::~FEM_Comm_Holder(void)
00037 {
00038 if (registered)
00039 {
00040 const char *caller="FEM_Comm_Holder::~FEM_Comm_Holder";
00041 IDXL_Chunk *owner=IDXL_Chunk::getNULL();
00042 if (owner) owner->destroy(idx,caller);
00043 }
00044 }
00045
00046
00047
00048 static void checkIsSet(int fem_mesh,bool wantSet,const char *caller) {
00049 if (FEM_Mesh_is_set(fem_mesh)!=wantSet) {
00050 const char *msg=wantSet?"This mesh (%d) is not a setting mesh":
00051 "This mesh (%d) is not a getting mesh";
00052 FEM_Abort(caller,msg,fem_mesh);
00053 }
00054 }
00055
00056
00057 CLINKAGE void
00058 FEM_Mesh_conn(int fem_mesh,int entity,
00059 int *conn, int firstItem, int length, int width)
00060 {
00061 FEM_Mesh_data(fem_mesh,entity,FEM_CONN, conn, firstItem,length, FEM_INDEX_0, width);
00062 }
00063 FLINKAGE void
00064 FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(int *fem_mesh,int *entity,
00065 int *conn, int *firstItem,int *length, int *width)
00066 {
00067
00068 FEM_Mesh_data(*fem_mesh,*entity,FEM_CONN, conn, *firstItem-1,*length, FEM_INDEX_1, *width);
00069 }
00070
00071 CLINKAGE void
00072 FEM_Mesh_set_conn(int fem_mesh,int entity,
00073 const int *conn, int firstItem,int length, int width)
00074 {
00075 checkIsSet(fem_mesh,true,"FEM_Mesh_set_conn");
00076 FEM_Mesh_conn(fem_mesh,entity,(int *)conn,firstItem,length,width);
00077 }
00078 FLINKAGE void
00079 FTN_NAME(FEM_MESH_SET_CONN,fem_mesh_set_conn)(int *fem_mesh,int *entity,
00080 const int *conn, int *firstItem,int *length, int *width)
00081 {
00082 checkIsSet(*fem_mesh,true,"fem_mesh_set_conn");
00083 FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,(int *)conn,firstItem,length,width);
00084 }
00085
00086 CLINKAGE void
00087 FEM_Mesh_get_conn(int fem_mesh,int entity,
00088 int *conn, int firstItem,int length, int width)
00089 {
00090 checkIsSet(fem_mesh,false,"FEM_Mesh_get_conn");
00091 FEM_Mesh_conn(fem_mesh,entity,conn,firstItem,length,width);
00092 }
00093 FLINKAGE void
00094 FTN_NAME(FEM_MESH_GET_CONN,fem_mesh_get_conn)(int *fem_mesh,int *entity,
00095 int *conn, int *firstItem,int *length, int *width)
00096 {
00097 checkIsSet(*fem_mesh,false,"fem_mesh_get_conn");
00098 FTN_NAME(FEM_MESH_CONN,fem_mesh_conn)(fem_mesh,entity,conn,firstItem,length,width);
00099 }
00100
00101
00102
00103 CLINKAGE void
00104 FEM_Mesh_data(int fem_mesh,int entity,int attr,
00105 void *data, int firstItem,int length, int datatype,int width)
00106 {
00107 IDXL_Layout lo(datatype,width);
00108 FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,lo);
00109 }
00110
00111 FORTRAN_AS_C(FEM_MESH_DATA,FEM_Mesh_data,fem_mesh_data,
00112 (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00113 (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00114 )
00115
00116
00117 CLINKAGE void
00118 FEM_Mesh_set_data(int fem_mesh,int entity,int attr,
00119 const void *data, int firstItem,int length, int datatype,int width)
00120 {
00121 checkIsSet(fem_mesh,true,"FEM_Mesh_set_data");
00122 FEM_Mesh_data(fem_mesh,entity,attr,(void *)data,firstItem,length,datatype,width);
00123 }
00124 FORTRAN_AS_C(FEM_MESH_SET_DATA,FEM_Mesh_set_data,fem_mesh_set_data,
00125 (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00126 (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00127 )
00128
00129 CLINKAGE void
00130 FEM_Mesh_get_data(int fem_mesh,int entity,int attr,
00131 void *data, int firstItem,int length, int datatype,int width)
00132 {
00133 checkIsSet(fem_mesh,false,"FEM_Mesh_get_data");
00134 FEM_Mesh_data(fem_mesh,entity,attr,data,firstItem,length,datatype,width);
00135 }
00136 FORTRAN_AS_C(FEM_MESH_GET_DATA,FEM_Mesh_get_data,fem_mesh_get_data,
00137 (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *datatype,int *width),
00138 (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*datatype,*width)
00139 )
00140
00141 CLINKAGE void
00142 FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
00143 void *data, int firstItem,int length, IDXL_Layout_t layout)
00144 {
00145 const char *caller="FEM_Mesh_data_layout";
00146 FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00147 IDXL_Layout_List::get().get(layout,caller));
00148 }
00149
00150 FORTRAN_AS_C(FEM_MESH_DATA_LAYOUT,FEM_Mesh_data_layout,fem_mesh_data_layout,
00151 (int *fem_mesh,int *entity,int *attr,void *data,int *firstItem,int *length,int *layout),
00152 (*fem_mesh,*entity,*attr,data,*firstItem-1,*length,*layout)
00153 )
00154
00155 CLINKAGE void
00156 FEM_Mesh_data_offset(int fem_mesh,int entity,int attr,
00157 void *data, int firstItem,int length,
00158 int type,int width, int offsetBytes,int distanceBytes,int skewBytes)
00159 {
00160 const char *caller="FEM_Mesh_data_offset";
00161 FEM_Mesh_data_layout(fem_mesh,entity,attr,data,firstItem,length,
00162 IDXL_Layout(type,width,offsetBytes,distanceBytes,skewBytes));
00163 }
00164 FORTRAN_AS_C(FEM_MESH_DATA_OFFSET,FEM_Mesh_data_offset,fem_mesh_data_offset,
00165 (int *fem_mesh,int *entity,int *attr,
00166 void *data,int *firstItem,int *length,
00167 int *type,int *width,int *offset,int *distance,int *skew),
00168 (*fem_mesh,*entity,*attr,
00169 data,*firstItem-1,*length,
00170 *type,*width,*offset,*distance,*skew)
00171 )
00172
00173
00174 void FEM_Register_array(int fem_mesh,int entity,int attr,
00175 void *data, int datatype,int width,int firstItem){
00176 IDXL_Layout lo(datatype,width);
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem,lo);
00187 }
00188
00189 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,
00190 void *data, IDXL_Layout_t layout,int firstItem){
00191 const char *caller="FEM_Register_array_layout";
00192 FEM_Register_array_layout(fem_mesh,entity,attr,data,firstItem,
00193 IDXL_Layout_List::get().get(layout,caller));
00194
00195 }
00196
00197
00198 CLINKAGE void
00199 FEM_Register_array(int fem_mesh,int entity,int attr,
00200 void *data, int datatype,int width)
00201 {
00202 FEM_Register_array(fem_mesh,entity,attr,data,datatype,width,0);
00203 }
00204
00205 CLINKAGE void
00206 FEM_Register_array_layout(int fem_mesh,int entity,int attr,
00207 void *data, IDXL_Layout_t layout){
00208 FEM_Register_array_layout(fem_mesh,entity,attr,data,layout,0);
00209 }
00210
00211
00212 CLINKAGE void
00213 FEM_Register_entity(int fem_mesh,int entity,void *data,
00214 int len,int max,FEM_Mesh_alloc_fn fn) {
00215 FEM_Register_entity_impl(fem_mesh,entity,data,len,max,fn);
00216 }
00217
00220 FORTRAN_AS_C(FEM_REGISTER_ARRAY,FEM_Register_array,fem_register_array,
00221 (int *fem_mesh,int *entity,int *attr,void *data,int *datatype,int *width),(*fem_mesh,*entity,*attr,data,*datatype,*width,0))
00222
00223
00224 FORTRAN_AS_C(FEM_REGISTER_ARRAY_LAYOUT,FEM_Register_array_layout,fem_register_array_layout,
00225 (int *fem_mesh,int *entity,int *attr,void *data,int *layout),(*fem_mesh,*entity,*attr,data,*layout,0))
00226
00227 FORTRAN_AS_C(FEM_REGISTER_ENTITY,FEM_Register_entity,fem_register_entity,
00228 (int *fem_mesh,int *entity,void *data,int *len,int *max,FEM_Mesh_alloc_fn fn),(*fem_mesh,*entity,data,*len,*max,fn))
00229
00230
00231
00232 CLINKAGE void
00233 FEM_Mesh_pup(int fem_mesh,int dataTag,FEM_Userdata_fn fn,void *data) {
00234 const char *caller="FEM_Mesh_pup"; FEMAPI(caller);
00235 FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00236 FEM_Userdata_item &i=m->udata.find(dataTag);
00237 FEM_Userdata_pupfn f(fn,data);
00238 if (m->isSetting()) i.store(f);
00239 else {
00240 if (!i.hasStored())
00241 FEM_Abort(caller,"Never stored any user data at tag %d",dataTag);
00242 i.restore(f);
00243 }
00244 }
00245 FORTRAN_AS_C(FEM_MESH_PUP,FEM_Mesh_pup,fem_mesh_pup,
00246 (int *m,int *t,FEM_Userdata_fn fn,void *data), (*m,*t,fn,data))
00247
00248
00249 CLINKAGE void
00250 FEM_Mesh_set_length(int fem_mesh,int entity,int newLength) {
00251 const char *caller="FEM_Mesh_set_length"; FEMAPI(caller);
00252 checkIsSet(fem_mesh,true,caller);
00253 FEM_Entity_lookup(fem_mesh,entity,caller)->setLength(newLength);
00254 }
00255 FORTRAN_AS_C(FEM_MESH_SET_LENGTH,FEM_Mesh_set_length,fem_mesh_set_length,
00256 (int *fem_mesh,int *entity,int *newLength),
00257 (*fem_mesh,*entity,*newLength)
00258 )
00259
00260
00261 CLINKAGE int
00262 FEM_Mesh_get_length(int fem_mesh,int entity) {
00263 const char *caller="FEM_Mesh_get_length"; FEMAPI(caller);
00264 int len=FEM_Entity_lookup(fem_mesh,entity,caller)->size();
00265 return len;
00266 }
00267 FORTRAN_AS_C_RETURN(int,
00268 FEM_MESH_GET_LENGTH,FEM_Mesh_get_length,fem_mesh_get_length,
00269 (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00270 )
00271
00272
00273 CLINKAGE void
00274 FEM_Mesh_set_width(int fem_mesh,int entity,int attr,int newWidth) {
00275 const char *caller="FEM_Mesh_set_width";
00276 FEMAPI(caller);
00277 checkIsSet(fem_mesh,true,caller);
00278 FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->setWidth(newWidth,caller);
00279 }
00280 FORTRAN_AS_C(FEM_MESH_SET_WIDTH,FEM_Mesh_set_width,fem_mesh_set_width,
00281 (int *fem_mesh,int *entity,int *attr,int *newWidth),
00282 (*fem_mesh,*entity,*attr,*newWidth)
00283 )
00284
00285 CLINKAGE int
00286 FEM_Mesh_get_width(int fem_mesh,int entity,int attr) {
00287 const char *caller="FEM_Mesh_get_width";
00288 FEMAPI(caller);
00289 return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getWidth();
00290 }
00291 FORTRAN_AS_C_RETURN(int,
00292 FEM_MESH_GET_WIDTH,FEM_Mesh_get_width,fem_mesh_get_width,
00293 (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00294 )
00295
00296 CLINKAGE int
00297 FEM_Mesh_get_datatype(int fem_mesh,int entity,int attr) {
00298 const char *caller="FEM_Mesh_get_datatype";
00299 FEMAPI(caller);
00300 return FEM_Attribute_lookup(fem_mesh,entity,attr,caller)->getDatatype();
00301 }
00302 FORTRAN_AS_C_RETURN(int,
00303 FEM_MESH_GET_DATATYPE,FEM_Mesh_get_datatype,fem_mesh_get_datatype,
00304 (int *fem_mesh,int *entity,int *attr),(*fem_mesh,*entity,*attr)
00305 )
00306
00307 CLINKAGE int
00308 FEM_Mesh_is_set(int fem_mesh)
00309 {
00310 return (FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00311 }
00312 FORTRAN_AS_C_RETURN(int,
00313 FEM_MESH_IS_SET,FEM_Mesh_is_set,fem_mesh_is_set,
00314 (int *fem_mesh),(*fem_mesh)
00315 )
00316
00317 CLINKAGE int
00318 FEM_Mesh_is_get(int fem_mesh)
00319 {
00320 return (!FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_is_get")->isSetting())?1:0;
00321 }
00322 FORTRAN_AS_C_RETURN(int,
00323 FEM_MESH_IS_GET,FEM_Mesh_is_get,fem_mesh_is_get,
00324 (int *fem_mesh),(*fem_mesh)
00325 )
00326
00327 CLINKAGE void
00328 FEM_Mesh_become_get(int fem_mesh)
00329 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeGetting(); }
00330 FORTRAN_AS_C(FEM_MESH_BECOME_GET,FEM_Mesh_become_get,fem_mesh_become_get, (int *m),(*m))
00331
00332 CLINKAGE void
00333 FEM_Mesh_become_set(int fem_mesh)
00334 { FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_become_get")->becomeSetting(); }
00335 FORTRAN_AS_C(FEM_MESH_BECOME_SET,FEM_Mesh_become_set,fem_mesh_become_set, (int *m),(*m))
00336
00337
00338 CLINKAGE IDXL_t
00339 FEM_Comm_shared(int fem_mesh,int entity) {
00340 const char *caller="FEM_Comm_shared";
00341 FEMAPI(caller);
00342 if (entity!=FEM_NODE) FEM_Abort(caller,"Only shared nodes supported");
00343 return FEM_Mesh_lookup(fem_mesh,caller)->node.
00344 sharedIDXL.getIndex(IDXL_Chunk::get(caller));
00345 }
00346 FORTRAN_AS_C_RETURN(int,
00347 FEM_COMM_SHARED,FEM_Comm_shared,fem_comm_shared,
00348 (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00349 )
00350
00351 CLINKAGE IDXL_t
00352 FEM_Comm_ghost(int fem_mesh,int entity) {
00353 const char *caller="FEM_Comm_ghost";
00354 FEMAPI(caller);
00355 FEM_Entity *e=FEM_Entity_lookup(fem_mesh,entity,caller);
00356 if (e->isGhost()) FEM_Abort(caller,"Can only call FEM_Comm_ghost on real entity type");
00357 return e->ghostIDXL.getIndex(IDXL_Chunk::get(caller));
00358 }
00359 FORTRAN_AS_C_RETURN(int,
00360 FEM_COMM_GHOST,FEM_Comm_ghost,fem_comm_ghost,
00361 (int *fem_mesh,int *entity),(*fem_mesh,*entity)
00362 )
00363
00364
00365
00366 void FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
00367 void *data, int firstItem,int length, const IDXL_Layout &layout)
00368 {
00369 if (femVersion == 0 && length==0) return;
00370 const char *caller="FEM_Mesh_data";
00371 FEMAPI(caller);
00372 FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00373 FEM_Attribute *a=m->lookup(entity,caller)->lookup(attr,caller);
00374
00375 if (m->isSetting())
00376 a->set(data,firstItem,length,layout,caller);
00377 else
00378 a->get(data,firstItem,length,layout,caller);
00379 }
00380
00382 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,void *data,int firstItem,const IDXL_Layout &layout){
00383 const char *caller="FEM_Register_array";
00384 FEMAPI(caller);
00385 FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00386 FEM_Entity *e = m->lookup(entity,caller);
00387 int length = e->size();
00388
00389 int max = e->getMax();
00390 FEM_Attribute *a = e->lookup(attr,caller);
00391 if(a->getWidth() == 0){
00395
00396 a->setWidth(layout.width);
00397 }
00398
00399
00400 if(m->isSetting()){
00401 a->register_data(data,length,max,layout,caller);
00402 }else{
00403 a->get(data,firstItem,length,layout,caller);
00404
00405 a->register_data(data,max,max,layout,caller);
00406 }
00407 }
00408 void FEM_Register_entity_impl(int fem_mesh,int entity,void *args,int len,int max,FEM_Mesh_alloc_fn fn){
00409 const char *caller = "FEM_Register_entity";
00410 FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,caller);
00411
00412
00413
00414
00415 FEM_Entity *e = m->lookup(entity,caller);
00416 e->setMaxLength(len,max,args,fn);
00417 }
00418
00419 FEM_Entity *FEM_Entity_lookup(int fem_mesh,int entity,const char *caller) {
00420 return FEM_Mesh_lookup(fem_mesh,caller)->lookup(entity,caller);
00421 }
00422 FEM_Attribute *FEM_Attribute_lookup(int fem_mesh,int entity,int attr,const char *caller) {
00423 return FEM_Entity_lookup(fem_mesh,entity,caller)->lookup(attr,caller);
00424 }
00425
00426 CLINKAGE int FEM_Mesh_get_entities(int fem_mesh, int *entities) {
00427 const char *caller="FEM_Mesh_get_entities";
00428 FEMAPI(caller);
00429 return FEM_Mesh_lookup(fem_mesh,caller)->getEntities(entities);
00430 }
00431 FORTRAN_AS_C_RETURN(int,
00432 FEM_MESH_GET_ENTITIES,FEM_Mesh_get_entities,fem_mesh_get_entities,
00433 (int *mesh,int *ent), (*mesh,ent)
00434 )
00435
00436 CLINKAGE int FEM_Mesh_get_attributes(int fem_mesh,int entity,int *attributes) {
00437 const char *caller="FEM_Mesh_get_attributes";
00438 FEMAPI(caller);
00439 return FEM_Entity_lookup(fem_mesh,entity,caller)->getAttrs(attributes);
00440 }
00441 FORTRAN_AS_C_RETURN(int,
00442 FEM_MESH_GET_ATTRIBUTES,FEM_Mesh_get_attributes,fem_mesh_get_attributes,
00443 (int *mesh,int *ent,int *attrs), (*mesh,*ent,attrs)
00444 )
00445
00446
00447
00448 CLINKAGE const char *FEM_Get_datatype_name(int datatype,char *storage) {
00449 switch(datatype) {
00450 case FEM_BYTE: return "FEM_BYTE";
00451 case FEM_INT: return "FEM_INT";
00452 case FEM_FLOAT: return "FEM_FLOAT";
00453 case FEM_DOUBLE: return "FEM_DOUBLE";
00454 case FEM_INDEX_0: return "FEM_INDEX_0";
00455 case FEM_INDEX_1: return "FEM_INDEX_1";
00456 };
00457 sprintf(storage,"unknown datatype code (%d)",datatype);
00458 return storage;
00459 }
00460
00463 CLINKAGE const char *FEM_Get_attr_name(int attr,char *storage)
00464 {
00465 if (attr<FEM_ATTRIB_TAG_MAX)
00466 {
00467 sprintf(storage,"FEM_DATA+%d",attr-FEM_DATA);
00468 return storage;
00469 }
00470 switch(attr) {
00471 case FEM_CONN: return "FEM_CONN";
00472 case FEM_SPARSE_ELEM: return "FEM_SPARSE_ELEM";
00473 case FEM_COOR: return "FEM_COOR";
00474 case FEM_GLOBALNO: return "FEM_GLOBALNO";
00475 case FEM_PARTITION: return "FEM_PARTITION";
00476 case FEM_SYMMETRIES: return "FEM_SYMMETRIES";
00477 case FEM_NODE_PRIMARY: return "FEM_NODE_PRIMARY";
00478 case FEM_NODE_ELEM_ADJACENCY: return "FEM_NODE_ELEM_ADJACENCY";
00479 case FEM_NODE_NODE_ADJACENCY: return "FEM_NODE_NODE_ADJACENCY";
00480 case FEM_ELEM_ELEM_ADJACENCY: return "FEM_ELEM_ELEM_ADJACENCY";
00481 case FEM_ELEM_ELEM_ADJ_TYPES: return "FEM_ELEM_ELEM_ADJ_TYPES";
00482 case FEM_IS_VALID_ATTR: return "FEM_IS_VALID_ATTR";
00483 case FEM_MESH_SIZING: return "FEM_MESH_SIZING";
00484
00485 default: break;
00486 };
00487 sprintf(storage,"unknown attribute code (%d)",attr);
00488 return storage;
00489 }
00490
00491
00492
00493 void FEM_Attribute::bad(const char *field,bool forRead,int cur,int next,const char *caller) const
00494 {
00495 char nameStorage[256];
00496 const char *name=FEM_Get_attr_name(attr,nameStorage);
00497 char errBuf[1024];
00498 const char *cannotBe=NULL;
00499 if (forRead) {
00500 if (cur==-1) {
00501 sprintf(errBuf,"The %s %s %s was never set-- it cannot now be read",
00502 e->getName(),name,field);
00503 }
00504 else
00505 cannotBe="read as";
00506 }
00507 else {
00508 cannotBe="set to";
00509 }
00510 if (cannotBe!=NULL)
00511 sprintf(errBuf,"The %s %s %s was previously set to %d; it cannot now be %s %d",
00512 e->getName(),name,field,cur,cannotBe,next);
00513
00514 FEM_Abort(caller,errBuf);
00515 }
00516
00517
00518 FEM_Attribute::FEM_Attribute(FEM_Entity *e_,int attr_)
00519 :e(e_),ghost(0),attr(attr_),width(0),datatype(-1), allocated(false)
00520 {
00521 tryAllocate();
00522 if (femVersion == 0) width=-1;
00523 }
00524 void FEM_Attribute::pup(PUP::er &p) {
00525
00526 p|width;
00527 if (p.isUnpacking() && femVersion > 0 && width<0) width=0;
00528 p|datatype;
00529 if (p.isUnpacking()) tryAllocate();
00530 }
00531 void FEM_Attribute::pupSingle(PUP::er &p, int pupindx) {
00532 return;
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:
00669 if (char_data) {
00670
00671
00672
00673 char_data->pup(p);
00674 }
00675 break;
00676 case FEM_INT:
00677 if (int_data) {
00678
00679
00680
00681 int_data->pup(p);
00682 }
00683 break;
00684 case FEM_FLOAT:
00685 if (float_data) {
00686
00687
00688
00689 float_data->pup(p);
00690 }
00691 break;
00692 case FEM_DOUBLE:
00693 if (double_data) {
00694
00695
00696
00697 double_data->pup(p);
00698 }
00699 break;
00700 default: CkAbort("Invalid datatype in FEM_DataAttribute::pup");
00701 }
00702 }
00703 void FEM_DataAttribute::pupSingle(PUP::er &p, int pupindx) {
00704 super::pupSingle(p,pupindx);
00705 switch(getDatatype()) {
00706 case -1: break;
00707 case FEM_BYTE: if (char_data) char_data->pupSingle(p,pupindx); break;
00708 case FEM_INT: if (int_data) int_data->pupSingle(p,pupindx); break;
00709 case FEM_FLOAT: if (float_data) float_data->pupSingle(p,pupindx); break;
00710 case FEM_DOUBLE: if (double_data) double_data->pupSingle(p,pupindx); break;
00711 default: CkAbort("Invalid datatype in FEM_DataAttribute::pupSingle");
00712 }
00713 }
00714 FEM_DataAttribute::~FEM_DataAttribute() {
00715 if (char_data) delete char_data;
00716 if (int_data) delete int_data;
00717 if (float_data) delete float_data;
00718 if (double_data) delete double_data;
00719
00720 }
00721
00723 template <class T>
00724 inline void setTableData(const void *user, int firstItem, int length,
00725 IDXL_LAYOUT_PARAM, AllocTable2d<T> *table)
00726 {
00727 for (int r=0;r<length;r++) {
00728 T *tableRow=table->getRow(firstItem+r);
00729 for (int c=0;c<width;c++)
00730 tableRow[c]=IDXL_LAYOUT_DEREF(T,user,r,c);
00731 }
00732 }
00733
00735 template <class T>
00736 inline void getTableData(void *user, int firstItem, int length,
00737 IDXL_LAYOUT_PARAM, const AllocTable2d<T> *table)
00738 {
00739 for (int r=0;r<length;r++) {
00740 const T *tableRow=table->getRow(firstItem+r);
00741 for (int c=0;c<width;c++)
00742 IDXL_LAYOUT_DEREF(T,user,r,c)=tableRow[c];
00743 }
00744
00745 }
00746
00747 void FEM_DataAttribute::set(const void *u, int f,int l,
00748 const IDXL_Layout &layout, const char *caller)
00749 {
00750 super::set(u,f,l,layout,caller);
00751 switch(getDatatype()) {
00752 case FEM_BYTE: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),char_data); break;
00753 case FEM_INT: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),int_data); break;
00754 case FEM_FLOAT: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),float_data); break;
00755 case FEM_DOUBLE: setTableData(u,f,l,IDXL_LAYOUT_CALL(layout),double_data); break;
00756 }
00757 }
00758
00759 void FEM_DataAttribute::get(void *u, int f,int l,
00760 const IDXL_Layout &layout, const char *caller) const
00761 {
00762 super::get(u,f,l,layout,caller);
00763 switch(getDatatype()) {
00764 case FEM_BYTE: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),char_data); break;
00765 case FEM_INT: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),int_data); break;
00766 case FEM_FLOAT: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),float_data); break;
00767 case FEM_DOUBLE: getTableData(u,f,l,IDXL_LAYOUT_CALL(layout),double_data); break;
00768 }
00769 }
00770
00771 void FEM_DataAttribute::register_data(void *u,int l,int max,
00772 const IDXL_Layout &layout, const char *caller)
00773 {
00774 super::register_data(u,l,max,layout,caller);
00775 switch(getDatatype()){
00776 case FEM_BYTE: char_data->register_data((unsigned char *)u,l,max); break;
00777 case FEM_INT: int_data->register_data((int *)u,l,max); break;
00778 case FEM_FLOAT: float_data->register_data((float *)u,l,max);break;
00779 case FEM_DOUBLE: double_data->register_data((double *)u,l,max);break;
00780 }
00781 }
00782
00783 template<class T>
00784 inline AllocTable2d<T> *allocTablePtr(AllocTable2d<T> *src,int len,int wid) {
00785 if (src==NULL) src=new AllocTable2d<T>;
00786 src->allocate(wid,len);
00787 return src;
00788 }
00789 void FEM_DataAttribute::allocate(int l,int w,int datatype)
00790 {
00791 switch(datatype) {
00792 case FEM_BYTE: char_data=allocTablePtr(char_data,l,w); break;
00793 case FEM_INT: int_data=allocTablePtr(int_data,l,w); break;
00794 case FEM_FLOAT: float_data=allocTablePtr(float_data,l,w); break;
00795 case FEM_DOUBLE: double_data=allocTablePtr(double_data,l,w); break;
00796 default: CkAbort("Invalid datatype in FEM_DataAttribute::allocate");
00797 };
00798 }
00799 void FEM_DataAttribute::copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity)
00800 {
00801 const FEM_DataAttribute *dsrc=(const FEM_DataAttribute *)&src;
00802 switch(getDatatype()) {
00803 case FEM_BYTE: char_data->setRow(dstEntity,dsrc->char_data->getRow(srcEntity)); break;
00804 case FEM_INT:
00805 int_data->setRow(dstEntity,dsrc->int_data->getRow(srcEntity)); break;
00806 case FEM_FLOAT: float_data->setRow(dstEntity,dsrc->float_data->getRow(srcEntity)); break;
00807 case FEM_DOUBLE: double_data->setRow(dstEntity,dsrc->double_data->getRow(srcEntity)); break;
00808 }
00809 }
00810
00811 template<class T>
00812 inline void interpolateAttrs(AllocTable2d<T> *data,int A,int B,int D,double frac,int width){
00813 T *rowA = data->getRow(A);
00814 T *rowB = data->getRow(B);
00815 T *rowD = data->getRow(D);
00816 for(int i=0;i<width;i++){
00817 double val = (double )rowA[i];
00818 val *= (frac);
00819 val += (1-frac) *((double )rowB[i]);
00820 rowD[i] = (T )val;
00821 }
00822 }
00823
00824 template<class T>
00825 inline void interpolateAttrs(AllocTable2d<T> *data,int *iNodes,int rNode,int k,int width){
00826 T *row[8];
00827 for (int i=0; i<k; i++) {
00828 row[i] = data->getRow(iNodes[i]);
00829 }
00830 T *rowR = data->getRow(rNode);
00831 for(int i=0;i<width;i++){
00832 double val = 0.0;
00833 for (int j=0; j<k; j++) {
00834 val += (double)row[j][i];
00835 }
00836 val = val/k;
00837 rowR[i] = (T )val;
00838 }
00839 }
00840
00841 template<class T>
00842 inline void minAttrs(AllocTable2d<T> *data,int A,int B,int D,double frac,int width){
00843 T *rowA = data->getRow(A);
00844 T *rowB = data->getRow(B);
00845 T *rowD = data->getRow(D);
00846 for(int i=0;i<width;i++){
00847 if(rowA[i] < rowB[i]){
00848 rowD[i] = rowA[i];
00849 }else{
00850 rowD[i] = rowB[i];
00851 }
00852 }
00853 }
00854
00855 template<class T>
00856 inline void minAttrs(AllocTable2d<T> *data,int *iNodes,int rNode,int k,int width){
00857 T *row[8];
00858 for (int i=0; i<k; i++) {
00859 row[i] = data->getRow(iNodes[i]);
00860 }
00861 T *rowR = data->getRow(rNode);
00862 for(int i=0;i<width;i++){
00863 rowR[i] = row[0][i];
00864 for (int j=1; j<k; j++) {
00865 if (row[j][i] < rowR[i]) {
00866 rowR[i] = row[j][i];
00867 }
00868 }
00869 }
00870 }
00871
00872 void FEM_DataAttribute::interpolate(int A,int B,int D,double frac){
00873 switch(getDatatype()){
00874 case FEM_BYTE:
00875 minAttrs(char_data,A,B,D,frac,getWidth());
00876 break;
00877 case FEM_INT:
00878 minAttrs(int_data,A,B,D,frac,getWidth());
00879 break;
00880 case FEM_FLOAT:
00881 interpolateAttrs(float_data,A,B,D,frac,getWidth());
00882 break;
00883 case FEM_DOUBLE:
00884 interpolateAttrs(double_data,A,B,D,frac,getWidth());
00885 break;
00886 }
00887 }
00888
00889 void FEM_DataAttribute::interpolate(int *iNodes,int rNode,int k){
00890 switch(getDatatype()){
00891 case FEM_BYTE:
00892 minAttrs(char_data,iNodes,rNode,k,getWidth());
00893 break;
00894 case FEM_INT:
00895 minAttrs(int_data,iNodes,rNode,k,getWidth());
00896 break;
00897 case FEM_FLOAT:
00898 interpolateAttrs(float_data,iNodes,rNode,k,getWidth());
00899 break;
00900 case FEM_DOUBLE:
00901 interpolateAttrs(double_data,iNodes,rNode,k,getWidth());
00902 break;
00903 }
00904 }
00905
00906
00907 FEM_IndexAttribute::Checker::~Checker() {}
00908
00909 FEM_IndexAttribute::FEM_IndexAttribute(FEM_Entity *e,int myAttr,FEM_IndexAttribute::Checker *checker_)
00910 :FEM_Attribute(e,myAttr), idx(0,0,-1), checker(checker_)
00911 {
00912 setDatatype(FEM_INT);
00913 }
00914 void FEM_IndexAttribute::pup(PUP::er &p) {
00915 super::pup(p);
00916
00917
00918
00919 p|idx;
00920 }
00921 void FEM_IndexAttribute::pupSingle(PUP::er &p, int pupindx) {
00922 super::pupSingle(p,pupindx);
00923 idx.pupSingle(p,pupindx);
00924 }
00925 FEM_IndexAttribute::~FEM_IndexAttribute() {
00926 if (checker) delete checker;
00927 }
00928
00929 void FEM_IndexAttribute::allocate(int length,int width,int datatype)
00930 {
00931 idx.allocate(width,length);
00932 }
00933
00939 static int type2base(int base_type,const char *caller) {
00940 if (base_type==FEM_INDEX_0) return 0;
00941 if (base_type==FEM_INDEX_1) return 1;
00942 FEM_Abort(caller,"You must use the datatype FEM_INDEX_0 or FEM_INDEX_1 with FEM_CONN, not %d",
00943 base_type);
00944 return 0;
00945 }
00946
00948 void setIndexTableData(const void *user, int firstItem, int length,
00949 IDXL_LAYOUT_PARAM, AllocTable2d<int> *table,int indexBase)
00950 {
00951 for (int r=0;r<length;r++) {
00952 int *tableRow=table->getRow(firstItem+r);
00953 for (int c=0;c<width;c++)
00954 tableRow[c]=IDXL_LAYOUT_DEREF(int,user,r,c)-indexBase;
00955 }
00956 }
00957
00959 void getIndexTableData(void *user, int firstItem, int length,
00960 IDXL_LAYOUT_PARAM, const AllocTable2d<int> *table,int indexBase)
00961 {
00962 for (int r=0;r<length;r++) {
00963 const int *tableRow=table->getRow(firstItem+r);
00964 for (int c=0;c<width;c++)
00965 IDXL_LAYOUT_DEREF(int,user,r,c)=tableRow[c]+indexBase;
00966 }
00967 }
00968
00969 void FEM_IndexAttribute::set(const void *src, int firstItem,int length,
00970 const IDXL_Layout &layout,const char *caller)
00971 {
00972 IDXL_Layout lo=layout; lo.type=FEM_INT;
00973 super::set(src,firstItem,length,lo,caller);
00974
00975 int indexBase=type2base(layout.type,caller);
00976 setIndexTableData(src,firstItem,length,IDXL_LAYOUT_CALL(layout),&idx,indexBase);
00977
00978 if (checker)
00979 for (int r=0;r<length;r++)
00980 checker->check(firstItem+r,idx,caller);
00981 }
00982
00983 void FEM_IndexAttribute::get(void *dest, int firstItem,int length,
00984 const IDXL_Layout &layout,const char *caller) const
00985 {
00986 IDXL_Layout lo=layout; lo.type=FEM_INT;
00987 super::get(dest,firstItem,length,lo,caller);
00988
00989 int indexBase=type2base(layout.type,caller);
00990 getIndexTableData(dest,firstItem,length,IDXL_LAYOUT_CALL(layout),&idx,indexBase);
00991 }
00992
00993 void FEM_IndexAttribute::register_data(void *user, int length,int max,
00994 const IDXL_Layout &layout, const char *caller){
00995 IDXL_Layout lo=layout; lo.type=FEM_INT;
00996 super::register_data(user,length,max,lo,caller);
00997
00998 idx.register_data((int *)user,length,max);
00999 }
01000
01001 void FEM_IndexAttribute::copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity)
01002 {
01003 const FEM_IndexAttribute *csrc=(const FEM_IndexAttribute *)&src;
01004 idx.setRow(dstEntity,csrc->idx.getRow(srcEntity));
01005 }
01006
01007
01008
01009 FEM_VarIndexAttribute::FEM_VarIndexAttribute(FEM_Entity *e,int myAttr)
01010 :FEM_Attribute(e,myAttr)
01011 {
01012 oldlength = 0;
01013 allocate(getMax(),getWidth(),getDatatype());
01014 setDatatype(FEM_INT);
01015 }
01016
01017 void FEM_VarIndexAttribute::pup(PUP::er &p){
01018 super::pup(p);
01019 p | idx;
01020 p|oldlength;
01021 }
01022
01023 void FEM_VarIndexAttribute::pupSingle(PUP::er &p, int pupindx){
01024 super::pupSingle(p,pupindx);
01025 p|idx[pupindx];
01026 }
01027
01028 void FEM_VarIndexAttribute::set(const void *src,int firstItem,int length,
01029 const IDXL_Layout &layout,const char *caller){
01030 printf("set not yet implemented for FEM_VarIndexAttribute \n");
01031 }
01032
01033 void FEM_VarIndexAttribute::get(void *dest, int firstItem,int length,
01034 const IDXL_Layout &layout, const char *caller) const{
01035 printf("get not yet implemented for FEM_VarIndexAttribute \n");
01036
01037 }
01038
01039 void FEM_VarIndexAttribute::copyEntity(int dstEntity,const FEM_Attribute &_src,int srcEntity){
01040 FEM_VarIndexAttribute &src = (FEM_VarIndexAttribute &)_src;
01041 const CkVec<CkVec<ElemID> > &srcTable = src.get();
01042 CkVec<ElemID> temp = srcTable[srcEntity];
01043 idx.insert(dstEntity, temp);
01044 }
01045
01046 void FEM_VarIndexAttribute::print(){
01047 for(int i=0;i<idx.size();i++){
01048 printf("%d -> ",i);
01049 for(int j=0;j<idx[i].size();j++){
01050 printf("(%d) ",((idx[i])[j]).id);
01051 }
01052 printf("\n");
01053 }
01054 }
01055
01056 int FEM_VarIndexAttribute::findInRow(int row, const ElemID &data){
01057 if(row >= idx.length()){
01058 return -1;
01059 }
01060 CkVec<ElemID> &rowVec = idx[row];
01061 for(int i=0;i<rowVec.length();i++){
01062 if(data == rowVec[i]){
01063 return i;
01064 }
01065 }
01066 return -1;
01067 }
01068
01069
01070
01072 CLINKAGE const char *FEM_Get_entity_name(int entity,char *storage)
01073 {
01074 char *dest=storage;
01075 if (entity<FEM_ENTITY_FIRST || entity>=FEM_ENTITY_LAST) {
01076 sprintf(dest,"unknown entity code (%d)",entity);
01077 }
01078 else {
01079 if (entity>FEM_ENTITY_FIRST+FEM_GHOST) {
01080 sprintf(dest,"FEM_GHOST+");
01081 dest+=strlen(dest);
01082 entity-=FEM_GHOST;
01083 }
01084 if (entity==FEM_NODE)
01085 sprintf(dest,"FEM_NODE");
01086 else if (entity>=FEM_SPARSE)
01087 sprintf(dest,"FEM_SPARSE+%d",entity-FEM_SPARSE);
01088 else
01089 sprintf(dest,"FEM_ELEM+%d",entity-FEM_ELEM);
01090 }
01091 return storage;
01092 }
01093
01094 FEM_Entity::FEM_Entity(FEM_Entity *ghost_)
01095 :length(0), max(0),ghost(ghost_), coord(0), sym(0), globalno(0), valid(0), meshSizing(0),
01096 ghostIDXL(ghost?&ghostSend:NULL, ghost?&ghost->ghostRecv:NULL),resize(NULL),
01097 invalidList(NULL),first_invalid(0),last_invalid(0),invalidListLen(0),invalidListAllLen(0)
01098 {
01099
01100 if (femVersion == 0) {
01101 length=-1;
01102 max=-1;
01103 }
01104 }
01105 void FEM_Entity::pup(PUP::er &p) {
01106 p|length;
01107 p|max;
01108 if (p.isUnpacking() && femVersion > 0 && length<0) length=0;
01109 p.comment(" Ghosts to send out: ");
01110 ghostSend.pup(p);
01111 p.comment(" Ghosts to recv: ");
01112 ghostRecv.pup(p);
01113 p.comment(" Ghost IDXL tag: ");
01114 ghostIDXL.pup(p);
01115
01116 int nAttributes=attributes.size();
01117 p|nAttributes;
01118 for (int a=0;a<nAttributes;a++)
01119 {
01120
01121
01122
01123
01124
01125
01126
01127 int attr=0;
01128 FEM_Attribute *r=NULL;
01129 if (!p.isUnpacking()) {
01130 r=attributes[a];
01131 attr=r->getAttr();
01132 }
01133 p|attr;
01134 if (p.isUnpacking()) {
01135 r=lookup(attr,"FEM_Entity::pup");
01136 }
01137
01138 {
01139 char attrNameStorage[256];
01140 p.comment(FEM_Get_attr_name(attr,attrNameStorage));
01141 }
01142 r->pup(p);
01143 }
01144 p|first_invalid;
01145 p|last_invalid;
01146 p|invalidListLen;
01147 p|invalidListAllLen;
01148 if(p.isUnpacking()) {
01149 delete[] invalidList;
01150 if(invalidListAllLen>0) invalidList = new int[invalidListAllLen];
01151 }
01152 if(invalidListAllLen>0) {
01153 PUParray(p, (int*)invalidList, invalidListAllLen);
01154 }
01155 if(p.isDeleting()) {
01156 delete[] invalidList;
01157 }
01158
01159 if (ghost!=NULL) {
01160 p.comment(" ---- Ghost attributes ---- ");
01161 ghost->pup(p);
01162 }
01163 }
01164
01165 FEM_Entity::~FEM_Entity()
01166 {
01167 delete ghost;
01168 for (int a=0;a<attributes.size();a++)
01169 delete attributes[a];
01170 }
01171
01173 void FEM_Entity::copyShape(const FEM_Entity &src) {
01174 for (int a=0;a<src.attributes.size();a++)
01175 {
01176 const FEM_Attribute *Asrc=src.attributes[a];
01177 FEM_Attribute *Adst=lookup(Asrc->getAttr(),"FEM_Entity::copyShape");
01178 Adst->copyShape(*Asrc);
01179 }
01180 if (ghost) ghost->copyShape(*src.ghost);
01181 }
01182
01183 void FEM_Entity::setLength(int newlen, bool f)
01184 {
01185 if (!resize) {
01186 if (size() != newlen) {
01187 length = newlen;
01188
01189 for (int a=0; a<attributes.size(); a++) {
01190 attributes[a]->reallocate();
01191 }
01192 }
01193 }
01194 else {
01195 int otherlen = length;
01196 if(!f) {
01197 otherlen = newlen;
01198 }
01199 length = newlen;
01200 if (length > max) {
01201 if (max > 4) {
01202 max = max + (max >> 2);
01203 } else {
01204 max = max + 10;
01205 }
01206 for (int a=0;a<attributes.size();a++){
01207 int code = attributes[a]->getAttr();
01208 if (!(code <= FEM_ATTRIB_TAG_MAX ||
01209 code == FEM_CONN || code == FEM_COORD ||
01210 code == FEM_BOUNDARY)) {
01211 attributes[a]->reallocate();
01212 }
01213 }
01214
01215
01216 resize(args,&otherlen,&max);
01217
01218 length = newlen;
01219 }
01220 }
01221 }
01222
01226 void FEM_Entity::reserveLength(int newlen)
01227 {
01228 if (newlen > max) {
01229 max = newlen;
01230 for (int a=0;a<attributes.size();a++){
01231 attributes[a]->reallocate();
01232 }
01233 }
01234 }
01235
01236 void FEM_Entity::allocateValid(void) {
01237 if (!valid){
01238 valid=new FEM_DataAttribute(this,FEM_IS_VALID_ATTR);
01239 add(valid);
01240 valid->setWidth(1);
01241 valid->setLength(size());
01242 valid->setDatatype(FEM_BYTE);
01243 valid->reallocate();
01244
01245
01246 for(int i=0;i<size();i++) {
01247 valid->getChar()(i,0)=1;
01248 }
01249 if(true) {
01250 invalidListLen=0; invalidListAllLen=16;
01251 invalidList = new int[invalidListAllLen];
01252
01253
01254 for(int i=0; i<invalidListAllLen; i++) {
01255 invalidList[i] = -1;
01256 }
01257 }
01258 else {
01259 first_invalid = last_invalid = 0;
01260 }
01261 }
01262 }
01263
01264 void FEM_Entity::set_valid(int idx, bool isNode){
01265 if(true) {
01266 CkAssert(idx < size() && idx >=0);
01267 valid->getChar()(idx,0)=1;
01268 if(invalidListLen>0) {
01269 if(invalidList[invalidListLen-1]==idx) {
01270 invalidListLen--;
01271 }
01272 }
01273 }
01274 else {
01275 int size1 = size();
01276 if(size1==0) {
01277 valid->getChar()(idx,0)=1;
01278 }
01279 else {
01280 CkAssert(idx < size1 && idx >=0 && first_invalid<=last_invalid);
01281 valid->getChar()(idx,0)=1;
01282 if(idx == first_invalid) {
01283
01284 while((first_invalid<last_invalid) && is_valid(first_invalid)){
01285 first_invalid++;
01286 }
01287 }
01288 else if(idx == last_invalid) {
01289
01290 while((first_invalid<last_invalid) && is_valid(last_invalid)) {
01291 last_invalid--;
01292 }
01293 }
01294 }
01295
01296 if( first_invalid == last_invalid && is_valid(first_invalid) )
01297 first_invalid = last_invalid = 0;
01298 }
01299 }
01300
01301 void FEM_Entity::set_invalid(int idx, bool isNode){
01302 if(true) {
01303 CkAssert(idx < size() && idx >=0);
01304 valid->getChar()(idx,0)=0;
01305 if(invalidListLen==invalidListAllLen) {
01306 invalidListAllLen = invalidListAllLen<<1;
01307 int* tmp = invalidList;
01308 invalidList = new int[invalidListAllLen];
01309 memcpy(invalidList,tmp,invalidListLen*sizeof(int));
01310 delete[] tmp;
01311 }
01312 invalidList[invalidListLen] = idx;
01313 invalidListLen++;
01314 }
01315 else {
01316 CkAssert(idx < size() && idx >=0 && first_invalid<=last_invalid);
01317 valid->getChar()(idx,0)=0;
01318
01319
01320 if(first_invalid==0 && last_invalid==0 && is_valid(0)){
01321 first_invalid = last_invalid = idx;
01322 return;
01323 }
01324 if(idx < first_invalid){
01325 first_invalid = idx;
01326 }
01327 if(idx > last_invalid){
01328 last_invalid = idx;
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338 }
01339 }
01340
01341
01343 int FEM_Entity::is_valid(int idx){
01344 CkAssert(idx < size() && idx >=0);
01345 return valid->getChar()(idx,0);
01346 }
01347
01349 int FEM_Entity::is_valid_any_idx(int idx){
01350 if(idx == -1 || idx >= size())
01351 return false;
01352 else if(idx < 0)
01353 return ghost->is_valid_any_idx(FEM_To_ghost_index(idx));
01354 else
01355 return valid->getChar()(idx,0);
01356 }
01357
01359 int FEM_Entity::is_valid_nonghost_idx(int idx){
01360 if(idx < 0 || idx >= size())
01361 return false;
01362 else
01363 return valid->getChar()(idx,0);
01364 }
01365
01367 int FEM_Entity::count_valid(){
01368 int count=0;
01369 for(int i=0;i<size();i++)
01370 if(is_valid(i)) count++;
01371 return count;
01372 }
01373
01374 void FEM_Entity::set_all_invalid(){
01375
01376 for(int i=0;i<size();i++) {
01377 valid->getChar()(i,0)=0;
01378 }
01379 }
01380
01381
01386 int FEM_Entity::get_next_invalid(FEM_Mesh *m, bool isNode, bool isGhost){
01387 int retval=0;
01388
01389 if(invalidListLen>0) {
01390 retval = invalidList[invalidListLen-1];
01391 }
01392 else {
01393 retval = size();
01394 setLength(retval+1,true);
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 set_valid(retval,isNode);
01452 return retval;
01453 }
01454
01455 void FEM_Entity::setMaxLength(int newLen,int newMaxLen,void *pargs,FEM_Mesh_alloc_fn fn){
01456
01457 max = newMaxLen;
01458 resize = fn;
01459 args = pargs;
01460 setLength(newLen);
01461 }
01462
01463
01465 void FEM_Entity::copyEntity(int dstEntity,const FEM_Entity &src,int srcEntity) {
01466 FEM_Entity *dp=this;
01467 const FEM_Entity *sp=&src;
01468 for (int a=0;a<sp->attributes.size();a++)
01469 {
01470 const FEM_Attribute *Asrc=sp->attributes[a];
01471 FEM_Attribute *Adst=dp->lookup(Asrc->getAttr(),"FEM_Entity::copyEntity");
01472 Adst->copyEntity(dstEntity,*Asrc,srcEntity);
01473 }
01474 }
01475
01478 int FEM_Entity::push_back(const FEM_Entity &src,int srcEntity) {
01479 int dstEntity=size();
01480 setLength(dstEntity+1);
01481 copyEntity(dstEntity,src,srcEntity);
01482 return dstEntity;
01483 }
01484
01487 void FEM_Entity::add(FEM_Attribute *attribute) {
01488 if (ghost!=NULL)
01489 {
01490 attribute->setGhost(ghost->lookup(attribute->getAttr(),"FEM_Entity::add"));
01491 }
01492 attributes.push_back(attribute);
01493 }
01494
01500 FEM_Attribute *FEM_Entity::lookup(int attr,const char *caller) {
01501
01502 for (int a=0;a<attributes.size();a++) {
01503 if (attributes[a]->getAttr()==attr)
01504 return attributes[a];
01505 }
01506
01507
01508 create(attr,caller);
01509
01510
01511 return lookup(attr,caller);
01512 }
01513
01520 void FEM_Entity::create(int attr,const char *caller) {
01521 if (attr<=FEM_ATTRIB_TAG_MAX)
01522 add(new FEM_DataAttribute(this,attr));
01523 else if (attr==FEM_COORD)
01524 allocateCoord();
01525 else if (attr==FEM_SYMMETRIES)
01526 allocateSym();
01527 else if (attr==FEM_GLOBALNO)
01528 allocateGlobalno();
01529 else if (attr==FEM_IS_VALID_ATTR)
01530 allocateValid();
01531 else if (attr==FEM_MESH_SIZING)
01532 allocateMeshSizing();
01533 else if(attr == FEM_CHUNK){
01534 FEM_IndexAttribute *chunkNo= new FEM_IndexAttribute(this,FEM_CHUNK,NULL);
01535 add(chunkNo);
01536 chunkNo->setWidth(1);
01537 }
01538 else if(attr == FEM_BOUNDARY){
01539 allocateBoundary();
01540 }else if(attr == FEM_ADAPT_FACE_ADJ){
01541 FEM_DataAttribute *adaptAdj = new FEM_DataAttribute(this,attr);
01542 adaptAdj->setDatatype(FEM_BYTE);
01543 add(adaptAdj);
01544 }else if(attr == FEM_ADAPT_EDGE_ADJ){
01545 FEM_DataAttribute *adaptAdj = new FEM_DataAttribute(this,attr);
01546 adaptAdj->setDatatype(FEM_BYTE);
01547 add(adaptAdj);
01548 }else if(attr == FEM_ADAPT_LOCK){
01549 FEM_DataAttribute *adaptLock = new FEM_DataAttribute(this,attr);
01550 adaptLock->setDatatype(FEM_INT);
01551 adaptLock->setWidth(2);
01552 add(adaptLock);
01553 }else if(attr == FEM_ADAPT_LOCK_PRIO){
01554 FEM_DataAttribute *adaptLockPrio = new FEM_DataAttribute(this,attr);
01555 adaptLockPrio->setDatatype(FEM_DOUBLE);
01556 adaptLockPrio->setWidth(1);
01557 add(adaptLockPrio);
01558 } else if (attr == FEM_PARTITION) {
01559 FEM_DataAttribute* partition = new FEM_DataAttribute(this, attr);
01560 partition->setDatatype(FEM_INT);
01561 partition->setWidth(1);
01562 add(partition);
01563 }
01564 else {
01565
01566 char attrNameStorage[256], msg[1024];
01567 sprintf(msg,"Could not locate the attribute %s for entity %s",
01568 FEM_Get_attr_name(attr,attrNameStorage), getName());
01569 FEM_Abort(caller,msg);
01570 }
01571 }
01572
01573 void FEM_Entity::allocateCoord(void) {
01574 if (coord) CkAbort("FEM_Entity::allocateCoord called, but already allocated");
01575 coord=new FEM_DataAttribute(this,FEM_COORD);
01576 add(coord);
01577 coord->setDatatype(FEM_DOUBLE);
01578 }
01579
01580 void FEM_Entity::allocateSym(void) {
01581 if (sym) CkAbort("FEM_Entity::allocateSym called, but already allocated");
01582 sym=new FEM_DataAttribute(this,FEM_SYMMETRIES);
01583 add(sym);
01584 sym->setWidth(1);
01585 sym->setDatatype(FEM_BYTE);
01586 }
01587
01588 void FEM_Entity::setSymmetries(int r,FEM_Symmetries_t s)
01589 {
01590 if (!sym) {
01591 if (s==0) return;
01592 allocateSym();
01593 }
01594 sym->getChar()(r,0)=s;
01595 }
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607 inline void FEM_Entity::set_coord(int idx, double x, double y){
01608 if(coord){
01609 coord->getDouble()(idx,0)=x;
01610 coord->getDouble()(idx,1)=y;
01611 }
01612 else {
01613 FEM_DataAttribute* attr = (FEM_DataAttribute*)lookup(FEM_DATA,"set_coord");
01614 attr->getDouble()(idx,0)=x;
01615 attr->getDouble()(idx,1)=y;
01616 }
01617 }
01618
01619 inline void FEM_Entity::set_coord(int idx, double x, double y, double z){
01620 if(coord){
01621 coord->getDouble()(idx,0)=x;
01622 coord->getDouble()(idx,1)=y;
01623 coord->getDouble()(idx,2)=z;
01624 }
01625 else {
01626 FEM_DataAttribute* attr = (FEM_DataAttribute*)lookup(FEM_DATA,"set_coord");
01627 attr->getDouble()(idx,0)=x;
01628 attr->getDouble()(idx,1)=y;
01629 attr->getDouble()(idx,2)=z;
01630 }
01631 }
01632
01633
01637 void FEM_Entity::get_coord(int idx, double &x, double &y){
01638 if(coord){
01639 if(idx<0){
01640 x = ghost->coord->getDouble()(FEM_From_ghost_index(idx),0);
01641 y = ghost->coord->getDouble()(FEM_From_ghost_index(idx),1);
01642 } else {
01643 x = coord->getDouble()(idx,0);
01644 y = coord->getDouble()(idx,1);
01645 }
01646
01647 }
01648 else {
01649
01650 if(idx<0){
01651 FEM_DataAttribute* attr = (FEM_DataAttribute*)ghost->lookup(FEM_DATA,"get_coord");
01652 x = attr->getDouble()(FEM_From_ghost_index(idx),0);
01653 y = attr->getDouble()(FEM_From_ghost_index(idx),1);
01654 } else {
01655 FEM_DataAttribute* attr = (FEM_DataAttribute*)lookup(FEM_DATA,"get_coord");
01656 x = attr->getDouble()(idx,0);
01657 y = attr->getDouble()(idx,1);
01658 }
01659
01660 }
01661
01662 }
01663
01667 void FEM_Entity::get_coord(int idx, double &x, double &y, double &z){
01668 if(coord){
01669 if(idx<0){
01670 x = ghost->coord->getDouble()(FEM_From_ghost_index(idx),0);
01671 y = ghost->coord->getDouble()(FEM_From_ghost_index(idx),1);
01672 z = ghost->coord->getDouble()(FEM_From_ghost_index(idx),2);
01673 } else {
01674 x = coord->getDouble()(idx,0);
01675 y = coord->getDouble()(idx,1);
01676 z = coord->getDouble()(idx,2);
01677 }
01678
01679 }
01680 else {
01681
01682 if(idx<0){
01683 FEM_DataAttribute* attr = (FEM_DataAttribute*)ghost->lookup(FEM_DATA,"get_coord");
01684 x = attr->getDouble()(FEM_From_ghost_index(idx),0);
01685 y = attr->getDouble()(FEM_From_ghost_index(idx),1);
01686 z = attr->getDouble()(FEM_From_ghost_index(idx),2);
01687 } else {
01688 FEM_DataAttribute* attr = (FEM_DataAttribute*)lookup(FEM_DATA,"get_coord");
01689 x = attr->getDouble()(idx,0);
01690 y = attr->getDouble()(idx,1);
01691 z = attr->getDouble()(idx,2);
01692 }
01693
01694 }
01695 }
01696
01697
01698
01699
01700
01701 void FEM_Entity::allocateGlobalno(void) {
01702 if (globalno) CkAbort("FEM_Entity::allocateGlobalno called, but already allocated");
01703 globalno=new FEM_IndexAttribute(this,FEM_GLOBALNO,NULL);
01704 add(globalno);
01705 globalno->setWidth(1);
01706 }
01707
01708 void FEM_Entity::allocateMeshSizing(void) {
01709 if (meshSizing)
01710 CkAbort("FEM_Entity::allocateMeshSizing called, but already allocated");
01711 meshSizing=new FEM_DataAttribute(this,FEM_MESH_SIZING);
01712 add(meshSizing);
01713 meshSizing->setWidth(1);
01714 meshSizing->setDatatype(FEM_DOUBLE);
01715 }
01716
01717 double FEM_Entity::getMeshSizing(int r) {
01718 if (!meshSizing) {
01719 allocateMeshSizing();
01720 return -1.0;
01721 }
01722 if (r >= 0) return meshSizing->getDouble()(r,0);
01723 else return ghost->meshSizing->getDouble()(FEM_To_ghost_index(r),0);
01724 }
01725
01726 void FEM_Entity::setMeshSizing(int r,double s)
01727 {
01728 if (!meshSizing) allocateMeshSizing();
01729 if (s <= 0.0) return;
01730 if (r >= 0) meshSizing->getDouble()(r,0)=s;
01731 else ghost->meshSizing->getDouble()(FEM_To_ghost_index(r),0)=s;
01732 }
01733
01734 void FEM_Entity::setMeshSizing(double *sf)
01735 {
01736 if (!meshSizing) allocateMeshSizing();
01737 int len = size();
01738 for (int i=0; i<len; i++)
01739 meshSizing->getDouble()(i,0)=sf[i];
01740 }
01741
01742 void FEM_Entity::allocateBoundary(){
01743 boundary = new FEM_DataAttribute(this,FEM_BOUNDARY);
01744 add(boundary);
01745 boundary->setWidth(1);
01746 boundary->setDatatype(FEM_INT);
01747 }
01748
01749
01750 int FEM_Entity::isBoundary(int idx){
01751 return boundary->getInt()(idx,0);
01752 }
01753
01754 void FEM_Entity::setGlobalno(int r,int g) {
01755 if (!globalno) allocateGlobalno();
01756 globalno->get()(r,0)=g;
01757 }
01758 void FEM_Entity::setAscendingGlobalno(void) {
01759 if (!globalno) {
01760 allocateGlobalno();
01761 int len=size();
01762 for (int i=0;i<len;i++) globalno->get()(i,0)=i;
01763 }
01764 }
01765 void FEM_Entity::setAscendingGlobalno(int base) {
01766 if (!globalno) {
01767 allocateGlobalno();
01768 int len=size();
01769 for (int i=0;i<len;i++) globalno->get()(i,0)=i+base;
01770 }
01771 }
01772 void FEM_Entity::copyOldGlobalno(const FEM_Entity &e) {
01773 if ((!hasGlobalno()) && e.hasGlobalno() && size()>=e.size()) {
01774 for (int i=0;i<size();i++)
01775 setGlobalno(i,e.getGlobalno(i));
01776 }
01777 }
01778
01779
01780
01781
01782
01783 void FEM_Entity::clearGhost(){
01784 CkAssert(ghost != NULL);
01785 ghostSend.clear();
01786 ghost->setLength(0);
01787 ghost->ghostRecv.clear();
01788 }
01789
01790
01791 FEM_Node::FEM_Node(FEM_Node *ghost_)
01792 :FEM_Entity(ghost_), primary(0), sharedIDXL(&shared,&shared),
01793 elemAdjacency(0),nodeAdjacency(0)
01794 {}
01795
01796 void FEM_Node::allocatePrimary(void) {
01797 if (primary) CkAbort("FEM_Node::allocatePrimary called, but already allocated");
01798 primary=new FEM_DataAttribute(this,FEM_NODE_PRIMARY);
01799 add(primary);
01800 primary->setWidth(1);
01801 primary->setDatatype(FEM_BYTE);
01802 }
01803
01804 bool FEM_Node::hasConn(int idx) {
01805 if((elemAdjacency->get()[idx].length() > 0)||(nodeAdjacency->get()[idx].length() > 0))
01806 return true;
01807 else return false;
01808 }
01809
01810 void FEM_Node::pup(PUP::er &p) {
01811 p.comment(" ---------------- Nodes ------------------ ");
01812 super::pup(p);
01813 p.comment(" ---- Shared nodes ----- ");
01814 shared.pup(p);
01815 p.comment(" shared nodes IDXL ");
01816 sharedIDXL.pup(p);
01817 }
01818 FEM_Node::~FEM_Node() {
01819 }
01820
01821
01822 const char *FEM_Node::getName(void) const {return "FEM_NODE";}
01823
01824 void FEM_Node::create(int attr,const char *caller) {
01825 if (attr==FEM_NODE_PRIMARY)
01826 allocatePrimary();
01827 else if(attr == FEM_NODE_ELEM_ADJACENCY)
01828 allocateElemAdjacency();
01829 else if(attr == FEM_NODE_NODE_ADJACENCY)
01830 allocateNodeAdjacency();
01831 else
01832 super::create(attr,caller);
01833 }
01834
01835
01836
01838 class FEM_Elem_Conn_Checker : public FEM_IndexAttribute::Checker {
01839 const FEM_Entity &sizeSrc;
01840 const FEM_Entity *sizeSrc2;
01841 public:
01842 FEM_Elem_Conn_Checker(const FEM_Entity &sizeSrc_,const FEM_Entity *sizeSrc2_)
01843 :sizeSrc(sizeSrc_), sizeSrc2(sizeSrc2_) {}
01844
01845 void check(int row,const BasicTable2d<int> &table,const char *caller) const {
01846 const int *idx=table.getRow(row);
01847 int n=table.width();
01848 int max=sizeSrc.size();
01849 if (sizeSrc2) max+=sizeSrc2->size();
01850 for (int i=0;i<n;i++)
01851 if ((idx[i]<0) || (idx[i]>=max))
01852 {
01853 if (idx[i]<0)
01854 FEM_Abort(caller,"Connectivity entry %d's value, %d, is negative",row,idx[i]);
01855 else
01856 FEM_Abort(caller,
01857 "Connectivity entry %d's value, %d, should be less than the number of nodes, %d",
01858 row,idx[i],max);
01859 }
01860 }
01861 };
01862
01863 FEM_Elem::FEM_Elem(const FEM_Mesh &mesh, FEM_Elem *ghost_)
01864 :FEM_Entity(ghost_), elemAdjacency(0), elemAdjacencyTypes(0)
01865 {
01866 FEM_IndexAttribute::Checker *c;
01867 if (isGhost())
01868 c=new FEM_Elem_Conn_Checker(mesh.node, mesh.node.getGhost());
01869 else
01870 c=new FEM_Elem_Conn_Checker(mesh.node, NULL);
01871 conn=new FEM_IndexAttribute(this,FEM_CONN,c);
01872 add(conn);
01873 }
01874 void FEM_Elem::pup(PUP::er &p) {
01875 p.comment(" ------------- Element data ---------- ");
01876 FEM_Entity::pup(p);
01877 }
01878 FEM_Elem::~FEM_Elem() {
01879 }
01880
01881
01882 void FEM_Elem::create(int attr,const char *caller) {
01883
01884
01885
01886
01887
01888
01889
01890 if(attr == FEM_CONN) ;
01891
01892 else if(attr == FEM_ELEM_ELEM_ADJACENCY)
01893 allocateElemAdjacency();
01894 else if(attr == FEM_ELEM_ELEM_ADJ_TYPES)
01895 allocateElemAdjacency();
01896 else
01897 super::create(attr,caller);
01898 }
01899
01900
01901 const char *FEM_Elem::getName(void) const {
01902 return "FEM_ELEM";
01903 }
01904
01905 bool FEM_Elem::hasConn(int idx) {
01906 return false;
01907 }
01908
01909
01914 class FEM_Sparse_Elem_Checker : public FEM_IndexAttribute::Checker {
01915 const FEM_Mesh &mesh;
01916 public:
01917 FEM_Sparse_Elem_Checker(const FEM_Mesh &mesh_) :mesh(mesh_) {}
01918
01919 void check(int row,const BasicTable2d<int> &table,const char *caller) const {
01920
01921 const int *elem=table.getRow(row);
01922 int maxT=mesh.elem.size();
01923 if ((elem[0]<0) || (elem[1]<0))
01924 FEM_Abort(caller,"Sparse element entry %d's values, %d and %d, are negative",
01925 row,elem[0],elem[1]);
01926 int t=elem[0];
01927 if (t>=maxT)
01928 FEM_Abort(caller,"Sparse element entry %d's element type, %d, is too big",
01929 row,elem[0]);
01930 if (elem[1]>=mesh.elem[t].size())
01931 FEM_Abort(caller,"Sparse element entry %d's element index, %d, is too big",
01932 row,elem[1]);
01933 }
01934 };
01935
01936 FEM_Sparse::FEM_Sparse(const FEM_Mesh &mesh_,FEM_Sparse *ghost_)
01937 :FEM_Elem(mesh_,ghost_), elem(0), mesh(mesh_)
01938 {
01939 }
01940 void FEM_Sparse::allocateElem(void) {
01941 if (elem) CkAbort("FEM_Sparse::allocateElem called, but already allocated");
01942 FEM_IndexAttribute::Checker *checker=new FEM_Sparse_Elem_Checker(mesh);
01943 elem=new FEM_IndexAttribute(this,FEM_SPARSE_ELEM,checker);
01944 add(elem);
01945 elem->setWidth(2);
01946 }
01947 void FEM_Sparse::pup(PUP::er &p) {
01948 p.comment(" ------------- Sparse Element ---------- ");
01949 super::pup(p);
01950 }
01951 FEM_Sparse::~FEM_Sparse() {
01952 }
01953
01954 const char *FEM_Sparse::getName(void) const { return "FEM_SPARSE"; }
01955
01956 void FEM_Sparse::create(int attr,const char *caller) {
01957 if (attr==FEM_SPARSE_ELEM)
01958 allocateElem();
01959 else FEM_Entity::create(attr,caller);
01960 }
01961
01962
01963
01964 FEM_Mesh::FEM_Mesh()
01965 :node(new FEM_Node(NULL)),
01966 elem(*this,"FEM_ELEM"),
01967 sparse(*this,"FEM_SPARSE"),
01968 lastElemAdjLayer(NULL),
01969 fmMM(NULL)
01970 {
01971 m_isSetting=true;
01972 lastLayerSet = false;
01973 }
01974
01975 FEM_Mesh::~FEM_Mesh() {
01976 }
01977
01978 FEM_Entity *FEM_Mesh::lookup(int entity,const char *caller) {
01979 FEM_Entity *e=NULL;
01980 if (entity>=FEM_ENTITY_FIRST && entity<FEM_ENTITY_LAST)
01981 {
01982 bool isGhost=false;
01983 if (entity-FEM_ENTITY_FIRST>=FEM_GHOST) {
01984 entity-=FEM_GHOST;
01985 isGhost=true;
01986 }
01987 if (entity==FEM_NODE)
01988 e=&node;
01989 else if (entity>=FEM_ELEM && entity<FEM_ELEM+100)
01990 {
01991 int elType=entity-FEM_ELEM;
01992 e=&elem.set(elType);
01993 }
01994 else if (entity>=FEM_SPARSE && entity<FEM_SPARSE+100)
01995 {
01996 int sID=entity-FEM_SPARSE;
01997 e=&sparse.set(sID);
01998 }
01999
02000 if (isGhost)
02001 e=e->getGhost();
02002 }
02003
02004 if (e==NULL)
02005 FEM_Abort(caller,"Expected an entity type (FEM_NODE, FEM_ELEM, etc.) but got %d",entity);
02006 return e;
02007 }
02008 const FEM_Entity *FEM_Mesh::lookup(int entity,const char *caller) const {
02011 return ((FEM_Mesh *)this)->lookup(entity,caller);
02012 }
02013
02014 void FEM_Mesh::setFemMeshModify(femMeshModify *m){
02015 fmMM = m;
02016 }
02017
02018 void FEM_Mesh::setParfumSA(ParFUMShadowArray *m){
02019 parfumSA = m;
02020 }
02021
02022
02023 femMeshModify *FEM_Mesh::getfmMM(){
02024 return fmMM;
02025 }
02026
02027 void FEM_Mesh::pup(PUP::er &p)
02028 {
02029 p.comment(" ------------- Node Data ---------- ");
02030 node.pup(p);
02031
02032 p.comment(" ------------- Element Types ---------- ");
02033 elem.pup(p);
02034
02035 p.comment("-------------- Sparse Types ------------");
02036 sparse.pup(p);
02037
02038 p.comment("-------------- Symmetries ------------");
02039 symList.pup(p);
02040
02041 p|m_isSetting;
02042 p|lastLayerSet;
02043 if(lastLayerSet) {
02044 if(p.isUnpacking()) {
02045 if(lastElemAdjLayer==NULL) lastElemAdjLayer = new FEM_ElemAdj_Layer();
02046 }
02047 lastElemAdjLayer->pup(p);
02048 }
02049 p.comment("-------------- Mesh data --------------");
02050 udata.pup(p);
02051
02052
02053
02054
02055
02056 }
02057
02058 int FEM_Mesh::chkET(int elType) const {
02059 if ((elType<0)||(elType>=elem.size())) {
02060 CkError("FEM Error! Bad element type %d!\n",elType);
02061 CkAbort("FEM Error! Bad element type used!\n");
02062 }
02063 return elType;
02064 }
02065
02066 int FEM_Mesh::nElems(int t_max) const
02067 {
02068 #if CMK_ERROR_CHECKING
02069 if (t_max<0 || t_max>elem.size()) {
02070 CkPrintf("FEM> Invalid element type %d used!\n");
02071 CkAbort("FEM> Invalid element type");
02072 }
02073 #endif
02074 int ret=0;
02075 for (int t=0;t<t_max;t++){
02076 if (elem.has(t)){
02077 ret+=elem.get(t).size();
02078 }
02079 }
02080 return ret;
02081 }
02082
02083 int FEM_Mesh::getGlobalElem(int elType,int elNo) const
02084 {
02085 int base=nElems(elType);
02086 #if CMK_ERROR_CHECKING
02087 if (elNo<0 || elNo>=elem[elType].size()) {
02088 CkPrintf("FEM> Element number %d is invalid-- element type %d has only %d elements\n",
02089 elNo,elType,elem[elType].size());
02090 CkAbort("FEM> Invalid element number, probably passed via FEM_Set_Sparse_elem");
02091 }
02092 #endif
02093 return base+elNo;
02094 }
02095
02097 void FEM_Mesh::setAscendingGlobalno(void) {
02098 node.setAscendingGlobalno();
02099 for (int e=0;e<elem.size();e++)
02100 if (elem.has(e)) elem[e].setAscendingGlobalno();
02101 for (int s=0;s<sparse.size();s++)
02102 if (sparse.has(s)) sparse[s].setAscendingGlobalno();
02103 }
02104 void FEM_Mesh::setAbsoluteGlobalno(){
02105 node.setAscendingGlobalno();
02106 for (int e=0;e<elem.size();e++){
02107 if (elem.has(e)) elem[e].setAscendingGlobalno(nElems(e));
02108 }
02109 }
02110
02111 void FEM_Mesh::copyOldGlobalno(const FEM_Mesh &m) {
02112 node.copyOldGlobalno(m.node);
02113 for (int e=0;e<m.elem.size();e++)
02114 if (m.elem.has(e) && e<elem.size() && elem.has(e))
02115 elem[e].copyOldGlobalno(m.elem[e]);
02116 for (int s=0;s<m.sparse.size();s++)
02117 if (m.sparse.has(s) && s<sparse.size() && sparse.has(s))
02118 sparse[s].copyOldGlobalno(m.sparse[s]);
02119 }
02120
02121 void FEM_Mesh::clearSharedNodes(){
02122 node.shared.clear();
02123 }
02124
02125 void FEM_Mesh::clearGhostNodes(){
02126 node.clearGhost();
02127 }
02128
02129 void FEM_Mesh::clearGhostElems(){
02130 for(int i=0;i<elem.size();i++){
02131 if(elem.has(i)){
02132 elem[i].clearGhost();
02133 }
02134 }
02135 }
02136
02137 void FEM_Index_Check(const char *caller,const char *entityType,int type,int maxType) {
02138 if (type<0 || type>maxType) {
02139 char msg[1024];
02140 sprintf(msg,"%s %d is not a valid entity type (it must be between %d and %d)",
02141 entityType,type, 0, maxType-1);
02142 FEM_Abort(caller,msg);
02143 }
02144 }
02145 void FEM_Is_NULL(const char *caller,const char *entityType,int type) {
02146 char msg[1024];
02147 sprintf(msg,"%s %d was never set--it cannot now be read",entityType,type);
02148 FEM_Abort(caller,msg);
02149 }
02150
02151 void FEM_Mesh::copyShape(const FEM_Mesh &src)
02152 {
02153 node.copyShape(src.node);
02154 for (int t=0;t<src.elem.size();t++)
02155 if (src.elem.has(t)) elem.set(t).copyShape(src.elem.get(t));
02156
02157 for (int s=0;s<src.sparse.size();s++)
02158 if (src.sparse.has(s)) sparse.set(s).copyShape(src.sparse.get(s));
02159
02160 setSymList(src.getSymList());
02161 }
02162
02164 int FEM_Mesh::getEntities(int *entities) {
02165 int len=0;
02166 entities[len++]=FEM_NODE;
02167 for (int t=0;t<elem.size();t++)
02168 if (elem.has(t)) entities[len++]=FEM_ELEM+t;
02169 for (int s=0;s<sparse.size();s++)
02170 if (sparse.has(s)) entities[len++]=FEM_SPARSE+s;
02171 return len;
02172 }
02173
02174
02175 FILE *FEM_openMeshFile(const char *prefix,int chunkNo,int nchunks,bool forRead)
02176 {
02177 char fname[256];
02178 static const char *meshFileNames="%s_vp%d_%d.dat";
02179 sprintf(fname, meshFileNames, prefix, nchunks, chunkNo);
02180 FILE *fp = fopen(fname, forRead?"r":"w");
02181 CkPrintf("FEM> %s %s...\n",forRead?"Reading":"Writing",fname);
02182 if(fp==0) {
02183 FEM_Abort(forRead?"FEM: unable to open input file"
02184 :"FEM: unable to create output file.\n");
02185 }
02186 return fp;
02187 }
02188
02189 static inline void read_version()
02190 {
02191 FILE *f = fopen("FEMVERSION", "r");
02192 if (f!=NULL) {
02193 fscanf(f, "%d", &femVersion);
02194 if (CkMyPe()==0) CkPrintf("FEM> femVersion detected: %d\n", femVersion);
02195 fclose(f);
02196 }
02197 }
02198
02199 static inline void write_version()
02200 {
02201 FILE *f = fopen("FEMVERSION", "w");
02202 if (f!=NULL) {
02203 fprintf(f, "%d", femVersion);
02204 fclose(f);
02205 }
02206 }
02207
02208 FEM_Mesh *FEM_readMesh(const char *prefix, int chunkNo, int nChunks)
02209 {
02210
02211 static int version_checked = 0;
02212 if (!version_checked) {
02213 version_checked = 1;
02214 read_version();
02215 }
02216
02217 FEM_Mesh *ret = new FEM_Mesh;
02218 ret->becomeGetting();
02219 FILE *fp = FEM_openMeshFile(prefix, chunkNo, nChunks, true);
02220 PUP::fromTextFile p(fp);
02221 ret->pup(p);
02222 fclose(fp);
02223
02224 #ifdef PRINT_SHARED_NODE_INFO
02225
02226
02227
02228 FEM_Comm &shared = ret->node.shared;
02229 int numNeighborVPs = shared.size();
02230
02231
02232 for(int i=0; i<numNeighborVPs; i++){
02233 IDXL_List list = shared.getLocalList(i);
02234
02235 double x, y, sumx = 0.0, sumy = 0.0;
02236 int nnodes = ret->node.size();
02237 for(int n=0; n<nnodes; n++){
02238 ret->node.get_coord(n, x, y);
02239 sumx += x;
02240 sumy += y;
02241 }
02242
02243 CkPrintf("chunk %d at %f %f communicates with chunk %d through %d shared nodes\n", chunkNo, sumx/(double)nnodes, sumy/(double)nnodes, list.getDest(), list.size());
02244 }
02245 #endif
02246
02247 return ret;
02248 }
02249
02250 void FEM_writeMesh(FEM_Mesh *m,const char *prefix,int chunkNo,int nChunks)
02251 {
02252 if (chunkNo == 0) {
02253 write_version();
02254 }
02255 FILE *fp = FEM_openMeshFile(prefix,chunkNo,nChunks,false);
02256 PUP::toTextFile p(fp);
02257 m->pup(p);
02258 fclose(fp);
02259 }
02260
02261
02262 CLINKAGE void FEM_traceBegin(){
02263 traceBegin();
02264 }
02265 FORTRAN_AS_C(FEM_TRACEBEGIN,
02266 FEM_traceBegin,
02267 fem_tracebegin,
02268 (), () )
02269
02270
02271 CLINKAGE void FEM_traceEnd(){
02272 traceEnd();
02273 }
02274 FORTRAN_AS_C(FEM_TRACEEND,
02275 FEM_traceEnd,
02276 fem_traceend,
02277 (), () )
02278
02279
02280
02281
02282
02283 CLINKAGE void FEM_Mesh_allocate_valid_attr(int fem_mesh, int entity_type){
02284 FEM_Mesh *m=FEM_Mesh_lookup(fem_mesh,"FEM_Mesh_create_valid_elem");
02285 FEM_Entity *entity = m->lookup(entity_type,"FEM_Mesh_allocate_valid_attr");
02286 entity->allocateValid();
02287 }
02288 FORTRAN_AS_C(FEM_MESH_ALLOCATE_VALID_ATTR,
02289 FEM_Mesh_allocate_valid_attr,
02290 fem_mesh_allocate_valid_attr,
02291 (int *fem_mesh, int *entity_type), (*fem_mesh, *entity_type) )
02292
02293
02294
02295 CLINKAGE void FEM_set_entity_valid(int mesh, int entityType, int entityIdx){
02296 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_");
02297 FEM_Entity *entity = m->lookup(entityType,"FEM_");
02298 entity->set_valid(entityIdx,true);
02299 }
02300 FORTRAN_AS_C(FEM_SET_ENTITY_VALID,
02301 FEM_set_entity_valid,
02302 fem_set_entity_valid,
02303 (int *fem_mesh, int *entity_type, int *entityIdx), (*fem_mesh, *entity_type, *entityIdx) )
02304
02305
02306
02307 CLINKAGE void FEM_set_entity_invalid(int mesh, int entityType, int entityIdx){
02308 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02309 FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02310 return entity->set_invalid(entityIdx,true);
02311 }
02312 FORTRAN_AS_C(FEM_SET_ENTITY_INVALID,
02313 FEM_set_entity_invalid,
02314 fem_set_entity_invalid,
02315 (int *fem_mesh, int *entity_type, int *entityIdx), (*fem_mesh, *entity_type, *entityIdx) )
02316
02317
02318
02319 CLINKAGE int FEM_is_valid(int mesh, int entityType, int entityIdx){
02320 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02321 FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02322 return (entity->is_valid(entityIdx) != 0);
02323 }
02324 FORTRAN_AS_C(FEM_IS_VALID,
02325 FEM_is_valid,
02326 fem_is_valid,
02327 (int *fem_mesh, int *entity_type, int *entityIdx), (*fem_mesh, *entity_type, *entityIdx) )
02328
02329
02330
02331 CLINKAGE int FEM_count_valid(int mesh, int entityType){
02332 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02333 FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02334 return entity->count_valid();
02335 }
02336 FORTRAN_AS_C(FEM_COUNT_VALID,
02337 FEM_count_valid,
02338 fem_count_valid,
02339 (int *fem_mesh, int *entity_type), (*fem_mesh, *entity_type) )
02340
02341
02342 CLINKAGE int FEM_is_node_shared(int mesh_id, int idx) {
02343 FEM_Mesh* mesh = FEM_Mesh_lookup(mesh_id,"FEM_is_node_shared");
02344 const IDXL_Rec *rec = mesh->node.shared.getRec(idx);
02345 return (int)(rec != NULL);
02346 }
02347 FORTRAN_AS_C(FEM_IS_NODE_SHARED,
02348 FEM_is_node_shared,
02349 fem_is_node_shared,
02350 (int* fem_mesh, int* node_idx), (*fem_mesh, *node_idx))
02351
02352
02353 CLINKAGE int FEM_find_node_owner(int mesh_id, int idx) {
02354 FEM_Mesh* mesh = FEM_Mesh_lookup(mesh_id,"FEM_find_node_owner");
02355 const IDXL_Rec *rec = mesh->node.shared.getRec(idx);
02356 int min = FEM_My_partition();
02357 if (!rec) {
02358 return min;
02359 }
02360 for (int i=0; i<rec->getShared(); i++) {
02361 int chk = rec->getChk(i);
02362 if (chk < min) {
02363 min = chk;
02364 }
02365 }
02366 return min;
02367 }
02368 FORTRAN_AS_C(FEM_FIND_NODE_OWNER,
02369 FEM_find_node_owner,
02370 fem_find_node_owner,
02371 (int* fem_mesh, int* node_idx), (*fem_mesh, *node_idx))
02372
02373
02374
02375 void FEM_set_entity_coord2(int mesh, int entityType, int idx, double x, double y){
02376 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02377 FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02378 entity->set_coord(idx,x,y);
02379 }
02380 void FEM_set_entity_coord3(int mesh, int entityType, int idx, double x, double y, double z){
02381 FEM_Mesh *m=FEM_Mesh_lookup(mesh,"FEM_Mesh_create_valid_elem");
02382 FEM_Entity *entity = m->lookup(entityType,"FEM_Mesh_allocate_valid_attr");
02383 entity->set_coord(idx,x,y,z);
02384 }