/* 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 */
/*ParseSet scan parameters off SET command */
#include "cddefines.h"
#include "physconst.h"
#include "geometry.h"
#include "kshllenr.h"
#include "input.h"
#include "prt.h"
#include "mole.h"
#include "rt.h"
#include "phycon.h"
#include "path.h"
#include "optimize.h"
#include "map.h"
#include "hmi.h"
#include "dense.h"
#include "iterations.h"
#include "conv.h"
#include "secondaries.h"
#include "rfield.h"
#include "ionbal.h"
#include "numderiv.h"
#include "dynamics.h"
#include "iso.h"
#include "punch.h"
#include "stopcalc.h"
#include "opacity.h"
#include "hydrogenic.h"
#include "peimbt.h"
#include "radius.h"
#include "atmdat.h"
#include "continuum.h"
#include "grains.h"
#include "grainvar.h"
#include "parse.h"
#include "lines.h"

#define NINT(X) ((long)((X) < 0. ? (X)-0.5 : (X)+0.5))

void ParseSet(char *chCard )
{
	int lgEOL ;
	long int i, 
		ip;
	char *chEnd;
	char chString[INPUT_LINE_LENGTH];

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

	/* first check for any strings within quotes - this will get the string
	 * and blank it out, so that these are not confused with keywords.  if
	 * double quotes not present routine returns null */
	GetQuote( chString , chCard , FALSE );

	/* commands to set certain variables, "SET XXX=" */
	if( lgMatch("ASSE",chCard) &&lgMatch(" FPE",chCard) )
	{
		/* set crash assert command, to tell the code to throw an FPE when an
		 * assert is thrown - poor way to get a traceback on an assert */
		lgAssertFPE = TRUE;
	}
	else if( lgMatch(" CHA",chCard) && !lgMatch( "HO ", chCard ) )
	{
		/* set log of minimum charge transfer rate for high ions and H
		 * default of 1.92e-10 set in zero */
		i = 5;
		atmdat.HCTAlex = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		if( atmdat.HCTAlex < 0. )
		{
			atmdat.HCTAlex = pow(10.,atmdat.HCTAlex);
		}
	}

	else if( lgMatch("CHEM",chCard ) && !lgMatch( "HO ", chCard ) )
	{
		/* thrun on Steve Federman's chemistry */
		if( lgMatch("FEDE",chCard ) )
		{
			if( lgMatch( " ON " , chCard ) )
			{
				/* This turns on the diffuse cloud chemical rates of 
				 * >> refer Zsargo, J. & Federman, S. R. 2003, ApJ, 589, 319*/
				co.lgFederman = TRUE;
			}
			else if( lgMatch( " OFF" , chCard ) )
			{
				co.lgFederman = FALSE;
			}
			else
			{
				/* this is the default when command used - true */
				co.lgFederman = TRUE;
			}
		}
		else
		{
			/* should not have happened ... */
			fprintf( ioQQQ, " There should have been an option on this SET CHEMISTRY command.\n" );
			fprintf( ioQQQ, " consult Hazy to find valid options.\n Sorry.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("COVE",chCard) )
	{
		iterations.lgConverge_set = TRUE;
		/* set coverage - limit number of iterations and zones */
		if( lgMatch("FAST",chCard) )
		{
			iterations.lim_zone = 1;
			iterations.lim_iter = 0;
		}
		else
		{
			iterations.lim_zone = 10;
			iterations.lim_iter = 1;
		}
	}

	else if( lgMatch("CSUP",chCard) )
	{
		/* force secondary ionization rate, log entered */
		i = 5;
		secondaries.SetCsupra = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		secondaries.lgCSetOn = TRUE;
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		secondaries.SetCsupra = (float)pow(10.f,secondaries.SetCsupra);
	}

	else if( lgMatch(" D/H",chCard) )
	{
		/* set deuterium abundance, D to H ratio */
		i = 5;
		hydro.D2H_ratio = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( hydro.D2H_ratio <= 0. || lgMatch( " LOG", chCard ) )
		{
			hydro.D2H_ratio = pow(10.,hydro.D2H_ratio);
		}
		if( lgEOL )
		{
			NoNumb(chCard);
		}
	}

	else if( lgMatch( " HO " , chCard) && lgMatch( "CHAR" , chCard) )
	{
		/* which solver will include H + O charge transfer?  done in
		 * chemistry by default */
		if( lgMatch( "CHEM" , chCard ) )
		{
			/* this is the default */
			ionbal.lgHO_ct_chem = TRUE;
		}
		else if( lgMatch( "IONI" , chCard ) )
		{
			/* do it in the ionization solver */
			ionbal.lgHO_ct_chem = FALSE;
		}
		else
		{
			fprintf( ioQQQ, " I did not recognize a subkey on this SET OH CHARge transfer line.\n" );
			fprintf( ioQQQ, " Valid keys are CHEMistry and IONIzation.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("12C1",chCard) )
	{
		/* set the 12C to 13C abundance ratio - default is 30 */
		i = 5;
		/* first two numbers on the line are 12 and 13 - we don't want them */
		co.RatioC12O16_2_C13O16 = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		co.RatioC12O16_2_C13O16 = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

		/* now we can get the ratio */
		co.RatioC12O16_2_C13O16 = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
			NoNumb(chCard);

		if( co.RatioC12O16_2_C13O16 <= 0. || lgMatch( " LOG", chCard ) )
			co.RatioC12O16_2_C13O16 = (float)pow(10.f,co.RatioC12O16_2_C13O16);
	}

	/* set dynamics ... */
	else if( lgMatch("DYNA",chCard) )
	{
		/* set dynamics advection length */
		if( lgMatch("ADVE",chCard) && lgMatch("LENG",chCard) )
		{
			/* <0 => relative fraction of length, + val in cm */
			i = 5;
			dynamics.AdvecLengthInit = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			/* if fraction is present, then number was linear fraction, if not present
			* then physical length in cm, log10 */
			if( lgMatch("FRAC",chCard) )
			{
				/* we scaned in the number, if it is a negative then it is the log of the fraction */
				if( dynamics.AdvecLengthInit <= 0. )
					dynamics.AdvecLengthInit = pow(10.,dynamics.AdvecLengthInit);

				/* make neg sign as flag for this in dynamics.c */
				dynamics.AdvecLengthInit *= -1.;
			}
			else
			{
				/* fraction did not occur, the number is the log of the length in cm -
				* convert to linear cm */
				dynamics.AdvecLengthInit = pow(10.,dynamics.AdvecLengthInit);
			}
		}
		else if( lgMatch("PRES",chCard) && lgMatch("MODE",chCard) )
		{
			dynamics.lgSetPresMode = TRUE;
			if( lgMatch("SUBS",chCard) )
			{
				/* subsonic */
				strcpy( dynamics.chPresMode , "subsonic" );
			}
			else if( lgMatch("SUPE",chCard) )
			{
				/* supersonic */
				strcpy( dynamics.chPresMode , "supersonic" );
			}
			else if( lgMatch("STRO",chCard) )
			{
				/* strong d */
				strcpy( dynamics.chPresMode , "strongd" );
			}
			else if( lgMatch("ORIG",chCard) )
			{
				/* original */
				strcpy( dynamics.chPresMode , "original" );
			}
		}
		else if( lgMatch("ANTI",chCard) && lgMatch("DEPT",chCard) )
		{
			dynamics.lgSetPresMode = TRUE;
			strcpy( dynamics.chPresMode , "antishock" );
			/* shock depth */
			i = 5;
			/* get log of shock depth in cm */
			dynamics.ShockDepth = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			dynamics.ShockDepth = pow( 10., dynamics.ShockDepth );
		}
		else if( lgMatch("ANTI",chCard) && lgMatch("MACH",chCard) )
		{
			dynamics.lgSetPresMode = TRUE;
			strcpy( dynamics.chPresMode , "antishock-by-mach" );
			/* Mach number */
			i = 5;
			/* get (isothermal) Mach number where we want antishock to occur */
			dynamics.ShockMach = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		}
		else if( lgMatch("SHOC",chCard) && lgMatch("DEPT",chCard) )
		{
			dynamics.lgSetPresMode = TRUE;
			strcpy( dynamics.chPresMode , "shock" );
			/* shock depth */
			i = 5;
			/* get log of shock depth in cm */
			dynamics.ShockDepth = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			dynamics.ShockDepth = pow( 10., dynamics.ShockDepth );
		}
		else if( lgMatch("STAR",chCard) )
		{
			/* set the first iteration to include dynamics rather than constant pressure */
			/* iteration number, initial iteration is 1, default is 2 */
			i = 5;
			/* iteration number */
			dynamics.iteration_first_dynamics = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}
			else if( dynamics.iteration_first_dynamics < 2 )
			{
				fprintf(ioQQQ," First iteration with dynamics must be > 1.  It was %li. Sorry.\n",
					dynamics.iteration_first_dynamics );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		else
		{
			/* should not have happened ... */
			fprintf( ioQQQ, " There should have been an option on this SET DYNAMICS command.\n" );
			fprintf( ioQQQ, " consult Hazy to find valid options.\n Sorry.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("DIDZ",chCard) )
	{
		/* set parameter to do with choice of dr;
		 * par is the largest optical depth to allow in the zone. 
		 * >>chng 96 jan 08 had been two numbers - dtau1 removed */
		i = 5;
		radius.drChange = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( radius.drChange <= 0. )
		{
			radius.drChange = (float)pow(10.f,radius.drChange);
		}
		if( lgEOL )
		{
			NoNumb(chCard);
		}

	}

	/* something to do with electron density */
	else if( lgMatch("EDEN",chCard) )
	{
		/* >>chng 02 apr 20, from ERROR to TOLERANCE to be parallel to set temp equivalent,
		 * >>chng 04 jun 03, but also accept error as keyword */
		if( lgMatch("CONV",chCard) || lgMatch("ERRO",chCard))
		{
			/* keyword is eden convergence  
			 * set tolerance in eden match */
			i = 5;
			conv.EdenErrorAllowed = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}

			if( conv.EdenErrorAllowed < 0. )
			{
				conv.EdenErrorAllowed = pow(10.,conv.EdenErrorAllowed);
			}
		}

		else if( lgMatch("SOLV",chCard) )
		{
			/* the electron density solver */
			if( lgMatch("NEW",chCard) ) 
			{
				/* new method */
				strcpy( conv.chSolverEden , "new" );
			}
			else
			{
				/* default method */
				strcpy( conv.chSolverEden , "simple" );
			}
		}
		else 
		{
			/* no keyword, assume log of electron density */
			i = 5;
			/* set the electron density */
			dense.EdenSet = (float)pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));
			/* warn that this model is meaningless */
			phycon.lgPhysOK = FALSE;
		}
	}

	else if( lgMatch("FINE",chCard ) && lgMatch("CONT",chCard ) )
	{
		/* set fine continuum - which element, and how many resolution elements,
		 * at lowest temperature to be considered */
		/* check which element is on the line, nelem is atomic number on C scale
		 * default is iron */
		if( (rfield.fine_opac_nelem = GetElem(chCard))<ipHYDROGEN )
		{
			fprintf( ioQQQ, " An element name must appear on this line\n Sorry.\n" );
			puts( "[Stop in ParsePunch]" );
			cdEXIT(EXIT_FAILURE);
		}
		i = 5;
		/* set the number of resolution elements in hwhm at lowest allowed temp 
		 * default is one elements */
		rfield.fine_opac_nresolv = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( rfield.fine_opac_nresolv< 1 )
		{
			fprintf( ioQQQ, " The number of resolution elements within fwhm of line must appear\n Sorry.\n" );
			puts( "[Stop in ParsePunch]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	/* these are the "set leiden hack" commands, used to turn off physics and
	 * sometimes replace with simple approximation */
	else if( lgMatch("LEID",chCard ) && lgMatch("HACK",chCard ) )
	{
		if( lgMatch( "H2* " , chCard ) && lgMatch( " OFF" , chCard ) )
		{
			/* turn off reactions with H2* in the chemistry network */
			hmi.lgLeiden_Keep_ipMH2s = FALSE;
			/* warn that this model is not the best we can do */
			phycon.lgPhysOK = FALSE;
		}
		else if( lgMatch( "CR " , chCard ) && lgMatch( " OFF" , chCard ) )
		{
			/* the CR leiden hack option - turn off CR excitations of H2 */
			hmi.lgLeidenCRHack = FALSE;
			
		}
		else if( lgMatch("RATE",chCard ) &&  lgMatch("UMIS",chCard ))
		{
			/* This command will use the rates given in the UMIST database,  It
			 * will set to zero many reactions in hmole_step.c that are not
			 * in UMIST */
			co.lgUMISTrates = FALSE;
		}
	}

	/* set H2 ... */
	else if( lgMatch(" H2 ",chCard) )
	{
		i = 5;
		ip = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( ip != 2 )
		{
			fprintf( ioQQQ, " The first number on this line must be the 2 in H2\n Sorry.\n" );
			puts( "[Stop in ParsePunch]" );
			cdEXIT(EXIT_FAILURE);
		}

		/* whioch approximation to Solomon process */
		if( lgMatch("SOLO",chCard) )
		{
			if( lgMatch("TH85", chCard ) )
			{
				/* rate from is eqn A8 of Tielens and Hollenbach 85a, */
				hmi.chSolomon = 'T';
			}
			else if( lgMatch( "BD96" , chCard ) )
			{
				/* this rate is equation 23 of
				 *>>refer	H2	dissoc	Bertoldi, F., & Draine, B.T., 1996, 458, 222 */
				/* this is the default */
				hmi.chSolomon = 'B';
			}
			else if( lgMatch( "ELWE" , chCard ) )
			{
				/* this rate is equation 23 of
				 *>>refer	H2	dissoc	Elwert et al., in preparation */
				/* this is the default */
				hmi.chSolomon = 'E';
			}
			else
			{
				fprintf( ioQQQ, " The first number on this line must be the 2 in H2\n Sorry.\n" );
				puts( "[Stop in ParsePunch]" );
				cdEXIT(EXIT_FAILURE);
			}
		}

		/* series of commands that deal with grains */
		/* which approximation to grain formation pumping */
		if( lgMatch("GRAI",chCard ) && lgMatch("FORM",chCard ) && lgMatch("PUMP",chCard )  )
		{
			if( lgMatch( "DB96" , chCard ) )
			{
				/* Draine & Bertoldi 1996 */
				hmi.chGrainFormPump = 'D';
			}
			else if( lgMatch( "TAKA" , chCard ) )
			{
				/* Takahashi 2001 */
				hmi.chGrainFormPump = 'T';
			}
			else if( lgMatch( "THER" , chCard ) )
			{
				/* thermal distribution, upper right column of page 239 of
				*>>refer	H2	formation	Le Bourlot, J, 1991, A&A, 242, 235 */
				hmi.chGrainFormPump = 't';
			}
			else
			{
				fprintf( ioQQQ, " The grain form pump option is wrong.\n Sorry.\n" );
				puts( "[Stop in ParsePunch]" );
				cdEXIT(EXIT_FAILURE);
			}
		}

		/* which approximation to Jura rate */
		else if( lgMatch("JURA",chCard) )
		{
			if( lgMatch("TH85", chCard ) )
			{
				/* rate from is eqn A8 of Tielens and Hollenbach 85a*/
				hmi.chJura = 'T';
			}
			else if( lgMatch( "CT02" , chCard ) )
			{
				/* this rate is equation cazeux & Tielens */
				hmi.chJura = 'C';
			}
			else if( lgMatch( "SN99" , chCard ) )
			{
				/* this rate is from Sternberg & Neufeld 99 */
				hmi.chJura = 'S';
			}
			else if( lgMatch( "RATE" , chCard ) )
			{
				/* set H2 rate - enters log of jura rate - C for constant,
				 * no dependence on grain properties */
				hmi.chJura = 'C';
				hmi.rate_h2_form_grains_set = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL) );
			}
			else if( lgMatch( "SCAL" , chCard ) )
			{
				/* this is a scale factor to multiply the Jura rate */
				hmi.ScaleJura = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
				/* log or negative number means log was entered */
				if( lgMatch( " LOG" , chCard ) || hmi.ScaleJura<0. )
				{
					hmi.ScaleJura = (float)pow( 10., (double)hmi.ScaleJura );
				}
				if( lgEOL )
				{
					NoNumb( chCard );
				}

				/* option to vary scale factor */
				if( optimize.lgVarOn )
				{
					optimize.nvarxt[optimize.nparm] = 1;
					strcpy( optimize.chVarFmt[optimize.nparm], "SET H2 JURA SCALE %f" );

					/* pointer to where to write */
					optimize.nvfpnt[optimize.nparm] = input.nRead;

					/* log of Jura rate scale factor will be parameter */
					optimize.vparm[0][optimize.nparm] = (float)log10(hmi.ScaleJura);
					optimize.vincr[optimize.nparm] = 0.3f;

					++optimize.nparm;
				}
			}
			else
			{
				fprintf( ioQQQ, " The Jura rate option is wrong.\n Sorry.\n" );
				puts( "[Stop in ParsePunch]" );
				cdEXIT(EXIT_FAILURE);
			}
		}

		/* what temperature to use for binding energy, Tad in Le Bourlot, J., 2000, A&A, 360, 656-662  */
		else if( lgMatch(" TAD",chCard) )
		{
			hmi.Tad = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
				NoNumb(chCard);
			/* log if <= 10. unless linear key appears too */
			if( hmi.Tad <=10. && !lgMatch("LINE",chCard) )
				hmi.Tad = (float)pow(10.f,hmi.Tad);
		}

		else if( lgMatch("FRAC",chCard ) )
		{
			/* this is special option to force H2 abundance to value for testing
			 * this factor will multiply the hydrogen density to become the H2 density
			 * no attempt to conserve particles, or do the rest of the molecular equilibrium
			 * set consistently is made */
			hmi.H2_frac_abund_set = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
				NoNumb( chCard );

			/* a number <= 0 is the log of the ratio */
			if( hmi.H2_frac_abund_set <= 0. )
				hmi.H2_frac_abund_set = pow(10., hmi.H2_frac_abund_set);
			/* don't let it exceed 0.5 */
			/* >>chng 03 jul 19, from 0.5 to 0.4999, do not want atomic density exactly zero */
			hmi.H2_frac_abund_set = MIN2(0.49999 , hmi.H2_frac_abund_set );
		}
	}

	/* this is a scale factor that changes the n(H0)*1.7e-4 that is added to the
	 * electron density to account for collisions with atomic H.  it is an order of
	 * magnitude guess, so this command provides ability to see whether it affects results */
	else if( lgMatch("HCOR",chCard)  )
	{
		dense.HCorrFac = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
			NoNumb( chCard );
	}

	else if( lgMatch(" PAH",chCard)  )
	{
		/* set one of severl possible PAH abundance distribution functions */
		if( lgMatch(" H0 " , chCard ) )
		{
			/* the default, abundance depends on H0 / Htot */
			strcpy( gv.chPAH_abundance_fcn , "H0" );
		}
		else if( lgMatch("CONS" , chCard ) )
		{
			/* constant PAH abundance */
			strcpy( gv.chPAH_abundance_fcn , "CON" );
		}

		else if(lgMatch("BAKE",chCard ) )
		{
			/* turn on simnple PAH heating from Bakes & Tielens - this is very approximate */
			/*>>>refer	PAH	heating	Bakes, E.L.O., & Tielens, A.G.G.M. 1994, ApJ, 427, 822 */
			gv.lgBakesPAH_heat = TRUE;
			/* warn that this model is not the best we can do */
			phycon.lgPhysOK = FALSE;
		}
		else
		{
			fprintf( ioQQQ, " one of the keywords H0, BAKES, or CONStant must appear.\n Sorry." );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("PRES",chCard) && lgMatch("IONI",chCard) )
	{
		/* set limit to number of calls from pressure to ionize solver,
		 * this set limit to conv.nPres2Ioniz */
		i = 5;
		conv.limPres2Ioniz = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		else if( conv.limPres2Ioniz <= 0 )
		{
			fprintf( ioQQQ, " The limit must be greater than zero.\n Sorry." );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}
	/* something to do with pressure */
	else if( lgMatch("PRES",chCard) )
	{
		/* tolerance on pressure convergence */
		if( lgMatch("CONV",chCard) )
		{
			/* keyword is tolerance 
			 * set tolerance in pressure match */
			i = 5;
			conv.PressureErrorAllowed = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}

			if( conv.PressureErrorAllowed < 0. )
			{
				conv.PressureErrorAllowed = (float)pow(10.f,conv.PressureErrorAllowed);
			}
		}

		else
		{
			/* >>chng 04 mar 02, printout had been wrong, saying TOLErange
			 * rather than CONVergence.  Nick Abel */
			fprintf( ioQQQ, " I didn\'t recognize a key on this SET PRESSURE line.\n" );
			fprintf( ioQQQ, " The ones I know about are: CONVergence.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}
	else if( lgMatch("RECO",chCard) && lgMatch("MBIN",chCard) )
	{
		/* dielectronic recombination */
		if( lgMatch("DIEL",chCard) && lgMatch("ECTR",chCard) )
		{
			/* change various factors for dielectronic recombination */
			if( lgMatch("KLUD",chCard) )
			{
				if( lgMatch("BADN",chCard) )
				{
					/* set true to use Badnell mean in place of existing hacks */
					ionbal.lg_use_DR_Badnell_rate_coef_mean_ion = TRUE;
				}
				else
				{
					int j;
					/* option to turn off guess of diel rec coef for 3rd row elements */
					i = 3;
					/* this is first call, no number, lgEOL true but zero returned, the intended effect*/
					ionbal.GuessDiel[0] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
					/* >>chng 06 jan 30 also turn off steve kraemer guess if GuessDiel set zero */
					if( ionbal.GuessDiel[0]<=0. || lgMatch(" OFF",chCard) )
						ionbal.lg_guess_coef = FALSE;

					for( j=1; j<4; ++j )
					{
						ionbal.GuessDiel[j] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
						/* here lgEOL means to use previous values */
						if( lgEOL )
							ionbal.GuessDiel[j] = ionbal.GuessDiel[j-1];
					}
				}
				/* option to add log normal noise */
				if( lgMatch("NOISE" , chCard ) ) 
				{
					i = 3;
					ionbal.guess_noise = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
					if( lgEOL )
						ionbal.guess_noise = 2.;
					/* Seed the random-number generator with current time so that
					 * the numbers will be different every time we run. */
					srand( (unsigned)time( NULL ) );
				}
				else
				{
					ionbal.guess_noise = 0.;
				}
			}

			else if( lgMatch("BURG"  , chCard) )
			{
				/* modify suppression of burgess dielectronic recombinations */
				if( lgMatch(" ON ",chCard) )
				{
					/* leave suppression on - this is default state */
					ionbal.lgSupDie[0] = TRUE;
				}

				else if( lgMatch(" OFF",chCard) )
				{
					/* turn suppression off */
					ionbal.lgSupDie[0] = FALSE;
				}

				else
				{
					fprintf( ioQQQ, " flag ON or OFF must appear.\n" );
					puts( "[Stop in ParseCommands]" );
					cdEXIT(EXIT_FAILURE);
				}
			}

			else if( lgMatch("NUSS"  , chCard) )
			{
				/* modify suppression of nussbaumer and storey dielectronic recomb */
				if( lgMatch(" ON ",chCard) )
				{
					/* turn suppression on */
					ionbal.lgSupDie[1] = TRUE;
				}
				else if( lgMatch(" OFF",chCard) )
				{
					/* leave suppression off - this is default state */
					ionbal.lgSupDie[1] = FALSE;
				}
				else
				{
					fprintf( ioQQQ, " flag ON or OFF must appear.\n" );
					puts( "[Stop in ParseCommands]" );
					cdEXIT(EXIT_FAILURE);
				}
			}

			else if( lgMatch("BADN" , chCard ) )
			{
				/* use the new (in early 2006) Badnell DR rates */
				ionbal.lgDR_recom_Badnell_use = TRUE;
				/* option to print rates then exit */
				if( lgMatch("PRIN" , chCard ) )
					ionbal.lgRecom_Badnell_print = TRUE;
			}
			else
			{
				fprintf( ioQQQ, " key KLUDge, BURGess, STEVE, or NUSSbaumer must appear.\n" );
				puts( "[Stop in ParseCommands]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		/* radiative recombination */
		else if( lgMatch("RADI",chCard) && lgMatch("ATIV",chCard) )
		{
			if( lgMatch("BADN" , chCard ) )
			{
				/* use the new (in early 2006) Badnell DR rates */
				ionbal.lgRR_recom_Badnell_use = TRUE;
				/* option to print rates then exit */
				if( lgMatch("PRIN" , chCard ) )
					ionbal.lgRecom_Badnell_print = TRUE;
			}
			else
			{
				fprintf( ioQQQ, " key BADNell must appear.\n" );
				puts( "[Stop in ParseCommands]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		else
		{
			fprintf( ioQQQ, " key RADIATIve or DIELECTRonic must appear on set recombination command.\n" );
			puts( "[Stop in ParseCommands]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("SPEC",chCard) )
	{
		/* "set spectrum" for optional parameters for punch spectrum command */
		if( lgMatch("RANG" , chCard ) )
		{
			/* energy range option - arg is energy in Rydbergs */
			i = 5;
			/* >>chng 05 aug 25, rm pow(10., - was wrong */
			punch.cp_range_min[punch.cp_npun] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			punch.cp_range_max[punch.cp_npun] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}
			/* contfirm that wavelengths are in correct order */
			if( punch.cp_range_min[punch.cp_npun] >= punch.cp_range_max[punch.cp_npun] )
			{
				fprintf( ioQQQ, " The limits must be in increasing order.\n" );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}
		}

		else if( lgMatch("RESO" , chCard ) )
		{
			/* resolving power, default is zero, which means leave at native resolution */
			/* >>chng 05 aug 25, following had pow(number), so crashed for high resolv power
			 * bug caught by Yan Changshou */
			i = 5;
			punch.cp_resolving_power[punch.cp_npun] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}
		}
	}

	else if( lgMatch(" DR ",chCard) )
	{
		/* set zone thickness by forcing drmax and drmin */
		i = 5;
		/* at this stage linear, but default is log */
		radius.sdrmax = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( !lgMatch("LINE",chCard) ) 
		{
			/* linear was not on command, so default is log */
			radius.sdrmax = pow( 10. , radius.sdrmax );
		}
		if( lgEOL )
		{
			NoNumb(chCard);
		}

		/* NB these being equal are tested in convinittemp to set dr */
		radius.sdrmin = radius.sdrmax;
		if( radius.sdrmax < DEPTH_OFFSET*1e4 )
		{
			fprintf( ioQQQ, "\n Thicknesses less than about %.0e will NOT give accurate results. If tricking the code\n",
					 DEPTH_OFFSET*1e4 );
			fprintf( ioQQQ, " into computing emissivities instead of intensities, try to instead use a thickness of unity,\n" );
			fprintf( ioQQQ, " and then multipy (divide) the results by the necessary thickness (product of densities).\n\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("DRMA",chCard) )
	{
		/* set maximum zone thickness */
		i = 5;
		radius.sdrmax = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));
		if( lgEOL )
		{
			NoNumb(chCard);
		}
	}

	else if( lgMatch("DRMI",chCard) )
	{
		/* set minimum zone thickness */
		i = 5;
		radius.sdrmin = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		radius.lgSMinON = TRUE;
	}

	else if( lgMatch("FLXF",chCard) )
	{
		/* faintest continuum flux to consider */
		i = 5;
		rfield.FluxFaint = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		if( rfield.FluxFaint < 0. )
		{
			rfield.FluxFaint = (float)pow(10.f,rfield.FluxFaint);
		}
	}

	else if( lgMatch("LINE",chCard) && lgMatch("PREC",chCard) )
	{
		/* set line precision (number of significant figures)
		 * this affects all aspects of reading and writing lines */
		i = 5;
		LineSave.sig_figs = (int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
		else if( LineSave.sig_figs > 5 )
		{
			fprintf( ioQQQ, " set line precision currently only works for up to 5 significant figures.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
		/* option to print main line array as a single column */
		/* prt.lgPrtLineArray = FALSE; */
	}

	/* >>chng 00 dec 08, command added by Peter van Hoof */
	else if( lgMatch("NFNU",chCard) )
	{
		/* set nFnu [incident_reflected] [incident_transmitted] [diffuse_inward] [diffuse_outward]
		 *   command for specifying what to include in the nFnu entries in LineSv */
		/* >>chng 01 nov 12, also accept form with space */
		/* "incident reflected" keyword */
		prt.lgSourceReflected = lgMatch("NT R",chCard) || lgMatch("NT_R",chCard);
		/* "incident transmitted" keyword */
		prt.lgSourceTransmitted = lgMatch("NT_T",chCard) || lgMatch("NT T",chCard);
		/* "diffuse inward" keyword */
		prt.lgDiffuseInward = lgMatch("SE_I",chCard) || lgMatch("SE I",chCard);
		/* "diffuse outward" keyword */
		prt.lgDiffuseOutward = lgMatch("SE_O",chCard) || lgMatch("SE O",chCard);

		/* at least one of these needs to be set ! */
		if( ! ( prt.lgSourceReflected || prt.lgSourceTransmitted ||
			prt.lgDiffuseInward || prt.lgDiffuseOutward ) )
		{
			fprintf( ioQQQ, " set nFnu expects one or more of the following keywords:\n" );
			fprintf( ioQQQ, " INCIDENT_REFLECTED, INCIDENT_TRANSMITTED, DIFFUSE_INWARD, DIFFUSE_OUTWARD\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
		/* automatically print the nFnu items in the output - it is not necessary to also include
		 * a print continua command if this is entered */
		prt.lgPrnDiff = TRUE;
	}

	else if( lgMatch("IND2",chCard) )
	{
		if( lgMatch(" ON ",chCard) )
		{
			/* set flag saying to off or on induced two photon processes */
			iso.lgInd2nu_On = TRUE;
		}
		else if( lgMatch(" OFF",chCard) )
		{
			iso.lgInd2nu_On = FALSE;
		}
		else
		{
			fprintf( ioQQQ, " set ind2 needs either ON or OFF.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("TEMP",chCard) )
	{
		/* set something to do with temperature, currently solver, tolerance, floor */
		if( lgMatch("SOLV",chCard) )
		{
			/* solver */
			/* the electron density solver */
			if( lgMatch("NEW",chCard) ) 
			{
				/* new method */
				strcpy( conv.chSolverTemp , "new" );
			}
			else
			{
				/* default method */
				strcpy( conv.chSolverTemp , "simple" );
			}
		}

		else if( lgMatch("FLOO",chCard) )
		{
			i = 5;
			StopCalc.TeFloor = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

			/*  linear option */
			if( StopCalc.TeFloor <= 10. && !lgMatch("LINE",chCard) )
			{
				StopCalc.TeFloor = (float)pow(10.f,StopCalc.TeFloor);
			}

			if( lgEOL )
			{
				NoNumb(chCard);
			}

			if( StopCalc.TeFloor < 2.8 )
			{
				fprintf( ioQQQ, " TE < 3K, reset to 2.8K.\n" );
				StopCalc.TeFloor = 2.8f;
			}
		}

		else if( lgMatch("CONV",chCard) || lgMatch("TOLE",chCard) )
		{
			/* error tolerance in heating cooling match, number is error/total */
			i = 5;
			conv.HeatCoolRelErrorAllowed = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}
			if( conv.HeatCoolRelErrorAllowed <= 0. )
			{
				conv.HeatCoolRelErrorAllowed = (float)pow(10.f,conv.HeatCoolRelErrorAllowed);
			}
		}

		else
		{
			fprintf( ioQQQ, "\nI did not recognize a keyword on this SET TEPERATURE command.\n%s\n" , chCard);
			fprintf( ioQQQ, "The keywords are SOLVer, FLOOr, and CONVergence.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("TEST",chCard) )
	{
		/* set flag saying to turn on some test - this is in cddefines.h in the global namespace */
		lgTestCodeEnabled = TRUE;
	}

	else if( lgMatch("TRIM",chCard) )
	{
		/* set trim upper or lower, for ionization stage trimming
		 * ion trimming ionization trimming 
		 * in routine TrimStage */
		i = 5;
		if( lgMatch("UPPE",chCard) )
		{
			/* set trim upper - either set value or turn off */
			double save = ionbal.trimhi;
			ionbal.trimhi = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));
			if( lgEOL  && lgMatch(" OFF",chCard) )
			{
				/* turn off upward trimming */
				lgEOL = FALSE;
				ionbal.lgTrimhiOn = FALSE;
				/* reset high limit to proper value */
				ionbal.trimhi = save;
			}
		}

		else if( lgMatch("LOWE",chCard) )
		{
			/* set trim lower */
			ionbal.trimlo = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));
		}

		/* turn off ionization stage trimming */
		else if( lgMatch("SMAL",chCard) || lgMatch(" OFF",chCard) )
		{
			/* set small limits to both upper and lower limit*/
			ionbal.trimlo = SMALLFLOAT;
			ionbal.trimhi = SMALLFLOAT;
			lgEOL = FALSE;
		}

		else
		{
			/* set trim upper */
			ionbal.trimhi = pow(10.,FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL));

			/* set trim lower to same number */
			ionbal.trimlo = ionbal.trimhi;
		}

		if( lgEOL )
		{
			NoNumb(chCard);
		}

		if( ionbal.trimlo >= 1. || ionbal.trimhi >= 1. )
		{
			fprintf( ioQQQ, " number must be negative since log\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("SKIP",chCard) )
	{
		/* skip punch command, for punching every n't point */
		i = 5;
		punch.ncPunchSkip = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
	}

	else if( lgMatch("EAKH",chCard) )
	{
		/* set WeakHeatCool, threshold on punch heating and cooling, default 0.05 */
		i = 5;
		punch.WeakHeatCool = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

		if( lgEOL )
		{
			NoNumb(chCard);
		}

		if( punch.WeakHeatCool < 0. )
		{
			punch.WeakHeatCool = (float)pow(10.f,punch.WeakHeatCool);
		}
	}

	else if( lgMatch("KSHE",chCard) )
	{
		/* upper limit to opacities for k-shell ionizaiton */
		i = 5;
		KshllEnr.EnergyKshell = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}

		if( KshllEnr.EnergyKshell == 0. )
		{
			/* arg of 0 causes upper limit to energy array */
			KshllEnr.EnergyKshell = rfield.egamry;
		}

		else if( KshllEnr.EnergyKshell < 194. )
		{
			fprintf( ioQQQ, " k-shell energy must be greater than 194 Ryd\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( lgMatch("NCHR",chCard) )
	{
		/* option to set the number of charge states for grain model */
		long ii = 5;
		double val = FFmtRead(chCard,&ii,INPUT_LINE_LENGTH,&lgEOL);

		if( lgEOL )
		{
			NoNumb(chCard);
		}
		else
		{
			long nChrg = NINT(val);
			if( nChrg < 2 || nChrg > NCHS )
			{
				fprintf( ioQQQ, " illegal value for number of charge states: %ld\n", nChrg );
				fprintf( ioQQQ, " choose a value between 2 and %ld\n", NCHS );
				fprintf( ioQQQ, " or increase NCHS in grainvar.h and recompile\n" );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}
			else
			{
				SetNChrgStates(nChrg);
			}
		}
	}

	else if( lgMatch("NEGO",chCard) )
	{
		/* punch negative opacities if they occur, set negopac */
		opac.lgNegOpacIO = TRUE;
	}

	else if( lgMatch("NEND",chCard) )
	{
		/* default limit to number of zones to be computed
		 * only do this if nend is NOT currently left at its default
		 * nend is set to nEndDflt in routine zero
		 * this command only has effect if stop zone not entered */
		if( geometry.lgEndDflt )
		{
			i = 5;
			/* this is default limit to number of zones, change it to this value */
			geometry.nEndDflt = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			geometry.lgEndDflt = FALSE;
			if( lgEOL )
			{
				NoNumb(chCard);
			}

			/* now change all limits, for all iterations, to this value */
			for( i=0; i < ITRDIM; i++ )
			{
				geometry.nend[i] = geometry.nEndDflt;
			}
		}
	}

	else if( lgMatch("TSQD",chCard) )
	{
		/* upper limit for highest density considered in the 
		 * Peimbert-style t^2 section of the printout */
		i = 5;
		peimbt.tsqden = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

		if( lgEOL )
		{
			NoNumb(chCard);
		}
		peimbt.tsqden = (float)pow(10.f,peimbt.tsqden);
	}

	else if( lgMatch("NMAP",chCard) )
	{
		/* how many steps in plot or punch of heating-cooling map */
		i = 5;
		map.nMapStep = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}
	}

	else if( lgMatch("NUME",chCard) && lgMatch("DERI",chCard) )
	{
		/* this is an option to use numerical derivatives for heating and cooling */
		NumDeriv.lgNumDeriv = TRUE;
	}

	/* set path for certain files */
	else if( lgMatch("PATH",chCard) )
	{
		/* set path for picking up files
		 * format is for path to be within double quotes */
		lgDataPathSet = TRUE;

		/* 
		 * get any string within double quotes, and return it as
		 * null terminated string to chDataPath
		 * also sets name in OrgCard and chCard to blanks so that
		 * do not trigger off it later 
		GetQuote( chDataPath , chCard , TRUE );*/
		strcpy( chDataPath , chString );
		/* make sure path ends with proper end of line for unix, dos, or vms *
		 * do nothing in any of these cases */

		/* find end of string, null char */
		chEnd = strchr( chDataPath ,'\0' );
		if( chEnd==NULL )
		{
			fprintf( ioQQQ, " strchr returned NULL in ParseSet\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}

		/* set pointer to last valid char */
		--chEnd;

		/* now see what this char is */
		if( (*chEnd != '/' && *chEnd != ']') && *chEnd != '\\' )
		{
			/* string is not ended properly, we will have to do it */

			/* find which character to end with since none set above *
			 * there must have been something within the string to indicate 
			 * what type of system we are on */
			if(strchr( chDataPath , '/' ) != NULL )
			{
				/* there was a forward slash somewhere, so cat another to the end */
				strcat( chDataPath , "/" );
			}
			else if( strchr( chDataPath , '\\' ) != NULL )
			{
				/* there was a backward slash somewhere, so cat another to the end */
				strcat( chDataPath , "\\" );
			}
			else if( strchr( chDataPath , '[' ) != NULL )
			{
				/* there was a [ somewhere, so cat ] to the end */
				/* this should work on a vms machine, but I have not tried it */
				strcat( chDataPath , "]" );
			}
			/* if none of the above were triggered then we did not find anything, 
			 * just leave it alone, either user knew something we didn't, or will
			 * fail when we try to open the file later on */
		}
		/*printf(" final path is %s \n",chDataPath );*/
	}

	else if( lgMatch("PHFI",chCard) )
	{
		/* which version of PHFIT to use, 1995 or 1996 */
		i = 5;
		ip = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
		if( lgEOL )
		{
			NoNumb(chCard);
		}

		if( ip == 1995 )
		{
			/* option to go back to old results, pre op */
			PhFitOn.lgPhFit = TRUE;
		}
		else if( ip == 1996 )
		{
			/* default is to use newer results, including opacity project */
			PhFitOn.lgPhFit = FALSE;
		}
		else
		{
			fprintf( ioQQQ, " Two possible values are 1995 and 1996.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	/* set punch xxx command */
	else if( lgMatch("PUNC",chCard) )
	{
		if( lgMatch("HASH",chCard) )
		{
			char chTmpHashString[INPUT_LINE_LENGTH];
			/* specify the terminator between punch output sets - normally a set of hash marks */
			/* 
			* get any string within double quotes, and return it as
			* null terminated string to chDataPath
			* also sets name in OrgCard and chCard to blanks so that
			* do not trigger off it later 
			GetQuote( chTmpHashString , chCard , TRUE );*/
			strcpy( chTmpHashString , chString );
			if( strcmp( chTmpHashString , "return" ) == 0 )
			{
				sprintf(punch.chHashString , "\n" );
			}
			else
			{
				sprintf(punch.chHashString , chTmpHashString );
			}
		}

		else if( lgMatch("WIDT",chCard) )
		{
			/* set punch line width for contrast in continuum plots */
			i = 5;
			/* units are km/sec */
			punch.PunchLWidth = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

			/* lgEOL if no number hit, could have been c */
			if( lgEOL )
			{
				if( lgMatch(" C " , chCard ) )
				{
					/* no number but _c_ entered, so enter speed of light in km/s */
					punch.PunchLWidth = (float)(SPEEDLIGHT/1e5);
				}
				else
				{
					NoNumb(chCard);
				}
			}

			if( punch.PunchLWidth <= 0. )
			{
				fprintf( ioQQQ, " line width must be greater than zero.\n" );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}

			else if( punch.PunchLWidth > SPEEDLIGHT )
			{
				fprintf( ioQQQ, " line width must be entered in cm/s and less than c.\n" );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}
			/* this is the factor that is used to add the lines to the continuum,
			* 15 converts to cm/s */
			punch.PunchLWidth = (float)(SPEEDLIGHT/(punch.PunchLWidth*1e5));

		}

		else if( lgMatch("PREF",chCard) )
		{
			/* specify a prefix before all punch filenames */
			/* 
			* get any string within double quotes, and return it as
			* null terminated string to chDataPath
			* also sets name in OrgCard and chCard to blanks so that
			* do not trigger off it later 
			
			GetQuote( punch.chFilenamePrefix , chCard , TRUE );*/
			strcpy( punch.chFilenamePrefix , chString );
		}

		else if( lgMatch("FLUS",chCard) )
		{
			/* flus the output after every iteration */
			punch.lgFLUSH = TRUE;
		}

		else
		{
			fprintf( ioQQQ, " There should have been an option on this command.\n" );
			fprintf( ioQQQ, " Valid options are HASH and PREFIX.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	/* set continuum .... options */
	else if( lgMatch("CONT" , chCard ) )
	{
		if( lgMatch("RESO" , chCard ) )
		{
			/* set resolution, get factor that will multiply continuum resolution that
			* is contained in the file continuum_mesh.dat */
			i = 5;
			continuum.ResolutionScaleFactor = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			if( lgEOL )
			{
				NoNumb(chCard);
			}
			/* negative numbers were logs */
			if( continuum.ResolutionScaleFactor <= 0. )
				continuum.ResolutionScaleFactor = pow(10.,continuum.ResolutionScaleFactor);
		}

		else if( lgMatch("SHIE" , chCard ) )
		{
			/* set continuum shielding function */
			/* these are all possible values of rt.nLineContShield,
			 * first is default, these are set with set continuum shielding */
			/*#define LINE_CONT_SHIELD_PESC	1*/
			/*#define LINE_CONT_SHIELD_FEDERMAN	2*/
			/*#define LINE_CONT_SHIELD_FERLAND	3*/
			if( lgMatch("PESC" , chCard ) )
			{
				/* this uses an inward looking escape probability */
				rt.nLineContShield = LINE_CONT_SHIELD_PESC;
			}
			else if( lgMatch("FEDE" , chCard ) )
			{
				/* set continuum shielding federmain,
				 * this is the default, and uses the appendix of
				 * >>refer	RT	continuum shielding	Federman, S.R., Glassgold, A.E., & 
				 * >>refercon	Kwan, J. 1979, ApJ, 227, 466*/
				rt.nLineContShield = LINE_CONT_SHIELD_FEDERMAN;
			}
			else if( lgMatch("FERL" , chCard ) )
			{
				rt.nLineContShield = LINE_CONT_SHIELD_FERLAND;
			}
			else if( lgMatch("NONE" , chCard ) )
			{
				/* turn off continuum shielding */
				rt.nLineContShield = 0;
			}
			else
			{
				fprintf( ioQQQ, " I didn\'t recognize a key on this SET CONTINUUM SHIELDing line.\n" );
				fprintf( ioQQQ, " The ones I know about are: PESC, FEDErman, & FERLand.\n" );
				puts( "[Stop in ParseSet]" );
				cdEXIT(EXIT_FAILURE);
			}
		}

		else
		{
			fprintf( ioQQQ, " I didn\'t recognize a key on this SET CONTINUUM line.\n" );
			fprintf( ioQQQ, " The ones I know about are: RESOlution.\n" );
			puts( "[Stop in ParseSet]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else
	{
		fprintf( ioQQQ, " I didn\'t recognize a key on this SET line.\n" );
		puts( "[Stop in ParseSet]" );
		cdEXIT(EXIT_FAILURE);
	}


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

