McStasMcXtrace / McCode

The home of the McStas (neutrons) and McXtrace (x-rays) Monte-Carlo ray-tracing instrument simulation codes.
https://github.com/McStasMcXtrace/McCode/wiki
GNU General Public License v3.0
77 stars 54 forks source link

McStas: problem with non-double USERVARS when accessed with particle_getvar function #1380

Open MilanKlausz opened 1 year ago

MilanKlausz commented 1 year ago

I have a problem when trying to use an int variable in the USERVARS section as a flag to indicate whether a neutron scattered on the sample or not. Using such a variable as a conditional parameter (WHEN (int_flag ==2)) works properly, but it doesn't work if I want to save its value as the userflag property in the MCPL_output component. I get the value 0 regardless of what values I set in the EXTEND block of the sample component.

Looking into the generated .c file, I can see that the MCPL_output component uses the particle_getvar function to access the variables defined in the USERVARS section (as opposed to the #define syntax used in case of EXTEND and WHEN). I might be wrong, but suspect that the source of the problem is that in the generated .c file, an explicit (double *) pointer conversion is used, regardless of the type defined in the USERVARS section. e.g.:

  // .instr file 
  USERVARS
  %{
   int int_flag;
   double double_flag;
  %}
  // .c file
 double particle_getvar(_class_particle *p, char *name, int *suc){
  (...)
  if(!str_comp("int_flag",name)){rval=*( (double *)(&(p->int_flag)) );s=0;}
  if(!str_comp("double_flag",name)){rval=*( (double *)(&(p->double_flag)) );s=0;}
  if (suc!=0x0) {*suc=s;}
  return rval;
 }

note1: in the MCPL_output.comp uvar = particle_getvar(_particle,userflag,&fail); if(fail) uvar=0;, if(fail) evaluates false, so that's not the reason why I get 0 value. note2: a particle_getuservar_byid function is also generated with the same fix (double *) type, but my components don't use this function. note3: everything works well with double USERVARS.

I tested my issue with a different component that uses particle_getvar, and found that Monitor_nD component also gives wrong results with an integer USERVAR.

willend commented 1 year ago

@MilanKlausz thanks for reporting - will try checking next week what this is all about.

In the meantime, thanks to a recent contribution from @g5t, we now also have this function void* particle_getvar_void(_class_particle *p, char *name, int *suc); which returns a void* which you may then cast as int - perhaps this gives you better mileage?

If you use the recently released 3.2, this function is in place.

willend commented 1 year ago

@MilanKlausz you are absolutely right, using an int USERVAR does not work as expected.

Attached you find a modified version of MCPL_output and the related test instrument which shows a potential way forward. The MCPL_output has yet another input parameter (flagtype) to select if userflag is double =0 or int =1.

Yes, indeed a bit clunky. :) Let's think of a better / more logical way of putting all of this together for 3.3... MCPL_output.comp.txt Test_MCPL_output.instr.txt

willend commented 1 year ago

Postponing full resolution until after release of McStas 3.3