/* 
 * Copyright (C) 1997, Slava Ilyin 
 * Copyright (C) 2001-2003, CompHEP Collaboration
 *----------------------------------------------------
 * $Id: alphas2.c,v 1.5 2003/11/08 19:46:05 kryukov Exp $
 *
 * $Log: alphas2.c,v $
 * Revision 1.5  2003/11/08 19:46:05  kryukov
 * To bring into according the usage of messanykey and warnanykey functions.
 *
 * Revision 1.4  2003/08/25 09:34:54  sherstnv
 * Some very little changes
 *
 * Revision 1.3  2003/07/11 20:36:41  kryukov
 * re_alpha is declared static and move our of alpha_2
 *
*/
#include "chep_crt/include/syst.h"
#include "symb/include/syst2.h"
#include "chep_crt/include/crt_util.h"
#include "plot/include/plot.h"
#include "service2/include/read_func.h"
#include "service2/include/parser.h"
#include "out_ext.h"

#include "4_vector.h"
#include "kinaux.h"
#include "const.h"
#include "strfun.h"
#include "sf_pdf.h"
#include "phys_val.h"
#include "alphas2.h"

#define  XMB 4.3
#define  XMC 1.3
#define  XMTOP 175.

static double b0[7], b1[7], b2[7];
static double qcdL6 = 0.1185;
static shortstr scale_str = "91.187";
static int re_alpha=1;

/**************************************************
* Transformation of Lambda_QCD from NF to NF-1    *
*    (formula from PDG-94)			  *
**************************************************/
static double 
tonf1 (double qcdl, double xmq, int nf)
{
  double rl, b10n, b10n1, a;

  rl = log (xmq / qcdl);

  b10n = b1[nf] / b0[nf];
  b10n1 = b1[nf - 1] / b0[nf - 1];

  a = qcdl * exp (-1 / b0[nf - 1] *
		  (

		    (b0[nf] - b0[nf - 1]) * rl
		    + (b10n - b10n1) * log (rl * 2.)
		    - b10n1 * log (b0[nf] / b0[nf - 1]) +
		    (
		      b10n * (b10n - b10n1) * log (rl * 2.)

		      + b10n * b10n - b10n1 * b10n1
		      - 0.5 * b2[nf] / b0[nf] + 0.5 * b2[nf - 1] / b0[nf - 1]
		      - 7. / 18.
		    ) / (b0[nf] * rl)
		  )
    );
/*fprintf(stderr,"\na=%f, b10n1=%f, b10n=%f, rl=%f\n",a,b10n1,b10n,rl); */
  return a;
}				/* tonf_1__ */

static double 
tonf (double qcdl, double xmq, int nf)
{
  double rl, a, a1;

  rl = log (xmq / qcdl);

  a = b1[nf] / b0[nf];
  a1 = b1[nf - 1] / b0[nf - 1];

  return qcdl * exp (-1 / b0[nf - 1] *
		     (
		       +(b0[nf] - b0[nf - 1]) * rl
		       + (a - a1) * log (2 * rl)
		       - a1 * log (b0[nf] / b0[nf - 1])
		       + (a * (a - a1) * log (2 * rl) + a * a - a1 * a1 - 0.5 * b2[nf] / b0[nf] + 0.5 * b2[nf - 1] / b0[nf - 1] - 7. / 18.)
		       / (b0[nf] * rl)
		     ));
}

static double 
alpha_2 (double dscale)
{
  double bb0, bb1, bb2, rl;
  double d1, d2;
  int nf;
  double qcdlf[7] = {0., 0., 0., 0., 0., 0., 0.};

  if (re_alpha)
    {
      for (nf = 0; nf <= 6; nf++)
	{
	  b0[nf] = 11. - (2. / 3.) * nf;
	  b1[nf] = 51. - (19. / 3.) * nf;
	  b2[nf] = 2857. - (5033. / 9.) * nf + (325. / 27.) * nf * nf;
	}
      re_alpha = 0;
    }
  qcdlf[6] = qcdL6;
  qcdlf[5] = tonf1 (qcdlf[6], XMTOP, 6);
  qcdlf[4] = tonf1 (qcdlf[5], XMB, 5);
  qcdlf[3] = tonf1 (qcdlf[4], XMC, 4);
/*fprintf(stderr,"\n3=%f  4=%f, 5=%f, 6=%f\n",qcdlf[3],qcdlf[4],qcdlf[5],qcdlf[6]); */

  if (alphaMode)
    return alpha_pdf (dscale);
/*
  if (qcdL6 != qcdlf[6])
    {
      qcdlf[6] = qcdL6;
      qcdlf[5] = tonf1 (qcdlf[6], XMTOP, 6);
      qcdlf[4] = tonf1 (qcdlf[5], XMB, 5);
      qcdlf[3] = tonf1 (qcdlf[4], XMC, 4);
      re_alpha = 0;
    }
*/
/*fprintf(stderr,"\n3=%f  4=%f, 5=%f, 6=%f\n",qcdlf[3],qcdlf[4],qcdlf[5],qcdlf[6]); */
  
  if (dscale > XMC)
    nf = 4;
  else
    nf = 3;
  if (dscale > XMTOP)
    nf = 6;
  if (dscale > XMB)
    nf = 5;

  bb0 = b0[nf];
  bb1 = b1[nf];
  bb2 = b2[nf];

  rl = 2 * log (dscale / qcdlf[nf]);
  d2 = log (rl) - 0.5;
  d1 = 2 * bb1 / (bb0 * bb0 * rl);

  return 4 * M_PI / (bb0 * rl) * (1 - 2 * bb1 * log (rl) / (bb0 * bb0 * rl)
		+ d1 * d1 * (d2 * d2 + bb2 * bb0 / (8 * bb1 * bb1) - 1.25));
}				/* alpha_2 */


/***************************************************************************
*  Flavour number matching inALPHAS2:					   *
*									   *
*	 NF		 6	 5	4	 3	  2		   *
*    Lambda_QCD (GeV)	 0.0683  0.135  0.1985   0.2408   0.2293	   *
*			 0.1052  0.200  0.28275  0.33078  failed	   *
*									   *
*   Comment: for NF=2 and Lambda_QCD(5)=QCDLF(5)=0.2GeV matching is failed *
* because of the term with LOG(LOG(Ms/QCDLF(3))) where Ms<QCDLF(3).	   *
***************************************************************************/
static int 
qq0 (char *s, double *v)
{
  char key, plist[20];

  if (isdigit (*s))
    {
      sscanf (s, "%lf", v);
      return 1;
    }
  if (checkPhysVal (s, &key, plist))
    {
      *v = 100;
      return 1;
    }
  else
    return 0;
}

int 
qcdmen_ (void)
{
  void *pscr = NULL;
  int mode;
  int returnCode = 0;

  initStrFun ();
L10:
  {
    char strmen[] = "\032"
    " QCD Lambda6= XXX         "
    " Q(GeV) = YYY             "
    " Alpha(Q) plot            ";

    if (alphaMode)
      improveStr (strmen, "XXX", "???");
    else
    {
      improveStr (strmen, "XXX", "%-.3lgGeV", qcdL6);
      re_alpha=1;
    }
    improveStr (strmen, "YYY", "%-.16s", scale_str);
    menu1 (52, 8, "QCD alpha", strmen, "n_alpha", &pscr, &mode);
  }
  switch (mode)
    {
    case 0:
      return returnCode;
    case 1:
      if (alphaMode)
	messanykey (20, 20, " alpha(s) is confined "
		    "by PDF structure function");
      else
	{
	  goto_xy (50, 12);
	  if (correctDouble (3, 15, "Enter new value ", &qcdL6, 1))
	    returnCode = 1;
	}
      break;
    case 2:
      {
	int npos = 1, rc;
	do
	  {
	    double dscale;
	    goto_xy (2, 12);
	    print ("QCD scale: ");
	    if (str_redact (scale_str, npos, 60) == KB_ENTER)
	      returnCode = 1;
	    goto_xy (2, 12);
	    clr_eol ();
	    rc = calcExpression (scale_str, qq0, &dscale);
	    if (rc && rc != cannotevaluate)
	      {
		npos = rderrpos;
		if (rc == unknownidentifier)
		  warnanykey (10, 10, " Unknown parameter");
		else
		  warnanykey (10, 10, " Syntax error");
	      }
	  }
	while (rc && rc != cannotevaluate);
      }
      break;
    case 3:
      {
	void *screen;
	int i;
	double f[150];

	static double qMin = 1, qMax = 1000;
	static int nPoints = 100;

	get_text (1, 1, maxCol (), maxRow (), &screen);

	if (correctDouble (40, 15, "Q_min=", &qMin, 0) && qMin >= 0.5
	    && correctDouble (40, 16, "Q_max=", &qMax, 0) && qMax > qMin
	    && correctInt (33, 17, "number of points=", &nPoints, 0)
	    && nPoints > 3 && nPoints <= 150)
	  {
	    for (i = 0; i < nPoints; i++)
	      {
		f[i] = alpha_2 (qMin + i * (qMax - qMin) / (nPoints - 1));
		fprintf (stderr, "   f[i] = %.5E\n", f[i]);
	      }
	    plot_0 (qMin, qMax, nPoints, f, NULL, " ", "Q [GeV]", "Alpha(Q)");
	  }
	else
	  messanykey (40, 18,
		      " Correct input is \n"
		      " 0.5<= Q_min <Q_max\n"
		      " number of points <=150 and >=4");
	put_text (&screen);
      }

    }
  goto L10;
}				/* qcdmen_ */

int 
w_qcd__ (FILE * mode)
{
  fprintf (mode, "Lambda6= %E  Scale= %s", qcdL6, scale_str);
  return 0;
}
double 
get_QCDLambda5 (void)
{
  fprintf (stderr, "\nqcdL6=%f, XMTOP=%f tonf=%f\n", qcdL6, XMTOP, tonf (qcdL6, XMTOP, 6));
  fprintf (stderr, "\ntonf=%f  tonf1=%f\n", tonf (qcdL6, XMTOP, 6), tonf1 (qcdL6, XMTOP, 6));
  return tonf (qcdL6, XMTOP, 6);
}

void 
i_qcd (void)
{
  strcpy (scale_str, "91.187");
}

int 
r_qcd__ (FILE * mode)
{
  fscanf (mode, " Lambda6= %lf  Scale= %s", &qcdL6, scale_str);
  return 0;
}

/********************************************************************
*   This subroutine is called during phase space integration	    *
*     (during BASES and SPRING run)				    *
*     for each phase space point after calculation particles	    *
*     momenta and just before calculation of structure functions    *
*     and squared matrix element.				    *
*								    *
*   It can be used, for example, to provide QCD running strong      *
*     coupling constant. In the program there is used the notation  *
*			   GG					    *
*     for QCD coupling constant.				    *
********************************************************************/
void 
alf_ (double q)
{
  int k;
  char xname[7];
/*... search for QCD coupling constant among process parameters */
  for (k = 1; k <= nvar_; k++)
    {
      vinf_ (k, xname, NULL);
      if (strcmp ("GG", xname) == 0)
	{
	  asgn_ (k, sqrt (4 * M_PI * alpha_2 (q)));
	  return;
	}
    }
}

/************************************************************
*  This subroutine user can call to evaluate the transfered *
*    momentum scale of the process - could be necessary for *
*    structure function interface.			    *
*							    *
*  In the example from STRFUN.F this subroutine is called   *
*    for the evaluation of transfered momentum scale.	    *
*  NSCALE = 0 for t-type, and =1 for s-type of  	    *
*    transfered momentum scale. 			    *
************************************************************/
static int 
qq1 (char *s, double *v)
{
  char key;
  char plist[20];

  if (isdigit (*s))
    {
      sscanf (s, "%lf", v);
      return 1;
    }
  checkPhysVal (s, &key, plist);
  *v = calcPhysVal (key, plist);
  return 1;
}

double 
scale_ (void)
{
  double dscale;
  if (calcExpression (scale_str, qq1, &dscale))
    {
      fprintf (stderr, " ERROR in evaluation of  QCD scale\n");
      exit (0);
    }

  if (dscale < .3f)
    dscale = .3f;
  return dscale;
}				/* scale_ */
