From hillier at ill.fr Wed Jul 19 14:48:20 2000 From: hillier at ill.fr (Adrian Hillier) Date: Wed, 19 Jul 2000 14:48:20 +0200 Subject: Problems with McStas Message-ID: <01JS0YSB1KYY8ZE5C3@risoe.dk> Hi, I am probably being a little dumb somewhere, but I am having some problems with McStas. I am trying to use 2 single crystal components in the sample instrument file, but when I try and compile it I receive an error message: ' ../Single_crystal.comp:347 invalid use of undefined type 'struct mccmono1_hkl_info' '. This message is repeated many times and references lines which access hkl_info. The instr file will compile with one of the single crystal components on their own and it does not matter which one. Please find attached the .instr file. I would greatly appreciate some advice in this matter. I look forward to hearing from you. Aidy Dr. Adrian Hillier Institut Laue Langevin 6 rue Jules Horowitz BP 156 38042 Grenoble Cedex 9 France Tel: +33 (0) 4 76 20 77 34 Fax: +33 (0) 4 76 20 76 48 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: working.instr Type: application/octet-stream Size: 4606 bytes Desc: not available URL: From kristian.nielsen at risoe.dk Fri Jul 21 10:58:41 2000 From: kristian.nielsen at risoe.dk (Kristian Nielsen) Date: Fri, 21 Jul 2000 10:58:41 +0200 Subject: Problems with McStas In-Reply-To: <007901bff17f$9eaf6a60$12dc39c2@ill.fr> (message from Adrian Hillier on Wed, 19 Jul 2000 14:48:20 +0200) Message-ID: <01JS0YSQ3BX48ZE5C3@risoe.dk> > Date: Wed, 19 Jul 2000 14:48:20 +0200 > From: Adrian Hillier Hi Adrian, > problems with McStas. I am trying to use 2 single crystal components > in the sample instrument file, but when I try and compile it I receive > an error message: You found a bug in the component. I have now fixed the problem, and a corrected (hopefully) component may be downloaded from http://neutron.risoe.dk/mcstas/mcdoc/components/samples/Single_crystal.comp (just copy it into the same directory as the instrument definition, and everything should work). I tried compiling your instrument with the corrected component, and it compiled without errors (I did not try to run the simulation though). I also added a note of this problem in the "known bugs" web page. Thanks for spotting this problem, and let me know if you experience further difficulties. - Kristian. -- Kristian Nielsen kristian.nielsen at risoe.dk Ris? National Laboratory Condensed Matter Physics and Chemistry Department Tel. +45 4677 5515 Fax +45 4677 4790 Encryption PGP key http://neutron.risoe.dk/kn.txt From farhi at ill.fr Thu Jul 6 18:11:23 2000 From: farhi at ill.fr (Farhi) Date: Thu, 06 Jul 2000 18:11:23 +0200 Subject: Future... Message-ID: <01JS13VCA2VC8ZE7DI@risoe.dk> Hello Kristian, As I told you last time you passed at the ILL, I have applied to a permanent position at the ILL in the Computer Simulation group. And that's OK ! So, starting from September 1st, I'll have more time to give to scientific computer stuff (less local contact, experiments, etc...). We have now some McStas simulations that are nearly finished (not including mines): IN6, IN10, IN16, D10, IN14, and I think I should gather ILL McStas users soon to exchange ideas about what should be fine for McStas evolutions, components and instruments. Well, in fact I had not a lot of time for McStas since my last email. I now turn back to it ! Before I go on with my general source/flux adapter (that should be able to simulate any kind of neutron beam), I'd like to ask you a few questions: 1) would it be possible to put, in the TRACE section, some bits of C code, e.g.: TRACE COMPONENT ... blahblah { long my_local_variable; my_local_variable = 5; } COMPONENT ... blahblah = bouh(a=my_local_variable) { my_local_variable = 6; } COMPONENT ... blahblah = bouh(a=my_local_variable) This avoids to create n variables if we only need 2 or 3 temporary variables to pass parameters to components. 2) would it be possible, for numerical component parameters, to indicate (in TRACE) an expression instead of a single variables name, e.g.: COMPONENT ... blahblah = bouh(a=my_local_variable*2) for strings, I guess it's more complicated, but we could think about COMPONENT ... blahblah = bouh(a=sprintf("file= %s other stuff", my_string_variable)) even though it is not straight forward... 3) about neutron polarisation, I'm lost. Should I use s1,s2 for spin components (that make them run with the 'normal' mcstas), or should I use sx,sy,sz and the component could only work in POLARISATION mode ? Example : Monitor_nD could detect the neutron spin, but should there be 2 versions of this component, one for normal and 1 for polarisation analysis ? For the time being, I use s1 s2 because I'm sure it works for everybody. If I use sx,sy,sz, these variables are not known except if one uses POLARISATION. I think a definitive choice should be made before people write too many components handling spin... I would prefer sx,sy,sz of course, but these should be defined in 'normal' mcstas else a 'polarisation' component will not compile in normal mode (and vice-versa). I probably plan to put in all my components things like #ifdef sz blahblah with sz #else things considering that sz = 0 (s1=sx, s2=sy) #endif If you choose to use sx,sy,sz for sure, then we should tell everybody to change their component sources (and handle s1 s2 in mcstas with warning message saying how to change to better code) 4) Concerning the flux_adapter, I will probably define an 'auto focus' mode that will set the beam divergence in order to match the preceeding component. If I want to rather focus on the next component, I need to use something like: COMPONENT Flux_adapter COMPONENT blahblah that follows COMPONENT Flux_adapter_monitor The Flux_adapter_monitor should record (in a short learning stage) the neutrons that pass through the component blahblah, and then compute the required divergences for a better MC shot. Perhaps it could check the presence of a Monitor_nD component, and get from it some divergence values. Or (simple) I use standard divergences (manual focussing, giving values in component option string or no focussing). 5) Would it be possible to define a macro PROTECT name that would append the current component/instrument name root and generate #define name component+name just as component and instrument parameters Cheers ! Emmanuel. -- Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html \|/ ____ \|/ TAS-Group, Institut Laue-Langevin (ILL) Grenoble ~@-/ oO \-@~ Avenue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France /_( \__/ )_\ Work :Tel (33/0) 4 76 20 71 83. Fax (33/0) 4 76 48 39 06 \__U_/ La Grande Arche, Chateau d'Uriage, 38410 Saint Martin d'Uriage 04 76 59 73 94 -------------- next part -------------- An HTML attachment was scrubbed... URL: From kristian.nielsen at risoe.dk Fri Jul 21 13:34:00 2000 From: kristian.nielsen at risoe.dk (Kristian Nielsen) Date: Fri, 21 Jul 2000 13:34:00 +0200 Subject: Future... In-Reply-To: <3964AFAB.27A9BDF3@ill.fr> (message from Farhi on Thu, 06 Jul 2000 18:11:23 +0200) Message-ID: <01JS1470H8ZM8ZE7DI@risoe.dk> Hi Emmanuel, Ok, I am now back from vacation, so here are some comments on the points you asked about on July 6. > As I told you last time you passed at the ILL, I have applied to a > permanent position at the ILL in the Computer Simulation group. > And that's OK ! Once again congratulations with your new positions, I hope this will mean that you will play an even more active role in McStas development. Several of your points touch upon a subtle but important detail in the way parameters are passed to components from the instrument definitions. This currently works (in the generated C code) using C macros (#define). Because of this, many of the usual problems with C macros apply. Using C macros was the easiest solution, but I kind of regret it now. It would have been better to use proper variables. However, in order to use real C variables, McStas will need to understand the C types of component parameters. Most of these are "double" of course, but they can also be strings, arrays, structures, function pointers, etc. It is not inherently difficult to make this extension in McStas, but it is some work because of the complexity of C. [Hm. Actually, McStas already knows the type of "SETTING PARAMETERS", since they are always "double"... ] In any case, the desirable features that you mention would be rather easy to implement once McStas was extended to use real C variables for component parameters instead of macros. You might want to take a closer look at the C code that McStas generates to see the details. > 1) would it be possible to put, in the TRACE section, some bits of C > code, e.g.: > COMPONENT ... blahblah = bouh(a=my_local_variable) I think I see what you want. It is difficult in the current design because of the use of C macros for parameters, but by using proper C variables it should be simple. > 2) would it be possible, for numerical component parameters, to indicate > (in TRACE) an expression instead of a single variables name, e.g.: > > COMPONENT ... blahblah = bouh(a=my_local_variable*2) Again, not so good when using C macros (the expression would be recomputed for each neutron!), but simple with real C variables. Of course, it would be necessary to write a parser for C expressions, which is not completely trivial. > 3) about neutron polarisation, I'm lost. I think we discussed this previously? Basically, the s1 and s2 STATE PARAMETERS are NOT used in McStas, period. The are just dummy names and have nothing to do with polarisation or anything else. For example, they are not transformed when components are ROTATED. Polarisation should always use POLARISATION PARAMETERS(sx,sy,sz). However, I see your point about the Monitor_nD. If you were to put in polarisation, non-polarisation instruments would create a bunch of warnings. I think we should just remove the warning and use POLARISATION PARAMETERS. No components need to be changed, those that do not use POLARISATION PARAMETERS will just pass on (sx,sy,sz) unchanged. > 5) Would it be possible to define a macro > PROTECT name > that would append the current component/instrument name root and > generate > #define name component+name > just as component and instrument parameters I think this is exactly what is achieved by including the name in the list of OUTPUT PARAMETERS. I should tell you that there is going to be a change of things here at Risoe concerning McStas. Management decisions two years ago have forced me to the opposite change of work that you do now, from scientific computing towards physics. I have decided that this is not what I want, and I am therefore leaving my job at Risoe, and hence McStas. The plan is that someone else at Risoe will take over, but nothing is decided yet. In any case, you have a lot of in-depth knowledge and interest concerning McStas, and with the intense simulation activity at the ILL I think it would be very good if you and the ILL got more involved in the development of McStas itself. - Kristian. From hillier at ill.fr Fri Jul 21 16:41:36 2000 From: hillier at ill.fr (Adrian Hillier) Date: Fri, 21 Jul 2000 16:41:36 +0200 Subject: Problems with McStas References: <01JS0YRHE3AA8ZE5C3@risoe.dk> Message-ID: <01JS2A9APSU48ZED3B@risoe.dk> Hi, Thanks for the quick response. It compiles now, and I am glad you didn't try the simulation because I realised I sent you one that would never have worked as a sensible simulation. Aidy ----- Original Message ----- From: Kristian Nielsen To: Sent: Friday, July 21, 2000 10:58 AM Subject: Re: Problems with McStas > > Date: Wed, 19 Jul 2000 14:48:20 +0200 > > From: Adrian Hillier > > Hi Adrian, > > > problems with McStas. I am trying to use 2 single crystal components > > in the sample instrument file, but when I try and compile it I receive > > an error message: > > You found a bug in the component. I have now fixed the problem, and a > corrected (hopefully) component may be downloaded from > > http://neutron.risoe.dk/mcstas/mcdoc/components/samples/Single_crystal.comp > > (just copy it into the same directory as the instrument definition, and > everything should work). I tried compiling your instrument with the > corrected component, and it compiled without errors (I did not try to > run the simulation though). > > I also added a note of this problem in the "known bugs" web page. > > Thanks for spotting this problem, and let me know if you experience > further difficulties. > > - Kristian. > > -- > Kristian Nielsen kristian.nielsen at risoe.dk > Ris? National Laboratory > Condensed Matter Physics and Chemistry Department > Tel. +45 4677 5515 Fax +45 4677 4790 > Encryption PGP key http://neutron.risoe.dk/kn.txt > > From PASeeger at aol.com Tue Jul 25 17:14:53 2000 From: PASeeger at aol.com (PASeeger at aol.com) Date: Tue, 25 Jul 2000 11:14:53 -0400 (EDT) Subject: Comparison Project Message-ID: <01JS7T2P3UW68ZF8ZI@risoe.dk> As you probably know by now, Larry Passell has proposed that the H8 Triple-Axis Spectrometer from BNL be used as a test case for intercomparison of Monte Carlo results. Attached to this message is a Word document with the specifications of the H8 TAS which could be used to create a Monte Carlo simulation. The first step in the project must be to agree on model specifications that we can ALL simulate. For instance, NISP is limited in arm motions, so I want to simulate a single setting of the TAS, with the only scan being a theta/2theta scan of the monochromator. When I look at the list of elements in McStas, I don't see curved crystals. If that is true, would the McStas team prefer that we change to sets of angled flat crystals (e.g., 3 for the monochromator and 5 for the analyzer)? What modifications of the model do the ORNL folks want to make? I hope that we can agree on the model quickly. Then we can worry about what it is we are going to compare. Total counts on detector, for sure. Phase diagrams at different points along the instrument? Transmission properties of each element? What do you suggest? Lets have fun with it -- Phil Seeger -------------- next part -------------- A non-text attachment was scrubbed... Name: H8_specs.doc Type: application/octet-stream Size: 100352 bytes Desc: not available URL: From kristian.nielsen at risoe.dk Fri Jul 28 15:53:03 2000 From: kristian.nielsen at risoe.dk (Kristian Nielsen) Date: Fri, 28 Jul 2000 15:53:03 +0200 Subject: New release v1.4 of McStas Message-ID: <01JSB12UT4MQ8ZFJKO@risoe.dk> Dear McStas users, I am pleased to announce that McStas v1.4 has been released and may be downloaded from the web site: http://neutron.risoe.dk/mcstas/ The main new feature in this release is the ability to use arbitrary expressions in instrument definitions when specifying component parameters and placement. See the CHANGES file in the distribution for details on what is new in v1.4. This will be the final release of McStas with me as the maintainer, since I am now leaving Risoe for another job. We expect that another maintainer will be appointed at Risoe; who that is going to be will be decided later this year. Let me take this opportunity to thank all of the users for all the work you have done and wish you all luck with your continued work on simulations. - Kristian. -- Kristian Nielsen kristian.nielsen at risoe.dk Ris? National Laboratory Condensed Matter Physics and Chemistry Department Tel. +45 4677 5515 Fax +45 4677 4790 Encryption PGP key http://neutron.risoe.dk/kn.txt From mcgreevy at studsvik.uu.se Fri Aug 18 15:15:32 2000 From: mcgreevy at studsvik.uu.se (Robert McGreevy) Date: Fri, 18 Aug 2000 15:15:32 +0200 Subject: SCANS meeting: Neutron polarisation in MC instrument simulations Message-ID: <3.0.6.32.20000818151532.007b4830@nflett.studsvik.uu.se> There will be an informal meeting of the SCANS (Software for Computer Aided Neutron Scattering) network at ILL on October 5-6. The aim of the meeting is to discuss in detail the requirements and possible protocols for the inclusion of polarisation analysis in Monte Carlo simulations of neutron scattering instruments. The meeting is open to anyone who is interested. Some participants in the ENPI network (European Neutron Polarisation Initiative) will also take part. If you wish to attend the meeting please make a preliminary registration with Francoise Giraud at ILL (giraud at ill.fr, Tel: +33 476207085, Fax: +33 476207700) and copy to me (mcgreevy at studsvik.uu.se) for information. Make sure that you state SCANS clearly, since there is a different network meeting (TECHNI) the week after. SCANS participants should note that travel and subsistence costs for this meeting can be charged to their contracts. Best regards Robert McGreevy *************************************************************************** Dr. Robert McGreevy Studsvik Neutron Research Laboratory Uppsala University S-611 82 Nykoping Sweden Tel: +46 155 221831 Mobile: +46 70 6792159 FAX: +46 155 263001 E-mail: mcgreevy at studsvik.uu.se http://www.studsvik.uu.se From farhi at ill.fr Tue Aug 29 14:45:35 2000 From: farhi at ill.fr (Farhi) Date: Tue, 29 Aug 2000 14:45:35 +0200 Subject: McStas 1.4 : instrument parameters as strings Message-ID: <39ABB06E.8D183E33@ill.fr> Hello all mcneutron readers, I've found a bug in the handling of string parameters for instruments. Thus, I corrected that, and this requires to update the cogen.c and lib/mcfrontlib.pl files before McStas 1.4 installation. Then you will be able to use mcstas simlations with instrument string parameters: for instance if you define an instrument by DEFINE INSTRUMENT D11(GuideSampleLength, string GuideType, Lambda) you can run it with mcrun d11 -f MyOutput -n 1e6 -N 32 GuideSampleLength=20 GuideType=Glass Lambda=4.5,20 mcplot is ok with it. Cheers. EF. -- Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html \|/ ____ \|/ TAS-Group, Institut Laue-Langevin (ILL) Grenoble ~@-/ oO \-@~ Avenue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France /_( \__/ )_\ Work :Tel (33/0) 4 76 20 71 83. Fax (33/0) 4 76 48 39 06 \__U_/ La Grande Arche, Chateau d'Uriage, 38410 Saint Martin d'Uriage 04 76 59 73 94 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- /******************************************************************************* * Code generation from instrument definition. * * Project: Monte Carlo Simulation of Triple Axis Spectrometers * File name: cogen.c * * Author: K.N. Aug 20, 1997 * * $Id: cogen.c,v 1.22 2000/07/27 09:05:30 kn Exp $ * * Copyright (C) Risoe National Laboratory, 1997-1998, All rights reserved *******************************************************************************/ #include #include #include #include "mcstas.h" /******************************************************************************* * Some general comments on code generation. * * Code is output in the form of strings using the following functions: * cout(); (one line at a time) * coutf(); (with printf-style formatting) * * The type of numbers used in the generated code is given by the macro MCNUM * (defined in mcstas-r.h). * * All generated identifiers are prefixed with the string ID_PRE, to make name * clashes less likely to occur. Currently, for simplicity, we output modified * names directly, eg. * * cout("void " ID_PRE "init(void);"); * * But to make a later transition to a better name generation scheme possible, * it is important to use the ID_PRE macro everywhere identifiers are * generated. * * After the ID_PRE prefix a few letters occur in generated names to * distinguish different kinds of identifiers (instrument parameters, * component definition parameters, internal temporary variables and so on). * Care must be takes to choose these letters such that no name clashes will * occur with names generated by other parts of the code or generated from * user symbols. * * Finally, names generated from user symbols are generally chosen to match * the originals as closely as possible to make the generated code more * readable (for debugging purposes). * * The following is a list of the identifiers generated in the output. The * ID_PRE prefix is denoted by ##. The first column gives the identifier as it * appears in the generated code, the second explains the origin of the * identifier in the instrument definition source (if any). * * ##ip From instrument parameter . * ##init Function containing initialization code. * ##inputtable Table of instrument parameters. * ##NUMIPAR Macro giving the number of instrument parameters. * ##numipar Global variable with the value of ##NUMIPAR. * ##c_

From definition or setting parameter

in component * instance . * ##posa Absolute position of coordinate system of . * ##posr Position of relative to previous component. * ##rota Absolute rotation. * ##rotr Relative rotation. * ##tc1 Temporary variable used to compute transformations. * ##tc2 * ##tr1 * ##tr2 * ##nx Neutron state (position, velocity, time, and spin). * ##ny * ##nz * ##nvx * ##nvy * ##nvz * ##nt * ##nsx * ##nsy * ##nsz * ##np * ##absorb *******************************************************************************/ /******************************************************************************* * Generation of declarations. * * The following declarations are generated (## denotes the value ID_PRE): * 1. Header file #include - "mcstas-r.h" for declarations for the * mcstas runtime. * 2. Declarations of global variables to hold the values of the instrument * parameters. For example, for an instrument parameter OMM, the * declaration "MCNUM ##ipOMM;" is generated. * 3. Declaration of a table ##inputtable containing the list of instrument * parameters. For each parameter, the name, a pointer to the * corresponding global variable, and the type (double, int, * string) is given. The macro ##NUMIPAR gives the number of * entries in the table and is also found as the value of the * variable ##numipar; in addition, the table is terminated by two * NULLs. This table is used to read the instrument parameters from * the user or from another program such as TASCOM. * 4. User declarations copied verbatim from the instrument definition file. * 5. Declarations for the component parameters. This uses #define for * definition parameters and global variables for setting parameters. * X. User declarations from component definitions. * X. Declarations of variables for coordinate system transformations. * X. Declaration of variables for neutron state. * X. Function prototypes. *******************************************************************************/ /* Functions for outputting code. */ /* Handle for output file. */ static FILE *output_handle = NULL;/* Handle for output file. */ static int num_next_output_line = 1; /* Line number for next output line. */ static char *quoted_output_file_name = NULL; /* str_quote()'ed name of output file. */ /* Convert instrument formal parameter type numbers to their enum name. */ char *instr_formal_type_names[] = { "instr_type_double", "instr_type_int", "instr_type_string" }; char *instr_formal_type_names_real[] = { "MCNUM", "int", "char*" }; /******************************************************************************* * Output a line of code * Assumes that the output does not contain newlines. *******************************************************************************/ static void cout(char *s) { fprintf(output_handle, "%s\n", s); num_next_output_line++; } /******************************************************************************* * Output a line of code using printf-style format string. * Assumes that the output does not contain newlines. *******************************************************************************/ static void coutf(char *format, ...) { va_list ap; va_start(ap, format); vfprintf(output_handle, format, ap); va_end(ap); fprintf(output_handle, "\n"); num_next_output_line++; } /******************************************************************************* * Output #line directive to handle code coming from a different file. * The filename is assumed to be already properly quoted for special chars. *******************************************************************************/ static void code_set_source(char *filename, int linenum) { if(linenum > 0) coutf("#line %d \"%s\"", linenum, filename); } /******************************************************************************* * Output #line directive to reset back to the generated output C file. *******************************************************************************/ static void code_reset_source(void) { /* Note: the number after #line refers to the line AFTER the directive. */ coutf("#line %d \"%s\"", num_next_output_line + 1, quoted_output_file_name); } static void codeblock_out(struct code_block *code) { List_handle liter; /* For list iteration. */ char *line; /* Single code line. */ if(list_len(code->lines) <= 0) return; code_set_source(code->quoted_filename, code->linenum + 1); liter = list_iterate(code->lines); while(line = list_next(liter)) { fprintf(output_handle, "%s", line); num_next_output_line++; } list_iterate_end(liter); code_reset_source(); } static void codeblock_out_brace(struct code_block *code) { List_handle liter; /* For list iteration. */ char *line; /* Single code line. */ if(list_len(code->lines) <= 0) return; code_set_source(code->quoted_filename, code->linenum); cout("{"); liter = list_iterate(code->lines); while(line = list_next(liter)) { fprintf(output_handle, "%s", line); num_next_output_line++; } list_iterate_end(liter); cout("}"); code_reset_source(); } struct code_block * codeblock_new(void) { struct code_block *cb; palloc(cb); cb->filename = NULL; cb->quoted_filename = NULL; cb->linenum = -1; cb->lines = list_create(); return cb; } /******************************************************************************* * Read a file and output it to the generated simulation code. Uses a * fixed-size buffer, and will silently and arbitrarily break long lines. *******************************************************************************/ static void embed_file(char *name) { char buf[4096]; FILE *f; int last; /* First look in the system directory. */ f = open_file_search_sys(name); /* If not found, look in the full search path. */ if(f == NULL) f = open_file_search(name); /* If still not found, abort. */ if(f == NULL) fatal_error("Could not find file '%s'\n", name); cout(""); code_set_source(name, 1); /* Now loop, reading lines and outputting them in the code. */ while(!feof(f)) { if(fgets(buf, 4096, f) == NULL) break; last = strlen(buf) - 1; if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r')) buf[last--] = '\0'; if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r')) buf[last--] = '\0'; cout(buf); } fclose(f); coutf("/* End of file \"%s\". */", name); cout(""); code_reset_source(); } /******************************************************************************* * The following two functions output #define directives around a given piece * of code to set up the right variable names (eg. the proper scope) for * instrument and component parameters. The functions are recursive on the * parameter lists. * * The functions first output an appropriate list of #define's, then call the * supplied function func with the argument data, and finally outputs a * matching list of #undef's. *******************************************************************************/ static void cogen_instrument_scope_rec(List_handle parlist, void (*func)(void *), void *data) { struct instr_formal *par; par = list_next(parlist); if(par != NULL) { coutf("#define %s %sip%s", par->id, ID_PRE, par->id); cogen_instrument_scope_rec(parlist, func, data); coutf("#undef %s", par->id); } else { (*func)(data); } } static void cogen_instrument_scope(struct instr_def *instr, void (*func)(void *), void *data) { List_handle parlist; /* This simply starts up the recursion. */ parlist = list_iterate(instr->formals); cogen_instrument_scope_rec(parlist, func, data); list_iterate_end(parlist); } /* Create the bindings for the SETTING parameter scope. Since the types of * setting parameters are known, local declarations can be used, avoiding the * problems with #define macro definitions. */ static void cogen_comp_scope_setpar(char *compname, List_handle set, int infunc, void (*func)(void *), void *data) { char *par; struct comp_iformal *formal; /* Get the next setting parameter. */ formal = list_next(set); if(formal != NULL) { /* Create local parameter equal to global value. */ if(infunc) coutf(" MCNUM %s = %sc%s_%s;", formal->id, ID_PRE, compname, formal->id); else coutf("#define %s %sc%s_%s", formal->id, ID_PRE, compname, formal->id); cogen_comp_scope_setpar(compname, set, infunc, func, data); if(!infunc) coutf("#undef %s", formal->id); } else { (*func)(data); /* Now do the body. */ } } /* Create the #define statements to set up the scope for DEFINITION and OUTPUT * parameters. */ static void cogen_comp_scope_rec(char *compname, List_handle def, List set_list, List_handle out, int infunc, void (*func)(void *), void *data) { char *par; struct comp_iformal *formal; /* First get the next DEFINITION or OUTPUT parameter, if any. */ if(def != NULL) { formal = list_next(def); if(formal == NULL) def = NULL; /* Now finished with definition parameters. */ else par = formal->id; } if(def == NULL) par = list_next(out); if(par != NULL) { /* Create #define / #undef pair for this parameter around rest of code. */ coutf("#define %s %sc%s_%s", par, ID_PRE, compname, par); cogen_comp_scope_rec(compname, def, set_list, out, infunc, func, data); coutf("#undef %s", par); } else { /* Now do the SETTING parameters. */ List_handle set; if(infunc && list_len(set_list) > 0) coutf("{ /* Declarations of SETTING parameters. */"); set = list_iterate(set_list); cogen_comp_scope_setpar(compname, set, infunc, func, data); list_iterate_end(set); if(infunc && list_len(set_list) > 0) coutf("} /* End of SETTING parameter declarations. */"); } } static void cogen_comp_scope(struct comp_inst *comp, int infunc, void (*func)(void *), void *data) { List_handle def, out; coutf("#define %scompcurname \"%s\"", ID_PRE, comp->name); def = list_iterate(comp->def->def_par); out = list_iterate(comp->def->out_par); cogen_comp_scope_rec(comp->name, def, comp->def->set_par, out, infunc, func, data); list_iterate_end(out); list_iterate_end(def); coutf("#undef %scompcurname", ID_PRE, comp->name); } /******************************************************************************* * Generate declarations from users declaration section in component definition. *******************************************************************************/ static void cogen_comp_decls_doit(void *arg) { struct comp_inst *comp = arg; /* Output the user declaration code block. */ codeblock_out(comp->def->decl_code); } static void cogen_comp_decls(struct comp_inst *comp) { cogen_comp_scope(comp, 0, cogen_comp_decls_doit, comp); } /******************************************************************************* * Generate declaration part of code. *******************************************************************************/ static void cogen_decls(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_iformal *c_formal;/* Name of component formal input parameter */ struct instr_formal *i_formal;/* Name of instrument formal parameter. */ struct comp_inst *comp; /* Component instance. */ /* 1. Function prototypes. */ coutf("void %sinit(void);", ID_PRE); coutf("void %sraytrace(void);", ID_PRE); coutf("void %sfinally(void);", ID_PRE); coutf("void %sdisplay(void);", ID_PRE); cout(""); /* 2. Global variables for instrument parameters. */ cout("/* Instrument parameters. */"); liter = list_iterate(instr->formals); while(i_formal = list_next(liter)) { coutf("%s " ID_PRE "ip%s;", instr_formal_type_names_real[i_formal->type], i_formal->id); } list_iterate_end(liter); cout(""); /* 3. Table of instrument parameters. */ coutf("#define %sNUMIPAR %d", ID_PRE, list_len(instr->formals)); coutf("int %snumipar = %d;", ID_PRE, list_len(instr->formals)); coutf("struct %sinputtable_struct %sinputtable[%sNUMIPAR+1] = {", ID_PRE, ID_PRE, ID_PRE); liter = list_iterate(instr->formals); while(i_formal = list_next(liter)) { coutf(" \"%s\", &%sip%s, %s,", i_formal->id, ID_PRE, i_formal->id, instr_formal_type_names[i_formal->type]); } list_iterate_end(liter); coutf(" NULL, NULL, instr_type_double"); coutf("};"); cout(""); /* User's declarations from the instrument definition file. */ cout("/* User declarations from instrument definition. */"); cogen_instrument_scope(instr, (void (*)(void *))codeblock_out, instr->decls); cout(""); /* Declaration of component definition and setting parameters. */ cout("/* Declarations of component definition and setting parameters. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { List_handle liter2; if(list_len(comp->def->def_par) > 0) { /* (The if avoids a redundant comment.) */ coutf("/* Definition parameters for component '%s'. */", comp->name); liter2 = list_iterate(comp->def->def_par); while(c_formal = list_next(liter2)) { struct Symtab_entry *entry = symtab_lookup(comp->defpar, c_formal->id); char *val = exp_tostring(entry->val); coutf("#define %sc%s_%s %s", ID_PRE, comp->name, c_formal->id, val); str_free(val); } list_iterate_end(liter2); } if(list_len(comp->def->set_par) > 0) { coutf("/* Setting parameters for component '%s'. */", comp->name); liter2 = list_iterate(comp->def->set_par); while(c_formal = list_next(liter2)) { coutf("MCNUM %sc%s_%s;", ID_PRE, comp->name, c_formal->id); } list_iterate_end(liter2); } if(list_len(comp->def->def_par) > 0 || list_len(comp->def->set_par) > 0) cout(""); } list_iterate_end(liter); /* User declarations from component definitions (for each instance). */ cout("/* User component declarations. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->decl_code->lines) > 0) { coutf("/* User declarations for component '%s'. */", comp->name); cogen_comp_decls(comp); cout(""); } } list_iterate_end(liter); /* Declarations for the position and rotation transformations between coordinate systems of components. */ liter = list_iterate(instr->complist); while(comp = list_next(liter)) { coutf("Coords %sposa%s, %sposr%s;", ID_PRE, comp->name, ID_PRE, comp->name); coutf("Rotation %srota%s, %srotr%s;", ID_PRE, comp->name, ID_PRE, comp->name); } list_iterate_end(liter); cout(""); /* Neutron state. */ coutf("MCNUM %snx, %sny, %snz, %snvx, %snvy, %snvz, %snt, " "%snsx, %snsy, %snsz, %snp;", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); cout(""); } /******************************************************************************* * Code generation for any NXDICT or NXDICTFILE declarations. *******************************************************************************/ static void cogen_nxdict(struct instr_def *instr) { List_handle liter; struct NXDentry *entry; coutf("#ifdef HAVE_NXDICT"); coutf("static NXDdict %snxd_handle;", ID_PRE); coutf("static NXhandle %snxd_file;", ID_PRE); coutf(""); coutf("void %snxdict_init(void) {", ID_PRE); /* Code to read any specified fictionary file. */ if(instr->nxdinfo->nxdfile) { char *quoted_name = str_quote(instr->nxdinfo->nxdfile); coutf(" %snxd_handle = NXDinitfromfile(\"%s\");", ID_PRE, quoted_name); str_free(quoted_name); } else { coutf(" %snxd_handle = NXDinitfromfile(NULL);", ID_PRE); } coutf(" if(%snxd_handle == NULL) {", ID_PRE); coutf(" printf(stderr, \"Error: could not read NeXus dictionary file.\\n\");"); coutf(" exit(1);"); coutf(" }", ID_PRE); /* Code for additional embedded dictionary entries. */ liter = list_iterate(instr->nxdinfo->nxdentries); while((entry = list_next(liter)) != NULL) { char *spec = exp_tostring(entry->spec); coutf(" NXDadd(%snxd_handle, \"%s_%s\",", ID_PRE, entry->compname, entry->param); code_set_source(instr->quoted_source, exp_getlineno(entry->spec)); coutf(" %s);", spec); code_reset_source(); str_free(spec); } list_iterate_end(liter); coutf("}"); coutf(""); coutf("void %snxdict_cleanup(void) {", ID_PRE); coutf(" NXDclose(%snxd_handle, NULL);", ID_PRE); coutf("}"); coutf(""); coutf("void %snxdict_nxout(void) {", ID_PRE); /* ToDo: automatically generate suitable calls to NXDputalias() here. */ coutf("}"); coutf("#else /* HAVE_NXDICT */"); coutf("void %snxdict_init(void) { }", ID_PRE); coutf("void %snxdict_cleanup(void) { }", ID_PRE); coutf("void %snxdict_nxout(void) { }", ID_PRE); coutf("#endif /* HAVE_NXDICT */", ID_PRE); coutf(""); } /******************************************************************************* * Generate the ##init() function. *******************************************************************************/ static void cogen_init(struct instr_def *instr) { List_handle liter; struct comp_inst *comp, *last; char *d2r; coutf("void %sinit(void) {", ID_PRE); /* User initializations from instrument definition. */ cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace, instr->inits); /* Initialization of component setting parameters and user initialization code. */ cout(" /* Component initializations. */"); liter = list_iterate(instr->complist); while((comp = list_next(liter)) != NULL) { List_handle setpar; struct comp_iformal *par; coutf(" /* Initializations for component %s. */", comp->name); /* Initialization of the component setting parameters. */ setpar = list_iterate(comp->def->set_par); while((par = list_next(setpar)) != NULL) { char *val; struct Symtab_entry *entry; entry = symtab_lookup(comp->setpar, par->id); val = exp_tostring(entry->val); code_set_source(instr->quoted_source, exp_getlineno(entry->val)); coutf(" %sc%s_%s = %s;", ID_PRE, comp->name, par->id, val); str_free(val); } list_iterate_end(setpar); if(list_len(comp->def->set_par) > 0) code_reset_source(); cout(""); /* Users initializations. */ if(list_len(comp->def->init_code->lines) > 0) cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->init_code); cout(""); } list_iterate_end(liter); /* Compute the necessary vectors and transformation matrices for coordinate system changes between components. */ cout(" /* Computation of coordinate transformations. */"); cout(" {"); coutf(" Coords %stc1, %stc2;", ID_PRE, ID_PRE); coutf(" Rotation %str1, %str2;", ID_PRE, ID_PRE); cout(""); /* Conversion factor degrees->radians for rotation angles. */ d2r = "DEG2RAD"; liter = list_iterate(instr->complist); last = NULL; coutf(" %sDEBUG_INSTR()", ID_PRE); while((comp = list_next(liter)) != NULL) { struct comp_inst *relcomp; /* Component relative to. */ char *x, *y, *z; coutf(" /* Component %s. */", comp->name); /* Absolute rotation. */ x = exp_tostring(comp->pos->orientation.x); y = exp_tostring(comp->pos->orientation.y); z = exp_tostring(comp->pos->orientation.z); relcomp = comp->pos->orientation_rel; if(relcomp == NULL) { /* Absolute orientation. */ coutf(" rot_set_rotation(%srota%s,", ID_PRE, comp->name); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.x)); coutf(" (%s)*%s,", x, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.y)); coutf(" (%s)*%s,", y, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.z)); coutf(" (%s)*%s);", z, d2r); code_reset_source(); } else { coutf(" rot_set_rotation(%str1,", ID_PRE); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.x)); coutf(" (%s)*%s,", x, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.y)); coutf(" (%s)*%s,", y, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.z)); coutf(" (%s)*%s);", z, d2r); code_reset_source(); coutf(" rot_mul(%str1, %srota%s, %srota%s);", ID_PRE, ID_PRE, relcomp->name, ID_PRE, comp->name); } str_free(z); str_free(y); str_free(x); /* Relative rotation. */ if(last == NULL) { /* First component. */ coutf(" rot_copy(%srotr%s, %srota%s);", ID_PRE, comp->name, ID_PRE, comp->name); } else { coutf(" rot_transpose(%srota%s, %str1);", ID_PRE, last->name, ID_PRE); coutf(" rot_mul(%srota%s, %str1, %srotr%s);", ID_PRE, comp->name, ID_PRE, ID_PRE, comp->name); } /* Absolute position. */ x = exp_tostring(comp->pos->place.x); y = exp_tostring(comp->pos->place.y); z = exp_tostring(comp->pos->place.z); relcomp = comp->pos->place_rel; if(relcomp == NULL) { coutf(" %sposa%s = coords_set(", ID_PRE, comp->name); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x)); coutf(" %s,", x); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y)); coutf(" %s,", y); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z)); coutf(" %s);", z); code_reset_source(); } else { coutf(" %stc1 = coords_set(", ID_PRE); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x)); coutf(" %s,", x); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y)); coutf(" %s,", y); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z)); coutf(" %s);", z); code_reset_source(); coutf(" rot_transpose(%srota%s, %str1);", ID_PRE, relcomp->name, ID_PRE); coutf(" %stc2 = rot_apply(%str1, %stc1);", ID_PRE, ID_PRE, ID_PRE); coutf(" %sposa%s = coords_add(%sposa%s, %stc2);", ID_PRE, comp->name, ID_PRE, relcomp->name, ID_PRE); } str_free(z); str_free(y); str_free(x); /* Relative position. */ if(last == NULL) coutf(" %stc1 = coords_neg(%sposa%s);", ID_PRE, ID_PRE, comp->name); else coutf(" %stc1 = coords_sub(%sposa%s, %sposa%s);", ID_PRE, ID_PRE, last->name, ID_PRE, comp->name); coutf(" %sposr%s = rot_apply(%srota%s, %stc1);", ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE); coutf(" %sDEBUG_COMPONENT(\"%s\", %sposa%s, %srota%s)", ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE, comp->name); last = comp; } list_iterate_end(liter); /* Output graphics representation of components. */ coutf(" if(mcdotrace) mcdisplay();"); coutf(" %sDEBUG_INSTR_END()", ID_PRE); cout(" }"); cout(""); cout("}"); cout(""); } static void cogen_trace(struct instr_def *instr) { List_handle liter; struct comp_inst *comp; /* Output the function header. */ coutf("void %sraytrace(void) {", ID_PRE); /* Local neutron state. */ cout(" /* Copy neutron state to local variables. */"); coutf(" MCNUM %snlx = %snx;", ID_PRE, ID_PRE); coutf(" MCNUM %snly = %sny;", ID_PRE, ID_PRE); coutf(" MCNUM %snlz = %snz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvx = %snvx;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvy = %snvy;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvz = %snvz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlt = %snt;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsx = %snsx;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsy = %snsy;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsz = %snsz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlp = %snp;", ID_PRE, ID_PRE); cout(""); /* Debugging (initial state). */ coutf(" %sDEBUG_ENTER()", ID_PRE); coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Now the trace code for each component. Proper scope is set up for each component using #define/#undef. */ liter = list_iterate(instr->complist); while((comp = list_next(liter)) != NULL) { char *statepars[10]; static char *statepars_names[10] = { "nlx", "nly", "nlz", "nlvx", "nlvy", "nlvz", "nlt", "nlsx", "nlsy", "nlp" }; int i; List_handle statepars_handle; coutf(" /* Component %s. */", comp->name); coutf(" %sDEBUG_COMP(\"%s\")", ID_PRE, comp->name); /* Change of coordinates. */ coutf(" %scoordschange(%sposr%s, %srotr%s,", ID_PRE, ID_PRE, comp->name, ID_PRE, comp->name); coutf(" &%snlx, &%snly, &%snlz,", ID_PRE, ID_PRE, ID_PRE); coutf(" &%snlvx, &%snlvy, &%snlvz,", ID_PRE, ID_PRE, ID_PRE); coutf(" &%snlt, &%snlsx, &%snlsy);", ID_PRE, ID_PRE, ID_PRE); if(instr->polarised) coutf(" %scoordschange_polarisation(" "%srotr%s, &%snlsx, &%snlsy, &%snlsz);", ID_PRE, ID_PRE, comp->name, ID_PRE, ID_PRE, ID_PRE); /* Debugging (entry into component). */ coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Trace code. */ for(i = 0; i < 10; i++) statepars[i] = NULL; statepars_handle = list_iterate(comp->def->state_par); for(i = 0; i < 10; i++) { statepars[i] = list_next(statepars_handle); if(statepars[i] == NULL) break; } list_iterate_end(statepars_handle); for(i = 0; i < 10; i++) { if(statepars[i] != NULL) coutf("#define %s %s%s", statepars[i], ID_PRE, statepars_names[i]); else break; } if(comp->def->polarisation_par) { coutf("#define %s %s%s", comp->def->polarisation_par[0], ID_PRE, "nlsx"); coutf("#define %s %s%s", comp->def->polarisation_par[1], ID_PRE, "nlsy"); coutf("#define %s %s%s", comp->def->polarisation_par[2], ID_PRE, "nlsz"); } cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->trace_code); if(comp->def->polarisation_par) { coutf("#undef %s", comp->def->polarisation_par[2]); coutf("#undef %s", comp->def->polarisation_par[1]); coutf("#undef %s", comp->def->polarisation_par[0]); } for(i = 9; i >= 0; i--) { if(statepars[i] != NULL) coutf("#undef %s", statepars[i]); } /* Debugging (exit from component). */ coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); cout(""); } list_iterate_end(liter); /* Absorbing neutrons - goto this label to skip remaining components. */ coutf(" %sabsorb:", ID_PRE); /* Debugging (final state). */ coutf(" %sDEBUG_LEAVE()", ID_PRE); coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Copy back neutron state to global variables. */ /* ToDo: Currently, this will be in the local coordinate system of the last component - should be transformed back into the global system. */ cout(" /* Copy neutron state to global variables. */"); coutf(" %snx = %snlx;", ID_PRE, ID_PRE); coutf(" %sny = %snly;", ID_PRE, ID_PRE); coutf(" %snz = %snlz;", ID_PRE, ID_PRE); coutf(" %snvx = %snlvx;", ID_PRE, ID_PRE); coutf(" %snvy = %snlvy;", ID_PRE, ID_PRE); coutf(" %snvz = %snlvz;", ID_PRE, ID_PRE); coutf(" %snt = %snlt;", ID_PRE, ID_PRE); coutf(" %snsx = %snlsx;", ID_PRE, ID_PRE); coutf(" %snsy = %snlsy;", ID_PRE, ID_PRE); coutf(" %snsz = %snlsz;", ID_PRE, ID_PRE); coutf(" %snp = %snlp;", ID_PRE, ID_PRE); /* Function end. */ cout("}"); cout(""); } static void cogen_finally(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_inst *comp; /* Component instance. */ /* User FINALLY code from component definitions (for each instance). */ coutf("void %sfinally(void) {", ID_PRE); cout(" /* User component FINALLY code. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->finally_code->lines) > 0) { coutf(" /* User FINALLY code for component '%s'. */", comp->name); cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->finally_code); cout(""); } } list_iterate_end(liter); /* User's FINALLY code from the instrument definition file. */ if(list_len(instr->finals->lines) > 0) { cout(" /* User FINALLY code from instrument definition. */"); cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace, instr->finals); cout(""); } cout("}"); } static void cogen_mcdisplay(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_inst *comp; /* Component instance. */ /* User FINALLY code from component definitions (for each instance). */ cout("#define magnify mcdis_magnify"); cout("#define line mcdis_line"); cout("#define multiline mcdis_multiline"); cout("#define circle mcdis_circle"); coutf("void %sdisplay(void) {", ID_PRE); cout(" printf(\"MCDISPLAY: start\\n\");"); cout(" /* Component MCDISPLAY code. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->mcdisplay_code->lines) > 0) { char *quoted_name = str_quote(comp->name); coutf(" /* MCDISPLAY code for component '%s'. */", comp->name); coutf(" printf(\"MCDISPLAY: component %%s\\n\", \"%s\");", quoted_name); cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->mcdisplay_code); cout(""); str_free(quoted_name); } } list_iterate_end(liter); cout(" printf(\"MCDISPLAY: end\\n\");"); cout("}"); cout("#undef magnify"); cout("#undef line"); cout("#undef multiline"); cout("#undef circle"); } /******************************************************************************* * Output code for the mcstas runtime system. Default is to copy the runtime * code into the generated executable, to minimize problems with finding the * right files during compilation and linking, but this may be changed using * the --no-runtime compiler switch. *******************************************************************************/ static void cogen_runtime(struct instr_def *instr) { if(instr->use_default_main) cout("#define MC_USE_DEFAULT_MAIN"); if(instr->enable_trace) cout("#define MC_TRACE_ENABLED"); if(instr->portable) cout("#define MC_PORTABLE"); if(instr->include_runtime) { cout("#define MC_EMBEDDED_RUNTIME"); /* Some stuff will be static. */ embed_file("mcstas-r.h"); embed_file("mcstas-r.c"); } else { cout("#include \"mcstas-r.h\""); } coutf("#ifdef MC_TRACE_ENABLED"); coutf("int %straceenabled = 1;", ID_PRE); coutf("#else"); coutf("int %straceenabled = 0;", ID_PRE); coutf("#endif"); coutf("int %sdefaultmain = %d;", ID_PRE, instr->use_default_main); coutf("char %sinstrument_name[] = \"%s\";", ID_PRE, instr->name); coutf("char %sinstrument_source[] = \"%s\";", ID_PRE, instr->source); if(instr->use_default_main) cout("int main(int argc, char *argv[]){return mcstas_main(argc, argv);}"); } /******************************************************************************* * Generate the output file (in C). *******************************************************************************/ void cogen(char *output_name, struct instr_def *instr) { /* Initialize output file. */ if(!output_name || !output_name[0] || !strcmp(output_name, "-")) { output_handle = fdopen(1, "w"); quoted_output_file_name = str_quote(""); } else { output_handle = fopen(output_name, "w"); quoted_output_file_name = str_quote(output_name); } num_next_output_line = 1; if(output_handle == NULL) fatal_error("Error opening output file '%s'\n", output_name); cout("/* Automatically generated file. Do not edit. */"); cout(""); cogen_runtime(instr); cogen_decls(instr); cogen_init(instr); if(instr->nxdinfo->any) cogen_nxdict(instr); /* Only if NXDICT/NXDICTFILE actually used */ cogen_trace(instr); cogen_finally(instr); cogen_mcdisplay(instr); } -------------- next part -------------- v 1.4.1.ef Aug 23, 2000 cogen.c : l127: add instr_formal_type_names_real lib/mcfrontlib.pl: l113: add case Param = string without quotes -------------- next part -------------- A non-text attachment was scrubbed... Name: mcfrontlib.pl Type: application/x-perl Size: 8329 bytes Desc: not available URL: From farhi at ill.fr Tue Aug 29 14:51:30 2000 From: farhi at ill.fr (Farhi) Date: Tue, 29 Aug 2000 14:51:30 +0200 Subject: McStas 1.4 : instrument parameters as strings Message-ID: <39ABB1D2.B086AB1A@ill.fr> (sorry, I think previous message was incomplete) Hello all mcneutron readers, I've found a bug in the handling of string parameters for instruments. Thus, I corrected that, and this requires to update the cogen.c and lib/mcfrontlib.pl files before McStas 1.4 installation. Then you will be able to use mcstas simlations with instrument string parameters: for instance if you define an instrument by DEFINE INSTRUMENT D11(GuideSampleLength, string GuideType, Lambda) you can run it with mcrun d11 -f MyOutput -n 1e6 -N 32 GuideSampleLength=20 GuideType=Glass Lambda=4.5,20 mcplot is ok with it. Cheers. EF. -- Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html \|/ ____ \|/ TAS-Group, Institut Laue-Langevin (ILL) Grenoble ~@-/ oO \-@~ Avenue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France /_( \__/ )_\ Work :Tel (33/0) 4 76 20 71 83. Fax (33/0) 4 76 48 39 06 \__U_/ La Grande Arche, Chateau d'Uriage, 38410 Saint Martin d'Uriage 04 76 59 73 94 -------------- next part -------------- /******************************************************************************* * Code generation from instrument definition. * * Project: Monte Carlo Simulation of Triple Axis Spectrometers * File name: cogen.c * * Author: K.N. Aug 20, 1997 * * $Id: cogen.c,v 1.22 2000/07/27 09:05:30 kn Exp $ * * Copyright (C) Risoe National Laboratory, 1997-1998, All rights reserved *******************************************************************************/ #include #include #include #include "mcstas.h" /******************************************************************************* * Some general comments on code generation. * * Code is output in the form of strings using the following functions: * cout(); (one line at a time) * coutf(); (with printf-style formatting) * * The type of numbers used in the generated code is given by the macro MCNUM * (defined in mcstas-r.h). * * All generated identifiers are prefixed with the string ID_PRE, to make name * clashes less likely to occur. Currently, for simplicity, we output modified * names directly, eg. * * cout("void " ID_PRE "init(void);"); * * But to make a later transition to a better name generation scheme possible, * it is important to use the ID_PRE macro everywhere identifiers are * generated. * * After the ID_PRE prefix a few letters occur in generated names to * distinguish different kinds of identifiers (instrument parameters, * component definition parameters, internal temporary variables and so on). * Care must be takes to choose these letters such that no name clashes will * occur with names generated by other parts of the code or generated from * user symbols. * * Finally, names generated from user symbols are generally chosen to match * the originals as closely as possible to make the generated code more * readable (for debugging purposes). * * The following is a list of the identifiers generated in the output. The * ID_PRE prefix is denoted by ##. The first column gives the identifier as it * appears in the generated code, the second explains the origin of the * identifier in the instrument definition source (if any). * * ##ip From instrument parameter . * ##init Function containing initialization code. * ##inputtable Table of instrument parameters. * ##NUMIPAR Macro giving the number of instrument parameters. * ##numipar Global variable with the value of ##NUMIPAR. * ##c_

From definition or setting parameter

in component * instance . * ##posa Absolute position of coordinate system of . * ##posr Position of relative to previous component. * ##rota Absolute rotation. * ##rotr Relative rotation. * ##tc1 Temporary variable used to compute transformations. * ##tc2 * ##tr1 * ##tr2 * ##nx Neutron state (position, velocity, time, and spin). * ##ny * ##nz * ##nvx * ##nvy * ##nvz * ##nt * ##nsx * ##nsy * ##nsz * ##np * ##absorb *******************************************************************************/ /******************************************************************************* * Generation of declarations. * * The following declarations are generated (## denotes the value ID_PRE): * 1. Header file #include - "mcstas-r.h" for declarations for the * mcstas runtime. * 2. Declarations of global variables to hold the values of the instrument * parameters. For example, for an instrument parameter OMM, the * declaration "MCNUM ##ipOMM;" is generated. * 3. Declaration of a table ##inputtable containing the list of instrument * parameters. For each parameter, the name, a pointer to the * corresponding global variable, and the type (double, int, * string) is given. The macro ##NUMIPAR gives the number of * entries in the table and is also found as the value of the * variable ##numipar; in addition, the table is terminated by two * NULLs. This table is used to read the instrument parameters from * the user or from another program such as TASCOM. * 4. User declarations copied verbatim from the instrument definition file. * 5. Declarations for the component parameters. This uses #define for * definition parameters and global variables for setting parameters. * X. User declarations from component definitions. * X. Declarations of variables for coordinate system transformations. * X. Declaration of variables for neutron state. * X. Function prototypes. *******************************************************************************/ /* Functions for outputting code. */ /* Handle for output file. */ static FILE *output_handle = NULL;/* Handle for output file. */ static int num_next_output_line = 1; /* Line number for next output line. */ static char *quoted_output_file_name = NULL; /* str_quote()'ed name of output file. */ /* Convert instrument formal parameter type numbers to their enum name. */ char *instr_formal_type_names[] = { "instr_type_double", "instr_type_int", "instr_type_string" }; char *instr_formal_type_names_real[] = { "MCNUM", "int", "char*" }; /******************************************************************************* * Output a line of code * Assumes that the output does not contain newlines. *******************************************************************************/ static void cout(char *s) { fprintf(output_handle, "%s\n", s); num_next_output_line++; } /******************************************************************************* * Output a line of code using printf-style format string. * Assumes that the output does not contain newlines. *******************************************************************************/ static void coutf(char *format, ...) { va_list ap; va_start(ap, format); vfprintf(output_handle, format, ap); va_end(ap); fprintf(output_handle, "\n"); num_next_output_line++; } /******************************************************************************* * Output #line directive to handle code coming from a different file. * The filename is assumed to be already properly quoted for special chars. *******************************************************************************/ static void code_set_source(char *filename, int linenum) { if(linenum > 0) coutf("#line %d \"%s\"", linenum, filename); } /******************************************************************************* * Output #line directive to reset back to the generated output C file. *******************************************************************************/ static void code_reset_source(void) { /* Note: the number after #line refers to the line AFTER the directive. */ coutf("#line %d \"%s\"", num_next_output_line + 1, quoted_output_file_name); } static void codeblock_out(struct code_block *code) { List_handle liter; /* For list iteration. */ char *line; /* Single code line. */ if(list_len(code->lines) <= 0) return; code_set_source(code->quoted_filename, code->linenum + 1); liter = list_iterate(code->lines); while(line = list_next(liter)) { fprintf(output_handle, "%s", line); num_next_output_line++; } list_iterate_end(liter); code_reset_source(); } static void codeblock_out_brace(struct code_block *code) { List_handle liter; /* For list iteration. */ char *line; /* Single code line. */ if(list_len(code->lines) <= 0) return; code_set_source(code->quoted_filename, code->linenum); cout("{"); liter = list_iterate(code->lines); while(line = list_next(liter)) { fprintf(output_handle, "%s", line); num_next_output_line++; } list_iterate_end(liter); cout("}"); code_reset_source(); } struct code_block * codeblock_new(void) { struct code_block *cb; palloc(cb); cb->filename = NULL; cb->quoted_filename = NULL; cb->linenum = -1; cb->lines = list_create(); return cb; } /******************************************************************************* * Read a file and output it to the generated simulation code. Uses a * fixed-size buffer, and will silently and arbitrarily break long lines. *******************************************************************************/ static void embed_file(char *name) { char buf[4096]; FILE *f; int last; /* First look in the system directory. */ f = open_file_search_sys(name); /* If not found, look in the full search path. */ if(f == NULL) f = open_file_search(name); /* If still not found, abort. */ if(f == NULL) fatal_error("Could not find file '%s'\n", name); cout(""); code_set_source(name, 1); /* Now loop, reading lines and outputting them in the code. */ while(!feof(f)) { if(fgets(buf, 4096, f) == NULL) break; last = strlen(buf) - 1; if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r')) buf[last--] = '\0'; if(last >= 0 && (buf[last] == '\n' || buf[last] == '\r')) buf[last--] = '\0'; cout(buf); } fclose(f); coutf("/* End of file \"%s\". */", name); cout(""); code_reset_source(); } /******************************************************************************* * The following two functions output #define directives around a given piece * of code to set up the right variable names (eg. the proper scope) for * instrument and component parameters. The functions are recursive on the * parameter lists. * * The functions first output an appropriate list of #define's, then call the * supplied function func with the argument data, and finally outputs a * matching list of #undef's. *******************************************************************************/ static void cogen_instrument_scope_rec(List_handle parlist, void (*func)(void *), void *data) { struct instr_formal *par; par = list_next(parlist); if(par != NULL) { coutf("#define %s %sip%s", par->id, ID_PRE, par->id); cogen_instrument_scope_rec(parlist, func, data); coutf("#undef %s", par->id); } else { (*func)(data); } } static void cogen_instrument_scope(struct instr_def *instr, void (*func)(void *), void *data) { List_handle parlist; /* This simply starts up the recursion. */ parlist = list_iterate(instr->formals); cogen_instrument_scope_rec(parlist, func, data); list_iterate_end(parlist); } /* Create the bindings for the SETTING parameter scope. Since the types of * setting parameters are known, local declarations can be used, avoiding the * problems with #define macro definitions. */ static void cogen_comp_scope_setpar(char *compname, List_handle set, int infunc, void (*func)(void *), void *data) { char *par; struct comp_iformal *formal; /* Get the next setting parameter. */ formal = list_next(set); if(formal != NULL) { /* Create local parameter equal to global value. */ if(infunc) coutf(" MCNUM %s = %sc%s_%s;", formal->id, ID_PRE, compname, formal->id); else coutf("#define %s %sc%s_%s", formal->id, ID_PRE, compname, formal->id); cogen_comp_scope_setpar(compname, set, infunc, func, data); if(!infunc) coutf("#undef %s", formal->id); } else { (*func)(data); /* Now do the body. */ } } /* Create the #define statements to set up the scope for DEFINITION and OUTPUT * parameters. */ static void cogen_comp_scope_rec(char *compname, List_handle def, List set_list, List_handle out, int infunc, void (*func)(void *), void *data) { char *par; struct comp_iformal *formal; /* First get the next DEFINITION or OUTPUT parameter, if any. */ if(def != NULL) { formal = list_next(def); if(formal == NULL) def = NULL; /* Now finished with definition parameters. */ else par = formal->id; } if(def == NULL) par = list_next(out); if(par != NULL) { /* Create #define / #undef pair for this parameter around rest of code. */ coutf("#define %s %sc%s_%s", par, ID_PRE, compname, par); cogen_comp_scope_rec(compname, def, set_list, out, infunc, func, data); coutf("#undef %s", par); } else { /* Now do the SETTING parameters. */ List_handle set; if(infunc && list_len(set_list) > 0) coutf("{ /* Declarations of SETTING parameters. */"); set = list_iterate(set_list); cogen_comp_scope_setpar(compname, set, infunc, func, data); list_iterate_end(set); if(infunc && list_len(set_list) > 0) coutf("} /* End of SETTING parameter declarations. */"); } } static void cogen_comp_scope(struct comp_inst *comp, int infunc, void (*func)(void *), void *data) { List_handle def, out; coutf("#define %scompcurname \"%s\"", ID_PRE, comp->name); def = list_iterate(comp->def->def_par); out = list_iterate(comp->def->out_par); cogen_comp_scope_rec(comp->name, def, comp->def->set_par, out, infunc, func, data); list_iterate_end(out); list_iterate_end(def); coutf("#undef %scompcurname", ID_PRE, comp->name); } /******************************************************************************* * Generate declarations from users declaration section in component definition. *******************************************************************************/ static void cogen_comp_decls_doit(void *arg) { struct comp_inst *comp = arg; /* Output the user declaration code block. */ codeblock_out(comp->def->decl_code); } static void cogen_comp_decls(struct comp_inst *comp) { cogen_comp_scope(comp, 0, cogen_comp_decls_doit, comp); } /******************************************************************************* * Generate declaration part of code. *******************************************************************************/ static void cogen_decls(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_iformal *c_formal;/* Name of component formal input parameter */ struct instr_formal *i_formal;/* Name of instrument formal parameter. */ struct comp_inst *comp; /* Component instance. */ /* 1. Function prototypes. */ coutf("void %sinit(void);", ID_PRE); coutf("void %sraytrace(void);", ID_PRE); coutf("void %sfinally(void);", ID_PRE); coutf("void %sdisplay(void);", ID_PRE); cout(""); /* 2. Global variables for instrument parameters. */ cout("/* Instrument parameters. */"); liter = list_iterate(instr->formals); while(i_formal = list_next(liter)) { coutf("%s " ID_PRE "ip%s;", instr_formal_type_names_real[i_formal->type], i_formal->id); } list_iterate_end(liter); cout(""); /* 3. Table of instrument parameters. */ coutf("#define %sNUMIPAR %d", ID_PRE, list_len(instr->formals)); coutf("int %snumipar = %d;", ID_PRE, list_len(instr->formals)); coutf("struct %sinputtable_struct %sinputtable[%sNUMIPAR+1] = {", ID_PRE, ID_PRE, ID_PRE); liter = list_iterate(instr->formals); while(i_formal = list_next(liter)) { coutf(" \"%s\", &%sip%s, %s,", i_formal->id, ID_PRE, i_formal->id, instr_formal_type_names[i_formal->type]); } list_iterate_end(liter); coutf(" NULL, NULL, instr_type_double"); coutf("};"); cout(""); /* User's declarations from the instrument definition file. */ cout("/* User declarations from instrument definition. */"); cogen_instrument_scope(instr, (void (*)(void *))codeblock_out, instr->decls); cout(""); /* Declaration of component definition and setting parameters. */ cout("/* Declarations of component definition and setting parameters. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { List_handle liter2; if(list_len(comp->def->def_par) > 0) { /* (The if avoids a redundant comment.) */ coutf("/* Definition parameters for component '%s'. */", comp->name); liter2 = list_iterate(comp->def->def_par); while(c_formal = list_next(liter2)) { struct Symtab_entry *entry = symtab_lookup(comp->defpar, c_formal->id); char *val = exp_tostring(entry->val); coutf("#define %sc%s_%s %s", ID_PRE, comp->name, c_formal->id, val); str_free(val); } list_iterate_end(liter2); } if(list_len(comp->def->set_par) > 0) { coutf("/* Setting parameters for component '%s'. */", comp->name); liter2 = list_iterate(comp->def->set_par); while(c_formal = list_next(liter2)) { coutf("MCNUM %sc%s_%s;", ID_PRE, comp->name, c_formal->id); } list_iterate_end(liter2); } if(list_len(comp->def->def_par) > 0 || list_len(comp->def->set_par) > 0) cout(""); } list_iterate_end(liter); /* User declarations from component definitions (for each instance). */ cout("/* User component declarations. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->decl_code->lines) > 0) { coutf("/* User declarations for component '%s'. */", comp->name); cogen_comp_decls(comp); cout(""); } } list_iterate_end(liter); /* Declarations for the position and rotation transformations between coordinate systems of components. */ liter = list_iterate(instr->complist); while(comp = list_next(liter)) { coutf("Coords %sposa%s, %sposr%s;", ID_PRE, comp->name, ID_PRE, comp->name); coutf("Rotation %srota%s, %srotr%s;", ID_PRE, comp->name, ID_PRE, comp->name); } list_iterate_end(liter); cout(""); /* Neutron state. */ coutf("MCNUM %snx, %sny, %snz, %snvx, %snvy, %snvz, %snt, " "%snsx, %snsy, %snsz, %snp;", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); cout(""); } /******************************************************************************* * Code generation for any NXDICT or NXDICTFILE declarations. *******************************************************************************/ static void cogen_nxdict(struct instr_def *instr) { List_handle liter; struct NXDentry *entry; coutf("#ifdef HAVE_NXDICT"); coutf("static NXDdict %snxd_handle;", ID_PRE); coutf("static NXhandle %snxd_file;", ID_PRE); coutf(""); coutf("void %snxdict_init(void) {", ID_PRE); /* Code to read any specified fictionary file. */ if(instr->nxdinfo->nxdfile) { char *quoted_name = str_quote(instr->nxdinfo->nxdfile); coutf(" %snxd_handle = NXDinitfromfile(\"%s\");", ID_PRE, quoted_name); str_free(quoted_name); } else { coutf(" %snxd_handle = NXDinitfromfile(NULL);", ID_PRE); } coutf(" if(%snxd_handle == NULL) {", ID_PRE); coutf(" printf(stderr, \"Error: could not read NeXus dictionary file.\\n\");"); coutf(" exit(1);"); coutf(" }", ID_PRE); /* Code for additional embedded dictionary entries. */ liter = list_iterate(instr->nxdinfo->nxdentries); while((entry = list_next(liter)) != NULL) { char *spec = exp_tostring(entry->spec); coutf(" NXDadd(%snxd_handle, \"%s_%s\",", ID_PRE, entry->compname, entry->param); code_set_source(instr->quoted_source, exp_getlineno(entry->spec)); coutf(" %s);", spec); code_reset_source(); str_free(spec); } list_iterate_end(liter); coutf("}"); coutf(""); coutf("void %snxdict_cleanup(void) {", ID_PRE); coutf(" NXDclose(%snxd_handle, NULL);", ID_PRE); coutf("}"); coutf(""); coutf("void %snxdict_nxout(void) {", ID_PRE); /* ToDo: automatically generate suitable calls to NXDputalias() here. */ coutf("}"); coutf("#else /* HAVE_NXDICT */"); coutf("void %snxdict_init(void) { }", ID_PRE); coutf("void %snxdict_cleanup(void) { }", ID_PRE); coutf("void %snxdict_nxout(void) { }", ID_PRE); coutf("#endif /* HAVE_NXDICT */", ID_PRE); coutf(""); } /******************************************************************************* * Generate the ##init() function. *******************************************************************************/ static void cogen_init(struct instr_def *instr) { List_handle liter; struct comp_inst *comp, *last; char *d2r; coutf("void %sinit(void) {", ID_PRE); /* User initializations from instrument definition. */ cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace, instr->inits); /* Initialization of component setting parameters and user initialization code. */ cout(" /* Component initializations. */"); liter = list_iterate(instr->complist); while((comp = list_next(liter)) != NULL) { List_handle setpar; struct comp_iformal *par; coutf(" /* Initializations for component %s. */", comp->name); /* Initialization of the component setting parameters. */ setpar = list_iterate(comp->def->set_par); while((par = list_next(setpar)) != NULL) { char *val; struct Symtab_entry *entry; entry = symtab_lookup(comp->setpar, par->id); val = exp_tostring(entry->val); code_set_source(instr->quoted_source, exp_getlineno(entry->val)); coutf(" %sc%s_%s = %s;", ID_PRE, comp->name, par->id, val); str_free(val); } list_iterate_end(setpar); if(list_len(comp->def->set_par) > 0) code_reset_source(); cout(""); /* Users initializations. */ if(list_len(comp->def->init_code->lines) > 0) cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->init_code); cout(""); } list_iterate_end(liter); /* Compute the necessary vectors and transformation matrices for coordinate system changes between components. */ cout(" /* Computation of coordinate transformations. */"); cout(" {"); coutf(" Coords %stc1, %stc2;", ID_PRE, ID_PRE); coutf(" Rotation %str1, %str2;", ID_PRE, ID_PRE); cout(""); /* Conversion factor degrees->radians for rotation angles. */ d2r = "DEG2RAD"; liter = list_iterate(instr->complist); last = NULL; coutf(" %sDEBUG_INSTR()", ID_PRE); while((comp = list_next(liter)) != NULL) { struct comp_inst *relcomp; /* Component relative to. */ char *x, *y, *z; coutf(" /* Component %s. */", comp->name); /* Absolute rotation. */ x = exp_tostring(comp->pos->orientation.x); y = exp_tostring(comp->pos->orientation.y); z = exp_tostring(comp->pos->orientation.z); relcomp = comp->pos->orientation_rel; if(relcomp == NULL) { /* Absolute orientation. */ coutf(" rot_set_rotation(%srota%s,", ID_PRE, comp->name); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.x)); coutf(" (%s)*%s,", x, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.y)); coutf(" (%s)*%s,", y, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.z)); coutf(" (%s)*%s);", z, d2r); code_reset_source(); } else { coutf(" rot_set_rotation(%str1,", ID_PRE); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.x)); coutf(" (%s)*%s,", x, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.y)); coutf(" (%s)*%s,", y, d2r); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->orientation.z)); coutf(" (%s)*%s);", z, d2r); code_reset_source(); coutf(" rot_mul(%str1, %srota%s, %srota%s);", ID_PRE, ID_PRE, relcomp->name, ID_PRE, comp->name); } str_free(z); str_free(y); str_free(x); /* Relative rotation. */ if(last == NULL) { /* First component. */ coutf(" rot_copy(%srotr%s, %srota%s);", ID_PRE, comp->name, ID_PRE, comp->name); } else { coutf(" rot_transpose(%srota%s, %str1);", ID_PRE, last->name, ID_PRE); coutf(" rot_mul(%srota%s, %str1, %srotr%s);", ID_PRE, comp->name, ID_PRE, ID_PRE, comp->name); } /* Absolute position. */ x = exp_tostring(comp->pos->place.x); y = exp_tostring(comp->pos->place.y); z = exp_tostring(comp->pos->place.z); relcomp = comp->pos->place_rel; if(relcomp == NULL) { coutf(" %sposa%s = coords_set(", ID_PRE, comp->name); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x)); coutf(" %s,", x); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y)); coutf(" %s,", y); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z)); coutf(" %s);", z); code_reset_source(); } else { coutf(" %stc1 = coords_set(", ID_PRE); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.x)); coutf(" %s,", x); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.y)); coutf(" %s,", y); code_set_source(instr->quoted_source, exp_getlineno(comp->pos->place.z)); coutf(" %s);", z); code_reset_source(); coutf(" rot_transpose(%srota%s, %str1);", ID_PRE, relcomp->name, ID_PRE); coutf(" %stc2 = rot_apply(%str1, %stc1);", ID_PRE, ID_PRE, ID_PRE); coutf(" %sposa%s = coords_add(%sposa%s, %stc2);", ID_PRE, comp->name, ID_PRE, relcomp->name, ID_PRE); } str_free(z); str_free(y); str_free(x); /* Relative position. */ if(last == NULL) coutf(" %stc1 = coords_neg(%sposa%s);", ID_PRE, ID_PRE, comp->name); else coutf(" %stc1 = coords_sub(%sposa%s, %sposa%s);", ID_PRE, ID_PRE, last->name, ID_PRE, comp->name); coutf(" %sposr%s = rot_apply(%srota%s, %stc1);", ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE); coutf(" %sDEBUG_COMPONENT(\"%s\", %sposa%s, %srota%s)", ID_PRE, comp->name, ID_PRE, comp->name, ID_PRE, comp->name); last = comp; } list_iterate_end(liter); /* Output graphics representation of components. */ coutf(" if(mcdotrace) mcdisplay();"); coutf(" %sDEBUG_INSTR_END()", ID_PRE); cout(" }"); cout(""); cout("}"); cout(""); } static void cogen_trace(struct instr_def *instr) { List_handle liter; struct comp_inst *comp; /* Output the function header. */ coutf("void %sraytrace(void) {", ID_PRE); /* Local neutron state. */ cout(" /* Copy neutron state to local variables. */"); coutf(" MCNUM %snlx = %snx;", ID_PRE, ID_PRE); coutf(" MCNUM %snly = %sny;", ID_PRE, ID_PRE); coutf(" MCNUM %snlz = %snz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvx = %snvx;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvy = %snvy;", ID_PRE, ID_PRE); coutf(" MCNUM %snlvz = %snvz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlt = %snt;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsx = %snsx;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsy = %snsy;", ID_PRE, ID_PRE); coutf(" MCNUM %snlsz = %snsz;", ID_PRE, ID_PRE); coutf(" MCNUM %snlp = %snp;", ID_PRE, ID_PRE); cout(""); /* Debugging (initial state). */ coutf(" %sDEBUG_ENTER()", ID_PRE); coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Now the trace code for each component. Proper scope is set up for each component using #define/#undef. */ liter = list_iterate(instr->complist); while((comp = list_next(liter)) != NULL) { char *statepars[10]; static char *statepars_names[10] = { "nlx", "nly", "nlz", "nlvx", "nlvy", "nlvz", "nlt", "nlsx", "nlsy", "nlp" }; int i; List_handle statepars_handle; coutf(" /* Component %s. */", comp->name); coutf(" %sDEBUG_COMP(\"%s\")", ID_PRE, comp->name); /* Change of coordinates. */ coutf(" %scoordschange(%sposr%s, %srotr%s,", ID_PRE, ID_PRE, comp->name, ID_PRE, comp->name); coutf(" &%snlx, &%snly, &%snlz,", ID_PRE, ID_PRE, ID_PRE); coutf(" &%snlvx, &%snlvy, &%snlvz,", ID_PRE, ID_PRE, ID_PRE); coutf(" &%snlt, &%snlsx, &%snlsy);", ID_PRE, ID_PRE, ID_PRE); if(instr->polarised) coutf(" %scoordschange_polarisation(" "%srotr%s, &%snlsx, &%snlsy, &%snlsz);", ID_PRE, ID_PRE, comp->name, ID_PRE, ID_PRE, ID_PRE); /* Debugging (entry into component). */ coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Trace code. */ for(i = 0; i < 10; i++) statepars[i] = NULL; statepars_handle = list_iterate(comp->def->state_par); for(i = 0; i < 10; i++) { statepars[i] = list_next(statepars_handle); if(statepars[i] == NULL) break; } list_iterate_end(statepars_handle); for(i = 0; i < 10; i++) { if(statepars[i] != NULL) coutf("#define %s %s%s", statepars[i], ID_PRE, statepars_names[i]); else break; } if(comp->def->polarisation_par) { coutf("#define %s %s%s", comp->def->polarisation_par[0], ID_PRE, "nlsx"); coutf("#define %s %s%s", comp->def->polarisation_par[1], ID_PRE, "nlsy"); coutf("#define %s %s%s", comp->def->polarisation_par[2], ID_PRE, "nlsz"); } cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->trace_code); if(comp->def->polarisation_par) { coutf("#undef %s", comp->def->polarisation_par[2]); coutf("#undef %s", comp->def->polarisation_par[1]); coutf("#undef %s", comp->def->polarisation_par[0]); } for(i = 9; i >= 0; i--) { if(statepars[i] != NULL) coutf("#undef %s", statepars[i]); } /* Debugging (exit from component). */ coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); cout(""); } list_iterate_end(liter); /* Absorbing neutrons - goto this label to skip remaining components. */ coutf(" %sabsorb:", ID_PRE); /* Debugging (final state). */ coutf(" %sDEBUG_LEAVE()", ID_PRE); coutf(" %sDEBUG_STATE(%snlx, %snly, %snlz, %snlvx, %snlvy, %snlvz," "%snlt,%snlsx,%snlsy, %snlp)", ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE, ID_PRE); /* Copy back neutron state to global variables. */ /* ToDo: Currently, this will be in the local coordinate system of the last component - should be transformed back into the global system. */ cout(" /* Copy neutron state to global variables. */"); coutf(" %snx = %snlx;", ID_PRE, ID_PRE); coutf(" %sny = %snly;", ID_PRE, ID_PRE); coutf(" %snz = %snlz;", ID_PRE, ID_PRE); coutf(" %snvx = %snlvx;", ID_PRE, ID_PRE); coutf(" %snvy = %snlvy;", ID_PRE, ID_PRE); coutf(" %snvz = %snlvz;", ID_PRE, ID_PRE); coutf(" %snt = %snlt;", ID_PRE, ID_PRE); coutf(" %snsx = %snlsx;", ID_PRE, ID_PRE); coutf(" %snsy = %snlsy;", ID_PRE, ID_PRE); coutf(" %snsz = %snlsz;", ID_PRE, ID_PRE); coutf(" %snp = %snlp;", ID_PRE, ID_PRE); /* Function end. */ cout("}"); cout(""); } static void cogen_finally(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_inst *comp; /* Component instance. */ /* User FINALLY code from component definitions (for each instance). */ coutf("void %sfinally(void) {", ID_PRE); cout(" /* User component FINALLY code. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->finally_code->lines) > 0) { coutf(" /* User FINALLY code for component '%s'. */", comp->name); cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->finally_code); cout(""); } } list_iterate_end(liter); /* User's FINALLY code from the instrument definition file. */ if(list_len(instr->finals->lines) > 0) { cout(" /* User FINALLY code from instrument definition. */"); cogen_instrument_scope(instr, (void (*)(void *))codeblock_out_brace, instr->finals); cout(""); } cout("}"); } static void cogen_mcdisplay(struct instr_def *instr) { List_handle liter; /* For list iteration. */ struct comp_inst *comp; /* Component instance. */ /* User FINALLY code from component definitions (for each instance). */ cout("#define magnify mcdis_magnify"); cout("#define line mcdis_line"); cout("#define multiline mcdis_multiline"); cout("#define circle mcdis_circle"); coutf("void %sdisplay(void) {", ID_PRE); cout(" printf(\"MCDISPLAY: start\\n\");"); cout(" /* Component MCDISPLAY code. */"); cout(""); liter = list_iterate(instr->complist); while(comp = list_next(liter)) { if(list_len(comp->def->mcdisplay_code->lines) > 0) { char *quoted_name = str_quote(comp->name); coutf(" /* MCDISPLAY code for component '%s'. */", comp->name); coutf(" printf(\"MCDISPLAY: component %%s\\n\", \"%s\");", quoted_name); cogen_comp_scope(comp, 1, (void (*)(void *))codeblock_out_brace, comp->def->mcdisplay_code); cout(""); str_free(quoted_name); } } list_iterate_end(liter); cout(" printf(\"MCDISPLAY: end\\n\");"); cout("}"); cout("#undef magnify"); cout("#undef line"); cout("#undef multiline"); cout("#undef circle"); } /******************************************************************************* * Output code for the mcstas runtime system. Default is to copy the runtime * code into the generated executable, to minimize problems with finding the * right files during compilation and linking, but this may be changed using * the --no-runtime compiler switch. *******************************************************************************/ static void cogen_runtime(struct instr_def *instr) { if(instr->use_default_main) cout("#define MC_USE_DEFAULT_MAIN"); if(instr->enable_trace) cout("#define MC_TRACE_ENABLED"); if(instr->portable) cout("#define MC_PORTABLE"); if(instr->include_runtime) { cout("#define MC_EMBEDDED_RUNTIME"); /* Some stuff will be static. */ embed_file("mcstas-r.h"); embed_file("mcstas-r.c"); } else { cout("#include \"mcstas-r.h\""); } coutf("#ifdef MC_TRACE_ENABLED"); coutf("int %straceenabled = 1;", ID_PRE); coutf("#else"); coutf("int %straceenabled = 0;", ID_PRE); coutf("#endif"); coutf("int %sdefaultmain = %d;", ID_PRE, instr->use_default_main); coutf("char %sinstrument_name[] = \"%s\";", ID_PRE, instr->name); coutf("char %sinstrument_source[] = \"%s\";", ID_PRE, instr->source); if(instr->use_default_main) cout("int main(int argc, char *argv[]){return mcstas_main(argc, argv);}"); } /******************************************************************************* * Generate the output file (in C). *******************************************************************************/ void cogen(char *output_name, struct instr_def *instr) { /* Initialize output file. */ if(!output_name || !output_name[0] || !strcmp(output_name, "-")) { output_handle = fdopen(1, "w"); quoted_output_file_name = str_quote(""); } else { output_handle = fopen(output_name, "w"); quoted_output_file_name = str_quote(output_name); } num_next_output_line = 1; if(output_handle == NULL) fatal_error("Error opening output file '%s'\n", output_name); cout("/* Automatically generated file. Do not edit. */"); cout(""); cogen_runtime(instr); cogen_decls(instr); cogen_init(instr); if(instr->nxdinfo->any) cogen_nxdict(instr); /* Only if NXDICT/NXDICTFILE actually used */ cogen_trace(instr); cogen_finally(instr); cogen_mcdisplay(instr); } -------------- next part -------------- v 1.4.1.ef Aug 23, 2000 cogen.c : l127: add instr_formal_type_names_real lib/mcfrontlib.pl: l113: add case Param = string without quotes -------------- next part -------------- A non-text attachment was scrubbed... Name: mcfrontlib.pl Type: application/x-perl Size: 8330 bytes Desc: not available URL: From farhi at ill.fr Wed Aug 30 14:21:20 2000 From: farhi at ill.fr (Farhi) Date: Wed, 30 Aug 2000 14:21:20 +0200 Subject: message sending problem Message-ID: <39ACFC40.320E56B7@ill.fr> Some messages sent to the neutron-mc list seem to be truncated when re-sent to the list members at ILL. This happens for more than 4 lines messages, with both netscape and eudora mailers, under various machines.... Cheers. EF. -- Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html \|/ ____ \|/ TAS-Group, Institut Laue-Langevin (ILL) Grenoble ~@-/ oO \-@~ Avenue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France /_( \__/ )_\ Work :Tel (33/0) 4 76 20 71 83. Fax (33/0) 4 76 48 39 06 \__U_/ La Grande Arche, Chateau d'Uriage, 38410 Saint Martin d'Uriage 04 76 59 73 94 -------------- next part -------------- An HTML attachment was scrubbed... URL: From yuan at phonon.ssd.ornl.gov Thu Sep 7 20:33:33 2000 From: yuan at phonon.ssd.ornl.gov (Yuan, Peng) Date: Thu, 07 Sep 2000 14:33:33 -0400 Subject: No subject Message-ID: <005201c018fa$20ed3100$4b25db80@ssd.ornl.gov> Hi, I am a new user of McStas. I have a problem each time when using McStas to generate c code. When I using: mcstas curved_bender.instr It says: ' in file 'curved_bender.instr', line 1. parse error, expecting `"NXDICT"' or `"NXDICTFILE"' or `"TRACE"' at line 1. Errors encountered during parse. Would you please give me some advice? Many advanced thanks. The curved_bender.instr is like this: DEFINE INSTRUMENT curved_bender() TRACE COMPONENT source = Source_flat(radius = 0.015, dist = 1, xw=0.024, yh=0.015, E0=8, dE=7) AT (0,0,0) ABSOLUTE COMPONENT slit1 = Slit(xmin=-0.02, xmax=0.02, ymin=-0.02, ymax=0.02) AT (0, 0, 2) RELATIVE source ROTATED (0, 0, 0) RELATIVE source COMPONENT arm = Arm() AT (0, 0, 2) RELATIVE source ROTATED (0, 0, 0) RELATIVE source COMPONENT bender = Bender(w=0.04, h=0.04, r=65, d=0, Win=0.046154, k=10, R0a=1.0, Qca=0.022, alphaa=3.64, ma=3.5,Wa=0, R0i=1.0, Qci=0.022, alphai=3.64, mi=3.5,Wi=0, R0s=1.0, Qcs=0.022, alphas=3.64, ms=3.5,Ws=0,) AT (0,0,0) RELATIVE arm ROTATED (0, 0, 0) RELATIVE arm COMPONENT slit2 = Slit(xmin=-0.02, xmax=0.02, ymin=-0.02, ymax=0.02) AT (0, 0, 2.9989) RELATIVE arm ROTATED (0,-0.046154,0) relative arm COMPONENT monitor = L_monitor(nchan=100, filename="cR65Ch10.wl", xmin=-0.1, xmax=0.1, ymin=-0.1, ymax=0.1, Lmin=1, Lmax=15) AT (0,0,0) RELATIVE slit2 ROTATED (0, 0, 0) RELATIVE slit2 END -------------- next part -------------- An HTML attachment was scrubbed... URL: From kadowaki at phys.metro-u.ac.jp Thu Sep 14 19:01:44 2000 From: kadowaki at phys.metro-u.ac.jp (H.Kadowaki) Date: Fri, 15 Sep 2000 02:01:44 +0900 Subject: a TOF source Message-ID: <200009141701.CAA38714@comp.metro-u.ac.jp> Hello McStas users, I have written a TOF source component producing pulse shapes of the Ikeda-Carpenter function. It emulates the energy spectrum and pulse shape of a KEK-JAERI 1MW pulse-source to be constructed, decoupled supercritical hydrogen moderator (12x12x5 cm^3) at 20 K with an H2O premoderator in a Pb reflector (decoupling energy = 1 eV). I am sending 3 files. (1) Modr_dcHPb_flux.comp TOF source component (2) modr_dcHPb.c functional forms of energy spectrum and pulse shape are described. (3) T_Modr_dcHPb_flux.instr example of testing Modr_dcHPb_flux.comp Its results are not so bad. Regards H. Kadowaki Department of Physics, Tokyo Metropolitan University, Hachioji-shi, Tokyo 192-0397, Japan E-mail: kadowaki at phys.metro-u.ac.jp ############### remove this line ################## /******************begin Modr_dcHPb_flux.comp ******/ /* * McStas, the neutron ray-tracing package * Maintained by Kristian Nielsen and Kim Lefmann, * Copyright 1997-2000 Risoe National Laboratory, Roskilde, Denmark * * %I * Written by: H KADOWAKI kadowaki at phys.metro-u.ac.jp * Date: 2000/9/8 * Version: 0.2 * Origin: modified from Moderator.comp of McStas1.3 release * * A pulsed source of a decoupled H_2 moderator for time-of-flight. * This emulates the energy spectrum and pulse shape of * a KEK-JAERI 1MW pulse-source to be constructed, * decoupled supercritical hydrogen moderator (12x12x5 cm^3) at 20 K * with an H2O premoderator in a Pb reflector (decoupling energy = 1 eV). * * %D * Produces a time-of-flight spectrum, with a energy distribution * using fitted functions written in the Ikead & Carpenter paper. * The functions espectr(E) and pulse_shape(E, t) are defined * in modr_dcHPb.c * * Since the flux of the source is given in an absolute scale and * the weight p is adjusted properly, the computed intensity I is * counting rate in unit time [counts/(sec MW)]. * * To use this component, compile with modr_dcHPb.c as follows. * mcstas test.instr * gcc -O -o test.ex test.c modr_dcHPb.c -lm * * %P * Input parameters: * * xws: (m) Width of source * yhs: (m) Height of source * angle (degree) Angle of rotation by which the front face is rotated * around the y-axis (angle=0 : xy-plane) * Emin: (meV) Lower edge of energy distribution * Emax (meV) Upper edge of energy distribution * dist: (m) Distance from source to the focusing rectangle * xw: (m) Width of focusing rectangle * yh: (m) Height of focusing rectangle * * %E ***************************************************************************/ DEFINE COMPONENT Modr_dcHPb_flux DEFINITION PARAMETERS (xws, yhs, angle, Emin, Emax, dist, xw, yh) SETTING PARAMETERS () OUTPUT PARAMETERS (hdiv,vdiv,p_in,angle_rad,xxx_low_limit,xx,del_E,n_E ,tauEtab) STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p) DECLARE %{ #define TABLE_LENGTH_E 1024 double hdiv,vdiv; double p_in,angle_rad,xxx_low_limit; double xx[TABLE_LENGTH_E],del_E; int n_E; double tauEtab[TABLE_LENGTH_E]; %} INITIALIZE %{ int i; double ee,denom,ang; extern double espectr( double ee); extern double pulse_shape(double ee, double ttt); hdiv = atan(xw/(2.0*dist)); vdiv = atan(yh/(2.0*dist)); ang=angle; angle_rad = ang/45.0*atan(1.0); /* set xx[i] */ n_E=TABLE_LENGTH_E-1; /* number of division */ del_E=(Emax-Emin)/n_E; /* step of E */ denom=0.0; for(i=0; i (yy*2.71) ) {tau=tt; break;} } } /* printf(" %g %g %g \n",ee,tpeak,tau); */ tauEtab[i]=tau; } %} TRACE %{ double theta0,phi0,theta,phi,v,E; double distp,hdivp,vdivp; double xxx,tauE; int il,ih,im; extern double pulse_shape(double ee, double ttt); p=p_in; x = xws*(-0.5+rand01()) ; /* Choose point on source */ y = yhs*(-0.5+rand01()) ; /* with uniform distribution. */ z = - x * sin(angle_rad); /* rotation around the y-axis */ x = x * cos(angle_rad); distp = dist-z; theta0 = -atan(x/distp); /* Angles to aim at target centre */ phi0 = -atan(y/distp); hdivp = atan(xw/(2.0*distp)); vdivp = atan(yh/(2.0*distp)); theta = theta0 + hdivp*randpm1(); /* Small angle approx. */ phi = phi0 + vdivp*randpm1(); /* set E by energy distribution of espectr(E) */ xxx=rand01(); /* xxx -> E */ /* xxx = [\int_{Emin}^{E } espectr(e) de ] /[\int_{Emin}^{Emax} espectr(e) de ] */ /* xx[il] <= xxx < xx[ih=il+1] find out il,ih */ il=0; ih=n_E; for(im=il+(ih-il)/2; (ih-il)>1; im=il+(ih-il)/2) { if(xxx= n_E) {il=n_E-1;} if(il < 0) {il=0;} xxx=(E-Emin-del_E*il)/del_E; xxx=(tauEtab[il+1]-tauEtab[il])*xxx; tauE=tauEtab[il]+xxx; /* linear interpolation */ /* set t using distribution exp(-t/tauE)/tauE */ do{ xxx=rand01(); /* 1-rand01() */ /* if(xxx <= xxx_low_limit ) {printf(" xxx <= %g, xxx= %g \n",xxx_low_limit,xxx);} discard small xxx , i.e., very large t, p */ } while( xxx <= xxx_low_limit ); t=-tauE*log(xxx); /* xxx -> t */ /* set p by weight multiplication weight = \pi_j = pulse_shape(E, t) / [exp(-t/tauE)/tauE] = pulse_shape(E, t)*tauE /(xxx=1-rand01()) */ xxx=tauE/xxx; xxx= pulse_shape(E, t)*xxx; /* weight \pi_j */ p=p*xxx; t=t*1.0e-6; /* microsec -> sec */ %} /* MCDISPLAY %{ double xmin,xmax,ymin,ymax,zmin,zmax; xmax=xws*0.5*cos(angle_rad);xmin=-xmax; ymax=yhs*0.5;ymin=-ymax; zmax=-xws*0.5*sin(angle_rad);zmin=-zmax magnify("xy"); multiline(5, (double)xmin, (double)ymin, (double)zmin, (double)xmax, (double)ymin, (double)zmax, (double)xmax, (double)ymax, (double)zmax, (double)xmin, (double)ymax, (double)zmin, (double)xmin, (double)ymin, (double)zmin); %} */ END /******************end Modr_dcHPb_flux.comp ******/ ############### remove this line ################## /** begin modr_dcHPb.c **/ /* written by H KADOWAKI kadowaki at phys.metro-u.ac.jp version 0.2 2000/9/8 */ /* Energy spectrum and pulse shape of Decoupled supercritical hydrogen moderator (12 x 12 x 5 cm^3) at 20 K with an H2O premoderator in a Pb reflector (decoupling energy = 1 eV) Data were provided by simulations by TESHIGAWARA(2000/8/3). To emulate these data in MCSTAS, they are fitted using functions of the Ikeda & Carpenter (IC) paper, and resulting functional forms are described as. espectr(E) and pulse_shape(E, t) Ref: S. Ikeda and J.M. Carpenter: Nucl. Instr. Meth. A239 (1985) 536. espectr(E) = neutron flux as a function of energy eq. (18) of IC [neutrons/(cm^2 sr eV sec MW)] E [meV] pulse_shape(E, t) = pulse shape of neutrons with energy=E eq. (10') (11) (14) of IC E [meV] t [microsec] \begin{eqnarray*} espectr(E) &=& \bar{i}(E) \\ &=& \bar{i}_{Th} \frac{E}{E_{T}^{2}} \exp(-E/E_{T}) + \bar{i}_{epi} \frac{\Delta(E)}{\Delta(E_0)} \frac{1}{E} \left( \frac{E}{E_0} \right)^{\alpha} \\ \Delta(E) &=& [1 + \exp (a \lambda -b ) ]^{-1} \end{eqnarray*} \begin{eqnarray*} time\_struct(E, t) &=& \psi(v, t) \\ &=& \frac{1}{2} (1-R) \alpha^3 t^2 \exp(- \alpha t) \\ &+& R \frac{\alpha^3 \beta}{(\alpha-\beta)^3} \{ \exp(- \beta t) - \exp(- \alpha t) [1+(\alpha-\beta) t + \frac{1}{2} (\alpha-\beta)^2 t^2] \} \\ \alpha &=& v \Sigma \\ \Sigma &=& (S_1^2 + S_2^2 \lambda^2 )^{1/2} \\ R &=& \exp (-E/E_0) \end{eqnarray*} To use these in MCSTAS, they should be declared as external functions and compile, for example, as follows. $mcstas test.instr $gcc -O -o test.ex test.c modr_dcHPb.c -lm */ #include #include /* Energy spectrum */ double espectr(double ee) { double e0=1000.0,wlen0=0.2860057; /* e0 = E_0 = 1000 [meV], wlen0 = \lambda_0 [Angstrom] of E_0 */ double pa1=0.9695810E+15; /* \bar{i}_{Th} */ double pa2= 4.100054 ; /* E_T [meV] */ double pa3=0.2948123E+15; /* \bar{i}_{epi} */ double pa4= 10.29586 ; /* a [Angstrom^{-1}] */ double pa5= 26.28562 ; /* b [1] */ double pa6=0.2965801E-01; /* \alpha [1] */ /* pa1-pa6 are based on fit in range 1< E < 1000 meV */ double xx,xxx,yyy,wlen; /* ee = energy [meV], wlen = wave length [Angstrom] xx,xxx,yyy = work variables */ xxx=pa1/(pa2*pa2); xx=-ee/pa2; xxx=xxx*ee*exp(xx); wlen=9.04429/sqrt(ee); yyy=pa3*(1.0+exp(pa4*wlen0-pa5)); yyy=yyy/(1.0+exp(pa4*wlen -pa5)); yyy=yyy/ee; yyy=yyy*pow((ee/e0),pa6); return (xxx+yyy); } /* pulse shape Ikeda & Cartpenter function */ double pulse_shape(double ee, double ttt) /* ee = energy [meV], ttt = time [microsec]*/ { double pa1= .9669852 ; /* S_1 [cm^{-1}] */ double pa2= .1525358 ; /* S_2 [cm^{-1} Angstrom^{-1}] */ double pa3=0.1200498E-01; /* \beta [microsec^{-1}]*/ double pa4= 20.94545 ; /* E_0 of R=exp(-E/E_0) [meV]*/ /* based on fit in range 1< E < 400 meV */ double pi=3.141592654; double velc,wlen,sigma,alpha,beta,amb,RR; double xxx,zz,yyy,yyy1,uu,vv; /* velc = velocity, wlen= wave length, sigma=\Sigma, alpha=\alpha, beta=\beta, amb=\alpha-\beta, RR=R, xxx,zz,yyy,yyy1,uu,vv= work variables */ if(ttt < 0.0) { xxx=0.0; } else { xxx=sqrt(ee/2.072); wlen=(2.0*pi)/xxx; /* wlen=\lambda [Angstrom]*/ velc=xxx*0.06296; /* velc=v=velocity [cm/micro sec] */ sigma=sqrt(pa1*pa1+(pa2*pa2*wlen*wlen)); /* sigma=\Sigma [cm^{-1}]*/ alpha=sigma*velc; RR=-ee/pa4; RR=exp(RR); /* R=exp(-E/E_0) */ xxx=0.5*alpha*(1.0-RR); zz=alpha*ttt; xxx=xxx*(zz*zz)*exp(-zz); /* 1st term of eq.(10') */ beta=pa3; amb=alpha-beta; yyy=alpha/amb; yyy=yyy*yyy*yyy; yyy=yyy*RR*beta; uu=beta*ttt; vv=amb*ttt; yyy1=1.0+vv+0.5*vv*vv; yyy1=exp(-uu)-exp(-zz)*yyy1; yyy=yyy*yyy1; /* 2nd term of eq.(10') */ xxx=xxx+yyy; } return (xxx); } /** end modr_dcHPb.c **/ ############### remove this line ################## DEFINE INSTRUMENT T_Modr_dcHPb_flux (Elow,Ehigh) /* T_Modr_dcHPb_flux.instr test of Modr_dcHPb_flux.comp mcstas T_Modr_dcHPb_flux.instr gcc -O -o T_Modr_dcHPb_flux.ex T_Modr_dcHPb_flux.c modr_dcHPb.c -lm */ TRACE COMPONENT arm1=Arm() AT (0,0,0) ABSOLUTE COMPONENT mod1=Modr_dcHPb_flux( xws=0.01, yhs=0.01, angle=0.0, Emin=Elow, Emax=Ehigh, dist=1.0, xw=0.01, yh=0.01) AT (0,0,0) RELATIVE arm1 COMPONENT mon1= TOF_monitor( xmin=-0.005,xmax=0.005,ymin=-0.005,ymax=0.005, nchan=1000,dt=0.5, filename="tstr.T.Mod.dH.dat3") AT (0,0,0.0001) RELATIVE arm1 COMPONENT mon2= E_monitor( xmin=-0.005,xmax=0.005,ymin=-0.005,ymax=0.005, Emin=Elow,Emax=Ehigh, nchan=2000, filename="espc.T.Mod.dH.dat3") AT (0,0,1.001) RELATIVE arm1 END