/*
OpenTHFD Version 4.0.2 (CPU + OpenMP)

solver
*/

#define MAIN
#include "oth.h"
#undef MAIN

#include "oth_prototype.h"

static void args(int, char *[], int *, int *, char []);
static void error_check(int, int);

int main(int argc, char *argv[])
{
	const char prog[] = "(CPU+OpenMP)";
	const char errfmt[] = "*** file %s open error.\n";
	char str[BUFSIZ];
	int ierr = 0;
	double cpu[] = {0, 0, 0, 0};
	FILE *fp_in = NULL, *fp_out = NULL, *fp_log = NULL;
	const int io = 1;  // cf. MPI

	// arguments
	SCALING = 1;
	MATRIX = 1;
	Iseed = 0;
	int nthread = 1;
	int prompt = 0;
	char fn_in[BUFSIZ] = "";
	args(argc, argv, &nthread, &prompt, fn_in);

	// set number of threads
#ifdef _OPENMP
	omp_set_num_threads(nthread);
#endif

	// cpu time
	cpu[0] = cputime();

	// input data
	if (io) {
		if ((fp_in = fopen(fn_in, "r")) == NULL) {
			printf(errfmt, fn_in);
			ierr = 1;
		}
		if (!ierr) {
			ierr = input_data(fp_in);
			fclose(fp_in);
		}
	}
	error_check(ierr, prompt);

	// open log file
	if (io) {
		if ((fp_log = fopen(FN_log, "w")) == NULL) {
			printf(errfmt, FN_log);
			ierr = 1;
		}
	}
	error_check(ierr, prompt);

	// monitor
	if (io) {
		// logo
		sprintf(str, "<<< %s %s Ver.%d.%d.%d >>>", PROGRAM, prog, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
		monitor1(fp_log, str);
		// thread and process
		sprintf(str, "Thread = %d, Process = 1", nthread);
		monitor1(fp_log, str);
	}

	// plot geometry 3d and exit
	if (io && Plot3dGeom) {
		plot3dGeom();
		ierr = 1;
	}
	error_check(ierr, prompt);

	// setup
	setupIndex();
	setupMaterial(0);
	setup();
	alloc_farfield();

	// monitor
	if (io) {
		monitor2(fp_log, 0, 0);
	}

	// solve
	cpu[1] = cputime();
	solve(fp_log, io);
	cpu[2] = cputime();

	// output
	if (io) {
		// calculation and output
		outputChars(fp_log);

		// output filenames
		monitor3(fp_log);

		// write oth.out
		if ((fp_out = fopen(FN_out, "wb")) == NULL) {
			printf(errfmt, FN_out);
			ierr = 1;
		}
		if (!ierr) {
			writeout(fp_out);
			fclose(fp_out);
		}
	}
	error_check(ierr, prompt);

	// cpu time
	cpu[3] = cputime();

	if (io) {
		// cpu time
		monitor4(fp_log, cpu);

		// close log file
		fclose(fp_log);
	}

	// prompt
	if (io && prompt) getchar();

	return 0;
}

static void args(int argc, char *argv[],
	int *nthread, int *prompt, char fn_in[])
{
	const char usage[] = "Usage : oth [-n <thread>] [-matrix|-nomatrix] [-scaling|-noscaling] <datafile>";

	if (argc < 2) {
		printf("%s\n", usage);
		exit(0);
	}

	while (--argc) {
		++argv;
		if (!strcmp(*argv, "-n")) {
			if (--argc) {
				*nthread = atoi(*++argv);
				if (*nthread < 1) *nthread = 1;
			}
			else {
				break;
			}
		}
		else if (!strcmp(*argv, "-scaling")) {
			SCALING = 1;
		}
		else if (!strcmp(*argv, "-noscaling")) {
			SCALING = 0;
		}
		else if (!strcmp(*argv, "-matrix")) {
			MATRIX = 1;
		}
		else if (!strcmp(*argv, "-nomatrix")) {
			MATRIX = 0;
		}
		else if (!strcmp(*argv, "-random")) {
			if (--argc) {
				Iseed = atoi(*++argv);
			}
			else {
				break;
			}
		}
		else if (!strcmp(*argv, "-prompt")) {
			*prompt = 1;
		}
		else if (!strcmp(*argv, "--help")) {
			printf("%s\n", usage);
			exit(0);
		}
		else if (!strcmp(*argv, "--version")) {
			printf("%s Ver.%d.%d.%d\n", PROGRAM, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
			exit(0);
		}
		else {
			strcpy(fn_in, *argv);
		}
	}
}


// error check
static void error_check(int ierr, int prompt)
{
	if (ierr) {
		if (prompt) {
			fflush(stdout);
			getchar();
		}
		exit(1);
	}
}
