File indexing completed on 2025-09-17 09:07:48
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <algorithm>
0010 #include <type_traits>
0011 #include <vector>
0012
0013 #include "corecel/Assert.hh"
0014 #include "corecel/cont/VariantUtils.hh"
0015 #include "corecel/math/Algorithms.hh"
0016 #include "orange/OrangeTypes.hh"
0017
0018 #include "../CsgTree.hh"
0019 #include "../CsgTypes.hh"
0020
0021 namespace celeritas
0022 {
0023 namespace orangeinp
0024 {
0025 namespace detail
0026 {
0027
0028
0029
0030
0031 struct BuildLogicResult
0032 {
0033 using VecLogic = std::vector<logic_int>;
0034 using VecSurface = std::vector<LocalSurfaceId>;
0035
0036 VecSurface faces;
0037 VecLogic logic;
0038 };
0039
0040
0041
0042
0043
0044 inline BuildLogicResult::VecSurface remap_faces(BuildLogicResult::VecLogic& lgc)
0045 {
0046
0047 BuildLogicResult::VecSurface faces;
0048 for (auto const& v : lgc)
0049 {
0050 if (!logic::is_operator_token(v))
0051 {
0052 faces.push_back(LocalSurfaceId{v});
0053 }
0054 }
0055
0056
0057 std::sort(faces.begin(), faces.end());
0058 faces.erase(std::unique(faces.begin(), faces.end()), faces.end());
0059
0060
0061 for (auto& v : lgc)
0062 {
0063 if (!logic::is_operator_token(v))
0064 {
0065 auto iter
0066 = find_sorted(faces.begin(), faces.end(), LocalSurfaceId{v});
0067 CELER_ASSUME(iter != faces.end());
0068 v = iter - faces.begin();
0069 }
0070 }
0071 return faces;
0072 }
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 template<class BuildLogicPolicy>
0091 inline BuildLogicResult build_logic(BuildLogicPolicy&& policy, NodeId n)
0092 {
0093 static_assert(std::is_invocable_v<BuildLogicPolicy, NodeId>);
0094 static_assert(std::is_rvalue_reference_v<BuildLogicPolicy&&>,
0095 "Will move from policy: rvalue ref expected");
0096 CELER_EXPECT(policy.empty());
0097
0098
0099 policy(n);
0100 auto lgc = std::forward<BuildLogicPolicy>(policy).logic();
0101 return {remap_faces(lgc), std::move(lgc)};
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111 template<class BuilderPolicy>
0112 class BaseBuildLogicPolicy
0113 {
0114 public:
0115
0116
0117 using VecLogic = std::vector<logic_int>;
0118 using VecSurface = std::vector<LocalSurfaceId>;
0119
0120
0121 static_assert(std::is_same_v<LocalSurfaceId::size_type, logic_int>,
0122 "unsupported: add enum logic conversion for different-sized "
0123 "face and surface ints");
0124
0125 public:
0126
0127 explicit inline BaseBuildLogicPolicy(CsgTree const& tree);
0128
0129 inline BaseBuildLogicPolicy(CsgTree const& tree, VecSurface const& vs);
0130
0131
0132 inline void operator()(NodeId const& n);
0133
0134
0135
0136
0137 inline void operator()(True const&);
0138
0139 inline void operator()(False const&);
0140
0141 inline void operator()(Surface const&);
0142
0143 inline void operator()(Aliased const&);
0144
0145
0146
0147 bool empty() const { return logic_.empty(); }
0148
0149
0150 VecLogic&& logic() && { return std::move(logic_); }
0151
0152 protected:
0153
0154 VecLogic& logic() & { return logic_; }
0155
0156 private:
0157 ContainerVisitor<CsgTree const&, NodeId> visit_node_;
0158 VecSurface const* mapping_{nullptr};
0159 VecLogic logic_;
0160 };
0161
0162
0163
0164
0165
0166 template<class BuilderPolicy>
0167 BaseBuildLogicPolicy<BuilderPolicy>::BaseBuildLogicPolicy(CsgTree const& tree)
0168 : visit_node_{tree}
0169 {
0170 static_assert(std::is_base_of_v<BaseBuildLogicPolicy, BuilderPolicy>,
0171 "CRTP: template parameter must be derived class");
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 template<class BuilderPolicy>
0183 BaseBuildLogicPolicy<BuilderPolicy>::BaseBuildLogicPolicy(CsgTree const& tree,
0184 VecSurface const& vs)
0185 : visit_node_{tree}, mapping_{&vs}
0186 {
0187 static_assert(std::is_base_of_v<BaseBuildLogicPolicy, BuilderPolicy>,
0188 "CRTP: template parameter must be derived class");
0189 }
0190
0191
0192
0193
0194
0195 template<class BuilderPolicy>
0196 void BaseBuildLogicPolicy<BuilderPolicy>::operator()(NodeId const& n)
0197 {
0198 visit_node_(static_cast<BuilderPolicy&>(*this), n);
0199 }
0200
0201
0202
0203
0204
0205 template<class BuilderPolicy>
0206 void BaseBuildLogicPolicy<BuilderPolicy>::operator()(True const&)
0207 {
0208 logic_.push_back(logic::ltrue);
0209 }
0210
0211
0212
0213
0214
0215
0216
0217 template<class BuilderPolicy>
0218 void BaseBuildLogicPolicy<BuilderPolicy>::operator()(False const&)
0219 {
0220 CELER_ASSERT_UNREACHABLE();
0221 }
0222
0223
0224
0225
0226
0227 template<class BuilderPolicy>
0228 void BaseBuildLogicPolicy<BuilderPolicy>::operator()(Surface const& s)
0229 {
0230 CELER_EXPECT(s.id < logic::lbegin);
0231
0232 logic_int sidx = [this, sid = s.id] {
0233 if (!mapping_)
0234 {
0235 return sid.unchecked_get();
0236 }
0237 else
0238 {
0239
0240 auto iter = find_sorted(mapping_->begin(), mapping_->end(), sid);
0241 CELER_ASSERT(iter != mapping_->end());
0242 return logic_int(iter - mapping_->begin());
0243 }
0244 }();
0245
0246 logic_.push_back(sidx);
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256 template<class BuilderPolicy>
0257 void BaseBuildLogicPolicy<BuilderPolicy>::operator()(Aliased const& n)
0258 {
0259 (*this)(n.node);
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 class PostfixBuildLogicPolicy
0276 : public BaseBuildLogicPolicy<PostfixBuildLogicPolicy>
0277 {
0278 public:
0279
0280
0281 using BaseBuildLogicPolicy::VecLogic;
0282 using BaseBuildLogicPolicy::VecSurface;
0283
0284
0285 public:
0286 using BaseBuildLogicPolicy::BaseBuildLogicPolicy;
0287
0288
0289
0290 using BaseBuildLogicPolicy::operator();
0291
0292
0293 void operator()(Negated const& n)
0294 {
0295 (*this)(n.node);
0296 logic().push_back(logic::lnot);
0297 }
0298
0299
0300 void operator()(Joined const& n)
0301 {
0302 CELER_EXPECT(n.nodes.size() > 1);
0303
0304
0305 auto iter = n.nodes.begin();
0306 (*this)(*iter++);
0307
0308 while (iter != n.nodes.end())
0309 {
0310 (*this)(*iter++);
0311 logic().push_back(n.op);
0312 }
0313 }
0314
0315 };
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330 class InfixBuildLogicPolicy : public BaseBuildLogicPolicy<InfixBuildLogicPolicy>
0331 {
0332 public:
0333
0334
0335 using BaseBuildLogicPolicy::VecLogic;
0336 using BaseBuildLogicPolicy::VecSurface;
0337
0338
0339 public:
0340 using BaseBuildLogicPolicy::BaseBuildLogicPolicy;
0341
0342
0343
0344 using BaseBuildLogicPolicy::operator();
0345
0346
0347 void operator()(Negated const& n)
0348 {
0349 this->logic().push_back(logic::lnot);
0350 (*this)(n.node);
0351 }
0352
0353
0354 void operator()(Joined const& n)
0355 {
0356 CELER_EXPECT(n.nodes.size() > 1);
0357 auto& logic = this->logic();
0358 logic.push_back(logic::lopen);
0359
0360 auto iter = n.nodes.begin();
0361 (*this)(*iter++);
0362
0363 while (iter != n.nodes.end())
0364 {
0365 logic.push_back(n.op);
0366 (*this)(*iter++);
0367 }
0368 logic.push_back(logic::lclose);
0369 }
0370
0371 };
0372
0373
0374 }
0375 }
0376 }