/* 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 */
/*punch_line parse punch lines command, or actually do the punch lines output */
/*Punch_Line_RT parse the punch line rt command - read in a set of lines */
#include "cddefines.h"
#include "cddrive.h"
#include "radius.h"
#include "taulines.h"
#include "opacity.h"
#include "phycon.h"
#include "dense.h"
#include "lines_service.h"
#include "input.h"
#include "prt.h"
#include "punch.h"
/* this is the limit to the number of lines we can store */
#define	NPUNLM	100L

void punch_line(FILE * ip, /* the file we will write to */
  const char *chDo, 
  int lgLog3)
{
	char chCap[INPUT_LINE_LENGTH], 
	  chCard[INPUT_LINE_LENGTH];

	static char chPLab[NPUNLM][5];
	int lgEOF, 
	  lgEOL, 
	  lgOK;
	static int lgRelhld;
	long int i;
	static long int nLinesEntered;
	static float wavelength[NPUNLM];
	static long int ipLine[NPUNLM];
	double a[32], 
	  absint, 
	  emiss, 
	  relint;
	double dlum[NPUNLM];

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

	if( strcmp(chDo,"READ") == 0 )
	{
		/* very first time this routine is called, chDo is "READ" and we read
		 * in lines from the input stream.  The line labels and wavelengths
		 * are store locally, and output in later calls to this routine */
		lgRelhld = lgLog3;

		/* number of lines we will save */
		nLinesEntered = 0;

		/* get the next line, and check for eof */
		input_readarray(chCard,&lgEOF);
		if( lgEOF )
		{
			fprintf( ioQQQ, 
				" Hit EOF while reading line list; use END to end list.\n" );
			puts( "[Stop in punch_line]" );
			cdEXIT(EXIT_FAILURE);
		}

		/* convert line to caps */
		strcpy( chCap, chCard );
		caps(chCap);

		while( strncmp(chCap, "END" ,3 ) != 0 )
		{
			if( nLinesEntered >= NPUNLM )
			{
				fprintf( ioQQQ, 
					" Too many lines have been entered; the %ld limit is.  Increase variable NPUNLM in routine punch_line.\n", 
				  NPUNLM );
				puts( "[Stop in punch_line]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* order on line is label (col 1-4), wavelength */
			strncpy( chPLab[nLinesEntered], chCard , 4 );

			/* null terminate the string*/
			chPLab[nLinesEntered][4] = 0;

			/* now get wavelength */
			i = 5;
			wavelength[nLinesEntered] = (float)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

			/* now convert wavelength to angstroms */
			/* line was entered, look for possible micron or cm label */
			if( input.chCARDCAPS[i-1] == 'M' )
			{
				/* microns */
				wavelength[nLinesEntered] *= 1e4;
			}
			else if( input.chCARDCAPS[i-1] == 'C' )
			{
				/* microns */
				wavelength[nLinesEntered] *= 1e8;
			}

			/* this is total number stored so far */
			++nLinesEntered;

			/* get next line and check for eof */
			input_readarray(chCard,&lgEOF);
			if( lgEOF )
			{
				fprintf( ioQQQ, " Hit EOF while reading line list; use END to end list.\n" );
				puts( "[Stop in punch_line]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* convert it to caps */
			strcpy( chCap, chCard );
			caps(chCap);
		}

		/*fprintf( ip, "%li lines were entered, they were;\n", 
		  nLinesEntered );*/

		fprintf( ip, "#depth\t");
		for( i=0; i < nLinesEntered; i++ )
		{
			fprintf( ip, "%s ", chPLab[i] );
			prt_wl(  ip, wavelength[i] );
			fprintf( ip, "\t" );
		}
		fprintf( ip, "\n" );
	}

	else if( strcmp(chDo,"PUNS") == 0 )
	{
		static int lgMustGetLines=TRUE,
			lgBadLine=FALSE;
		lgBadLine = FALSE;
		/* punch lines structure command */
		for( i=0; i < nLinesEntered; i++ )
		{
			if( nzone <= 1 && lgMustGetLines )
			{
				if( (ipLine[i] = cdEmis((char*)chPLab[i],wavelength[i],&emiss)) <= 0 )
				{
					/* next just to trick the lint */
					dlum[i] = emiss;
					fprintf( ioQQQ, " PUNLIN could not find line: %s %f\n", 
					  chPLab[i], wavelength[i] );
					lgBadLine = TRUE;
				}
			}
			/* 0th line is dummy, can't be used, so this is safe */
			ASSERT( ipLine[i] > 0 || lgBadLine );
			/* this version of cdEmis uses index, does not search, do not call if line could not be found */
			if( !lgBadLine )
				cdEmis_ip(ipLine[i],&dlum[i]);
		}
		if( lgBadLine )
		{
			puts( "[Stop in punch_line]" );
			cdEXIT(EXIT_FAILURE);
		}
		lgMustGetLines = FALSE;

		/* print depth */
		fprintf( ip, "%.5e", radius.depth_mid_zone );

		/* then print all line emissivity */
		for( i=0; i < nLinesEntered; i++ )
		{
			/*lint -e644 dlum not initialized */
			fprintf( ip, "\t%12.4e", dlum[i] );
			/*lint +e644 dlum not initialized */
		}
		fprintf( ip, "\n" );
	}

	else if( strcmp(chDo,"PUNC") == 0 )
	{
		/* punch lines cumulative command */
		for( i=0; i < nLinesEntered; i++ )
		{
			if( lgRelhld )
			{
				lgOK = (int)cdLine((char*)chPLab[i],wavelength[i],&a[i],&absint) ;
			}
			else
			{
				lgOK = (int)cdLine((char*)chPLab[i],wavelength[i],&relint,&a[i]) ;
			}

			if( lgOK<=0 )
			{
				fprintf( ioQQQ, " PUNLIN could not fine line: %s %f\n", 
				  chPLab[i], wavelength[i] );
				puts( "[Stop in punch_line]" );
				cdEXIT(EXIT_FAILURE);
			}
		}
		fprintf( ip, "%.5e", radius.depth_mid_zone );

		for( i=0; i < nLinesEntered; i++ )
		{
			/*lint -e771 a not initialized */
			fprintf( ip, "%12.4e", a[i] );
			/*lint +e771 a not initialized */
		}
		fprintf( ip, "\n" );

	}
	else
	{
		fprintf( ioQQQ, 
			" unrecognized key for punch_line=%4.4s\n", 
		  chDo );
		puts( "[Stop in punch_line]" );
		cdEXIT(EXIT_FAILURE);
	}

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

/*Punch_Line_RT parse the punch line rt command - read in a set of lines */
void Punch_Line_RT( 
	FILE * ip, /* the file we will write to */
	char *chDo )
{
#	define LIMLINE	10
	/* punch line rt parameters */
	static long int 
		line_RT_type[LIMLINE] = 
	{LONG_MIN , LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN },
		line_RT_ipISO[LIMLINE] =  
	{LONG_MIN , LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN },
		line_RT_nelem[LIMLINE] =  
	{LONG_MIN , LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN },
		line_RT_ipHi[LIMLINE] =  
	{LONG_MIN , LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN },
		line_RT_ipLo[LIMLINE] = 
	{LONG_MIN , LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN ,LONG_MIN };
	static int lgMustPrintHeader=TRUE;
	static long int nLine=-1;
	long int i;
	int lgEOF , lgEOL;
	char chCap[LIMLINE][INPUT_LINE_LENGTH], 
	  chCard[INPUT_LINE_LENGTH];


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

	if( strcmp(chDo,"READ") == 0 )
	{
		/* very first time this routine is called, chDo is "READ" and we read
		 * in lines from the input stream.  The line labels and wavelengths
		 * are store locally, and output in later calls to this routine */

		/* say that we must print the header */
		lgMustPrintHeader = TRUE;

		/* get the next line, and check for eof */
		nLine = 0;
		input_readarray(chCard,&lgEOF);
		if( lgEOF )
		{
			fprintf( ioQQQ, 
				" Hit EOF while reading line list; use END to end list.\n" );
			puts( "[Stop in Punch_Line_RT]" );
			cdEXIT(EXIT_FAILURE);
		}

		do
		{
			if(nLine>=LIMLINE )
			{
				fprintf(ioQQQ," PUNCH RT has too many lines - increase LIMLINE in punch_line.c\n");
				puts( "[Stop in Punch_Line_RT]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* convert line to caps */
			strcpy( chCap[nLine], chCard );
			caps(chCap[nLine]);

			/* right now it just does lines in the iso sequences */
			i = 1;
			line_RT_type[nLine] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			line_RT_ipISO[nLine] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			line_RT_nelem[nLine] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			line_RT_ipHi[nLine] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
			line_RT_ipLo[nLine] = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);

			if( lgEOL )
			{
				fprintf( ioQQQ, 
					" there must be five numbers on this line =%s\n", 
				chCard );
				puts( "[Stop in Punch_Line_RT]" );
				cdEXIT(EXIT_FAILURE);
			}

			/* now increment number of lines */
			++nLine;

			/* now get next line until we hit eof or the word END */
			input_readarray(chCard,&lgEOF);
			caps(chCard);
		} while( !lgEOF && !lgMatch( "END" , chCard) );
		if( lgEOF )
		{
			fprintf( ioQQQ, 
				" Punch_Line_RT hit end of file looking for END of RT lines =%s\n", 
			chCard );
			puts( "[Stop in Punch_Line_RT]" );
			cdEXIT(EXIT_FAILURE);
		}
	}

	else if( strcmp(chDo,"PUNC") == 0 )
	{
		static char chLabel[LIMLINE][30];
		long int n;
		if( lgMustPrintHeader )
		{
			fprintf( ip , "Line\tP(con,inc)\tAul\tgl\tgu\n");
			for( n=0; n<nLine; ++n )
			{
				/* print info for header of file, line id and pump rate */
				sprintf( chLabel[n] , "%s ", 
					chLineLbl(&EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]]) );
				fprintf( ip , "%s ", chLabel[n] );
				fprintf( ip , "%.4e ",
					EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].pump);
				fprintf( ip , "%.4e ",
					EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].Aul);
				fprintf( ip , "%.0f ",
					EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].gLo);
				fprintf( ip , "%.0f ",
					EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].gHi);
				fprintf( ip , "\n");

				if( line_RT_type[n]!=0. )
				{
					/* for now code only exists for H He like iso - assert this */
					fprintf( ioQQQ, 
						" PunchLine_RT only H, He like allowed for now\n");
					puts( "[Stop in Punch_Line_RT]" );
					cdEXIT(EXIT_FAILURE);
				}
			}
			fprintf( ip , "Line\tTauIn\tPopLo\tPopHi\tCul\tk(line)\tk(con,abs)\tk(con,scat)\n");
			lgMustPrintHeader = FALSE;
		}

		fprintf(ip, "RADIUS\t%e\tDEPTH\t%e\tTe\t%e\tNe\t%e\n",
			radius.Radius_mid_zone ,
			radius.depth_mid_zone ,
			phycon.te ,
			dense.eden );
		for( n=0; n<nLine; ++n )
		{
			/* index for line within continuum array */
			long int ipCont = EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].ipCont;
			fprintf( ip , "%s ", chLabel[n] );
			fprintf( ip , "\t%e\t%e\t%e",
				EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].TauIn ,
				EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].PopLo ,
				EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].PopHi
			 );
			fprintf( ip , "\t%e",
				EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].ColUL 
			 );

			fprintf( ip , "\t%e\t%e\t%e\n",
				EmisLines[line_RT_ipISO[n]][line_RT_nelem[n]][line_RT_ipHi[n]][line_RT_ipLo[n]].PopOpc ,
				opac.opacity_abs[ipCont-1] ,
				opac.opacity_sct[ipCont-1] 
			 );
		}
	}

	else
	{
		fprintf( ioQQQ, 
			" internal error, unrecognized key for punch line rt=%4.4s\n", 
		  chDo );
		puts( "[Stop in Punch_Line_RT]" );
		cdEXIT(EXIT_FAILURE);
	}

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


