Beispiel #1
0
static void
write_cdata(char *opath)
{
    FILE *out;
	ac_uint4 bytes;
    ac_uint4 i, idx, nprops;
#if !(HARDCODE_DATA)
    ac_uint2 casecnt[2];
#endif
    char path[BUFSIZ];
#if HARDCODE_DATA
    int j, k;

    /*****************************************************************
     *
     * Generate the ctype data.
     *
     *****************************************************************/

    /*
     * Open the output file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "uctable.h", opath);
    if ((out = fopen(path, "w")) == 0)
      return;
#else
    /*
     * Open the ctype.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;
#endif

    /*
     * Collect the offsets for the properties.  The offsets array is
     * on a 4-byte boundary to keep things efficient for architectures
     * that need such a thing.
     */
    for (i = idx = 0; i < NUMPROPS; i++) {
        propcnt[i] = (proptbl[i].used != 0) ? idx : 0xffff;
        idx += proptbl[i].used;
    }

    /*
     * Add the sentinel index which is used by the binary search as the upper
     * bound for a search.
     */
    propcnt[i] = idx;

    /*
     * Record the actual number of property lists.  This may be different than
     * the number of offsets actually written because of aligning on a 4-byte
     * boundary.
     */
    hdr[1] = NUMPROPS;

    /*
     * Calculate the byte count needed and pad the property counts array to a
     * 4-byte boundary.
     */
    if ((bytes = sizeof(ac_uint2) * (NUMPROPS + 1)) & 3)
      bytes += 4 - (bytes & 3);
    nprops = bytes / sizeof(ac_uint2);
    bytes += sizeof(ac_uint4) * idx;

#if HARDCODE_DATA
    fprintf(out,
        "/* This file was generated from a modified version UCData's ucgendat.\n"
        " *\n"
        " *                     DO NOT EDIT THIS FILE!\n"
        " * \n"
        " * Instead, compile ucgendat.c (bundled with PHP in ext/mbstring), download\n"
        " * the appropriate UnicodeData-x.x.x.txt and CompositionExclusions-x.x.x.txt\n"
        " * files from  http://www.unicode.org/Public/ and run this program.\n"
        " *\n"
        " * More information can be found in the UCData package. Unfortunately,\n"
        " * the project's page doesn't seem to be live anymore, so you can use\n"
        " * OpenLDAPs modified copy (look in libraries/liblunicode/ucdata) */\n\n");

    fprintf(out, PREF "unsigned short _ucprop_size = %d;\n\n", NUMPROPS);

    fprintf(out, PREF "unsigned short  _ucprop_offsets[] = {");

    for (i = 0; i<nprops; i++) {
       if (i) fprintf(out, ",");
       if (!(i&7)) fprintf(out, "\n\t");
       else fprintf(out, " ");
       fprintf(out, "0x%04x", propcnt[i]);
    }
    fprintf(out, "\n};\n\n");

    fprintf(out, PREF "unsigned int _ucprop_ranges[] = {");

    k = 0;
    for (i = 0; i < NUMPROPS; i++) {
	if (proptbl[i].used > 0) {
	  for (j=0; j<proptbl[i].used; j++) {
	    if (k) fprintf(out, ",");
	    if (!(k&3)) fprintf(out,"\n\t");
	    else fprintf(out, " ");
	    k++;
	    fprintf(out, "0x%08lx", (unsigned long) proptbl[i].ranges[j]);
	  }
	}
    }
    fprintf(out, "\n};\n\n");
#else
    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write the byte count.
     */
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

    /*
     * Write the property list counts.
     */
    fwrite((char *) propcnt, sizeof(ac_uint2), nprops, out);

    /*
     * Write the property lists.
     */
    for (i = 0; i < NUMPROPS; i++) {
        if (proptbl[i].used > 0)
          fwrite((char *) proptbl[i].ranges, sizeof(ac_uint4),
                 proptbl[i].used, out);
    }

    fclose(out);
#endif

    /*****************************************************************
     *
     * Generate the case mapping data.
     *
     *****************************************************************/

#if HARDCODE_DATA
    fprintf(out, PREF "unsigned int _uccase_size = %ld;\n\n",
        (long) (upper_used + lower_used + title_used));

    fprintf(out,
        "/* Starting indexes of the case tables\n"
        " * UpperIndex = 0\n"
        " * LowerIndex = _uccase_len[0]\n"
        " * TitleIndex = LowerIndex + _uccase_len[1] */\n\n");
    fprintf(out, PREF "unsigned short _uccase_len[2] = {%ld, %ld};\n\n",
        (long) upper_used * 3, (long) lower_used * 3);
    fprintf(out, PREF "unsigned int _uccase_map[] = {");

    if (upper_used > 0)
      /*
       * Write the upper case table.
       */
      write_case(out, upper, upper_used, 1);

    if (lower_used > 0)
      /*
       * Write the lower case table.
       */
      write_case(out, lower, lower_used, !upper_used);

    if (title_used > 0)
      /*
       * Write the title case table.
       */
      write_case(out, title, title_used, !(upper_used||lower_used));

    if (!(upper_used || lower_used || title_used))
	fprintf(out, "\t0");

    fprintf(out, "\n};\n\n");
#else
    /*
     * Open the case.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;

    /*
     * Write the case mapping tables.
     */
    hdr[1] = upper_used + lower_used + title_used;
    casecnt[0] = upper_used;
    casecnt[1] = lower_used;

    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write the upper and lower case table sizes.
     */
    fwrite((char *) casecnt, sizeof(ac_uint2), 2, out);

    if (upper_used > 0)
      /*
       * Write the upper case table.
       */
      fwrite((char *) upper, sizeof(_case_t), upper_used, out);

    if (lower_used > 0)
      /*
       * Write the lower case table.
       */
      fwrite((char *) lower, sizeof(_case_t), lower_used, out);

    if (title_used > 0)
      /*
       * Write the title case table.
       */
      fwrite((char *) title, sizeof(_case_t), title_used, out);

    fclose(out);
#endif

#if 0

    /*****************************************************************
     *
     * Generate the composition data.
     *
     *****************************************************************/
    
    /*
     * Create compositions from decomposition data
     */
    create_comps();
    
#if HARDCODE_DATA
    fprintf(out, PREF "ac_uint4 _uccomp_size = %ld;\n\n",
        comps_used * 4L);

    fprintf(out, PREF "ac_uint4 _uccomp_data[] = {");

     /*
      * Now, if comps exist, write them out.
      */
    if (comps_used > 0) {
	for (i=0; i<comps_used; i++) {
	    if (i) fprintf(out, ",");
	    fprintf(out, "\n\t0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx",
	        (unsigned long) comps[i].comp, (unsigned long) comps[i].count,
	        (unsigned long) comps[i].code1, (unsigned long) comps[i].code2);
	}
    } else {
	fprintf(out, "\t0");
    }
    fprintf(out, "\n};\n\n");
#else
    /*
     * Open the comp.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
	return;
    
    /*
     * Write the header.
     */
    hdr[1] = (ac_uint2) comps_used * 4;
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
    
    /*
     * Write out the byte count to maintain header size.
     */
    bytes = comps_used * sizeof(_comp_t);
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
    
    /*
     * Now, if comps exist, write them out.
     */
    if (comps_used > 0)
        fwrite((char *) comps, sizeof(_comp_t), comps_used, out);
    
    fclose(out);
#endif
    
    /*****************************************************************
     *
     * Generate the decomposition data.
     *
     *****************************************************************/

    /*
     * Fully expand all decompositions before generating the output file.
     */
    expand_decomp();

#if HARDCODE_DATA
    fprintf(out, PREF "ac_uint4 _ucdcmp_size = %ld;\n\n",
        decomps_used * 2L);

    fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {");

    if (decomps_used) {
	/*
	 * Write the list of decomp nodes.
	 */
	for (i = idx = 0; i < decomps_used; i++) {
	    fprintf(out, "\n\t0x%08lx, 0x%08lx,",
	        (unsigned long) decomps[i].code, (unsigned long) idx);
	    idx += decomps[i].used;
	}

	/*
	 * Write the sentinel index as the last decomp node.
	 */
	fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);

	fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {");
	/*
	 * Write the decompositions themselves.
	 */
	k = 0;
	for (i = 0; i < decomps_used; i++)
	  for (j=0; j<decomps[i].used; j++) {
	    if (k) fprintf(out, ",");
	    if (!(k&3)) fprintf(out,"\n\t");
	    else fprintf(out, " ");
	    k++;
	    fprintf(out, "0x%08lx", (unsigned long) decomps[i].decomp[j]);
	  }
	fprintf(out, "\n};\n\n");
    }
#else
    /*
     * Open the decomp.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;

    hdr[1] = decomps_used;

    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write a temporary byte count which will be calculated as the
     * decompositions are written out.
     */
    bytes = 0;
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

    if (decomps_used) {
        /*
         * Write the list of decomp nodes.
         */
        for (i = idx = 0; i < decomps_used; i++) {
            fwrite((char *) &decomps[i].code, sizeof(ac_uint4), 1, out);
            fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
            idx += decomps[i].used;
        }

        /*
         * Write the sentinel index as the last decomp node.
         */
        fwrite((char *) &idx, sizeof(ac_uint4), 1, out);

        /*
         * Write the decompositions themselves.
         */
        for (i = 0; i < decomps_used; i++)
          fwrite((char *) decomps[i].decomp, sizeof(ac_uint4),
                 decomps[i].used, out);

        /*
         * Seek back to the beginning and write the byte count.
         */
        bytes = (sizeof(ac_uint4) * idx) +
            (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
        fseek(out, sizeof(ac_uint2) << 1, 0L);
        fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

        fclose(out);
    }
#endif

#ifdef HARDCODE_DATA
    fprintf(out, PREF "ac_uint4 _uckdcmp_size = %ld;\n\n",
        kdecomps_used * 2L);

    fprintf(out, PREF "ac_uint4 _uckdcmp_nodes[] = {");

    if (kdecomps_used) {
	/*
	 * Write the list of kdecomp nodes.
	 */
	for (i = idx = 0; i < kdecomps_used; i++) {
	    fprintf(out, "\n\t0x%08lx, 0x%08lx,",
	        (unsigned long) kdecomps[i].code, (unsigned long) idx);
	    idx += kdecomps[i].used;
	}

	/*
	 * Write the sentinel index as the last decomp node.
	 */
	fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);

	fprintf(out, PREF "ac_uint4 _uckdcmp_decomp[] = {");

	/*
	 * Write the decompositions themselves.
	 */
	k = 0;
	for (i = 0; i < kdecomps_used; i++)
	  for (j=0; j<kdecomps[i].used; j++) {
	    if (k) fprintf(out, ",");
	    if (!(k&3)) fprintf(out,"\n\t");
	    else fprintf(out, " ");
	    k++;
	    fprintf(out, "0x%08lx", (unsigned long) kdecomps[i].decomp[j]);
	  }
	fprintf(out, "\n};\n\n");
    }
#else
    /*
     * Open the kdecomp.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;

    hdr[1] = kdecomps_used;

    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write a temporary byte count which will be calculated as the
     * decompositions are written out.
     */
    bytes = 0;
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

    if (kdecomps_used) {
        /*
         * Write the list of kdecomp nodes.
         */
        for (i = idx = 0; i < kdecomps_used; i++) {
            fwrite((char *) &kdecomps[i].code, sizeof(ac_uint4), 1, out);
            fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
            idx += kdecomps[i].used;
        }

        /*
         * Write the sentinel index as the last decomp node.
         */
        fwrite((char *) &idx, sizeof(ac_uint4), 1, out);

        /*
         * Write the decompositions themselves.
         */
        for (i = 0; i < kdecomps_used; i++)
          fwrite((char *) kdecomps[i].decomp, sizeof(ac_uint4),
                 kdecomps[i].used, out);

        /*
         * Seek back to the beginning and write the byte count.
         */
        bytes = (sizeof(ac_uint4) * idx) +
            (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
        fseek(out, sizeof(ac_uint2) << 1, 0L);
        fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

        fclose(out);
    }
#endif

    /*****************************************************************
     *
     * Generate the combining class data.
     *
     *****************************************************************/
#ifdef HARDCODE_DATA
    fprintf(out, PREF "ac_uint4 _uccmcl_size = %ld;\n\n", (long) ccl_used);

    fprintf(out, PREF "ac_uint4 _uccmcl_nodes[] = {");

    if (ccl_used > 0) {
	/*
	 * Write the combining class ranges out.
	 */
	for (i = 0; i<ccl_used; i++) {
	    if (i) fprintf(out, ",");
	    if (!(i&3)) fprintf(out, "\n\t");
	    else fprintf(out, " ");
	    fprintf(out, "0x%08lx", (unsigned long) ccl[i]);
	}
    } else {
	fprintf(out, "\t0");
    }
    fprintf(out, "\n};\n\n");
#else
    /*
     * Open the cmbcl.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;

    /*
     * Set the number of ranges used.  Each range has a combining class which
     * means each entry is a 3-tuple.
     */
    hdr[1] = ccl_used / 3;

    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write out the byte count to maintain header size.
     */
    bytes = ccl_used * sizeof(ac_uint4);
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

    if (ccl_used > 0)
      /*
       * Write the combining class ranges out.
       */
      fwrite((char *) ccl, sizeof(ac_uint4), ccl_used, out);

    fclose(out);
#endif

    /*****************************************************************
     *
     * Generate the number data.
     *
     *****************************************************************/

#if HARDCODE_DATA
    fprintf(out, PREF "ac_uint4 _ucnum_size = %lu;\n\n",
        (unsigned long)ncodes_used<<1);

    fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {");

    /*
     * Now, if number mappings exist, write them out.
     */
    if (ncodes_used > 0) {
	for (i = 0; i<ncodes_used; i++) {
	    if (i) fprintf(out, ",");
	    if (!(i&1)) fprintf(out, "\n\t");
	    else fprintf(out, " ");
	    fprintf(out, "0x%08lx, 0x%08lx",
	        (unsigned long) ncodes[i].code, (unsigned long) ncodes[i].idx);
	}
	fprintf(out, "\n};\n\n");

	fprintf(out, PREF "short _ucnum_vals[] = {");
	for (i = 0; i<nums_used; i++) {
	    if (i) fprintf(out, ",");
	    if (!(i&3)) fprintf(out, "\n\t");
	    else fprintf(out, " ");
	    if (nums[i].numerator < 0) {
		fprintf(out, "%6d, 0x%04x",
		  nums[i].numerator, nums[i].denominator);
	    } else {
		fprintf(out, "0x%04x, 0x%04x",
		  nums[i].numerator, nums[i].denominator);
	    }
	}
	fprintf(out, "\n};\n\n");
    }
#else
    /*
     * Open the num.dat file.
     */
    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath);
    if ((out = fopen(path, "wb")) == 0)
      return;

    /*
     * The count part of the header will be the total number of codes that
     * have numbers.
     */
    hdr[1] = (ac_uint2) (ncodes_used << 1);
    bytes = (ncodes_used * sizeof(_codeidx_t)) + (nums_used * sizeof(_num_t));

    /*
     * Write the header.
     */
    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);

    /*
     * Write out the byte count to maintain header size.
     */
    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);

    /*
     * Now, if number mappings exist, write them out.
     */
    if (ncodes_used > 0) {
        fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out);
        fwrite((char *) nums, sizeof(_num_t), nums_used, out);
    }
#endif

#endif

    fclose(out);
}
Beispiel #2
0
int main(int argc, char *argv[])
{
	exit_if_false(argc == 2,"exactly one input argument required");

	timer_start();

	//-------------------------------------------------------------------//
	
	// counters
	int i, n;

	// file paths
	char *input_file_path, *geometry_file_path, *case_file_path, *data_file_path, *data_numbered_file_path, *display_file_path, *display_numbered_file_path;
	exit_if_false(geometry_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating geometry file path");
	exit_if_false(case_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating case file path");
	exit_if_false(data_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating data file path");
	exit_if_false(data_numbered_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating data numbered file path");
	exit_if_false(display_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating display file path");
	exit_if_false(display_numbered_file_path = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating display numbered file path");

	// print string
	char *print;
	exit_if_false(print = (char *)malloc(MAX_STRING_LENGTH * sizeof(char)),"allocating the print string");

	// mesh structures
	int n_nodes, n_faces, n_elements, n_boundaries_old = 0, n_boundaries, n_terms;
	struct NODE *node;
	struct FACE *face;
	struct ELEMENT *element;
	struct BOUNDARY *boundary_old = NULL, *boundary;
	struct TERM *term;
	EXPRESSION *initial = NULL;
	
	// solution vectors
	int n_u_old = 0, n_u;
	double *u_old = NULL, *u;

	// files
	FILE *input_file, *case_file, *data_file, *geometry_file, *display_file;

	//-------------------------------------------------------------------//

	// opening the input file
	print_info("opening the input file %s",argv[1]);
	input_file_path = argv[1];
	input_file = fopen(input_file_path,"r");
	exit_if_false(input_file != NULL,"opening %s",input_file_path);

	// reading the case file path
	print_info("reading the case file path");
	exit_if_false(fetch_value(input_file,"case_file_path",'s',case_file_path) == FETCH_SUCCESS,"reading case_file_path from %s",input_file_path);
	print_continue(case_file_path);

	// reading the number of variables, variable names and orders
	print_info("reading the variables");
	int n_variables_old = 0, n_variables;
	exit_if_false(fetch_value(input_file,"number_of_variables",'i',&n_variables) == FETCH_SUCCESS,"reading number_of_variables from %s",input_file_path);
	int *variable_order_old = NULL, *variable_order = (int *)malloc(n_variables * sizeof(int));
	exit_if_false(variable_order != NULL,"allocating orders");
	exit_if_false(fetch_vector(input_file, "variable_order", 'i', n_variables, variable_order) == FETCH_SUCCESS,"reading variable_order from %s",input_file_path);
	char **variable_name = allocate_character_matrix(NULL,n_variables,MAX_STRING_LENGTH);
	exit_if_false(variable_name != NULL,"allocating variable names");
	warn_if_false(fetch_vector(input_file,"variable_name",'s',n_variables,variable_name) == FETCH_SUCCESS,"reading variable_name from %s",input_file_path);
	for(i = 0; i < n_variables; i ++) print_continue("%s order %i",variable_name[i],variable_order[i]);

	// reading the number of inner and outer iterations to perform
	print_info("reading the numbers of iterations");
	int outer_iteration = 0, inner_iteration;
	int n_outer_iterations, n_inner_iterations, data_n_outer_iterations, display_n_outer_iterations;
	exit_if_false(fetch_value(input_file,"number_of_inner_iterations",'i',&n_inner_iterations) == FETCH_SUCCESS,"reading number_of_inner_iterations from %s",input_file_path);
	exit_if_false(fetch_value(input_file,"number_of_outer_iterations",'i',&n_outer_iterations) == FETCH_SUCCESS,"reading number_of_outer_iterations from %s",input_file_path);
	print_continue("%i outer of %i inner iterations to be done",n_outer_iterations,n_inner_iterations);

	// read existing case and data
	case_file = fopen(case_file_path,"r");
	if(case_file != NULL)
	{
		print_info("reading existing case file %s",case_file_path);
		read_case(case_file, &n_variables_old, &variable_order_old, &n_nodes, &node, &n_faces, &face, &n_elements, &element, &n_boundaries_old, &boundary_old);
		fclose(case_file);
		n = 0; for(i = 0; i < n_variables; i ++) n += n_elements*ORDER_TO_N_BASIS(variable_order[i]);

		if(fetch_value(input_file,"initial_data_file_path",'s',data_file_path) == FETCH_SUCCESS)
		{
			print_info("reading existing data file %s",data_file_path);
			exit_if_false(data_file = fopen(data_file_path,"r"),"opening %s",data_file_path);
			read_data(data_file, &n_u_old, &u_old, &outer_iteration);
			fclose(data_file);
			exit_if_false(n_u_old == n,"case and initial data does not match");
		}
	}

	// construct new case
	else
	{
		print_info("reading the geometry file path");
		exit_if_false(fetch_value(input_file,"geometry_file_path",'s',geometry_file_path) == FETCH_SUCCESS,"reading geometry_file_path from %s",input_file_path);
		print_continue(geometry_file_path);

		print_info("reading the geometry file %s",geometry_file_path);
		exit_if_false(geometry_file = fopen(geometry_file_path,"r"),"opening %s",geometry_file_path);
		read_geometry(geometry_file, &n_nodes, &node, &n_faces, &face, &n_elements, &element);
		fclose(geometry_file);
		print_continue("%i nodes, %i faces and %i elements",n_nodes,n_faces,n_elements);

		print_info("generating additional connectivity and geometry");
		process_geometry(n_nodes, node, n_faces, face, n_elements, element);
	}

	// read the data file path and output frequency
	print_info("reading the data file path and output frequency");
	exit_if_false(fetch_value(input_file,"data_file_path",'s',data_file_path) == FETCH_SUCCESS,"reading data_file_path from %s",input_file_path);
	if(fetch_value(input_file,"data_number_of_outer_iterations",'i',&data_n_outer_iterations) != FETCH_SUCCESS)
		data_n_outer_iterations = n_outer_iterations + outer_iteration;
	print_continue("data to be written to %s every %i outer iterations",data_file_path,data_n_outer_iterations);

	// read boundaries
	print_info("reading boundaries");
	boundaries_input(input_file, n_faces, face, &n_boundaries, &boundary);
	print_continue("%i boundaries",n_boundaries);

	// read terms
	print_info("reading PDE terms");
	terms_input(input_file, &n_terms, &term);
	print_continue("%i terms",n_terms);

	// update unknown indices and values
	print_info("updating the numbering of the degrees of freedom");
	update_element_unknowns(n_variables_old, n_variables, variable_order_old, variable_order, n_elements, element, n_u_old, &n_u, u_old, &u);
	print_continue("%i degrees of freedom",n_u);

	// update face boundaries
	print_info("updating the face boundary associations");
	update_face_boundaries(n_variables, n_faces, face, n_boundaries, boundary);

	// update integration
	print_info("updating integration");
	i = update_face_integration(n_variables_old, n_variables, variable_order_old, variable_order, n_faces, face);
	if(i) print_continue("updated %i face quadratures",i);
	i = update_element_integration(n_variables_old, n_variables, variable_order_old, variable_order, n_elements, element);
	if(i) print_continue("updated %i element quadratures",i);

	// update numerics
	print_info("updating numerics");
	i = update_face_numerics(n_variables_old, n_variables, variable_order_old, variable_order, n_faces, face, n_boundaries_old, boundary_old);
	if(i) print_continue("updated %i face interpolations",i);
	i = update_element_numerics(n_variables_old, n_variables, variable_order_old, variable_order, n_elements, element);
	if(i) print_continue("updated %i element interpolations",i);

	// write case file
	print_info("writing case file %s",case_file_path);
	exit_if_false(case_file = fopen(case_file_path,"w"),"opening %s",case_file_path);
	write_case(case_file, n_variables, variable_order, n_nodes, node, n_faces, face, n_elements, element, n_boundaries, boundary);
	fclose(case_file);

	// read the display file path and output frequency
	print_info("reading the display file path and output frequency");
	if(
			fetch_value(input_file,"display_file_path",'s',display_file_path) == FETCH_SUCCESS &&
			fetch_value(input_file,"display_number_of_outer_iterations",'i',&display_n_outer_iterations) == FETCH_SUCCESS
	  )
		print_continue("display to be written to %s every %i outer iterations",display_file_path,display_n_outer_iterations);
	else
	{
		display_n_outer_iterations = 0;
		warn_if_false(0,"display files will not be written");
	}

	// initialise
	if(initial_input(input_file, n_variables, &initial))
	{
		print_info("initialising the degrees of freedom");
		initialise_values(n_variables, variable_order, n_elements, element, initial, u);
	}

	//-------------------------------------------------------------------//
	
	// allocate and initialise the system
	print_info("allocating and initialising the system");
	SPARSE system = NULL;
	initialise_system(n_variables, variable_order, n_elements, element, n_u, &system);
	double *residual, *max_residual, *du, *max_du;
	exit_if_false(residual = (double *)malloc(n_u * sizeof(double)),"allocating the residuals");
	exit_if_false(max_residual = (double *)malloc(n_variables * sizeof(double)),"allocating the maximum residuals");
	exit_if_false(du = (double *)malloc(n_u * sizeof(double)),"allocating du");
	exit_if_false(max_du = (double *)malloc(n_variables * sizeof(double)),"allocating the maximum changes");
	exit_if_false(u_old = (double *)realloc(u_old, n_u * sizeof(double)),"re-allocating u_old");

	timer_reset();

	// iterate
	print_info("iterating");
	n_outer_iterations += outer_iteration;
	for(; outer_iteration < n_outer_iterations; outer_iteration ++)
	{
		print_output("iteration %i", outer_iteration);

		for(i = 0; i < n_u; i ++) u_old[i] = u[i];

		for(inner_iteration = 0; inner_iteration < n_inner_iterations; inner_iteration ++)
		{
			calculate_system(n_variables, variable_order, n_faces, face, n_elements, element, n_terms, term, n_u, u_old, u, system, residual);

			exit_if_false(sparse_solve(system, du, residual) == SPARSE_SUCCESS,"solving system");
			for(i = 0; i < n_u; i ++) u[i] -= du[i];

			calculate_maximum_changes_and_residuals(n_variables, variable_order, n_elements, element, du, max_du, residual, max_residual);
			for(i = 0; i < n_variables; i ++) sprintf(&print[26*i],"%.6e|%.6e ",max_du[i],max_residual[i]);
			print_continue("%s",print);
		}

		slope_limit(n_variables, variable_order, n_nodes, node, n_elements, element, n_boundaries, boundary, u);

		if(data_n_outer_iterations && outer_iteration % data_n_outer_iterations == 0)
		{
			generate_numbered_file_path(data_numbered_file_path, data_file_path, outer_iteration);
			print_info("writing data to %s",data_numbered_file_path);
			exit_if_false(data_file = fopen(data_numbered_file_path,"w"),"opening %s",data_numbered_file_path);
			write_data(data_file, n_u, u, outer_iteration);
			fclose(data_file);
		}

		if(display_n_outer_iterations && outer_iteration % display_n_outer_iterations == 0)
		{
			generate_numbered_file_path(display_numbered_file_path, display_file_path, outer_iteration);
			print_info("writing display to %s",data_numbered_file_path);
			exit_if_false(display_file = fopen(display_numbered_file_path,"w"),"opening %s",display_numbered_file_path);
			write_display(display_file, n_variables, variable_name, variable_order, n_elements, element, n_u, u);
			fclose(display_file);
		}

		timer_print();
	}

	//-------------------------------------------------------------------//
	
	print_info("freeing all memory");

	fclose(input_file);

	free(geometry_file_path);
	free(case_file_path);
	free(data_file_path);
	free(data_numbered_file_path);
	free(display_file_path);
	free(display_numbered_file_path);

	free(print);

	destroy_nodes(n_nodes,node);
	destroy_faces(n_faces,face,n_variables);
	destroy_elements(n_elements,element,n_variables);
	destroy_boundaries(n_boundaries_old,boundary_old);
	destroy_boundaries(n_boundaries,boundary);
	destroy_terms(n_terms,term);
	destroy_initial(n_variables,initial);

	free(variable_order_old);
	free(variable_order);
	destroy_matrix((void *)variable_name);

	free(u_old);
	free(u);

	sparse_destroy(system);
	free(residual);
	free(max_residual);
	free(du);
	free(max_du);

	return 0;
}