/* This file is part of Cloudy and is copyright (C) 1978-2004 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);
	}

	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);
				}
			}

			if( mole.n_h2_elec_states < 2 )
			{
				fprintf( ioQQQ, " This would be too few levels.\n" );
				puts( "[Stop in ParseAtomH2]" );
				cdEXIT(EXIT_FAILURE);
			}
			/* 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;
			}
		}
		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( lgEOL && !lgMatch(" OFF",chCard) )
		{
			/* this branch hit eol but OFF is not on line - this is a mistake */
			fprintf( ioQQQ, 
				" The total number of levels used in the matrix solver must be entered.\n Sorry.\n");
			puts( "[Stop in ParseAtomH2]" );
			cdEXIT(EXIT_FAILURE);
		}
		else if( lgEOL && lgMatch(" ALL",chCard) )
		{
			/* " all" means do all of X */
			nXLevelsMatrix = nLevels_per_elec[0];
		}
		/* 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("RATE",chCard ) )
	{
		/* change some rate within the H2 molecule by a scale factor */
		float factor = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		/* negative is a log, 0 is zero, to kill process */
		if( factor<0. )
			factor = (float)pow(10.,factor);

		else if( lgMatch("GRAIN",chCard ) )
		{
			/* scale factor for grain formation rate */
			hmi.grain_form_factor = factor;
		}
		else
		{
			fprintf( ioQQQ, 
				" There should have been a keyword - the available ones are GRAIN.\n Sorry.\n");
			puts( "[Stop in ParseAtomH2]" );
			cdEXIT(EXIT_FAILURE);
		}
	}
	else if( lgMatch("TRAC",chCard ) )
	{
		/* turns on trace printout */
		mole.lgH2_TRACE = TRUE;
	}
	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 */
	/* the mere calling of this routine turns the large H2 molecule on */
	h2.lgH2ON = TRUE;

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