/* 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 */
/*ConvIoniz called by ConvEdenIonz, it calls ConvBase until converged */
#include "cddefines.h"
#include "thermal.h"
#include "trace.h"
#include "converge.h"

/*ConvIoniz called by ConvEdenIonz, it calls ConvBase until converged 
 * returns 1 if error condtion, 0 if ok */
int ConvIoniz(void)
{
	long int 
		/* the oinization loop counter */
		loopi ,
		/* the limit to how many times we will try calling ConvBase before giving up */
		LoopLimit;

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

	/* this routine is called by ConvTempIonz, it calls ConvBase
	 * until it converges */

	if( conv.lgSearch )
	{
		/* expand limit to number of calls to ConvBase during search phase */
		LoopLimit = 30;
	}
	else
	{
		LoopLimit = 20;
	}

	/* zero the ionization loop counter */
	loopi = 0;

	/* do not go into the loop with first call to ioniz,
	 * since results will be bogus - do it here */
	if( !conv.lgSearch && conv.nPres2Ioniz == 0 )
	{
		if( ConvBase(loopi) )
		{
#			ifdef DEBUG_FUN
			fputs( " <->ConvIoniz()\n", debug_fp );
#			endif
			return 1 ;
		}
	}

	strcpy( conv.chConvIoniz, " NONE!!!!!" );
	/* this is ionization/electron density convergence loop
	 * keep calling ConvBase until lgIonDone is true */
	do 
	{
		/* compute the current ionization, ots rates, secondary ionization rates */
		if( ConvBase(loopi) )
		{
#			ifdef DEBUG_FUN
			fputs( " <->ConvIoniz()\n", debug_fp );
#			endif

			return 1 ;
		}

		if( trace.lgTrConvg>=4 )
		{
			/* cooling has not been evaluated yet */
			fprintf( ioQQQ, 
				"    ConvIoniz4%4ld heat:%10.2e cool:%10.2e ", 
			  loopi, thermal.htot , thermal.ctot );

			/* this is flag saying whether or not ionization/eden has converged */
			if( conv.lgConvIoniz )
			{
				fprintf( ioQQQ, " ioniz converged\n" );
			}
			else
			{
				fprintf( ioQQQ, " ioniz no conv:%10.10s old %.4e new %.4e OscilOTS %c\n", 
				  conv.chConvIoniz , 
				  conv.BadConvIoniz[0] ,
				  conv.BadConvIoniz[1] ,
				  TorF(conv.lgOscilOTS) );
			}
		}

		/* increment ionization loop, and keep going until we converge */
		++loopi;
	}	while( !conv.lgConvIoniz && loopi < LoopLimit && !conv.lgAbort );

	if( !conv.lgConvIoniz )
	{
		/* this is a major problem, ConvIoniz did not converge the ionization */
		++conv.nConvIonizFails;
		/* this is flag saying that an ionization convergence problem occurred in this
		 * zone, will be used to help choose next dr */
		++conv.lgConvIonizThisZone;
	}

	/* if trace convergence is in operation and we did not converge, give warning */
	if( trace.lgTrConvg>=4 && !conv.lgConvIoniz )
	{
		fprintf( ioQQQ, 
			"    ConvIoniz4>>>>>>>>>>exit without converging after %li tries!!!!\n",loopi);
	}
#	if 0
	{
#include "grainvar.h"
#include "dense.h"
#include "co.h"
	fprintf(ioQQQ,"DEBUG co mol eden\t%.2f\t%e\t%e\t%e\t%e\n",
		fnzone,
		dense.eden,
		gv.TotalEden,
		co.comole_eden ,
		dense.EdenTrue);
	}
#	endif

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

	return 0 ;
}

