File indexing completed on 2026-04-09 07:49:31
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <cassert>
0018 #include <csignal>
0019 #include <string>
0020 #include <vector>
0021 #include <array>
0022 #include <sstream>
0023 #include <set>
0024
0025 #include "NP.hh"
0026 #include "sstr.h"
0027 #include "sdigest.h"
0028 #include "sproplist.h"
0029 #include "sidxname.h"
0030
0031
0032
0033 struct SBnd
0034 {
0035 const NP* bnd ;
0036
0037
0038 static constexpr const int MISSING = -1 ;
0039
0040 static constexpr const char* EXAMPLE = "Pyrex/HamamatsuR12860_PMT_20inch_photocathode_mirror_logsurf/HamamatsuR12860_PMT_20inch_photocathode_mirror_logsurf/Vacuum" ;
0041
0042 const std::vector<std::string>& bnames ;
0043
0044 SBnd(const NP* bnd_);
0045
0046 std::string getItemDigest( int i, int j, int w=8 ) const ;
0047 std::string descBoundary() const ;
0048 int getNumBoundary() const ;
0049 const char* getBoundarySpec(int idx) const ;
0050 void getBoundarySpec(std::vector<std::string>& names, const int* idx , int num_idx ) const ;
0051
0052 int getBoundaryIndex(const char* spec) const ;
0053
0054 static constexpr const char* getBoundaryIndices_NOTES = R"(
0055 SBnd::getBoundaryIndices_NOTES
0056 --------------------------------
0057
0058 Failure to look up a boundary index indicates the spec string
0059 specifies a boundary that is not present within the current geometry.
0060 For example check the spec is present in the bnd_names.txt of the bnd array
0061 be used::
0062
0063 $HOME/.opticks/GEOM/$GEOM/CSGFoundry/SSim/stree/standard/bnd.npy
0064 $HOME/.opticks/GEOM/$GEOM/CSGFoundry/SSim/stree/standard/bnd_names.txt
0065
0066
0067 )" ;
0068
0069 bool hasAllBoundaryIndices( const char* bnd_sequence, char delim=',' ) const ;
0070 void getBoundaryIndices( std::vector<int>& bnd_idx, const char* bnd_sequence, char delim=',' ) const ;
0071 std::string descBoundaryIndices( const std::vector<int>& bnd_idx ) const ;
0072
0073 int getBoundaryLine(const char* spec, int j) const ;
0074 static int GetMaterialLine( const char* material, const std::vector<std::string>& specs );
0075 int getMaterialLine( const char* material ) const ;
0076
0077 static std::string DescDigest(const NP* bnd, int w=16) ;
0078
0079 std::string desc() const ;
0080
0081 void getMaterialNames( std::vector<std::string>& names ) const ;
0082 static std::string DescNames( std::vector<std::string>& names ) ;
0083
0084
0085
0086 bool findName( int& i, int& j, const char* qname ) const ;
0087 static bool FindName( int& i, int& j, const char* qname, const std::vector<std::string>& names ) ;
0088
0089 NP* getPropertyGroup(const char* qname, int k=-1) const ;
0090
0091 template<typename T>
0092 void getProperty(std::vector<T>& out, const char* qname, const char* propname ) const ;
0093
0094
0095 static void FillMaterialLine(
0096 std::vector<int>& mtline,
0097 const std::vector<int>& mtindex,
0098 const std::vector<std::string>& mtname,
0099 const std::vector<std::string>& specs
0100 );
0101
0102
0103 static void GetSpecsFromString( std::vector<std::string>& specs , const char* specs_, char delim='\n' );
0104
0105
0106
0107 NP* bd_from_optical(const NP* op ) const ;
0108 NP* mat_from_bd(const NP* bd) const ;
0109 NP* reconstruct_sur() const ;
0110
0111 };
0112
0113
0114 inline SBnd::SBnd(const NP* bnd_)
0115 :
0116 bnd(bnd_),
0117 bnames(bnd->names)
0118 {
0119 int num_bnames = bnames.size() ;
0120 if( num_bnames == 0 ) std::cerr << "SBnd::SBnd no names from bnd " << ( bnd ? bnd->sstr() : "-" ) << std::endl ;
0121
0122 }
0123
0124 inline std::string SBnd::getItemDigest( int i, int j, int w ) const
0125 {
0126 return sdigest::Item(bnd, i, j, w );
0127 }
0128 inline std::string SBnd::descBoundary() const
0129 {
0130 std::stringstream ss ;
0131 for(int i=0 ; i < int(bnames.size()) ; i++)
0132 ss << std::setw(2) << i << " " << bnames[i] << std::endl ;
0133 std::string s = ss.str();
0134 return s ;
0135 }
0136
0137
0138 inline int SBnd::getNumBoundary() const
0139 {
0140 return bnames.size();
0141 }
0142 inline const char* SBnd::getBoundarySpec(int idx) const
0143 {
0144 assert( idx < int(bnames.size()) );
0145 const std::string& s = bnames[idx];
0146 return s.c_str();
0147 }
0148 inline void SBnd::getBoundarySpec(std::vector<std::string>& names, const int* idx , int num_idx ) const
0149 {
0150 for(int i=0 ; i < num_idx ; i++)
0151 {
0152 int index = idx[i] ;
0153 const char* spec = getBoundarySpec(index);
0154 names.push_back(spec);
0155 }
0156 }
0157
0158
0159 inline int SBnd::getBoundaryIndex(const char* spec) const
0160 {
0161 int idx = MISSING ;
0162 for(int i=0 ; i < int(bnames.size()) ; i++)
0163 {
0164 if(spec && strcmp(bnames[i].c_str(), spec) == 0)
0165 {
0166 idx = i ;
0167 break ;
0168 }
0169 }
0170 return idx ;
0171 }
0172
0173
0174 inline bool SBnd::hasAllBoundaryIndices( const char* bnd_sequence, char delim ) const
0175 {
0176 std::vector<std::string> bnd ;
0177 sstr::SplitTrim(bnd_sequence,delim, bnd );
0178 int missing = 0 ;
0179
0180 for(int i=0 ; i < int(bnd.size()) ; i++)
0181 {
0182 const char* spec = bnd[i].c_str();
0183 if(strlen(spec) == 0) continue ;
0184 int bidx = getBoundaryIndex(spec);
0185 if( bidx == MISSING ) missing += 1 ;
0186 }
0187 return missing == 0 ;
0188 }
0189
0190 inline void SBnd::getBoundaryIndices( std::vector<int>& bnd_idx, const char* bnd_sequence, char delim ) const
0191 {
0192 assert( bnd_idx.size() == 0 );
0193
0194 std::vector<std::string> bnd ;
0195 sstr::SplitTrim(bnd_sequence,delim, bnd );
0196
0197 for(int i=0 ; i < int(bnd.size()) ; i++)
0198 {
0199 const char* spec = bnd[i].c_str();
0200 if(strlen(spec) == 0) continue ;
0201 int bidx = getBoundaryIndex(spec);
0202 if( bidx == MISSING ) std::cerr
0203 << " SBnd::getBoundaryIndices "
0204 << " i " << i << " invalid spec [" << spec << "]"
0205 << std::endl
0206 << getBoundaryIndices_NOTES
0207 << std::endl
0208 ;
0209 assert( bidx != MISSING );
0210 bnd_idx.push_back(bidx) ;
0211 }
0212 }
0213
0214 inline std::string SBnd::descBoundaryIndices( const std::vector<int>& bnd_idx ) const
0215 {
0216 int num_bnd_idx = bnd_idx.size() ;
0217 std::stringstream ss ;
0218 for(int i=0 ; i < num_bnd_idx ; i++)
0219 {
0220 int bidx = bnd_idx[i] ;
0221 const char* spec = getBoundarySpec(bidx);
0222 ss
0223 << " i " << std::setw(3) << i
0224 << " bidx " << std::setw(3) << bidx
0225 << " spec " << spec
0226 << std::endl
0227 ;
0228 }
0229 std::string s = ss.str();
0230 return s ;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 inline int SBnd::getBoundaryLine(const char* spec, int j) const
0243 {
0244 int num_bnames = bnames.size() ;
0245 int idx = getBoundaryIndex(spec);
0246 bool is_missing = idx == MISSING ;
0247 bool is_valid = !is_missing && idx < num_bnames ;
0248
0249 if(!is_valid)
0250 {
0251 std::cerr
0252 << " not is_valid "
0253 << " spec " << spec
0254 << " idx " << idx
0255 << " is_missing " << is_missing
0256 << " bnames.size " << bnames.size()
0257 << std::endl
0258 ;
0259 }
0260
0261 assert( is_valid );
0262 int line = 4*idx + j ;
0263 return line ;
0264 }
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 inline int SBnd::GetMaterialLine( const char* material, const std::vector<std::string>& specs )
0276 {
0277 int line = MISSING ;
0278 for(int i=0 ; i < int(specs.size()) ; i++)
0279 {
0280 std::vector<std::string> elem ;
0281 sstr::Split(specs[i].c_str(), '/', elem );
0282 const char* omat = elem[0].c_str();
0283 const char* imat = elem[3].c_str();
0284
0285 if(strcmp( material, omat ) == 0 )
0286 {
0287 line = i*4 + 0 ;
0288 break ;
0289 }
0290 if(strcmp( material, imat ) == 0 )
0291 {
0292 line = i*4 + 3 ;
0293 break ;
0294 }
0295 }
0296 return line ;
0297 }
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 inline int SBnd::getMaterialLine( const char* material ) const
0309 {
0310 return GetMaterialLine(material, bnames);
0311 }
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 inline std::string SBnd::DescDigest(const NP* bnd, int w )
0343 {
0344 int ni = bnd->shape[0] ;
0345 int nj = bnd->shape[1] ;
0346
0347 const std::vector<std::string>& names = bnd->names ;
0348 assert( int(names.size()) == ni );
0349
0350 std::stringstream ss ;
0351 ss << "SBnd::DescDigest" << std::endl ;
0352 for(int i=0 ; i < ni ; i++)
0353 {
0354 ss << std::setw(3) << i << " " ;
0355 for(int j=0 ; j < nj ; j++)
0356 {
0357 std::string dig = sdigest::Item(bnd, i, j ) ;
0358 std::string sdig = dig.substr(0, w);
0359 ss << std::setw(w) << sdig << " " ;
0360 }
0361 ss << " " << names[i] << std::endl ;
0362 }
0363 std::string s = ss.str();
0364 return s ;
0365 }
0366
0367
0368 inline std::string SBnd::desc() const
0369 {
0370 return DescDigest(bnd,8) ;
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381 inline void SBnd::getMaterialNames( std::vector<std::string>& names ) const
0382 {
0383 for(int i=0 ; i < int(bnames.size()) ; i++)
0384 {
0385 std::vector<std::string> elem ;
0386 sstr::Split(bnames[i].c_str(), '/', elem );
0387 const char* omat = elem[0].c_str();
0388 const char* imat = elem[3].c_str();
0389
0390 if(std::find(names.begin(), names.end(), omat) == names.end()) names.push_back(omat);
0391 if(std::find(names.begin(), names.end(), imat) == names.end()) names.push_back(imat);
0392 }
0393 }
0394 inline std::string SBnd::DescNames( std::vector<std::string>& names )
0395 {
0396 std::stringstream ss ;
0397 for(int i=0 ; i < int(names.size()) ; i++) ss << names[i] << std::endl ;
0398 std::string s = ss.str();
0399 return s ;
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419 inline bool SBnd::findName( int& i, int& j, const char* qname ) const
0420 {
0421 return FindName(i, j, qname, bnames ) ;
0422 }
0423
0424 inline bool SBnd::FindName( int& i, int& j, const char* qname, const std::vector<std::string>& names )
0425 {
0426 i = -1 ;
0427 j = -1 ;
0428 for(int b=0 ; b < int(names.size()) ; b++)
0429 {
0430 std::vector<std::string> elem ;
0431 sstr::Split(names[b].c_str(), '/', elem );
0432
0433 for(int s=0 ; s < 4 ; s++)
0434 {
0435 const char* name = elem[s].c_str();
0436 if(strcmp(name, qname) == 0 )
0437 {
0438 i = b ;
0439 j = s ;
0440 return true ;
0441 }
0442 }
0443 }
0444 return false ;
0445 }
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464 inline NP* SBnd::getPropertyGroup(const char* qname, int k) const
0465 {
0466 int i, j ;
0467 bool found = findName(i, j, qname);
0468 if(!found) std::raise(SIGINT) ;
0469 assert(found);
0470 return bnd->spawn_item(i,j,k);
0471 }
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487 template<typename T>
0488 inline void SBnd::getProperty(std::vector<T>& out, const char* qname, const char* propname ) const
0489 {
0490 assert( sizeof(T) == bnd->ebyte );
0491
0492 int boundary, species ;
0493 bool found_qname = findName(boundary, species, qname);
0494 assert(found_qname);
0495 if(!found_qname) std::raise(SIGINT);
0496
0497
0498
0499 const sproplist* pm = sproplist::Material();
0500 const sprop* bp = pm->findProp(propname) ;
0501 assert(bp);
0502 if(!bp) std::raise(SIGINT);
0503
0504 int group = bp->group ;
0505 int prop = bp->prop ;
0506 int wavelength = -1 ;
0507
0508 bnd->slice(out, boundary, species, group, wavelength, prop );
0509 }
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526 inline void SBnd::FillMaterialLine(
0527 std::vector<int>& mtline,
0528 const std::vector<int>& mtindex,
0529 const std::vector<std::string>& mtname,
0530 const std::vector<std::string>& specs )
0531 {
0532 assert( mtindex.size() == mtname.size() );
0533 int num_mt = mtindex.size() ;
0534 mtline.clear();
0535
0536 for(int i=0 ; i < num_mt ; i++)
0537 {
0538 const char* mt = mtname[i].c_str() ;
0539 int mt_line = GetMaterialLine(mt, specs) ;
0540 mtline.push_back(mt_line);
0541 }
0542 }
0543
0544
0545 inline void SBnd::GetSpecsFromString( std::vector<std::string>& specs , const char* specs_, char delim )
0546 {
0547 std::stringstream ss;
0548 ss.str(specs_) ;
0549 std::string s;
0550 while (std::getline(ss, s, delim)) if(!sstr::Blank(s.c_str())) specs.push_back(s) ;
0551 std::cout << " specs_ [" << specs_ << "] specs.size " << specs.size() ;
0552 }
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568 inline NP* SBnd::bd_from_optical(const NP* op ) const
0569 {
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 assert( op && op->uifc == 'i' && op->shape.size() == 3 && op->shape[1] == 4 && op->shape[2] == 4 ) ;
0581 int num_bd = op->shape[0] ;
0582
0583
0584 const int* op_v = op->cvalues<int>() ;
0585 int ni = num_bd ;
0586 int nj = 4 ;
0587
0588 NP* bd = NP::Make<int>(ni, nj) ;
0589 int* bd_v = bd->values<int>() ;
0590
0591 for(int i=0 ; i < ni ; i++)
0592 for(int j=0 ; j < nj ; j++)
0593 {
0594 int src_index = (i*nj + j)*4 ;
0595 int dst_index = i*nj + j ;
0596 bd_v[dst_index] = int(op_v[src_index]) - 1 ;
0597 }
0598 bd->set_names(bnd->names) ;
0599 return bd ;
0600 }
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628 inline NP* SBnd::mat_from_bd(const NP* bd) const
0629 {
0630
0631
0632 assert( bd && bd->uifc == 'i' && bd->shape.size() == 2 && bd->shape[1] == 4 ) ;
0633 assert( int(bd->names.size()) == bd->shape[0] );
0634 const int* bd_v = bd->cvalues<int>();
0635
0636
0637
0638
0639 const std::vector<NP::INT>& bnd_sh = bnd->shape ;
0640 assert( bnd && bnd->uifc == 'f' && bnd->ebyte == 8 );
0641 assert( int(bnd_sh.size()) == 5 ) ;
0642 assert( bnd_sh[0] == bd->shape[0] );
0643 const double* bnd_v = bnd->cvalues<double>() ;
0644
0645
0646
0647
0648 NP::INT ni = bd->shape[0] ;
0649 NP::INT nj = 4 ;
0650
0651 std::set<sidxname, sidxname_ordering> mm ;
0652 for(NP::INT i=0 ; i < ni ; i++)
0653 {
0654 int omat = bd_v[i*nj+0] ;
0655 int imat = bd_v[i*nj+3] ;
0656
0657 const char* bdn = bd->names[i].c_str() ;
0658 std::vector<std::string> elem ;
0659 sstr::Split(bdn, '/', elem );
0660 const char* omat_ = elem[0].c_str();
0661 const char* imat_ = elem[3].c_str();
0662
0663 sidxname om(omat,omat_) ;
0664 sidxname im(imat,imat_) ;
0665
0666 mm.insert(om);
0667 mm.insert(im);
0668 }
0669
0670 std::vector<sidxname> vmm(mm.begin(),mm.end()) ;
0671 int num_mt = vmm.size() ;
0672
0673
0674
0675 for(int i=0 ; i < num_mt ; i++) assert( i == vmm[i].idx ) ;
0676 for(int i=0 ; i < num_mt ; i++) std::cout << vmm[i].desc() << std::endl;
0677
0678 std::vector<std::string> names ;
0679 for(int i=0 ; i < num_mt ; i++)
0680 {
0681 names.push_back( vmm[i].name ) ;
0682 }
0683
0684 std::cout
0685 << "SBnd::mat_from_bd"
0686 << " bd->names.size " << bd->names.size()
0687 << " bnd->names.size " << bnd->names.size()
0688 << " bnd->shape[0] " << bnd->shape[0]
0689 << " bnd->sstr() " << bnd->sstr()
0690 << " ni " << ni
0691 << std::endl
0692 ;
0693
0694
0695
0696
0697 int np = bnd_sh[2]*bnd_sh[3]*bnd_sh[4] ;
0698
0699 NP* mat = NP::Make<double>(num_mt,bnd_sh[2], bnd_sh[3], bnd_sh[4] ) ;
0700 mat->set_names(names) ;
0701
0702 double* mat_v = mat->values<double>();
0703
0704
0705
0706
0707
0708 for(int i=0 ; i < ni ; i++)
0709 {
0710 int omat = bd_v[i*nj+0] ;
0711 assert( omat > -1 && omat < num_mt );
0712 for(int p=0 ; p < np ; p++) mat_v[omat*np+p] = bnd_v[(i*4+0)*np+p] ;
0713
0714 int imat = bd_v[i*nj+3] ;
0715 assert( imat > -1 && imat < num_mt );
0716 for(int p=0 ; p < np ; p++) mat_v[imat*np+p] = bnd_v[(i*4+3)*np+p] ;
0717 }
0718
0719 return mat ;
0720 }
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731 inline NP* SBnd::reconstruct_sur() const
0732 {
0733 return nullptr ;
0734 }
0735