/* 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 */
/*ParseAtomHLike parse information from the atom h-like command line */
#include "cddefines.h"
#include "taulines.h"
#include "hydrogenic.h"
#include "phycon.h"
#include "iso.h"
#include "rfield.h"
#include "parse.h"

void ParseAtomHLike(char *chCard )
{
	int lgEOL;
	long int i , 
		nh ,
		nelem ;

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

	if( lgMatch("COLL",chCard) )
	{
		/* option to turn hydrogen collisions off, all are
		 * set to 1 in zero.  command can accept only one option at a time */
		if( lgMatch("EXCI",chCard) )
		{
			/* turn off collisional excitation */
			iso.lgColl_excite[ipH_LIKE] = FALSE;
			phycon.lgPhysOK = FALSE;
		}
		else if( lgMatch("IONI",chCard) )
		{
			/* turn off collisional ionization */
			iso.lgColl_ionize[ipH_LIKE] = FALSE;
			phycon.lgPhysOK = FALSE;
		}

		else if( lgMatch("2S2P",chCard) || lgMatch("2P2S",chCard) )
		{
			/* >>chng 02 feb 07, change from 2s2p to l-mixing */
			/* this is the atom h-like collision l-mixing command */
			fprintf(ioQQQ,"This command changed to ATOM H-LIKE COLLISIONS L-MIXING\n");
			fprintf(ioQQQ,"I will parse it for now, but may not in the future.\n");
			/* turn off 2s - 2p collisions */
			iso.lgColl_l_mixing[ipH_LIKE] = FALSE;
			phycon.lgPhysOK = FALSE;
		}

		else if( lgMatch("L-MI",chCard)  )
		{
			/* >>chng 02 feb 07, change from 2s2p to l-mixing */
			/* this is the atom h-like collision l-mixing command */
			iso.lgColl_l_mixing[ipH_LIKE] = FALSE;
			phycon.lgPhysOK = FALSE;
		}
		else
		{
			/* turn everything off, since no keyword given */
			iso.lgColl_excite[ipH_LIKE] = FALSE;
			iso.lgColl_ionize[ipH_LIKE] = FALSE;
			iso.lgColl_l_mixing[ipH_LIKE] = FALSE;
			phycon.lgPhysOK = FALSE;
		}
	}

	else if( lgMatch("DAMP",chCard) )
	{
		/* turn off absorption due to lyalpha damping wings */
		hydro.DampOnFac = 0.;
	}

	else if( lgMatch("EMIS",chCard) )
	{
		/* hydrogenic emission lines will be emissivity not intensity or luminosity */
		hydro.lgHydEmiss = TRUE;
	}

	else if( lgMatch("LEVE",chCard) )
	{
		/* number of levels for hydrogen at, 2s is this plus one */
		/* there are two options here,
		 * when keyword ELEMENT appears, scan off element name and change levels only for
		 * that one.
		 * when there is no ELEMENT then set all nhlevels to same number */

		/* lgHydroMalloc is FALSE at start of calculation, set true when space 
		 * allocated for the hydrogen lines.  Once done we must ignore all 
		 * future changes in the number of levels */
		if( !lgHydroMalloc )
		{
			i = 5;
			nh = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

			if( lgEOL )
			{
				/* must be a number, or a key, either large (or limit) or small
				 * if no number but LARGER or SMALL then set to preset number */
				if( lgMatch("LARG",chCard) )
				{
					/* there is no real limit, but this seems pretty big */
					nh = 50;
				}

				/* this is small or compact keyword */
				else if( lgMatch("SMAL",chCard) || lgMatch("COMP",chCard) )
				{
					if( lgMatch("VERY" , chCard ) )
					{
						/* a small atom is the same as c84 */
						nh = 4;
					}
					else
					{
						/* a small atom is the same as c84 */
						nh = 10;
					}
				}

				/* this is limit keyword, sets to largest possible value */
				else if( lgMatch("LIMI",chCard) )
				{
					nh = NHYDRO_MAX_LEVEL-2;
				}

				else
				{
					/* punch out if no number */
					NoNumb(chCard);
				}
			}

			if( nh < 4 )
			{
				fprintf( ioQQQ, " This would be too few levels.\n" );
				puts( "[Stop in ParseAtomHLike]" );
				cdEXIT(EXIT_FAILURE);
			}

			if( nh > NHYDRO_MAX_LEVEL-2 )
			{
				fprintf( ioQQQ, " Not possible to set nhlvl to >NHYDRO_MAX_LEVEL-2= %li\n", 
				  NHYDRO_MAX_LEVEL-2 );
				fprintf( ioQQQ, " change NHYDRO_MAX_LEVEL\n");
				puts( "[Stop in ParseAtomHLike]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* this is check that alpha transition of highest level is within energy
			 * bounds of continuum */
			if( 2. / POW3((double)nh) < rfield.emm )
			{
				fprintf( ioQQQ, " Not possible to set iso.numLevels_max[ipH_LIKE][ipHYDROGEN] to such a high value, since "
					"alpha transition not within energy bounds of code\n");

				fprintf( ioQQQ, " lowest energy is %e and corresponding highest level is %li\n" ,
					rfield.emm, (long)pow(2./rfield.emm, 0.3333) );
				puts( "[Stop in ParseAtomHLike]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* we now have the desired number of levels, and it has been fully qualified. 
			 * now check whether ELEMENT keyword is on line, if not then set all to
			 * the number, if so then only element in use */
			if( lgMatch("ELEM",chCard) )
			{
				/* check which element is on the line, nelem is atomic number on C scale */
				nelem = GetElem(chCard);
				/* only set number of levels for this one element */
				iso.n_HighestResolved_max[ipH_LIKE][nelem] = nh;
				/* >>chng 02 jan 19, increase numb of H levels by 1 so that loops are < n 
				 * should be no net change in levels as a result */
				iso.numLevels_max[ipH_LIKE][nelem] = nh+1;
				iso.numPrintLevels[ipH_LIKE][nelem] = nh;
				/* make sure topoff level is less than nh */
				iso.nTopOff[ipH_LIKE][nelem] = MIN2(nh-1,iso.nTopOff[ipH_LIKE][nelem]);
			}
			else
			{
				/* keyword element did not appear, so set all h-like species to this number */
				for( nelem=ipHYDROGEN; nelem<LIMELM; ++nelem )
				{
					iso.n_HighestResolved_max[ipH_LIKE][nelem] = nh;
					iso.numLevels_max[ipH_LIKE][nelem] = nh+1;
					iso.numPrintLevels[ipH_LIKE][nelem] = nh;
					/* make sure topoff level is less than nh */
					iso.nTopOff[ipH_LIKE][nelem] = MIN2(nh-1,iso.nTopOff[ipH_LIKE][nelem]);
				}
			}
		}
	}

	else if( lgMatch("LYMA",chCard) )
	{
		if( lgMatch("PUMP",chCard) )
		{
			/* >>chng 05 jul 08, separate out lyman pump commands */
			if( lgMatch(" OFF",chCard) )
			{
				/* option to turn off all continuum pumping of Lyman lines */
				hydro.lgLymanPumping = FALSE;
			}
			else if( lgMatch("SCALE",chCard) )
			{
				/* mutilplicative factor for all continuum pumping of H I Lyman lines,
				 * account for possible emission in the line */
				i = 5;
				hydro.xLymanPumpingScaleFactor = 
					(float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			}
			else
			{
				fprintf(ioQQQ," Sorry, I didn\'t recognize an option on this ATOM H-LIKE LYMAN PUMP command.\n");
				fprintf(ioQQQ," The options are \" OFF\", and \"SCALE\".\n");  
				puts( "[Stop in ParseAtomHLike]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		else if( lgMatch("EXTR",chCard) )
		{
			/* option to set number of "extra" lyman lines, used for optical depths only */
			i = 5;
			iso.nLyman[ipH_LIKE] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
				NoNumb(chCard);
		}
		else
		{
			fprintf(ioQQQ," Sorry, I didn\'t recognize an option on this ATOM H-LIKE LYMAN command.\n");
			fprintf(ioQQQ," The options are \"PUMPING\", and \"EXTRA\".\n");  
			puts( "[Stop in ParseAtomHLike]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("REDI",chCard) )
	{
		int ipRedis=0;
		/* there are three functions, PRD_, CRD_, and CRDW,
		 * representing partial redistribution, 
		 * complete redistribution (doppler core only, no wings)
		 * and complete with wings */
		/* partial redistribution */
		if( lgMatch(" PRD",chCard) )
		{
			ipRedis = ipPRD;
		}
		/* complete redistribution no wings */
		else if( lgMatch(" CRD",chCard) )
		{
			ipRedis = ipCRD;
		}
		/* complete redistribution with wings */
		else if( lgMatch("CRDW",chCard) )
		{
			ipRedis = ipCRDW;
		}

		/* if not SHOW option (handled below) then we have a problem */
		else if( !lgMatch("SHOW",chCard) )
		{
			fprintf(ioQQQ," There should have been a second keyword on this command.\n");
			fprintf(ioQQQ," Options are _PRD, _CRD, CRDW (_ is space).  Sorry.\n");
			puts( "[Stop in ParseAtomHLike]" );
			cdEXIT(EXIT_FAILURE);
		}

		/* resonance lines - not Lya*/
		if( lgMatch("ALPH",chCard) )
		{
			iso.ipLyaRedist[ipH_LIKE] = ipRedis;
		}
		/* Lya itself */
		if( lgMatch("RESO",chCard) )
		{
			iso.ipResoRedist[ipH_LIKE] = ipRedis;
		}
		/* subordinate lines */
		else if( lgMatch("SUBO",chCard) )
		{
			iso.ipSubRedist[ipH_LIKE] = ipRedis;
		}
		/* the show option, say what we are assuming */
		else if( lgMatch("SHOW",chCard) )
		{
			fprintf(ioQQQ," Ly a is ");
			if( iso.ipLyaRedist[ipH_LIKE] ==ipCRDW )
			{
				fprintf(ioQQQ,"complete redistribution with wings\n");
			}
			else if( iso.ipLyaRedist[ipH_LIKE] ==ipCRD )
			{
				fprintf(ioQQQ,"complete redistribution with core only.\n");
			}
			else if( iso.ipLyaRedist[ipH_LIKE] ==ipPRD )
			{
				fprintf(ioQQQ,"partial redistribution.\n");
			}
			else if( iso.ipLyaRedist[ipH_LIKE] ==ipLY_A )
			{
				fprintf(ioQQQ,"special Lya.\n");
			}
			else
			{
				fprintf(ioQQQ," PROBLEM Impossible value for iso.ipLyaRedist.\n");
				TotalInsanity();
			}

			fprintf(ioQQQ," Other H resonance lines are ");
			if( iso.ipResoRedist[ipH_LIKE] ==ipCRDW )
			{
				fprintf(ioQQQ,"complete redistribution with wings\n");
			}
			else if( iso.ipResoRedist[ipH_LIKE] ==ipCRD )
			{
				fprintf(ioQQQ,"complete redistribution with core only.\n");
			}
			else if( iso.ipResoRedist[ipH_LIKE] ==ipPRD )
			{
				fprintf(ioQQQ,"partial redistribution.\n");
			}
			else
			{
				fprintf(ioQQQ," PROBLEM Impossible value for iso.ipResoRedist.\n");
				TotalInsanity();
			}

			fprintf(ioQQQ," H subordinate lines are ");
			if( iso.ipSubRedist[ipH_LIKE] ==ipCRDW )
			{
				fprintf(ioQQQ,"complete redistribution with wings\n");
			}
			else if( iso.ipSubRedist[ipH_LIKE] ==ipCRD )
			{
				fprintf(ioQQQ,"complete redistribution with core only.\n");
			}
			else if( iso.ipSubRedist[ipH_LIKE] ==ipPRD )
			{
				fprintf(ioQQQ,"partial redistribution.\n");
			}
			else
			{
				fprintf(ioQQQ," PROBLEM Impossible value for iso.ipSubRedist.\n");
				TotalInsanity();
			}
		}
		else
		{
			fprintf(ioQQQ," here should have been another keyword on this command.\n");
			fprintf(ioQQQ," Options are ALPHA, RESONANCE, SUBORDINATE.  Sorry.\n");
			puts( "[Stop in ParseAtomHLike]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("TOPO",chCard) )
	{
		/* set lowest level for hydrogen atom top off topoff */
		i = 5;
		iso.nTopOff[ipH_LIKE][ipHYDROGEN] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

		if( iso.nTopOff[ipH_LIKE][ipHYDROGEN] > iso.numLevels_max[ipH_LIKE][ipHYDROGEN] )
		{
			fprintf( ioQQQ, " Not possible to set nHTopOff to more than nhlvl=%4ld\n", 
			  iso.numLevels_max[ipH_LIKE][ipHYDROGEN] );
			fprintf( ioQQQ, " change nhlvl first with ATOM H-LIKE LEVELS command\n");
			puts( "[Stop in ParseAtomHLike]" );
			cdEXIT(EXIT_FAILURE);
		}

		if( lgEOL )
		{
			NoNumb(chCard);
		}

		if( lgMatch(" ADD",chCard) )
		{
			/* add extra part */
			strcpy( hydro.chHTopType, " add" );
		}
		else if( lgMatch("SCAL",chCard) )
		{
			/* use scale factors */
			strcpy( hydro.chHTopType, "scal" );
		}
		else
		{
			/* this is the default */
			strcpy( hydro.chHTopType, " add" );
		}
	}

	/* which type of matrix solution, populations or lowt */
	else if( lgMatch("MATR",chCard) )
	{
		if( lgMatch(" POP",chCard) )
		{
			strcpy( iso.chTypeAtomSet[ipH_LIKE] , "POPU" );
		}
		else if( lgMatch(" LOW",chCard) )
		{
			strcpy( iso.chTypeAtomSet[ipH_LIKE] , "LOWT" );
		}
		else
		{
			fprintf( ioQQQ, " There should have been a keyword on the MATRIX option.\n");
			fprintf( ioQQQ, " The keywords are POPulations, and LOWte.\n");
			fprintf( ioQQQ, " Stop in ParseAtomHLike\n" );
			puts( "[Stop in ParseAtomHLike]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else
	{
		fprintf( ioQQQ, " There should have been a keyword - Stop in ParseAtomHLike\n" );
		puts( "[Stop in ParseAtomHLike]" );
		cdEXIT(EXIT_FAILURE);
	}

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

