Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 67 additions & 3 deletions compact/far_backward/magnets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@
<constant name="Q2PR_Coil_Center_posY" value="0*cm"/>
<constant name="Q2PR_Coil_Center_posZ" value="-1274.73*cm"/>

<!-- B2AeR Parameters-->
<constant name="B2AeR_OuterWidth" value="412.55*mm"/>
<constant name="B2AeR_OuterHeight" value="298.48*mm"/>
<constant name="B2AeR_InnerWidth" value="332.55*mm"/>
<constant name="B2AeR_InnerHeight" value="218.48*mm"/>
<constant name="B2AeR_Length" value="3800.0*mm"/>
<constant name="B2AeR_PoleGap" value="120*mm"/>
<constant name="B2AeR_YokeOuterWidth" value="221.15*mm"/>
<constant name="B2AeR_YokeInnerWidth" value="191.45*mm"/>

<!-- B2BeR Parameters-->
<constant name="B2BeR_OuterWidth" value="825.21*mm"/>
<constant name="B2BeR_OuterHeight" value="966.83*mm"/>
<constant name="B2BeR_InnerWidth" value="585.21*mm"/>
<constant name="B2BeR_InnerHeight" value="676.83*mm"/>
<constant name="B2BeR_Length" value="1500.0*mm"/>
<constant name="B2BeR_PoleGap" value="120*mm"/>
<constant name="B2BeR_YokeOuterWidth" value="305.21*mm"/>
<constant name="B2BeR_YokeInnerWidth" value="245.56*mm"/>

<constant name="B2BeR_Coil_Width" value="18.0*mm"/>
<constant name="B2BeR_Coil_Height" value="250.0*mm"/>
<constant name="B2BeR_Coil_Xpos1" value="168.605*mm"/>
<constant name="B2BeR_Coil_Xpos2" value="190.605*mm"/>
<constant name="B2BeR_Coil_Ypos" value="206.415*mm"/>

</define>

<comment> Electron side magnets </comment>
Expand Down Expand Up @@ -120,9 +146,49 @@
rout1="B2BeR_InnerRadius" rout2="B2BeR_InnerRadius">
</pipe>
</detector>

<comment> Electron side beam magnet volumes </comment>

<detector
name="Magnets_B2AeR"
type="BeamlineDipoleMagnet"
vis="BeamPipeVis"
pole_gap="B2AeR_PoleGap"
yoke_outer_width="B2AeR_YokeOuterWidth"
yoke_inner_width="B2AeR_YokeInnerWidth">
<dimensions_mainbody_outer x="B2AeR_OuterWidth" y="B2AeR_OuterHeight" z="B2AeR_Length" />
<dimensions_mainbody_inner x="B2AeR_InnerWidth" y="B2AeR_InnerHeight" z="B2AeR_Length" />
<dimensions_leg_outer x="10*cm" y="10*cm" z="10*cm" />
<dimensions_leg_inner x="10*cm" y="10*cm" z="10*cm" />
<position x="-2*m" y="0" z="0" />
<rotation x="0*rad" y="0*rad" z="0*rad" />
</detector>

<detector
name="Magnets_B2BeR"
type="BeamlineDipoleMagnet"
vis="BeamPipeVis"
pole_gap="B2BeR_PoleGap"
yoke_outer_width="B2BeR_YokeOuterWidth"
yoke_inner_width="B2BeR_YokeInnerWidth">
<dimensions_mainbody_outer x="B2BeR_OuterWidth" y="B2BeR_OuterHeight" z="B2BeR_Length" />
<dimensions_mainbody_inner x="B2BeR_InnerWidth" y="B2BeR_InnerHeight" z="B2BeR_Length" />
<dimensions_leg_outer x="10*cm" y="10*cm" z="10*cm" />
<dimensions_leg_inner x="10*cm" y="10*cm" z="10*cm" />
<position x="2*m" y="0" z="0" />
<rotation x="0*rad" y="0*rad" z="0*rad" />
<coil width="B2BeR_Coil_Width" height="B2BeR_Coil_Height" length="B2BeR_Length">
<position x="B2BeR_Coil_Xpos1" y="B2BeR_Coil_Ypos" z="0*cm"/>
<position x="B2BeR_Coil_Xpos2" y="B2BeR_Coil_Ypos" z="0*cm"/>
<position x="B2BeR_Coil_Xpos1" y="-B2BeR_Coil_Ypos" z="0*cm"/>
<position x="B2BeR_Coil_Xpos2" y="-B2BeR_Coil_Ypos" z="0*cm"/>
<position x="-B2BeR_Coil_Xpos1" y="B2BeR_Coil_Ypos" z="0*cm"/>
<position x="-B2BeR_Coil_Xpos2" y="B2BeR_Coil_Ypos" z="0*cm"/>
<position x="-B2BeR_Coil_Xpos1" y="-B2BeR_Coil_Ypos" z="0*cm"/>
<position x="-B2BeR_Coil_Xpos2" y="-B2BeR_Coil_Ypos" z="0*cm"/>
</coil>
</detector>


<detector
name="Magnets_Q3eR"
type="CylindricalMagnetChain"
Expand All @@ -135,7 +201,6 @@


<comment> Hadron side magnets </comment>

<!-- Q1ApR magnet -->
<detector name="Q1APR_BeamlineMagnet" type="ip6_CryostatMagnet">
<yoke name="Q1APR_Yoke" vis="MagnetVis">
Expand Down Expand Up @@ -507,7 +572,6 @@
</cut>
</cryoend>
</detector>

</detectors>

<fields>
Expand Down
132 changes: 132 additions & 0 deletions src/BeamlineDipoleMagnet_geo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2023-2025 Justin Chan, Simon Gardner

#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
#include "TMath.h"
#include <XML/Helper.h>

using namespace std;
using namespace dd4hep;

static Ref_t create_detector(Detector& det, xml_h e, SensitiveDetector /* sens */) {

using namespace ROOT::Math;
xml_det_t x_det = e;
string det_name = x_det.nameStr();
DetElement sdet(det_name, x_det.id());
Assembly assembly(det_name + "_assembly");
Material m_Iron = det.material("Iron");
const string vis1 = getAttrOrDefault<string>(x_det, _Unicode(vis), "AnlGreen");

// Creates the outer box for the main body
xml::Component outer_box_dim = x_det.child(_Unicode(dimensions_mainbody_outer));
double outer_height = outer_box_dim.attr<double>(_Unicode(y));
double outer_width = outer_box_dim.attr<double>(_Unicode(x));
double outer_depth = outer_box_dim.attr<double>(_Unicode(z));

Box box_outer(outer_width / 2., outer_height / 2., outer_depth / 2.);

// Creates the innner box for the main body
xml::Component inner_box_dim = x_det.child(_Unicode(dimensions_mainbody_inner));
double inner_height = inner_box_dim.attr<double>(_Unicode(y));
double inner_width = inner_box_dim.attr<double>(_Unicode(x));

// Yoke/coil parameters
double pole_gap = getAttrOrDefault<double>(x_det, _Unicode(pole_gap), inner_height / 2.0);
double yoke_height = inner_height / 2.0 - pole_gap / 2;
double yoke_outer_dim = getAttrOrDefault<double>(x_det, _Unicode(yoke_outer_width), inner_width);
double yoke_inner_dim = getAttrOrDefault<double>(x_det, _Unicode(yoke_inner_width), inner_width);

// Sets box position
xml::Component box_pos = x_det.child(_Unicode(position));
double x = box_pos.attr<double>(_Unicode(x));
double y = box_pos.attr<double>(_Unicode(y));
double z = box_pos.attr<double>(_Unicode(z));

// Calculate wall thickness
double thickness_x = (outer_width - inner_width) / 2.0;
double thickness_y = (outer_height - inner_height) / 2.0;

// Create 4 separate box volumes for the sides of the rectangular tube
// Top wall (full width, thickness in y, full depth)
Box box_top(outer_width / 2.0, thickness_y / 2.0, outer_depth / 2.0);
Volume vol_top(det_name + "_vol_top", box_top, m_Iron);
vol_top.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);

// Bottom wall (full width, thickness in y, full depth)
Volume vol_bottom(det_name + "_vol_bottom", box_top, m_Iron);
vol_bottom.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);

// Left wall (thickness in x, inner height, full depth)
Box box_side(thickness_x / 2.0, inner_height / 2.0, outer_depth / 2.0);
Volume vol_left(det_name + "_vol_left", box_side, m_Iron);
vol_left.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);

// Right wall (thickness in x, inner height, full depth)
Volume vol_right(det_name + "_vol_right", box_side, m_Iron);
vol_right.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);

// Upper coils/yoke - This is not entirely accurate as CAD has curved edges
Trd1 yoke_trap(yoke_outer_dim / 2.0, yoke_inner_dim / 2.0, outer_depth / 2.0, yoke_height / 2.0);
Volume vol_yoke(det_name + "_vol_yoke", yoke_trap, m_Iron);
vol_yoke.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);

// Create assembly for the magnet
Assembly magnet_assembly(det_name + "_magnet_assembly");

// Place the 4 walls
// Top wall at +y
magnet_assembly.placeVolume(vol_top, Position(0, outer_height / 2.0 - thickness_y / 2.0, 0));

// Bottom wall at -y
magnet_assembly.placeVolume(vol_bottom, Position(0, -outer_height / 2.0 + thickness_y / 2.0, 0));

// Left wall at -x
magnet_assembly.placeVolume(vol_left, Position(-outer_width / 2.0 + thickness_x / 2.0, 0, 0));

// Right wall at +x
magnet_assembly.placeVolume(vol_right, Position(outer_width / 2.0 - thickness_x / 2.0, 0, 0));

//Translation for top and bottom yoke

// Place the top yoke with position and rotation around X axis
magnet_assembly.placeVolume(vol_yoke,
Transform3D(RotationX(TMath::Pi() / 2),
Position(0, inner_height / 2.0 - yoke_height / 2.0, 0)));

// Place the bottom yoke
magnet_assembly.placeVolume(vol_yoke,
Transform3D(RotationX(-TMath::Pi() / 2),
Position(0, -inner_height / 2.0 + yoke_height / 2.0, 0)));

// Coil parameters
for (xml_coll_t coil_coll(x_det, _Unicode(coil)); coil_coll; ++coil_coll) {
double coil_width = coil_coll.attr<double>(_Unicode(width));
double coil_height = coil_coll.attr<double>(_Unicode(height));
double coil_length = coil_coll.attr<double>(_Unicode(length));
// Create box for coil
Box coil_box(coil_width / 2., coil_height / 2., coil_length / 2.);
Volume vol_coil(det_name + "_vol_coil", coil_box, m_Iron);
vol_coil.setAttributes(det, x_det.regionStr(), x_det.limitsStr(), vis1);
for (xml_coll_t pos(coil_coll, _Unicode(position)); pos; ++pos) {
double posX = pos.attr<double>(_Unicode(x));
double posY = pos.attr<double>(_Unicode(y));
double posZ = pos.attr<double>(_Unicode(z));
// Place coil at specified position
magnet_assembly.placeVolume(vol_coil, Position(posX, posY, posZ));
}
}

// Final placement
auto pv_assembly = det.pickMotherVolume(sdet).placeVolume(
magnet_assembly, Transform3D(RotationZYX(0.0, 0.0, 0.0), Position(x, y, z)));

sdet.setPlacement(pv_assembly);

// assembly->GetShape()->ComputeBBox();

return sdet;
}

DECLARE_DETELEMENT(BeamlineDipoleMagnet, create_detector)
Loading