/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2024, All rights reserved
*         Copyright (C) DTU Physics and Risoe National Laboratory, 1997-2024
*         Additions (C) Institut Laue Langevin, 2003-2019
*
* Component: Source_4PI
*
* %I
*
* Written by: Peter Willendrup
* Date: May 2024
* Origin: DTU
*
* Spherical, 4PI-emitting, monochromatic source for benchmarking purposes
*
* %D
* Spherical, 4PI-emitting, monochromatic source for benchmarking purposes
*
* %P
* dimension:  [m] Side-length of cubic source
* E0:       [meV] Mean energy of neutrons.
* dE:       [meV] Energy half spread of neutrons (flat or gaussian sigma).
* lambda0:   [AA] Mean wavelength of neutrons.
* dlambda:   [AA] Wavelength half spread of neutrons.
*
* %E
*******************************************************************************/

DEFINE COMPONENT Source_4PI

SETTING PARAMETERS (radius=0, flux=1e14, gauss=0, E0=0, dE=0, lambda0=0, dlambda=0)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */

DECLARE
%{
  double pmul;
%}

INITIALIZE %{
  pmul=flux/mcget_ncount();

  if ((!lambda0 && !E0 && !dE && !dlambda)) {
    printf("Source_4PI: %s: You must specify either a wavelength or energy range!\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
    exit(0);
  }
  if ((!lambda0 && !dlambda && (E0 <= 0 || dE < 0 || E0-dE <= 0))
    || (!E0 && !dE && (lambda0 <= 0 || dlambda < 0 || lambda0-dlambda <= 0))) {
    printf("Source_4PI: %s: Unmeaningful definition of wavelength or energy range!\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
      exit(0);
  }
%}

TRACE
%{
  double r0, E, lambda, v;
  // Initiate particle at random position within dim x dim x dim
  r0=radius*rand01();
  // Find random position within sphere
  randvec_target_circle(&x, &y, &z, NULL, 0, 0, 1e-6,0);
  x*=r0;
  y*=r0;
  z*=r0;
  
  // Pick random direction into 4PI
  randvec_target_circle(&vx, &vy, &vz, NULL, 0, 0, 1e-6,0);
  NORM(vx,vy,vz);
  if(lambda0==0) {
    if (!gauss) {
      E=E0+dE*randpm1();              /*  Choose from uniform distribution */
    } else {
      E=E0+randnorm()*dE;
    }
    v=sqrt(E)*SE2V;
  } else {
    if (!gauss) {
      lambda=lambda0+dlambda*randpm1();
    } else {
      lambda=lambda0+randnorm()*dlambda;
    }
    v = K2V*(2*PI/lambda);
  }

  vx*=v;
  vy*=v;
  vz*=v;
  p = pmul;
%}

MCDISPLAY
%{
  /* A bit ugly; hard-coded dimensions. */
  
  sphere(0,0,0,radius);
%}

END
