File indexing completed on 2026-04-09 07:49:47
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 #include <limits>
0081 #include <array>
0082 #include <csignal>
0083
0084 #include "NPFold.h"
0085 #include "NPX.h"
0086 #include "sproplist.h"
0087 #include "sdomain.h"
0088 #include "smatsur.h"
0089 #include "snam.h"
0090
0091 struct sstandard
0092 {
0093 static constexpr const bool VERBOSE = false ;
0094 static constexpr const char* IMPLICIT_PREFIX = "Implicit_RINDEX_NoRINDEX" ;
0095 const sdomain* dom ;
0096
0097 const NP* wavelength ;
0098 const NP* energy ;
0099 const NP* rayleigh ;
0100 const NP* mat ;
0101 const NP* sur ;
0102 const NP* bd ;
0103 const NP* bnd ;
0104 const NP* optical ;
0105
0106 const NP* icdf ;
0107
0108
0109 sstandard();
0110
0111 void deferred_init(
0112 const std::vector<int4>& vbd,
0113 const std::vector<std::string>& bdname,
0114 const std::vector<std::string>& suname,
0115 const NPFold* surface
0116 );
0117
0118 NPFold* serialize() const ;
0119 void import(const NPFold* fold );
0120
0121 void save(const char* base, const char* rel );
0122 void load(const char* base, const char* rel );
0123
0124
0125 static NP* make_bd(
0126 const std::vector<int4>& vbd,
0127 const std::vector<std::string>& bdname
0128 );
0129
0130 static NP* make_optical(
0131 const std::vector<int4>& vbd,
0132 const std::vector<std::string>& suname,
0133 const NPFold* surface
0134 );
0135
0136 static NP* make_bnd(
0137 const std::vector<int4>& vbd,
0138 const std::vector<std::string>& bdname,
0139 const NP* mat,
0140 const NP* sur
0141 );
0142
0143 static void column_range(int4& mn, int4& mx, const std::vector<int4>& vbd) ;
0144 static NP* unused_mat(const std::vector<std::string>& names, const NPFold* fold );
0145 static NP* unused_sur(const std::vector<std::string>& names, const NPFold* fold );
0146 static NP* unused_create(const sproplist* pl, const std::vector<std::string>& names, const NPFold* fold );
0147 };
0148
0149
0150 inline sstandard::sstandard()
0151 :
0152 dom(nullptr),
0153 wavelength(nullptr),
0154 energy(nullptr),
0155 rayleigh(nullptr),
0156 mat(nullptr),
0157 sur(nullptr),
0158 bd(nullptr),
0159 bnd(nullptr),
0160 optical(nullptr),
0161 icdf(nullptr)
0162 {
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 inline void sstandard::deferred_init(
0180 const std::vector<int4>& vbd,
0181 const std::vector<std::string>& bdname,
0182 const std::vector<std::string>& suname,
0183 const NPFold* surface
0184 )
0185 {
0186 dom = new sdomain ;
0187
0188 wavelength = dom->get_wavelength_nm() ;
0189 energy = dom->get_energy_eV() ;
0190
0191 bd = make_bd( vbd, bdname );
0192 bnd = make_bnd( vbd, bdname, mat, sur ) ;
0193 optical = make_optical(vbd, suname, surface) ;
0194 }
0195
0196
0197 inline NPFold* sstandard::serialize() const
0198 {
0199 NPFold* fold = new NPFold ;
0200
0201 fold->add(snam::WAVELENGTH , wavelength );
0202 fold->add(snam::ENERGY, energy );
0203
0204 fold->add(snam::RAYLEIGH, rayleigh );
0205 fold->add(snam::MAT , mat );
0206 fold->add(snam::SUR , sur );
0207
0208 fold->add(snam::BD, bd );
0209 fold->add(snam::BND, bnd );
0210 fold->add(snam::OPTICAL, optical );
0211
0212 fold->add(snam::ICDF, icdf) ;
0213
0214 return fold ;
0215 }
0216
0217 inline void sstandard::import(const NPFold* fold )
0218 {
0219 wavelength = fold->get(snam::WAVELENGTH);
0220 energy = fold->get(snam::ENERGY);
0221
0222 rayleigh = fold->get(snam::RAYLEIGH);
0223 mat = fold->get(snam::MAT);
0224 sur = fold->get(snam::SUR);
0225
0226 bd = fold->get(snam::BD);
0227 bnd = fold->get(snam::BND);
0228 optical = fold->get(snam::OPTICAL);
0229
0230 icdf = fold->get(snam::ICDF);
0231 }
0232
0233 inline void sstandard::save(const char* base, const char* rel )
0234 {
0235 NPFold* fold = serialize();
0236 fold->save(base, rel);
0237 }
0238
0239 inline void sstandard::load(const char* base, const char* rel )
0240 {
0241 NPFold* fold = NPFold::Load(base, rel) ;
0242 import(fold) ;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 inline NP* sstandard::make_bd( const std::vector<int4>& vbd, const std::vector<std::string>& bdname )
0255 {
0256 NP* a_bd = NPX::ArrayFromVec<int, int4>( vbd );
0257 a_bd->set_names( bdname );
0258 return a_bd ;
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 inline NP* sstandard::make_optical(
0312 const std::vector<int4>& vbd,
0313 const std::vector<std::string>& suname,
0314 const NPFold* surface )
0315 {
0316 int ni = vbd.size() ;
0317 int nj = 4 ;
0318 int nk = 4 ;
0319
0320 NP* op = NP::Make<int>(ni, nj, nk);
0321 int* op_v = op->values<int>();
0322
0323 for(int i=0 ; i < ni ; i++)
0324 {
0325 const int4& bd_ = vbd[i] ;
0326 for(int j=0 ; j < nj ; j++)
0327 {
0328 int op_index = i*nj*nk + j*nk ;
0329
0330 int idx = -2 ;
0331 switch(j)
0332 {
0333 case 0: idx = bd_.x ; break ;
0334 case 1: idx = bd_.y ; break ;
0335 case 2: idx = bd_.z ; break ;
0336 case 3: idx = bd_.w ; break ;
0337 }
0338 int idx1 = idx+1 ;
0339 bool is_mat = j == 0 || j == 3 ;
0340 bool is_sur = j == 1 || j == 2 ;
0341
0342 if(is_mat)
0343 {
0344 assert( idx > -1 );
0345 op_v[op_index+0] = idx1 ;
0346 op_v[op_index+1] = 0 ;
0347 op_v[op_index+2] = 0 ;
0348 op_v[op_index+3] = 0 ;
0349 }
0350 else if(is_sur)
0351 {
0352 const char* surfname = snam::get(suname, idx) ;
0353
0354 bool no_surfname_for_surface_idx = idx > -1 && surfname == nullptr ;
0355
0356 if(no_surfname_for_surface_idx) std::cerr
0357 << "sstandard::make_optical"
0358 << " ERROR "
0359 << " no_surfname_for_surface_idx " << ( no_surfname_for_surface_idx ? "YES" : "NO " )
0360 << " sur idx from bd " << idx
0361 << " but no corresponding surfname "
0362 << " suname.size " << suname.size()
0363 << " surface.subfold.size " << surface->subfold.size()
0364 << " surface.ff.size " << surface->ff.size()
0365 << "\n"
0366 << " snam::Desc(suname)\n"
0367 << snam::Desc(suname)
0368 << "\n"
0369 ;
0370
0371 if(idx > -1 ) assert(surfname) ;
0372
0373
0374 NPFold* surf = surfname ? surface->get_subfold(surfname) : nullptr ;
0375 bool is_implicit = surfname && strncmp(surfname, IMPLICIT_PREFIX, strlen(IMPLICIT_PREFIX) ) == 0 ;
0376 int Type = -2 ;
0377 int Finish = -2 ;
0378 int ModelValuePercent = -2 ;
0379 std::string OSN = "-" ;
0380
0381 if( is_implicit )
0382 {
0383 assert( surf == nullptr ) ;
0384 Type = 1 ;
0385 Finish = 1 ;
0386 ModelValuePercent = 100 ;
0387 OSN = "X" ;
0388 }
0389 else
0390 {
0391 int missing = 0 ;
0392 Type = surf ? surf->get_meta<int>("Type",-1) : missing ;
0393 Finish = surf ? surf->get_meta<int>("Finish", -1 ) : missing ;
0394 ModelValuePercent = surf ? int(100.*surf->get_meta<double>("ModelValue", 0.)) : missing ;
0395 OSN = surf ? surf->get_meta<std::string>("OpticalSurfaceName", "-") : "-" ;
0396 }
0397
0398
0399 char OSN0 = *OSN.c_str() ;
0400 int ems = smatsur::TypeFromChar(OSN0) ;
0401
0402
0403
0404
0405
0406
0407
0408 int Payload_Y = ems ;
0409
0410 if(VERBOSE) std::cout
0411 << " bnd:i " << std::setw(3) << i
0412 << " sur:idx " << std::setw(3) << idx
0413 << " Type " << std::setw(2) << Type
0414 << " Finish " << std::setw(2) << Finish
0415 << " MVP " << std::setw(3) << ModelValuePercent
0416 << " surf " << ( surf ? "YES" : "NO " )
0417 << " impl " << ( is_implicit ? "YES" : "NO " )
0418 << " osn0 " << ( OSN0 == '\0' ? '0' : OSN0 )
0419 << " OSN " << OSN
0420 << " ems " << ems
0421 << " emsn " << smatsur::Name(ems)
0422 << " surfname " << ( surfname ? surfname : "-" )
0423 << std::endl
0424 ;
0425
0426 op_v[op_index+0] = idx1 ;
0427 op_v[op_index+1] = Payload_Y ;
0428 op_v[op_index+2] = Finish ;
0429 op_v[op_index+3] = ModelValuePercent ;
0430 }
0431 }
0432 }
0433 return op ;
0434 }
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 inline NP* sstandard::make_bnd(
0448 const std::vector<int4>& vbd,
0449 const std::vector<std::string>& bdname,
0450 const NP* mat,
0451 const NP* sur )
0452 {
0453 assert( mat->shape.size() == 4 );
0454 assert( sur->shape.size() == 4 );
0455
0456 int num_mat = mat->shape[0] ;
0457 int num_sur = sur->shape[0] ;
0458
0459 for(int d=1 ; d < 4 ; d++) assert( mat->shape[d] == sur->shape[d] ) ;
0460
0461 assert( mat->shape[1] == sprop::NUM_PAYLOAD_GRP );
0462 int num_domain = mat->shape[2] ;
0463 assert( mat->shape[3] == sprop::NUM_PAYLOAD_VAL );
0464
0465 const double* mat_v = mat->cvalues<double>();
0466 const double* sur_v = sur->cvalues<double>();
0467
0468 int num_bnd = vbd.size() ;
0469 int num_bdname = bdname.size() ;
0470
0471 bool num_bnd_expect = num_bnd == num_bdname ;
0472 if(!num_bnd_expect) std::raise(SIGINT) ;
0473 assert( num_bnd_expect);
0474
0475 int4 mn ;
0476 int4 mx ;
0477 column_range(mn, mx, vbd );
0478 if(VERBOSE) std::cout << " sstandard::bnd mn " << mn << " mx " << mx << std::endl ;
0479
0480 bool mat_expect = mx.x < num_mat && mx.w < num_mat ;
0481 bool sur_expect = mx.y < num_sur && mx.z < num_sur ;
0482
0483 if(!mat_expect) std::raise(SIGINT);
0484 if(!sur_expect) std::raise(SIGINT);
0485
0486 assert( mat_expect );
0487 assert( sur_expect );
0488
0489 int ni = num_bnd ;
0490 int nj = sprop::NUM_MATSUR ;
0491 int nk = sprop::NUM_PAYLOAD_GRP ;
0492 int nl = num_domain ;
0493 int nn = sprop::NUM_PAYLOAD_VAL ;
0494
0495 int np = nk*nl*nn ;
0496
0497
0498 NP* bnd_ = NP::Make<double>(ni, nj, nk, nl, nn );
0499 bnd_->fill<double>(-1.) ;
0500 bnd_->set_names( bdname );
0501
0502
0503 bnd_->set_meta<float>("domain_low", sdomain::DomainLow() );
0504 bnd_->set_meta<float>("domain_high", sdomain::DomainHigh() );
0505 bnd_->set_meta<float>("domain_step", sdomain::DomainStep() );
0506 bnd_->set_meta<float>("domain_range", sdomain::DomainRange() );
0507
0508 double* bnd_v = bnd_->values<double>() ;
0509
0510 for(int i=0 ; i < ni ; i++)
0511 {
0512 std::array<int, 4> _bd = {{ vbd[i].x, vbd[i].y, vbd[i].z, vbd[i].w }} ;
0513 for(int j=0 ; j < nj ; j++)
0514 {
0515 int ptr = _bd[j] ;
0516 if( ptr < 0 ) continue ;
0517 bool is_mat = j == 0 || j == 3 ;
0518 bool is_sur = j == 1 || j == 2 ;
0519 if(is_mat) assert( ptr < num_mat );
0520 if(is_sur) assert( ptr < num_sur );
0521
0522 int src_index = ptr*np ;
0523 int dst_index = (i*nj + j)*np ;
0524 const double* src_v = is_mat ? mat_v : sur_v ;
0525
0526 for(int p=0 ; p < np ; p++) bnd_v[dst_index + p] = src_v[src_index + p] ;
0527 }
0528 }
0529 return bnd_ ;
0530 }
0531
0532 inline void sstandard::column_range(int4& mn, int4& mx, const std::vector<int4>& vbd)
0533 {
0534 mn.x = std::numeric_limits<int>::max() ;
0535 mn.y = std::numeric_limits<int>::max() ;
0536 mn.z = std::numeric_limits<int>::max() ;
0537 mn.w = std::numeric_limits<int>::max() ;
0538
0539 mx.x = std::numeric_limits<int>::min() ;
0540 mx.y = std::numeric_limits<int>::min() ;
0541 mx.z = std::numeric_limits<int>::min() ;
0542 mx.w = std::numeric_limits<int>::min() ;
0543
0544 int num = vbd.size();
0545 for(int i=0 ; i < num ; i++)
0546 {
0547 const int4& b = vbd[i] ;
0548 if(b.x > mx.x) mx.x = b.x ;
0549 if(b.y > mx.y) mx.y = b.y ;
0550 if(b.z > mx.z) mx.z = b.z ;
0551 if(b.w > mx.w) mx.w = b.w ;
0552
0553 if(b.x < mn.x) mn.x = b.x ;
0554 if(b.y < mn.y) mn.y = b.y ;
0555 if(b.z < mn.z) mn.z = b.z ;
0556 if(b.w < mn.w) mn.w = b.w ;
0557 }
0558 }
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572 inline NP* sstandard::unused_mat( const std::vector<std::string>& names, const NPFold* fold )
0573 {
0574 assert(0);
0575 const sproplist* pl = sproplist::Material() ;
0576 return unused_create(pl, names, fold );
0577 }
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590 inline NP* sstandard::unused_sur( const std::vector<std::string>& names, const NPFold* fold )
0591 {
0592 assert(0);
0593 const sproplist* pl = sproplist::Surface() ;
0594 return unused_create(pl, names, fold );
0595 }
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606 inline NP* sstandard::unused_create(const sproplist* pl, const std::vector<std::string>& names, const NPFold* fold )
0607 {
0608 assert(0);
0609 sdomain dom ;
0610
0611 int ni = names.size() ;
0612 int nj = sprop::NUM_PAYLOAD_GRP ;
0613 int nk = dom.length ;
0614 int nl = sprop::NUM_PAYLOAD_VAL ;
0615
0616 NP* sta = NP::Make<double>(ni, nj, nk, nl) ;
0617 sta->set_names(names);
0618 double* sta_v = sta->values<double>();
0619
0620 std::cout << "sstandard::create sta.sstr " << sta->sstr() << std::endl ;
0621
0622 for(int i=0 ; i < ni ; i++ )
0623 {
0624 const char* name = names[i].c_str() ;
0625 NPFold* sub = fold->get_subfold(name) ;
0626
0627 std::cout
0628 << std::setw(4) << i
0629 << " : "
0630 << std::setw(60) << name
0631 << " : "
0632 << sub->stats()
0633 << std::endl
0634 ;
0635
0636 for(int j=0 ; j < nj ; j++)
0637 {
0638 for(int k=0 ; k < nk ; k++)
0639 {
0640
0641 double energy_eV = dom.energy_eV[k] ;
0642 double energy = energy_eV * 1.e-6 ;
0643
0644 for(int l=0 ; l < nl ; l++)
0645 {
0646 const sprop* prop = pl->get(j,l) ;
0647 assert( prop );
0648
0649 const char* pn = prop->name ;
0650 const NP* a = sub->get(pn) ;
0651 double value = a ? a->interp( energy ) : prop->def ;
0652
0653 int index = i*nj*nk*nl + j*nk*nl + k*nl + l ;
0654 sta_v[index] = value ;
0655 }
0656 }
0657 }
0658 }
0659 return sta ;
0660 }
0661
0662