diff options
-rw-r--r-- | src/Boundary.c | 454 |
1 files changed, 212 insertions, 242 deletions
diff --git a/src/Boundary.c b/src/Boundary.c index c7ae95d..43f50f5 100644 --- a/src/Boundary.c +++ b/src/Boundary.c @@ -18,8 +18,6 @@ #include "util_String.h" #include "Boundary.h" -#include "cctk_FortranString.h" /* Needed until Fortran function aliasing is working properly */ - static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusBase_Boundary_Boundary_c); @@ -29,49 +27,49 @@ CCTK_FILEVERSION(CactusBase_Boundary_Boundary_c); ********************************************************************/ /* #define DEBUG 1 */ -/* Linked list for holding variables selected for a bc: +/* Linked list, called a var list, for holding variables selected for a bc: * Entries are sorted in the order they appear in struct BCVAR, - * i.e. the var_index varies most rapidly, and bc_name least rapidly. + * i.e. the var index varies more rapidly that table handle. + * (Currently no sorting is done on faces specification.) + * + * There will be one such linked list for each type of boundary + * condition selected (i.e. one for each bc_name). */ struct BCVAR { - struct BCVAR *next_entry; - char *bc_name; - /* CCTK_FPOINTER bc_fn_pointer; // store fn pointers, since they are - easier to sort? */ - int faces; - int table; - int var_index; + struct BCVAR *next; /* pointer to next entry in list */ + int faces; /* set of faces for this application of bc */ + int table; /* table handle holding extra arguments */ + int var; /* index of grid variable to which to apply the bc */ }; /* - * Linked list of pointers to the - * first entry marked for bc 'A', the first marked for bc 'B', etc. - * This will speed both adding entries and retreiving them. One could - * also provide a pointer to the first entry with bc 'B', table handle - * 12. For now, since usually all bcs are marked for the same bc, I - * won't bother to implement this. + * Linked list of var lists, one for each type of requested bc + * (i.e. one for each bc_name). * * Here is also recorded how many of each bc type have * been selected so far, so that the GetSelectedBCs doesn't have to be - * run through twice; once simply to get the number of selected vars! + * run through twice; once simply to get the number of selected vars. * - * Could also save a string comparison at each iteration of - * Boundary_Boundary_SelectedGVs() if we also store and manage bcdata->stop. + * This list is sorted by bc_name. Alternatively one could sort it by + * associated function pointer, but this seems a bit obtuse. */ struct BCDATA { - struct BCDATA *next; - const char *bc_name; /* name of bc */ - struct BCVAR *start; /* start of this bc in BCVAR list */ - int num; /* number of entries for this bc in BCVAR list */ + struct BCDATA *next; /* pointer to next element of this list */ + struct BCVAR *var_list; /* pointer to first element of a var list */ + const char *bc_name; /* name of bc */ + int num; /* number of entries for this bc in var list */ }; /******************************************************************** ********************* Local Routine Prototypes ********************* ********************************************************************/ -static int entry_less_than(struct BCVAR *new, struct BCVAR *current); +static int entry_greater_than(struct BCVAR *new, struct BCVAR *current); +#ifdef DEBUG +static void print_selections_database(void); +#endif /******************************************************************** ***************** Aliased Routine Prototypes *********************** @@ -114,23 +112,16 @@ void Boundary_ApplyPhysicalBCs(CCTK_ARGUMENTS); void Boundary_ClearSelection(void); /******************************************************************** - ********************* Other Routine Prototypes ********************* - ********************************************************************/ - -/******************************************************************** ********************* Local Data ***************************** ********************************************************************/ /* Table for holding function pointers associated with each boundary condition: * This table has - * key = boundary condition name (eg "Radiative") + * key = boundary condition name (eg "Radiation") * value = a CCTK_FPOINTER pointing to a function to implement that BC */ static int physbc_table_handle = -1; -/* Linked list for storing selected vars data */ -static struct BCVAR *selections_list = NULL; - /* Linked list for storing data associated with selections list itself */ static struct BCDATA *bcdata_list = NULL; @@ -143,12 +134,12 @@ static struct BCDATA *bcdata_list = NULL; @routine Bdry_Boundary_RegisterPhysicalBC @date Sun Nov 3 19:51:37 CET 2002 @author David Rideout - @desc + @desc Used to register physical boundary conditions with the boundary - thorn. - @enddesc - @calls - @history + thorn. + @enddesc + @calls + @history @endhistory @var GH @vdesc cctkGH * @@ -174,7 +165,7 @@ static struct BCDATA *bcdata_list = NULL; @endreturndesc @@*/ CCTK_INT Bdry_Boundary_RegisterPhysicalBC(CCTK_POINTER GH, - CCTK_FPOINTER fn_pointer, + CCTK_FPOINTER fn_pointer, CCTK_STRING bc_name) { int retval; @@ -240,10 +231,10 @@ CCTK_INT Bdry_Boundary_RegisterPhysicalBC(CCTK_POINTER GH, @desc Used to select a Cactus variable to have boundary conditions applied, using its variable name. - @enddesc - @calls - @history - @endhistory + @enddesc + @calls + @history + @endhistory @var GH @vdesc cctkGH * @vtype CCTK_POINTER @@ -263,7 +254,7 @@ CCTK_INT Bdry_Boundary_RegisterPhysicalBC(CCTK_POINTER GH, @vdesc name of variable to which to apply bc @vtype CCTK_STRING @vio in - @endvar + @endvar @var bc_name @vdesc name of bc to apply @vtype CCTK_STRING @@ -346,7 +337,7 @@ CCTK_INT Bdry_Boundary_SelectVarForBC(CCTK_POINTER GH, -4 error allocating memory for new entry in 'bcdata' database @endreturndesc @@*/ -CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, +CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, CCTK_INT faces, CCTK_INT table_handle, CCTK_INT var_index, @@ -358,6 +349,7 @@ CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, struct BCVAR *previous; struct BCDATA *current_bcdata; struct BCDATA *previous_bcdata; + struct BCDATA *new_bcdata; retval = 0; current = NULL; @@ -365,16 +357,17 @@ CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, previous_bcdata = NULL; #ifdef DEBUG - printf("Boundary_SelectVarForBCI: called with table_handle=%d, var_index=%d, bc_name=%s\n", table_handle, var_index, bc_name); - printf(" vi %d corresponds to %s\n", var_index, CCTK_VarName(var_index)); + printf("Boundary_SelectVarForBCI:\n"); + printf(" called with table_handle=%d, var_index=%d, bc_name=%s\n", + table_handle, var_index, bc_name); + printf(" vi %d corresponds to %s\n", var_index, CCTK_VarName(var_index)); #endif /* Ignore GH */ GH = GH; /* Has some function implementing bc_name been registered? */ - if (!Util_TableQueryValueInfo(physbc_table_handle, NULL, NULL, - bc_name)) + if (!Util_TableQueryValueInfo(physbc_table_handle, NULL, NULL, bc_name)) { CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING, "There is no function implementing the physical boundary " @@ -391,21 +384,15 @@ CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, "'selected for bcs' database"); retval = -1; } -#ifdef DEBUG - printf("Boundary_SelectVarForBCI: new entry in list will be stored at %p\n", new_entry); -#endif /* populate new entry with data */ - new_entry -> bc_name = Util_Strdup(bc_name); + // new_entry -> bc_name = Util_Strdup(bc_name); ### new_entry -> faces = faces; new_entry -> table = table_handle; - new_entry -> var_index = var_index; - /* new_entry -> next_entry will be filled in later */ -#ifdef DEBUG - printf("Boundary_SelectVarForBCI: sucessfully stored data in new entry\n"); -#endif + new_entry -> var = var_index; + /* new_entry -> next will be filled in later */ - /* Use bcdata list to jump to appropriate 'sector' of selections list */ + /* Into which of bcdata's lists should this variable be placed? */ for (current_bcdata = bcdata_list; current_bcdata; previous_bcdata=current_bcdata, current_bcdata = current_bcdata->next) @@ -417,17 +404,16 @@ CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, if (CCTK_Equals(current_bcdata->bc_name,bc_name)) { - current = current_bcdata->start; + current = current_bcdata->var_list; current_bcdata->num++; #ifdef DEBUG printf("Boundary_SelectVarForBCI: var %s brings bc %s to %d vars\n", CCTK_VarName(var_index),bc_name, current_bcdata->num); #endif + break; /* now that current is set we don't need to look at any + more bcdata entries */ } } -#ifdef DEBUG - printf("Boundary_SelectVarForBCI: current starting at %p\n", current); -#endif /* If current has not been initialized yet, this is a new bc_name * that does not appear in the bcdata list. @@ -438,92 +424,101 @@ CCTK_INT Bdry_Boundary_SelectVarForBCI(CCTK_POINTER GH, printf("Boundary_SelectVarForBCI: adding new entry to bcdata list\n"); #endif - /* new bc_name. Add entry to end of bcdata list. */ - current_bcdata = (struct BCDATA *) malloc(sizeof(struct BCDATA)); - if (!current_bcdata) { + /* new bc_name. Create new entry for bcdata list. */ + new_bcdata = (struct BCDATA *) malloc(sizeof(struct BCDATA)); + if (!new_bcdata) { CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING, "Unable to allocate memory for internal 'bcdata' list"); retval = -4; } else { - current_bcdata->next = NULL; - current_bcdata->bc_name = Util_Strdup(bc_name); - current_bcdata->start = NULL; /* this will be filled in below */ - current_bcdata->num = 1; + new_bcdata->var_list = new_entry; /* new_entry will be first element */ + new_entry->next = NULL; /* of var list for this bcdata entry */ + new_bcdata->bc_name = Util_Strdup(bc_name); + new_bcdata->num = 1; } - /* Place entry into bcdata list */ - if (bcdata_list) /* this is not the first entry */ + /* Place new entry into bcdata list, maintaining case independent sort. */ + for (current_bcdata = bcdata_list, previous_bcdata = NULL; + current_bcdata; + previous_bcdata=current_bcdata, current_bcdata = current_bcdata->next) { - previous_bcdata->next = current_bcdata; - } else +#ifdef DEBUG + printf(" looping through bcdata list, to insert new entry; at %s\n", + current_bcdata->bc_name); +#endif + if (Util_StrCmpi(bc_name, current_bcdata->bc_name) < 0) + { + /* bc_name precedes current->bc_name; place new entry here */ + if (!previous_bcdata) /* goes at start of bcdata list */ + { + bcdata_list = new_bcdata; + new_bcdata->next = current_bcdata; + } else + { + new_bcdata->next = current_bcdata; + previous_bcdata->next = new_bcdata; + } + break; + } + } + + /* If current_bcdata is still NULL, then this is the first entry */ + if (!current_bcdata) { - bcdata_list = current_bcdata; + bcdata_list = new_bcdata; + new_bcdata->next = NULL; } + } + #ifdef DEBUG - printf("bcdata_list is now %p\n", bcdata_list); - printf("bcdata_list->bc_name is %s\n", bcdata_list->bc_name); - printf("current_bcdata->bc_name is %s\n", current_bcdata->bc_name); + printf(" Preparing to loop through elements of var list. current is %p" + " previous is %p\n", current, previous); #endif - /* bc_name does not appear in bcdata_list, so start at beginning */ - current = selections_list; - } - - /* enter into correct location in linked list */ - /* Note that this loop is skipped if current is NULL. */ + /* Enter new_entry into correct location in linked list. + * Note that this loop is skipped if new_entry was already inserted as first + * element of a new var list above (since in that case current will be + * NULL) */ for (; /* starting value for current is selected using the bcdata list, above */ - current && !entry_less_than(new_entry,current); + current && entry_greater_than(new_entry,current) > 0; /* continue if not at end of list, and new_entry is greater than current entry */ - previous = current, current = current->next_entry) + previous = current, current = current->next) /* store previous value for later use */ { } /* The possibilities: * 1 nothing NULL: new_entry goes between previous and current - * 2 previous NULL, but current non-null : new_entry goes at the start of the - * selections list - * 3 current NULL, previous non-NULL : new_entry goes at the end of the - * selections list - * 4 both NULL: selections list is empty + * 2 previous NULL, but current non-null : new_entry goes at the start of + * the list + * 3 current NULL, previous non-NULL : new_entry goes at the end of the list + * 4 both NULL: selections list is empty, case already caught above */ if (previous) /* case 1 or 3 */ { if (current) /* case 1 : goes in middle of list */ { - previous->next_entry = new_entry; - new_entry->next_entry = current; + previous->next = new_entry; + new_entry->next = current; } else /* case 3 : goes at end of list */ { - previous->next_entry = new_entry; - new_entry->next_entry = NULL; + previous->next = new_entry; + new_entry->next = NULL; } } else /* case 2 or 4 */ { - if (current) /* case 2 : goes at start of list*/ + if (current) /* case 2 : goes at start of list */ { - selections_list = new_entry; - new_entry->next_entry = current; - } else /* case 4 : starts list */ - { -#ifdef DEBUG - printf("Boundary_SelectVarForBCI: starting new selections list\n"); -#endif - new_entry->next_entry = NULL; - selections_list = new_entry; - } - } - - /* If new bcdata entry, update current_bcdata->start as promised above */ - if (current_bcdata && !current_bcdata->start) - { - current_bcdata->start = new_entry; + current_bcdata->var_list = new_entry; + new_entry->next = current; + } /* case 4 : starts list, this case has already been handled above */ } #ifdef DEBUG + print_selections_database(); printf("\n"); #endif return retval; @@ -665,6 +660,10 @@ CCTK_INT Bdry_Boundary_SelectGroupForBCI(CCTK_POINTER GH, "Invalid variable index"); retval = -7; } + +#ifdef DEBUG + printf("Boundary_SelectGroupForBCI: group %s has %d vars\n", CCTK_GroupName(group_index), num_vars); +#endif /* loop over variables in group */ vi = CCTK_FirstVarIndexI(group_index); @@ -745,104 +744,53 @@ CCTK_INT Bdry_Boundary_SelectedGVs(CCTK_POINTER GH, GH = GH; #ifdef DEBUG - printf("Boundary_SelectedGVs: called with bc_name=\"%s\" array_size=%d\n", bc_name, array_size); + printf("Boundary_SelectedGVs: called with bc_name=\"%s\" array_size=%d\n", + bc_name, array_size); #endif - /* Step through bcdata list to find starting point, and to compute return - value */ + /* Step through bcdata list */ for (current_bcdata = bcdata_list; current_bcdata; current_bcdata = current_bcdata->next) { - #ifdef DEBUG - printf("Boundary_SelectedGVs: looping through bcdata list\n" - " current_bcdata->bc_name=\"%s\"\n", - current_bcdata->bc_name); + printf(" looping through bcdata list, at bcdata entry for %s bc\n", current_bcdata->bc_name); #endif if (!bc_name || CCTK_Equals(current_bcdata->bc_name,bc_name)) { -#ifdef DEBUG - printf("Boundary_SelectedGVs: strings match, using this start value\n"); -#endif - /* If bc_name matches, use this entry to set current */ - current = current_bcdata->start; + + /* Add these selected vars to return value */ retval += current_bcdata->num; - if (bc_name) + current = current_bcdata->var_list; + + /* Loop through var list */ + for (i=0; /* i indexes the location in the returned arrays */ + i<array_size && current; + current = current->next, ++i) { - /* No more needs be added to retval if a specific bc_name has - been requested. */ - break; - } - } - } - /* Do we want to return an error code if an 'invalid' bc_name is used? - * if (!current) - * { - * CCTK_VWarn(2, __LINE__, __FILE__, CCTK_THORNSTRING, - * "No variables are marked for boundary condition %s", bc_name); - * retval = -1; - * } - */ - if (!bc_name) - { - /* If bc_name is NULL then start from the beginning */ - current = selections_list; - } #ifdef DEBUG - printf("Boundary_SelectedGVs: initializing current to %p\n", current); -#endif - /* If current is still NULL, bc_name did not match any entry in the - * bcdata list, i.e. no variables were selected for this bc. - * - * If array_size is zero, then just exit immediately, because there - * is nothing more to do. - */ - if (current && array_size) - { - /* loop through selections list, grabbing entries with bc_name, or - * all if bc_name==NULL - * - * could save a string comparison at each iteration if we also - * stored bcdata->end - */ - for (i=0; /* i indexes the location in the returned arrays, - and is incremented after use */ - current; - current = current->next_entry) - { -#ifdef DEBUG - printf("Boundary_SelectedGVs: looping through selected vars, at current->var_index = %d\n",current->var_index); - printf(" current->next_entry is %p\n",current->next_entry); + printf(" looping through selected vars, at current->var_index = " + "%d\n",current->var); + printf(" current->next is %p\n",current->next); #endif - if (!bc_name || CCTK_Equals(current->bc_name, bc_name)) - { - if (i < array_size) - { - ((int *) faces)[i] = current->faces; - ((int *) table_handles)[i] = current->table; - ((int *) var_indices)[i] = current->var_index; - } - ++i; - } else - { - if (i==0) - { - printf("Boundary_SelectedGVs: Internal error: I am " - "past the relevant section of the selections list, yet no " - "vars have been 'selected'.\n"); - } - - /* can stop looking if we are past the relevant section of the - list */ - break; + ((int *) faces)[i] = current->faces; + ((int *) table_handles)[i] = current->table; + ((int *) var_indices)[i] = current->var; } } } + /* Do we want to return an error code if an 'invalid' bc_name is used? */ + if (!current) + { + CCTK_VWarn(2, __LINE__, __FILE__, CCTK_THORNSTRING, + "No variables are marked for boundary condition %s", bc_name); + /*retval = -1;*/ + } + return retval; } @@ -889,23 +837,24 @@ void Boundary_ApplyPhysicalBCs(CCTK_ARGUMENTS) current_bcdata = current_bcdata->next) { #ifdef DEBUG - printf("Boundary_ApplyPhysicalBCs: current_bcdata %p holds: next=%p " - "bc_name=%s start=%p num=%d\n", - current_bcdata, current_bcdata->next, current_bcdata->bc_name, - current_bcdata->start, current_bcdata->num); + printf("Boundary_ApplyPhysicalBCs: looping through bcdata list, at bcdata entry for %s bc\n", current_bcdata->bc_name); + printf(" max_num_vars is %d\n", max_num_vars); #endif - /* Allocate memory to hold selected bcs */ + /* Allocate memory to hold selected vars */ num_vars = current_bcdata->num; +#ifdef DEBUG + printf(" num_vars is %d\n", num_vars); +#endif if (num_vars > max_num_vars) { max_num_vars = num_vars; /* store new maximum */ if (vars) { /* reallocate arrays if necessary */ - realloc(vars, num_vars*sizeof(int)); - realloc(faces, num_vars*sizeof(int)); - realloc(tables, num_vars*sizeof(int)); + vars = (int *) realloc(vars, num_vars*sizeof(int)); + faces = (int *) realloc(faces, num_vars*sizeof(int)); + tables = (int *) realloc(tables, num_vars*sizeof(int)); } else { vars = (int *) malloc(num_vars*sizeof(int)); @@ -914,8 +863,8 @@ void Boundary_ApplyPhysicalBCs(CCTK_ARGUMENTS) } } - /* get selected vars for this bc_name*/ - err = Bdry_Boundary_SelectedGVs(cctkGH, num_vars, vars, faces, tables, + /* get selected vars for this bc_name */ + err = Bdry_Boundary_SelectedGVs(cctkGH, num_vars, vars, faces, tables, current_bcdata->bc_name); if (err<0) /* This is a redundant test for now, Bdry_Boundary_SelectedGVs never returns <0 */ @@ -985,33 +934,29 @@ void Boundary_ApplyPhysicalBCs(CCTK_ARGUMENTS) void Boundary_ClearSelection(void) { struct BCVAR *current, *next; - struct BCDATA *current_bcdata, *next_bcdata; - - /* Free selections list */ - next = selections_list; - for (current = selections_list; next; current = next) - { - next = current->next_entry; - free(current->bc_name); - free(current); - } - selections_list = NULL; + struct BCDATA *current_bcdata; - /* Free bcdata list */ + /* Step through bcdata list */ #ifdef DEBUG printf("Boundary_ClearSelection: looping through bcdata list for freeing\n"); #endif - next_bcdata = bcdata_list; /* simply so that it will be non-NULL */ - for (current_bcdata = bcdata_list; next_bcdata; current_bcdata = next_bcdata) + for (current_bcdata = bcdata_list; current_bcdata; + current_bcdata = current_bcdata->next) { - next_bcdata = current_bcdata->next; - /* free(current_bcdata->bc_name); Must one free this? */ #ifdef DEBUG printf("Boundary_ClearSelection: freeing %p\n",current_bcdata); #endif - free(current_bcdata); + + /* Free selections list */ + current = next = current_bcdata->var_list; + for (; current; current = next) + { + next = current->next; + free(current); + } + + current_bcdata->var_list = NULL; } - bcdata_list = NULL; } /******************************************************************** @@ -1019,11 +964,12 @@ void Boundary_ClearSelection(void) ********************************************************************/ /*@@ - @routine entry_less_than + @routine entry_greater_than @date Sun Nov 3 19:51:37 CET 2002 @author David Rideout @desc - Sorts entries in selections list + Sorts entries in selections list. + Returns non-zero value if new > current. @enddesc @calls @history @@ -1041,47 +987,71 @@ void Boundary_ClearSelection(void) @returntype CCTK_INT @returndesc -1 new equals current - 0 new 'greater than' current - 1 new 'less than' current - 2 new and current have same bc_name, but new has smaller table - handle - 3 new and current have same bc_name and table handle, but new - has smaller variable index + 0 new 'less than' current + 1 new->table_handle > current->table_handle + 2 new and current have same table_handle, but new has greater + var_index @endreturndesc @@*/ -static int entry_less_than(struct BCVAR *new, struct BCVAR *current) +static int entry_greater_than(struct BCVAR *new, struct BCVAR *current) { int retval; /* can assume both arguments are valid (non-null) */ - /* Perhaps this can be done more intelligently... */ - retval = Util_StrCmpi(new->bc_name, current->bc_name); - if (retval < 0) + if (new->table > current->table) { - retval = 1; /* new < current */ - } else if (retval>0) - { - retval = 0; + retval = 1; } else if (new->table < current->table) { - retval = 2; - } else if (new->table > current->table) - { retval = 0; - } else if (new->var_index < current->var_index) + } else if (new->var > current->var) { - retval = 3; - } else if (new->var_index > current->var_index) + retval = 2; + } else if (new->var < current->var) { retval = 0; } else { CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING, - "Duplicate entry %s marked for boundary condition %s, " - "with table handle %d\n", CCTK_VarName(new->var_index), - new->bc_name, new->table); + "%s has already been selected for an alternate boundary " + "condition", CCTK_VarName(new->var)); retval = -1; } return retval; } + + /*@@ + @routine print_selections_database + @date 13 March 2003 + @author David Rideout + @desc + Prints selected variables database, for debugging only + @enddesc + @calls + @history + @endhistory +@@*/ + +#ifdef DEBUG + +static void print_selections_database(void) +{ + struct BCDATA *current_bcdata; + struct BCVAR *current; + + printf("Current list of selected vars:\n"); + printf(" bc name vi var name table handle\n"); + for (current_bcdata = bcdata_list; current_bcdata; + current_bcdata = current_bcdata->next) + { + for (current = current_bcdata->var_list; current; + current = current->next) + { + printf("%9s %2d %12s %2d\n", current_bcdata->bc_name, current->var, + CCTK_VarName(current->var), current->table); + } + } +} + +#endif |