/*******************************************************************************
*
* McStas, neutron ray-tracing package
* Copyright 1997-2002, All rights reserved
* Risoe National Laboratory, Roskilde, Denmark
* Institut Laue Langevin, Grenoble, France
*
* Component: Monitor_Optimizer
*
* %Identification
* Written by: Emmanuel Farhi
* Date: 17 Sept 1999
* Origin: ILL (France)
* Release: McStas 1.6
* Version: $Revision: 1.6 $
* Modified by: EF, (Feb 2000)
* Modified by: EF, Mar 10th, 2000 : now uses struct
* Modified by: EF, Oct 12th, 2000 ; optim divergence (0.08)
*
* To be used after the Source_Optimizer component
*
* %Description
* A component that optimizes the neutron flux passing through the
* Source_Optimizer in order to have the maximum flux at the
* Monitor_Optimizer position(s).
* Source_optimizer should be placed just after the source.
* Monitor_Optimizer should be placed at the position to optimize.
* I prefer to put one just before the sample.
*
* See Source_Optimizer for
* usage example and additional informations.
*
* %Parameters
* INPUT PARAMETERS:
*
* xmin: Lower x bound of detector opening (m)
* xmax: Upper x bound of detector opening (m)
* ymin: Lower y bound of detector opening (m)
* ymax: Upper y bound of detector opening (m)
* optim_comp: name of the Source_Optimizer component in the
* instrument definition. Do not use quotes (no quotes)
*
* OUTPUT PARAMETERS:
*
* none (see Source_Optimizer.comp)
*
* %Link
* McStas at ILL
* %Link
* Source_Optimizer
*
* %End
*******************************************************************************/
DEFINE COMPONENT Monitor_Optimizer
DEFINITION PARAMETERS (optim_comp)
SETTING PARAMETERS (xmin=-0.1, xmax=0.1, ymin=-0.1, ymax=0.1)
OUTPUT PARAMETERS (This_Monitor_id)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx, sy, sz)
DECLARE
%{
#ifndef Source_Optimizer_Here
#error McStas : Source_Optimizer component has to be used before Monitor_Optimizer
#endif
int This_Monitor_id;
%}
INITIALIZE
%{
struct Optim_Variables *Vars = &(MC_GETPAR(optim_comp, Vars));
Vars->Monitor_Number++;
This_Monitor_id = Vars->Monitor_Number;
%}
TRACE
%{
struct Optim_Defines *DEFS = &(MC_GETPAR(optim_comp, DEFS));
struct Optim_Variables *Vars = &(MC_GETPAR(optim_comp, Vars));
PROP_Z0;
if ((Vars->Phase != DEFS->PHASE_UNACTIVATE)
&& (x>xmin && xymin && ycur_p = p;
Vars->Monitor_Counts++; /* initialized to 0 in DEFS->PHASE_SET_REF */
if (Vars->Flag_Smooth )
{ /* to evaluate correctly the un-optimized flux, we restore original weight in these phases */
if ((Vars->Phase == DEFS->PHASE_GET_REF) || (Vars->Phase == DEFS->PHASE_GET_LIMITS))
Vars->cur_p /= Vars->dkeep;
}
if (This_Monitor_id == 1) /* only count flux once !! */
{
Vars->Monitor_Flux += Vars->cur_p;
}
Vars->Total_Monitor_Counts++;
if (Vars->Flag_Auto
&& (Vars->Phase == DEFS->PHASE_GET_REF))
{
if (((Vars->Reference_Counts > mcget_ncount()*Vars->dstep) && (Vars->Monitor_Counts >= Vars->nbins*10))
|| (Vars->Monitor_Counts >= Vars->nbins*100) || (Vars->Reference_Counts > 2*mcget_ncount()*Vars->dstep))
{
Vars->Phase_Counts_R = 0; /* enough counts on monitor */
if (Vars->Flag_Verbose)
{
printf(">> AUTO monitor has reached %.1f counts (non optimized",Vars->Monitor_Counts);
if (Vars->Flag_Smooth) printf(", smoothed");
printf(")\n");
}
Vars->Phase_Counts = (Vars->Reference_Counts+Vars->Limits_Counts);
Vars->dstep = (double)Vars->Phase_Counts/(double)mcget_ncount();
/* Vars->dkeep = Vars->nbins*10/Vars->Monitor_Counts;
if (Vars->dkeep < Vars->dkeep_target) Vars->dkeep = Vars->dkeep_target;
if (Vars->dkeep > .9) Vars->dkeep = 0.9; */
if (Vars->Monitor_Counts < 3*Vars->nbins)
{
printf("Source_Optimizer: monitor only reached %.1f counts. \n", Vars->Monitor_Counts);
printf("* WARNING * You'd better unactivate it or increase number of neutrons\n");
}
}
}
if ((Vars->Phase == DEFS->PHASE_GET_REF)
|| ((Vars->Phase == DEFS->PHASE_OPTIM) && (Vars->Flag_Continuous) )) /* build the Optimized Source distributions */
{
if (Vars->vx_max-Vars->vx_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dvx -Vars->vx_min)/(Vars->vx_max-Vars->vx_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_vx[Vars->index]++;
if (Vars->vy_max-Vars->vy_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dvy -Vars->vy_min)/(Vars->vy_max-Vars->vy_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_vy[Vars->index]++;
if (Vars->vz_max-Vars->vz_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dvz -Vars->vz_min)/(Vars->vz_max-Vars->vz_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_vz[Vars->index]++;
if (Vars->x_max-Vars->x_min)
Vars->index = (int)rint(Vars->nbins * (Vars->cur_x -Vars->x_min)/(Vars->x_max-Vars->x_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_x[Vars->index]++;
if (Vars->y_max-Vars->y_min)
Vars->index = (int)rint(Vars->nbins * (Vars->cur_y -Vars->y_min)/(Vars->y_max-Vars->y_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_y[Vars->index]++;
if (Vars->sx_max-Vars->sx_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dsx -Vars->sx_min)/(Vars->sx_max-Vars->sx_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_sx[Vars->index]++;
if (Vars->sy_max-Vars->sy_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dsy -Vars->sy_min)/(Vars->sy_max-Vars->sy_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_sy[Vars->index]++;
if (Vars->sz_max-Vars->sz_min)
Vars->index = (int)rint(Vars->nbins * (Vars->dsz -Vars->sz_min)/(Vars->sz_max-Vars->sz_min));
else
Vars->index = 0;
if (Vars->index < 0) Vars->index = 0;
if (Vars->index >= Vars->nbins) Vars->index = Vars->nbins - 1;
Vars->New_Source_sz[Vars->index]++;
} /* end if Vars->Phase */
} /* end if xy in optimizer */
/* end trace */
%}
FINALLY
%{
struct Optim_Variables *Vars = &(MC_GETPAR(optim_comp, Vars));
if (Vars->Monitor_Number == 0)
{
/* initial Reference distribution arrays (for weights) */
free(Vars->Reference_x);
free(Vars->Reference_y);
free(Vars->Reference_vx);
free(Vars->Reference_vy);
free(Vars->Reference_vz);
free(Vars->Reference_sx);
free(Vars->Reference_sy);
free(Vars->Reference_sz);
/* optimized Source distribution arrays (to reach) */
free(Vars->Source_x);
free(Vars->Source_y);
free(Vars->Source_vx);
free(Vars->Source_vy);
free(Vars->Source_vz);
free(Vars->Source_sx);
free(Vars->Source_sy);
free(Vars->Source_sz);
/* optimized New_Source distribution arrays (to reach in next step, passed to Source) */
free(Vars->New_Source_x);
free(Vars->New_Source_y);
free(Vars->New_Source_vx);
free(Vars->New_Source_vy);
free(Vars->New_Source_vz);
free(Vars->New_Source_sx);
free(Vars->New_Source_sy);
free(Vars->New_Source_sz);
/* Passing distribution arrays (should grow to reach Source) */
free(Vars->Passing_x);
free(Vars->Passing_y);
free(Vars->Passing_vx);
free(Vars->Passing_vy);
free(Vars->Passing_vz);
free(Vars->Passing_sx);
free(Vars->Passing_sy);
free(Vars->Passing_sz);
Vars->Monitor_Number = 1; /* to only free once */
}
%}
MCDISPLAY
%{
magnify("xy");
multiline(5, (double)xmin, (double)ymin, 0.0,
(double)xmax, (double)ymin, 0.0,
(double)xmax, (double)ymax, 0.0,
(double)xmin, (double)ymax, 0.0,
(double)xmin, (double)ymin, 0.0);
%}
END