/* This file is part of Cloudy and is copyright (C)1978-2006 by Gary J. Ferland
 * For conditions of distribution and use see copyright notice in license.txt */
/*ParseAtomH2 parse information from the atom command line */
#include "cddefines.h" 
#include "hmi.h" 
#include "mole.h" 
#include "h2_priv.h" 
#include "h2.h" 
#include "parse.h" 

/*ParseAtomH2 parse information from the atom command line */
void ParseAtomH2(char *chCard )
{
	int lgEOL;
	long int i , j;

#	ifdef DEBUG_FUN
	fputs( "<+>ParseAtomH2()\n", debug_fp );
#	endif

	/* this command has a 2 in the H2 label - must not parse the two by
	 * accident.  Get the first number off the line image, and confirm that
	 * it is a 2 */
	i = 5;
	j = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
	if( j != 2 )
	{
		fprintf( ioQQQ, " Something is wrong with the order of the numbers on this line.\n" );
		fprintf( ioQQQ, " The first number I encounter should be a 2.\n Sorry.\n" );
		puts( "[Stop in ParseAtomH2]" );
		cdEXIT(EXIT_FAILURE);
	}

	/* the mere calling of this routine turns the large H2 molecule on */
	h2.lgH2ON = TRUE;

	if( lgMatch("LEVE",chCard) )
	{
		/* number of electronic levels */

		/* lgH2_READ_DATA is FALSE at start of calculation, set true when space 
		 * allocated for the H lines.  Once done we must ignore all 
		 * future changes in the number of levels */
		if( !lgH2_READ_DATA )
		{
			mole.n_h2_elec_states = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				if( lgMatch("LARG",chCard) )
				{
					/* LARGE is option to use the most number of electronic levels */
					mole.n_h2_elec_states = N_H2_ELEC;
				}
				else
				{
					NoNumb(chCard);
				}
			}

			/* do not allow fewer than 3 - that includes lyman werner bands */
			if( mole.n_h2_elec_states < 3 )
			{
				fprintf( ioQQQ, " This would be too few electronic levels - resetting to 3.\n" );
				mole.n_h2_elec_states = 3;
			}
			/* N_H2_ELEC is in h2.h and is the greatest number of elec lev possible */
			else if( mole.n_h2_elec_states > N_H2_ELEC )
			{
				fprintf( ioQQQ, 
					" This would be too many levels, the limit is %i.\n" , 
					N_H2_ELEC);
				puts( "[Stop in ParseAtomH2]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
	}

	else if( lgMatch("LIMI",chCard) )
	{
		/* the limit to the H2 / Htot ratio - 
		 * if smaller than this, do not compute large H2 mole */
		mole.H2_to_H_limit = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			/* did not find a number, either mistake or key " off" */
			if( lgMatch( " OFF" , chCard ) )
			{
				/* turn off limit */
				mole.H2_to_H_limit = -1.;
			}
			else
			{
				fprintf( ioQQQ," The limit must appear on this line.\n");
				NoNumb( chCard );
			}
		}
		else
		{
			/* got a number, check if negative and so a log */
			/* a number <= 0 is the log of the ratio */
			if( mole.H2_to_H_limit <= 0. )
				mole.H2_to_H_limit = pow(10., mole.H2_to_H_limit);
		}
	}
	else if( lgMatch("GBAR",chCard ) )
	{
		/* option to either use, or not use, gbar approximation for low X levels with no
		 * collision data - by default it is on */
		if( lgMatch(" OFF",chCard ) )
		{
			mole.lgColl_gbar = FALSE;
		}
		else if( lgMatch(" ON ",chCard ) )
		{
			mole.lgColl_gbar = TRUE;
		}
		else
		{
			fprintf( ioQQQ, 
				" The gbar approximation must be off (\" OFF\") or on (\" ON \").\n");
			puts( "[Stop in ParseAtomH2]" );
			cdEXIT(EXIT_FAILURE);
		}
	}
	/* option to turn collisional effects off or on */
	else if( lgMatch("COLL",chCard ) )
	{
		/* option to turn collisional dissociation off or on */
		if( lgMatch("DISS",chCard ) )
		{
			/* option to turn collisions off */
			if( lgMatch(" ON ",chCard ) )
			{
				/* this is the default, leave collisions off */
				mole.lgColl_dissoc_coll = TRUE;
			}
			else
			{
				/* default (and only reason for this command) is to turn off collisions */
				mole.lgColl_dissoc_coll = FALSE;
			}
		}
		/* option to turn collisional dissociation off or on 
		 * >>chng 06 mar 01, had been simply if - so all collisions were turned off
		 * when dissociation collisions turned off - 
		 * due to bucket else at end */
		else if( lgMatch("ORTH",chCard ) && lgMatch("PARA",chCard ) )
		{
			/* option to turn ortho - para collisions with particles off */
			if( lgMatch(" ON ",chCard ) )
			{
				/* this is the default, leave collisions off */
				mole.lgH2_ortho_para_coll_on = TRUE;
			}
			else
			{
				/* default (and only reason for this command) is to turn off ortho-para collisions */
				mole.lgH2_ortho_para_coll_on = FALSE;
			}
		}

		/* option to turn collisional effects off or on */
		else if( lgMatch("GRAI",chCard ) )
		{
			/* option to turn collisions off */
			if( lgMatch(" ON",chCard ) )
			{
				/* this is the default, leave collisions off */
				mole.lgH2_grain_deexcitation = TRUE;
			}
			else
			{
				/* default (and only reason for this command) is to turn off collisions */
				mole.lgH2_grain_deexcitation = FALSE;
			}
		}
		else if( lgMatch(" HE ",chCard ) )
		{
			/* atom H2 He collisions NEW OLD OFF
			 * which data set for He collisions, 
			 * three options, old, new, and off */
			if( lgMatch(" NEW",chCard ) )
			{
				/* use the new coefficients */
				mole.lgH2_He_Meudon = FALSE;
				mole.lgH2_He_Stancil = TRUE;
			}
			else if( lgMatch(" OLD",chCard ) )
			{
				/* use the old coefficients */
				mole.lgH2_He_Meudon = TRUE;
				mole.lgH2_He_Stancil = FALSE;
			}
			else if( lgMatch(" OFF",chCard ) )
			{
				/* leave collisions off */
				mole.lgH2_He_Meudon = FALSE;
				mole.lgH2_He_Stancil = FALSE;
			}
			else
			{
				fprintf( ioQQQ, 
					" I did not find a keyword on this ATOM H2 HE command - I know about the keys OLD, NEW, and OFF\n");
				puts( "[Stop in ParseAtomH2]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		else
		{
			/* option to turn all collisions off */
			if( lgMatch(" ON ",chCard ) )
			{
				/* this is the default, leave collisions on */
				mole.lgColl_deexec_Calc = TRUE;
			}
			else
			{
				/* default (and only reason for this command) is to turn off collisions */
				mole.lgColl_deexec_Calc = FALSE;
			}
		}
	}

	else if( lgMatch("MATR",chCard ) )
	{
		/* matrix option sets the number of levels that will
		 * be included in the matrix solution */
		nXLevelsMatrix = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgMatch(" ALL",chCard) )
		{
			/* " all" means do all of X, but space has not yet been allocated,
			 * so we do know know how many levels are within X - set special
			 * flag that will be used then this is known */
			/*nXLevelsMatrix = nLevels_per_elec[0];*/
			nXLevelsMatrix = -1;
		}
		else if( lgEOL && !(lgMatch(" OFF",chCard) || lgMatch("NONE",chCard) ) )
		{
			/* this branch hit eol but OFF or NONE is not on line - this is a mistake */
			fprintf( ioQQQ, 
				" The total number of levels used in the matrix solver must be entered, or keywords ALL or NONE entered.\n Sorry.\n");
			puts( "[Stop in ParseAtomH2]" );
			cdEXIT(EXIT_FAILURE);
		}
		/* cannot check less than total number of levesl within x since not yet set */
		/* routine does not certify that matrix limits are greater than 1 -
		 * zero or <0 limits just turns if off, as did the off option */
	}
	else if( lgMatch(" LTE",chCard ) )
	{
		/* LTE option causes code to assume LTE for level populations  */
		mole.lgH2_LTE = TRUE;
	}

	else if( lgMatch("TRAC",chCard ) )
	{
		/* these are used to set trace levels of output 
		mole.lgH2_trace_final = 1;
		mole.lgH2_trace_iterations = 2;
		mole.lgH2_trace_full = 3;
		mole.lgH2_trace_matrix = 4*/

		/* turns on trace printout - there are multiple levels */
		if( lgMatch("FINA",chCard ) )
		{
			/* FINAL gives only final information when solver exits */
			mole.lgH2_TRACE = mole.lgH2_trace_final;
		}
		else if( lgMatch("ITER",chCard ) )
		{
			/* follow iterations within each call */
			mole.lgH2_TRACE = mole.lgH2_trace_iterations;
		}
		else if( lgMatch("FULL",chCard ) )
		{
			/* full details of solution - this is also the default*/
			mole.lgH2_TRACE = mole.lgH2_trace_full;
		}
		else if( lgMatch("MATR",chCard ) )
		{
			/* print the matrices used for X */
			mole.lgH2_TRACE = mole.lgH2_trace_matrix;
		}
		else
		{
			/* full details of solution is also the default*/
			mole.lgH2_TRACE = mole.lgH2_trace_full;
		}
	}
	else if( lgMatch("NOIS",chCard ) )
	{
		unsigned int iseed;
		/* check on effects of uncertainties in collision rates */
		mole.lgH2_NOISE = TRUE;
		mole.lgH2_NOISECOSMIC = TRUE;

		/* optional mean - default is 0 */
		mole.xMeanNoise = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
			mole.xMeanNoise = 0.;

		/* this is the standard deviation for the mole, with default */
		mole.xSTDNoise = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
			mole.xSTDNoise = 0.5;

		/* this may be a seed for the random number generator.  if no seed is
		 * set then use system time, and always get different sequence */
		iseed = (unsigned int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		/* returned 0 if eol hit */
		if( iseed > 0 )
		{
			/* user set seed */
			srand( iseed );
		}
		else
		{
			srand( (unsigned)time( NULL ) );
		}
	}

	else if( lgMatch("THER",chCard ) )
	{
		/* change the treatment of the heating - cooling effects of H2,
		 * options are simple (use TH85 expressions) and full (use large molecule)*/
		if( lgMatch("SIMP",chCard ) )
		{
			hmi.lgH2_Thermal_BigH2 = FALSE;
		}
		else if( lgMatch("FULL",chCard ) )
		{
			/* this is the default - use big atom */
			hmi.lgH2_Thermal_BigH2 = TRUE;
		}
	}

	else if( lgMatch("CHEM",chCard ) )
	{
		/* change the treatment of the chemistry - formation and destruction,
		 * options are simple (use TH85 expressions) and full (use large molecule)*/
		if( lgMatch("SIMP",chCard ) )
		{
			hmi.lgH2_Chemistry_BigH2 = FALSE;
		}
		else if( lgMatch("FULL",chCard ) )
		{
			/* this is the default - use big atom */
			hmi.lgH2_Chemistry_BigH2 = TRUE;
		}
	}

	/* there is no final branch - if we do not find a keyword, simply
	 * turn on the H2 molecule */

#	ifdef DEBUG_FUN
	fputs( " <->ParseAtomH2()\n", debug_fp );
#	endif
	return;
}
