void tecplotter(HashTable* El_Table, HashTable* NodeTable, MatProps* matprops, TimeProps* timeprops, MapNames* mapnames, double v_star) { int i_buck, i_neigh; //indices int xp, xm, yp, ym; //x plus, x minus, y plus, y minus directions int gen, *neigh_gen; //level of grid refinement int numprocs; //number of processes int myid, *neigh_proc; //process id's int done = 1; unsigned key[2]; int TECTAG = 123; MPI_Status status; MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); Element *EmTemp, *EmArray[4]; HashEntry *entryp; int e_buckets=El_Table->get_no_of_buckets(); /*There are 2 ways to draw triangles 1) as a separate ZONE of triangles 2) as quads with duplicate points I chose the 2nd option. Why? Because I want all the elements from a given processor to be in a single zone. Also duplicate points for every element that uses them have been eliminated. That makes the "boundary" option in tecplot work right, but more importantly the nodes the triangles use aren't repeated (you get the triangles for free apart from the element conectivity data) and nodes for quads are reduced by about a factor of 4. This reduces file the size by about a factor of 4 when grid adaptation is used, and by about a factor of 3 when it's not. MODIFICATION: 20070115: Now Each And Every BUBBLE Node of Active and Ghost Elements are printed once in the order they appear in the Element HashTable. This eliminates the need to sort (quick or otherwise) the elements speeding up tecplot, at the cost of slightly increasing the file size on multiprocessor runs (adding BUBBLE nodes of GHOST elements along the right and upper edges of the collection of elements this processor "owns") */ //count the number of BUBBLE nodes, and tecplot quads and tecplot //triangles I need to draw int num_tec_node=0, num_tec_tri=0, num_tec_quad=0; for(i_buck=0;i_buck<e_buckets;i_buck++) { entryp = *(El_Table->getbucketptr()+i_buck); while(entryp) { EmArray[0]=EmTemp=(Element*)entryp->value; assert(EmTemp); entryp=entryp->next; if((EmTemp->get_adapted_flag()!=TOBEDELETED)&& (abs(EmTemp->get_adapted_flag())<=BUFFER) ) { num_tec_node++; EmTemp->put_ithelem(num_tec_node); if(EmTemp->get_adapted_flag()>TOBEDELETED) { switch(get_ll_polygon(El_Table,NodeTable,myid,EmArray)) { case 4: //we should draw a lower left quad num_tec_quad++; break; case 3: //we should draw a lower left triangle num_tec_tri++; break; case 0: //we should NOT draw a lower left polygon break; default: //something wierd happened report this to the "FBI" assert(0); }//switch(get_ll_polygon(El_Table,NodeTable,myid,EmArray)) //match the lower left triangle at the lower left corner of //a different subdomain with an upper right triangle in this //subdomain if(get_ur_tri(El_Table,NodeTable,myid,EmArray)) num_tec_tri++; neigh_proc = EmTemp->get_neigh_proc(); gen=EmTemp->get_gen(); neigh_gen=EmTemp->get_neigh_gen(); //one triangle is added to an element for each side whose //neighboring element is more refined than current element //provided the triangle wouldn't fall on a domain boundary for(i_neigh=0; i_neigh<4; i_neigh++) if((neigh_gen[i_neigh]>gen)&&(neigh_proc[i_neigh]!=INIT)) num_tec_tri++; }//if(EmTemp->get_adapted_flag()>TOBEDELETED) }//if((EmTemp->get_adapted_flag()!=TOBEDELETED)&& }//while(entryp) }//for(i_buck=0;i_buck<e_buckets;i_buck++) int num_tec_elem=num_tec_quad+num_tec_tri; int num_tec_elem2=0; char filename[20]; sprintf(filename,"tecpl%02d%08d.tec",myid,timeprops->iter); FILE *fp=fopen(filename,"w"); //print the tecplot header int hrs, mins; double secs; timeprops->chunktime(&hrs,&mins,&secs); fprintf ( fp, "TITLE= \" %s: time %d:%02d:%g (hrs:min:sec), V*=%g\"\n", mapnames->gis_map,hrs,mins,secs,v_star); fprintf ( fp, "VARIABLES = \"X\", \"Y\", \"Z\", \"PILE_HEIGHT\"," "\"PHI\", \"SOLID_X_MOMENTUM\", \"SOLID_Y_MOMENTUM\"," "\"FLUID_X_MOMENTUM\", \"FLUID_Y_MOMENTUM\"," "\"ELEVATION\", \"SOLID_SPEED\", \"FLUID_SPEED\" \n"); fprintf(fp,"\n"); fprintf(fp,"ZONE N=%d, E=%d, F=FEPOINT, ET=QUADRILATERAL\n", num_tec_node, num_tec_elem); //print the element/BUBBLE-node information int num_missing_bubble_node=0; //for legacy debugging, I (Keith) //believe the missing BUBBLE node problem has been solved, it //doesn't seem to be a problem anymore for(i_buck=0;i_buck<e_buckets;i_buck++) { entryp = *(El_Table->getbucketptr()+i_buck); while(entryp) { EmTemp=(Element*)entryp->value; assert(EmTemp); entryp=entryp->next; if((EmTemp->get_adapted_flag()!=TOBEDELETED)&& (abs(EmTemp->get_adapted_flag())<=BUFFER) ) num_missing_bubble_node+= print_bubble_node(fp, NodeTable, matprops, EmTemp); }//while(entryp) }//for(i_buck=0;i_buck<e_buckets;i_buck++) //print the tecplot element connectivity data int tec_nodes_in_tec_quad[4]; for(i_buck=0;i_buck<e_buckets;i_buck++) { entryp = *(El_Table->getbucketptr()+i_buck); while(entryp) { EmArray[0]=EmTemp=(Element*)entryp->value; assert(EmTemp); entryp=entryp->next; if((EmTemp->get_adapted_flag()>TOBEDELETED)&& (EmTemp->get_adapted_flag()<=BUFFER) ) { neigh_proc = EmTemp->get_neigh_proc(); gen=EmTemp->get_gen(); neigh_gen=EmTemp->get_neigh_gen(); switch(get_ll_polygon(El_Table,NodeTable,myid,EmArray)) { case 4: //we should draw a lower left quad tec_nodes_in_tec_quad[0]=EmArray[2]->get_ithelem(); tec_nodes_in_tec_quad[1]=EmArray[0]->get_ithelem(); tec_nodes_in_tec_quad[2]=EmArray[1]->get_ithelem(); tec_nodes_in_tec_quad[3]=EmArray[3]->get_ithelem(); fprintf(fp,"%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements break; case 3: //we should draw a lower left triangle tec_nodes_in_tec_quad[ 0]=EmArray[2]->get_ithelem(); tec_nodes_in_tec_quad[ 1]=EmArray[0]->get_ithelem(); tec_nodes_in_tec_quad[ 2]= tec_nodes_in_tec_quad[3]=EmArray[1]->get_ithelem(); fprintf(fp,"%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements break; case 0: //we should NOT draw a lower left polygon break; default: //something weird happened report this to the "FBI" assert(0); }//switch(get_ll_polygon(El_Table, myid, EmArray)) /**********************************************************/ /* match the lower left triangle at the lower left corner */ /* of a different subdomain with an upper right one */ /**********************************************************/ if(get_ur_tri(El_Table,NodeTable,myid,EmArray)) { tec_nodes_in_tec_quad[ 0]=EmArray[1]->get_ithelem(); tec_nodes_in_tec_quad[ 1]=EmArray[2]->get_ithelem(); tec_nodes_in_tec_quad[ 2]= tec_nodes_in_tec_quad[3]=EmArray[0]->get_ithelem(); fprintf(fp,"%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements }//if(get_ur_tri(El_Table,myid,EmArray)) /**********************************************************/ /* add triangles for elements with more refined neighbors */ /* (aka split neighbors) this fills in the holes */ /**********************************************************/ tec_nodes_in_tec_quad[0]=EmTemp->get_ithelem(); for(i_neigh=0; i_neigh<4; i_neigh++) if((neigh_gen[i_neigh]>gen)&&(neigh_proc[i_neigh]!=INIT)){ /* draw triangles as quads with the last corner of the triangle repeated. The three corners are 1) this element 2) the primary neighbor (one of sides 0->3) 3) the secondary neighbor (the primary +4 side) */ EmArray[1]=EmArray[2]=EmArray[3]=NULL; //The Primary Neighbor EmArray[1]=(Element*) El_Table->lookup(EmTemp->get_neighbors()+i_neigh*KEYLENGTH); assert(EmArray[1]); tec_nodes_in_tec_quad[ 1]=EmArray[1]->get_ithelem(); //The Secondary Neighbor EmArray[2]=(Element*) El_Table->lookup(EmTemp->get_neighbors()+(i_neigh+4)*KEYLENGTH); assert(EmArray[2]); tec_nodes_in_tec_quad[ 2]= tec_nodes_in_tec_quad[3]=EmArray[2]->get_ithelem(); fprintf(fp,"%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements }//if((neigh_gen[i_neigh]>gen)&&(neigh_proc[i_neigh]!=INIT)) }//if((EmTemp->get_adapted_flag()>TOBEDELETED)&& ... }//while(entryp) }//for(i_buck=0;i_buck<e_buckets;i_buck++) fflush(fp); fclose(fp); //printf("num_tec_elem {1/2}={%d/%d}\n",num_tec_elem,num_tec_elem2); assert(num_tec_elem2==num_tec_elem); MPI_Barrier(MPI_COMM_WORLD); return; }
void tecplotter (HashTable * El_Table, HashTable * NodeTable, MatProps * matprops, TimeProps * timeprops, MapNames * mapnames, double v_star) { int i_buck, i_neigh; //indices int xp, xm, yp, ym; //x plus, x minus, y plus, y minus directions int gen, *neigh_gen; //level of grid refinement int numprocs; //number of processes int myid, *neigh_proc; //process id's int done = 1; unsigned key[2]; int TECTAG = 123; MPI_Status status; MPI_Comm_size (MPI_COMM_WORLD, &numprocs); MPI_Comm_rank (MPI_COMM_WORLD, &myid); Element *EmTemp, *EmArray[4]; HashEntry *entryp; int e_buckets = El_Table->get_no_of_buckets (); //move_data(numprocs, myid, El_Table, NodeTable,timeprops); if (myid == TARGETPROCA) { printf ("at tecplotter 1.0\n"); fflush (stdout); } //count the number of BUBBLE nodes, and tecplot quads and tecplot //triangles I need to draw int num_tec_node = 0, num_tec_tri = 0, num_tec_quad = 0; for (i_buck = 0; i_buck < e_buckets; i_buck++) { entryp = *(El_Table->getbucketptr () + i_buck); while (entryp) { EmArray[0] = EmTemp = (Element *) entryp->value; assert (EmTemp); entryp = entryp->next; if ((EmTemp->get_adapted_flag () != TOBEDELETED) && (abs (EmTemp->get_adapted_flag ()) <= BUFFER)) { num_tec_node++; EmTemp->put_ithelem (num_tec_node); if (EmTemp->get_adapted_flag () > TOBEDELETED) { switch (get_ll_polygon (El_Table, NodeTable, myid, EmArray)) { case 4: //we should draw a lower left quad num_tec_quad++; break; case 3: //we should draw a lower left triangle num_tec_tri++; break; case 0: //we should NOT draw a lower left polygon break; default: //something wierd happened report this to the "FBI" assert (0); } //switch(get_ll_polygon(El_Table,NodeTable,myid,EmArray)) //match the lower left triangle at the lower left corner of //a different subdomain with an upper right triangle in this //subdomain if (get_ur_tri (El_Table, NodeTable, myid, EmArray)) num_tec_tri++; neigh_proc = EmTemp->get_neigh_proc (); gen = EmTemp->get_gen (); neigh_gen = EmTemp->get_neigh_gen (); //one triangle is added to an element for each side whose //neighboring element is more refined than current element //provided the triangle wouldn't fall on a domain boundary for (i_neigh = 0; i_neigh < 4; i_neigh++) if ((neigh_gen[i_neigh] > gen) && (neigh_proc[i_neigh] != INIT)) num_tec_tri++; } //if(EmTemp->get_adapted_flag()>TOBEDELETED) } //if((EmTemp->get_adapted_flag()!=TOBEDELETED)&& } //while(entryp) } //for(i_buck=0;i_buck<e_buckets;i_buck++) int num_tec_elem = num_tec_quad + num_tec_tri; int num_tec_elem2 = 0; char filename[20]; sprintf (filename, "tecpl%02d%08d.tec", myid, timeprops->iter); FILE *fp = fopen (filename, "w"); //print the tecplot header int hrs, mins; double secs; timeprops->chunktime (&hrs, &mins, &secs); fprintf (fp, "TITLE= \" %s: time %d:%02d:%g (hrs:min:sec), V*=%g\"\n", mapnames->gis_map, hrs, mins, secs, v_star); fprintf (fp, "VARIABLES = \"X\", \"Y\", \"Z\", \"PILE_HEIGHT\", \"X_MOMENTUM\", \"Y_MOMENTUM\", \"ELEVATION\", \"CORRECTSPEED\" \n"); //} fprintf (fp, "\n"); fprintf (fp, "ZONE N=%d, E=%d, F=FEPOINT, ET=QUADRILATERAL\n", num_tec_node, num_tec_elem); //print the element/BUBBLE-node information int num_missing_bubble_node = 0; //for legacy debugging, I (Keith) //believe the missing BUBBLE node problem has been solved, it //doesn't seem to be a problem anymore for (i_buck = 0; i_buck < e_buckets; i_buck++) { entryp = *(El_Table->getbucketptr () + i_buck); while (entryp) { EmTemp = (Element *) entryp->value; assert (EmTemp); entryp = entryp->next; if ((EmTemp->get_adapted_flag () != TOBEDELETED) && (abs (EmTemp->get_adapted_flag ()) <= BUFFER)) num_missing_bubble_node += print_bubble_node (fp, NodeTable, matprops, EmTemp); } //while(entryp) } //for(i_buck=0;i_buck<e_buckets;i_buck++) //print the tecplot element connectivity data int tec_nodes_in_tec_quad[4]; for (i_buck = 0; i_buck < e_buckets; i_buck++) { entryp = *(El_Table->getbucketptr () + i_buck); while (entryp) { EmArray[0] = EmTemp = (Element *) entryp->value; assert (EmTemp); entryp = entryp->next; if ((EmTemp->get_adapted_flag () > TOBEDELETED) && (EmTemp->get_adapted_flag () <= BUFFER)) { neigh_proc = EmTemp->get_neigh_proc (); gen = EmTemp->get_gen (); neigh_gen = EmTemp->get_neigh_gen (); switch (get_ll_polygon (El_Table, NodeTable, myid, EmArray)) { case 4: //we should draw a lower left quad tec_nodes_in_tec_quad[0] = EmArray[2]->get_ithelem (); tec_nodes_in_tec_quad[1] = EmArray[0]->get_ithelem (); tec_nodes_in_tec_quad[2] = EmArray[1]->get_ithelem (); tec_nodes_in_tec_quad[3] = EmArray[3]->get_ithelem (); fprintf (fp, "%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements break; case 3: //we should draw a lower left triangle tec_nodes_in_tec_quad[0] = EmArray[2]->get_ithelem (); tec_nodes_in_tec_quad[1] = EmArray[0]->get_ithelem (); tec_nodes_in_tec_quad[2] = tec_nodes_in_tec_quad[3] = EmArray[1]->get_ithelem (); fprintf (fp, "%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements break; case 0: //we should NOT draw a lower left polygon break; default: //something weird happened report this to the "FBI" assert (0); } //switch(get_ll_polygon(El_Table, myid, EmArray)) /**********************************************************/ /* match the lower left triangle at the lower left corner */ /* of a different subdomain with an upper right one */ /**********************************************************/ if (get_ur_tri (El_Table, NodeTable, myid, EmArray)) { tec_nodes_in_tec_quad[0] = EmArray[1]->get_ithelem (); tec_nodes_in_tec_quad[1] = EmArray[2]->get_ithelem (); tec_nodes_in_tec_quad[2] = tec_nodes_in_tec_quad[3] = EmArray[0]->get_ithelem (); fprintf (fp, "%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements } //if(get_ur_tri(El_Table,myid,EmArray)) /**********************************************************/ /* add triangles for elements with more refined neighbors */ /* (aka split neighbors) this fills in the holes */ /**********************************************************/ tec_nodes_in_tec_quad[0] = EmTemp->get_ithelem (); for (i_neigh = 0; i_neigh < 4; i_neigh++) if ((neigh_gen[i_neigh] > gen) && (neigh_proc[i_neigh] != INIT)) { /* draw triangles as quads with the last corner of the triangle repeated. The three corners are 1) this element 2) the primary neighbor (one of sides 0->3) 3) the secondary neighbor (the primary +4 side) */ EmArray[1] = EmArray[2] = EmArray[3] = NULL; //The Primary Neighbor EmArray[1] = (Element *) El_Table->lookup (EmTemp->get_neighbors () + i_neigh * KEYLENGTH); assert (EmArray[1]); tec_nodes_in_tec_quad[1] = EmArray[1]->get_ithelem (); //The Secondary Neighbor EmArray[2] = (Element *) El_Table->lookup (EmTemp->get_neighbors () + (i_neigh + 4) * KEYLENGTH); assert (EmArray[2]); tec_nodes_in_tec_quad[2] = tec_nodes_in_tec_quad[3] = EmArray[2]->get_ithelem (); fprintf (fp, "%d %d %d %d\n", tec_nodes_in_tec_quad[0], tec_nodes_in_tec_quad[1], tec_nodes_in_tec_quad[2], tec_nodes_in_tec_quad[3]); num_tec_elem2++; //counter of number of drawing elements } //if((neigh_gen[i_neigh]>gen)&&(neigh_proc[i_neigh]!=INIT)) } //if((EmTemp->get_adapted_flag()>TOBEDELETED)&& ... } //while(entryp) } //for(i_buck=0;i_buck<e_buckets;i_buck++) fflush (fp); fclose (fp); assert (num_tec_elem2 == num_tec_elem); MPI_Barrier (MPI_COMM_WORLD); return; }