Skip to content
38 changes: 38 additions & 0 deletions docs/GRAMMAR/ADR-records/ADR_20260904_COPY_INSTRUMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# INSTRUMENT keyword COPY(instance) - only copy instance type and paramters

## Status

*Proposed* and prototype *implemented*

## Context

As demonstrated by @g5t in https://github.com/mccode-dev/McCode/issues/2621, a bug was found in relation to the `COPY` keyword and `EXTEND` blocks, leading to a confusing warning of the form

```c
WARNING: Existing (COPY) EXTEND block in COMPONENT image_plate_scattered:
EXTEND %{
/* take into account ZnS scintillator efficiency */
double eff=0.5;
double v=sqrt(vx*vx+vy*vy+vz*vz);
p *= 1.0-exp(3960.0/v*log(1.0-eff/100.0));
%}

is overwritten by:
EXTEND %{
%}
```
even in the case of an empty / non-existent EXTEND %{%} block on the copy.

## Decision

For sake of simplicity and to ensure instrument-readability @willend, @g5t and @mads-bertelsen have agreed to no longer include an `EXTEND` from `instance` when `COPY(instance)`. Adding an explicit `EXTEND` block (even if duplicated) is much more explicit.

By symmetry, `METADATA`, `GROUP`, `WHEN`, `JUMP`, and `SPLIT` are from now on also not copied - only `instamnce` and its `instance->actual` are copied.

[`mccode-antlr`](https://github.com/mccode-dev/mccode-antlr/) already implements this behaviour for `EXTEND` since [this commit](https://github.com/mccode-dev/mccode-antlr/commit/7786fd31efde941a16e028f6a616f5b8284c0b50)

## Consequences

* A statistic om the combined use of COPY with the affected keywords will be provided soon
* CHANGELOG should be crystal clear on this change / potential incompatibility

46 changes: 13 additions & 33 deletions mccode/src/instrument.y
Original file line number Diff line number Diff line change
Expand Up @@ -1284,15 +1284,16 @@ instref: "COPY" '(' compref ')' actuallist /* make a copy of a previous instance
comp_src = $3;
palloc(comp);
comp->def = comp_src->def;
comp->extend = comp_src->extend;
comp->group = comp_src->group;
comp->jump = comp_src->jump;
comp->when = comp_src->when;
/* now catenate src and actual parameters */
comp->actuals= symtab_create();
symtab_cat(comp->actuals, $5);
symtab_cat(comp->actuals, comp_src->actuals);
comp->metadata = metadata_list_copy(comp_src->metadata);
/* All other proprties are initialized from fresh */
comp->extend = codeblock_new();
comp->group = NULL;
comp->jump = list_create();
comp->when = NULL;
comp->metadata = list_create();
$$ = comp;
}
| "COPY" '(' compref ')'
Expand All @@ -1304,12 +1305,13 @@ instref: "COPY" '(' compref ')' actuallist /* make a copy of a previous instance
comp->defpar = comp_src->defpar;
comp->setpar = comp_src->setpar;
comp->def = comp_src->def;
comp->extend = comp_src->extend;
comp->group = comp_src->group;
comp->jump = comp_src->jump;
comp->when = comp_src->when;
comp->actuals= comp_src->actuals;
comp->metadata = metadata_list_copy(comp_src->metadata);
/* All other proprties are initialized from fresh */
comp->extend = codeblock_new();
comp->group = NULL;
comp->jump = list_create();
comp->when = NULL;
comp->metadata = list_create();
$$ = comp;
}
| TOK_ID actuallist /* define new instance with def+set parameters */
Expand All @@ -1325,7 +1327,7 @@ instref: "COPY" '(' compref ')' actuallist /* make a copy of a previous instance
comp->jump = list_create();
comp->when = NULL;
comp->actuals= $2;
comp->metadata = metadata_list_copy(def->metadata);
comp->metadata = list_create();
$$ = comp;
}
;
Expand Down Expand Up @@ -1417,28 +1419,6 @@ component: removable cpuonly split "COMPONENT" instname '=' instref
}
}
if ($13->linenum) {
#ifdef GENERATE_C
if (comp->extend->linenum>0) {
fprintf(stderr, "\n-----------------------------------------------------------\n");
fprintf(stderr, "WARNING: Existing (COPY) EXTEND block in COMPONENT %s:\n", comp->name);
List_handle liter = list_iterate(comp->extend->lines);
List_handle liter2 = list_iterate($13->lines);
char *line, *line2;
fprintf(stderr, " EXTEND %%{\n");
while((line = list_next(liter))) {
fprintf(stderr, " %s",line);
}
list_iterate_end(liter);
fprintf(stderr, " %%}\n");
fprintf(stderr, "\nis overwritten by:\n");
fprintf(stderr, " EXTEND %%{\n");
while((line2 = list_next(liter2))) {
fprintf(stderr, " %s",line2);
}
list_iterate_end(liter2);
fprintf(stderr, " %%}\n-----------------------------------------------------------\n");
}
#endif
comp->extend= $13; /* EXTEND block*/
}
if (list_len($14)) comp->jump = $14;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The `SEMSANS_instrument` Instrument
# The `SEMSANS_inst` Instrument

*McStas: SEMSANS-instrument*

Expand Down Expand Up @@ -62,6 +62,6 @@ Parameters in **boldface** are required; the others are optional.

## Links

- [Source code](SEMSANS_instrument.instr) for `SEMSANS_instrument.instr`.
- [Source code](SEMSANS_inst.instr) for `SEMSANS_inst.instr`.

---
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* SEMSANS instrument with 2 isosceles triangular field coils
*
* %Example: -y Detector: TOF_det_I=2.87073e-09
* %Example: debug=1 Detector: TOF_det_I=2.87073e-09
*
* %Parameters
* triacoil_depth: [m] Half of the triangular coil depth in z-direction (one right triangle)
Expand Down Expand Up @@ -56,10 +57,11 @@
* detector_pos: [m] Position of detector
* tlow: [mu-s] tmin of detector
* thigh: [mu-s] tmax of detector
* debug: [1] Debug flag - when enabled more monitor outputs appear
*
* %End
*******************************************************************************/
DEFINE INSTRUMENT SEMSANS_instrument(triacoil_depth=1.935000e-01, triacoil_width=7.042824e-02, triacoil_height=3.000000e-01, pol_zdepth=9.300000e-01, vcoil_zdepth=1.500000e-01, Guide1_depth=1.650000e-02, Guide2_depth=3.315000e-01, Guide3_depth=3.315000e-01, Guide4_depth=5.650000e-02, Bguide=-5.000000e-04, Bextra=-2.120000e-02, Bt2=-4.440000e-03, Bt1=-2.560000e-03, DLambda=4.166366e+00, Lambda=4.559500e+00, flippos=3.100000e-02, FLIP=1.000000e+00, chop1_pos=5.000000e-01, chop2_pos=9.740000e-01, pol_pos=1.907000e+00, analyser_pos=6.072000e+00, grating_w=1.570000e-03, grating_a=2.930000e-03, slit_1_pos=2.957000e+00, slit_2_pos=5.437000e+00, Guide1_pos=3.307000e+00, Guide2_pos=3.710500e+00, Guide3_pos=4.342000e+00, Guide4_pos=5.060500e+00, vcoil_12_pos=3.157000e+00, vcoil_34_pos=4.192000e+00, vcoil_56_pos=5.267000e+00, triacoil_1_pos=3.517000e+00, triacoil_2_pos=4.867000e+00, grating_pos=6.757000e+00, detector_pos=6.957000e+00, tlow=2.190523040779461e+03, thigh=1.214744595341338e+04)
DEFINE INSTRUMENT SEMSANS_inst(triacoil_depth=1.935000e-01, triacoil_width=7.042824e-02, triacoil_height=3.000000e-01, pol_zdepth=9.300000e-01, vcoil_zdepth=1.500000e-01, Guide1_depth=1.650000e-02, Guide2_depth=3.315000e-01, Guide3_depth=3.315000e-01, Guide4_depth=5.650000e-02, Bguide=-5.000000e-04, Bextra=-2.120000e-02, Bt2=-4.440000e-03, Bt1=-2.560000e-03, DLambda=4.166366e+00, Lambda=4.559500e+00, flippos=3.100000e-02, FLIP=1.000000e+00, chop1_pos=5.000000e-01, chop2_pos=9.740000e-01, pol_pos=1.907000e+00, analyser_pos=6.072000e+00, grating_w=1.570000e-03, grating_a=2.930000e-03, slit_1_pos=2.957000e+00, slit_2_pos=5.437000e+00, Guide1_pos=3.307000e+00, Guide2_pos=3.710500e+00, Guide3_pos=4.342000e+00, Guide4_pos=5.060500e+00, vcoil_12_pos=3.157000e+00, vcoil_34_pos=4.192000e+00, vcoil_56_pos=5.267000e+00, triacoil_1_pos=3.517000e+00, triacoil_2_pos=4.867000e+00, grating_pos=6.757000e+00, detector_pos=6.957000e+00, tlow=2.190523040779461e+03, thigh=1.214744595341338e+04, int debug=0)

/* The DECLARE section allows us to declare variables or small */
/* functions in C syntax. These may be used in the whole instrument. */
Expand Down Expand Up @@ -88,6 +90,13 @@ COMPONENT source = Source_simple(
lambda0 = Lambda,dlambda = DLambda)
AT (0, 0, 0) RELATIVE Origin

// Monitors at source
COMPONENT sourcePSD = PSD_monitor(xwidth=0.01,yheight=0.01, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE Origin

COMPONENT sourceWL = L_monitor(xwidth=0.01,yheight=0.01, Lmin=Lambda-DLambda/2.0, Lmax=Lambda+DLambda/2.0, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE Origin

// First chopper
COMPONENT chop1 = DiskChopper(radius=0.21, theta_0=20, nu=25, nslit=2, phase=-10, isfirst=1, yheight=0.21)
AT (0, 0, chop1_pos) RELATIVE Origin
Expand All @@ -96,6 +105,11 @@ AT (0, 0, chop1_pos) RELATIVE Origin
COMPONENT chop2 = DiskChopper(radius=0.21, theta_0=20, nu=25, nslit=2, phase=20-10, isfirst=0, yheight=0.21)
AT (0, 0, chop2_pos) RELATIVE Origin

// Lmon post chopper
COMPONENT chopWL = L_monitor(xwidth=0.01,yheight=0.01, Lmin=Lambda-DLambda/2.0, Lmax=Lambda+DLambda/2.0, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE chop2


// Polariser
COMPONENT polarizer = Set_pol(py=1)
AT (0, 0, pol_pos+0.5*pol_zdepth) RELATIVE Origin
Expand All @@ -105,25 +119,32 @@ COMPONENT slit_1 = Slit(
xwidth=15e-3,yheight=15e-3)
AT (0,0,slit_1_pos) RELATIVE Origin

// PSD post first slit
COMPONENT slitPSD = PSD_monitor(xwidth=0.02,yheight=0.02, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE slit_1

//First v-coil of first v-coil pair
COMPONENT vcoil1=Pol_pi_2_rotator(
xwidth=0.15,yheight=0.15,zdepth=vcoil_zdepth,rx=0,ry=0,rz=FLIP*1)
xwidth=0.15,yheight=0.15,zdepth=vcoil_zdepth,rx=0,ry=0,rz=FLIP*1.0)
AT (0,0,vcoil_12_pos-vcoil_zdepth) RELATIVE Origin

//Second v-coil of first v-coil pair
COMPONENT vcoil2=Pol_pi_2_rotator(
xwidth=0.15,yheight=0.15,zdepth=vcoil_zdepth,rx=0,ry=1,rz=0)
AT (0,0,vcoil_12_pos) RELATIVE Origin

// PSD post 1st v-coil pair
COMPONENT vcoilPSD = PSD_monitor(xwidth=0.2,yheight=0.2, nowritefile=(!debug))
WHEN (debug) AT (0,0,vcoil_zdepth) RELATIVE vcoil2

// START GUIDEFIELD 1
COMPONENT Guide_field1 = Pol_Bfield(field_type=1, xwidth=0.4, yheight=0.4, Bx=0, By=Bguide+Bextra, Bz=0)
AT (0,0,Guide1_pos) RELATIVE Origin
AT (0,0,Guide1_pos) RELATIVE Origin


// STOP GUIDE FIELD 1
COMPONENT Guide_field1_cp = Pol_Bfield_stop()
AT (0,0,Guide1_pos+Guide1_depth) RELATIVE Origin
AT (0,0,Guide1_pos+Guide1_depth) RELATIVE Origin


// TRIA COIL 1
Expand All @@ -132,10 +153,13 @@ COMPONENT triacoil_1=Pol_triafield(
B=Bt1, Bguide=Bguide)
AT (0,0,triacoil_1_pos-triacoil_depth) RELATIVE Origin

// PSD post triangular coil 1
COMPONENT triaPSD = PSD_monitor(xwidth=0.4,yheight=0.4, nowritefile=(!debug))
WHEN (debug) AT (0,0,Guide2_pos) RELATIVE Origin

// START GUIDEFIELD 2
COMPONENT Guide_field2 = Pol_Bfield(field_type=1, xwidth=0.4, yheight=0.4, Bx=0, By=Bguide, Bz=0)
AT (0,0,Guide2_pos) RELATIVE Origin
AT (0,0,Guide2_pos) RELATIVE Origin


// STOP GUIDE FIELD 2
Expand All @@ -156,24 +180,24 @@ AT (0,0,vcoil_34_pos+flippos) RELATIVE Origin

// START GUIDEFIELD 3
COMPONENT Guide_field3 = Pol_Bfield(field_type=1, xwidth=0.4, yheight=0.4, Bx=0, By=Bguide, Bz=0)
AT (0,0,Guide3_pos+flippos) RELATIVE Origin
AT (0,0,Guide3_pos+flippos) RELATIVE Origin


// STOP GUIDE FIELD 3
COMPONENT Guide_field3_cp = Pol_Bfield_stop()
AT (0,0,Guide3_pos+Guide3_depth) RELATIVE Origin
AT (0,0,Guide3_pos+Guide3_depth) RELATIVE Origin


// START TRIA COIL 2
COMPONENT triacoil_2=Pol_triafield(
xwidth=triacoil_width,yheight=triacoil_height,zdepth=2*triacoil_depth,
B=Bt2, Bguide=Bguide)
AT (0,0,triacoil_2_pos-triacoil_depth) RELATIVE Origin
AT (0,0,triacoil_2_pos-triacoil_depth) RELATIVE Origin


// START GUIDEFIELD 4
COMPONENT Guide_field4 = Pol_Bfield(field_type=1, xwidth=0.4, yheight=0.4, Bx=0, By=Bguide, Bz=0)
AT (0,0,Guide4_pos) RELATIVE Origin
AT (0,0,Guide4_pos) RELATIVE Origin


// STOP GUIDE FIELD 4
Expand All @@ -195,10 +219,17 @@ COMPONENT slit_2=Slit(
xwidth=15e-3,yheight=15e-3)
AT(0,0,slit_2_pos) RELATIVE Origin

// PSD post second slit
COMPONENT slit2PSD = PSD_monitor(xwidth=0.4,yheight=0.4, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE slit_2

//Analyser
COMPONENT analyser=PolAnalyser_ideal(mx=0,my=1,mz=0)
AT(0,0,analyser_pos) RELATIVE Origin
AT(0,0,analyser_pos) RELATIVE Origin

// PSD post analyser
COMPONENT anaPSD = PSD_monitor(xwidth=0.4,yheight=0.4, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE analyser

//THIS IS GRATING
COMPONENT GratingSlit1_1 = Slit(xwidth=grating_w,yheight=5e-3)
Expand Down Expand Up @@ -241,6 +272,9 @@ COMPONENT TOF_det = TOF_monitor(xwidth = 0.05, yheight = 0.05,
nt=251, tmin=tlow, tmax=thigh, filename="TOF_det")
AT (0, 0, detector_pos) RELATIVE Origin

// Final PSD
COMPONENT finalPSD = PSD_monitor(xwidth=0.05,yheight=0.05, nowritefile=(!debug))
WHEN (debug) AT (0,0,0) RELATIVE TOF_det

/* This section is executed when the simulation ends (C code). Other */
/* optional sections are : SAVE */
Expand Down
Loading