From 37a9be28e346951d132bc452f5b8ffd197f9de1a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 3 Jul 2024 17:22:28 +0100 Subject: [PATCH 001/117] Fix time bug in Barnes gamma thermalisation and ray-tracing error in Wollaeger gamma thermalisation (#95) --- gammapkt.cc | 10 +- .../results_md5_final.txt | 632 +++++++++--------- .../results_md5_job0.txt | 24 +- 3 files changed, 332 insertions(+), 334 deletions(-) diff --git a/gammapkt.cc b/gammapkt.cc index 9ae7806c7..3072bb576 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -984,13 +984,10 @@ void barnes_thermalisation(Packet &pkt) // determine average initial density via kinetic energy const double E_kin = grid::get_ejecta_kinetic_energy(); const double v_ej = sqrt(E_kin * 2 / grid::mtot_input); - const double t_0 = globals::tmin; // const double t_ineff = sqrt(rho_0 * R_0 * pow(t_0, 2) * mean_gamma_opac); const double t_ineff = 1.4 * 86400. * sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * ((0.2 * 29979200000) / v_ej); - // get current time - const double t = t_0 + pkt.prop_time; - const double tau = pow(t_ineff / t, 2.); + const double tau = pow(t_ineff / pkt.prop_time, 2.); const double f_gamma = 1. - exp(-tau); assert_always(f_gamma >= 0.); assert_always(f_gamma <= 1.); @@ -1012,13 +1009,14 @@ void wollaeger_thermalisation(Packet &pkt) { // integration: requires distances within single cells in radial direction and the corresponding densities // need to create a packet copy which is moved during the integration Packet pkt_copy = pkt; + pkt.dir = vec_norm(pkt_copy.pos); const double t_current = pkt.prop_time; double tau = 0.; bool end_packet = false; while (!end_packet) { // distance to the next cell - const auto [sdist, snext] = grid::boundary_distance(vec_norm(pkt_copy.pos), pkt_copy.pos, pkt_copy.prop_time, - pkt_copy.where, &pkt_copy.last_cross); + const auto [sdist, snext] = + grid::boundary_distance(pkt_copy.dir, pkt_copy.pos, pkt_copy.prop_time, pkt_copy.where, &pkt_copy.last_cross); const double s_cont = sdist * t_current * t_current * t_current / std::pow(pkt_copy.prop_time, 3); const int mgi = grid::get_cell_modelgridindex(pkt_copy.where); if (mgi != grid::get_npts_model()) { diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index 0f9fd3ab3..b6c02ae15 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -94090a73b642cd79b4208d34570e5c23 absorption.out -fb7beca851f29fb6d65385671fffdb57 absorption_res_00.out -adaa2826953ac4096930dff9dacf0d5c absorption_res_01.out -7344690a948ddfc603dcced766c4b5b6 absorption_res_02.out -39911c110ee79aa5fa51d48971cefa17 absorption_res_03.out -bc714fe852d7e234590b25a6533e45ac absorption_res_04.out -4b7a4f11a11e57e2fb66d787fe8660bb absorption_res_05.out -106adab262f9234cac82adce9dac3918 absorption_res_06.out -ae48c6f51a67aafd9833d220f97192c5 absorption_res_07.out -97230f16fe902a5aaac5210a625661c5 absorption_res_08.out -66d668b41921cfe581c832cafe89e1db absorption_res_09.out -fbddf2cfd97af2e57aa385fa24d6201c absorption_res_10.out -0fcfda4869243258019a72f48b7867d5 absorption_res_11.out -f2d3979d49991144be2bdbefe836fb69 absorption_res_12.out -c02020563bf66e9ff380188d71a2a866 absorption_res_13.out -f42e4ba4121ea49e2edaa623d4b04b4b absorption_res_14.out -0ce7160a2da38507a7c9047b82afb91c absorption_res_15.out -a5e7ec3545fbfe942ce45004ffbdbe2d absorption_res_16.out -7eda519a04e42d82d63695a85848ede6 absorption_res_17.out -728817befeaedc60520b6904f11ad076 absorption_res_18.out -228c256ae49356fc327b2535b9f3fbff absorption_res_19.out -44e19bbb31dcef1446bc47b51da98947 absorption_res_20.out -112dac2ba4efb244fd7d241ccd4f97b0 absorption_res_21.out -ca5898dd263c4dad666015c7d281428b absorption_res_22.out -6515511bb9956e602a37ce8c70c15896 absorption_res_23.out -117cf9220638ab943df515369a4d8abc absorption_res_24.out -106a896343829f47b949dd43d4c175b6 absorption_res_25.out -0603d8c4009649962a21aa77e1136fc9 absorption_res_26.out -541374ddc59ac621e01f6a3526bfcb3f absorption_res_27.out -eb41c81645f17a6e47333971acb71c0e absorption_res_28.out -639a404bc36ba87355e37bfbb5ac2941 absorption_res_29.out -a2138feb96a829dd99473beed7f58e1d absorption_res_30.out -c1268d1421702dc119b03cfbcb807bec absorption_res_31.out -de34aac06e303e71fff926197a61ed05 absorption_res_32.out -3ede93fec5dbc4975eebd18ee9f7588e absorption_res_33.out -1c79444ab7361d99535b462059a27dbc absorption_res_34.out -143969f3fc05282a4f6b40d6a0780933 absorption_res_35.out -626fa790afc439822038ec24f8df215d absorption_res_36.out -7d30c56f39c63acf9c39c16aa23ae0fe absorption_res_37.out -1aa9a31d3d341a059273107c67f7622d absorption_res_38.out -5827e42c2f836c35630d7d79c9421320 absorption_res_39.out -01820c7ba5a95b29fd799d66cff87203 absorption_res_40.out -308bdab5337138fb4cab9e5983de16ea absorption_res_41.out -b477e21ea7e5403a947a825db27e2f5e absorption_res_42.out -c721d8eaeb6dfc36ee7a513da3446718 absorption_res_43.out -acc3ef7d155705c7f073e42d85fa3490 absorption_res_44.out -c1e0e28812ed0361bfadc6a755085d34 absorption_res_45.out -c31e19aeba478d0c29283f031ab31b7b absorption_res_46.out -41eee3c7220528ddaa420f67598bbf37 absorption_res_47.out -59d3e1724b45e8435900eabdd6ffc81e absorption_res_48.out -7ab8c4b2087685de82373c887f024af8 absorption_res_49.out -075bc2932af9227566eb71315954b917 absorption_res_50.out -1f42e0c35c43e94c2f0e926fc9cf7303 absorption_res_51.out -763bc79eb2c4f5e3c7f0c4592fba14a2 absorption_res_52.out -4055b805831ce3e2ca8e16d93becef32 absorption_res_53.out -416edf1a831f7d301c5f62c2c7fa3537 absorption_res_54.out -c631b917488b0568bdf0f8c281e1b366 absorption_res_55.out -a5e6a181252ad097ffb8fb8ac5398acd absorption_res_56.out -b6071144acd24f7d7776e1babbbd872c absorption_res_57.out -ab81627695045115888bf42af140630c absorption_res_58.out -1c80e46950996e823537121918bfaa42 absorption_res_59.out -559eed3c52f311717ebedb467d910a06 absorption_res_60.out -efe106d8e76799d9e23804ae88e1058e absorption_res_61.out -325d7777e283a1d82e3a9bd659b28626 absorption_res_62.out -0a610b52650ad8427ecdd1e462b71ebc absorption_res_63.out -b4a708d6f51f539e0dd38d3c96278732 absorption_res_64.out -0bb0e1b87091720282a5e4fc044a8eb9 absorption_res_65.out -c544d469c5e9124a1eef1b45348d7d26 absorption_res_66.out -f9d00f24af556ec4265690df01cf96e6 absorption_res_67.out -1324fe23d3e62925883bc529e0013755 absorption_res_68.out -dd9e1eae994a5fcc6e845ceb85b9800d absorption_res_69.out -52f82d4f08ed82ffb07ab84747f26bd5 absorption_res_70.out -a2165f13ec6971a0c6f0cc18244fad2f absorption_res_71.out -c0fbc6862fc513b7eab8eddfc2710e4e absorption_res_72.out -db03e654cc52773398683d95eae0dc12 absorption_res_73.out -69ca416174283f14ba95563020afcd97 absorption_res_74.out -c6b475da35c6064920bf4a810a018395 absorption_res_75.out -3504b37263b345bdeddbf90f5ee55719 absorption_res_76.out -3fcfb6b66759ae77a910509eb12d325e absorption_res_77.out -85bdf8e7d96616263fc41a83f9a60ccf absorption_res_78.out -bf5ae82ea6cea7a4d230851267d09f7a absorption_res_79.out -36633e6926a72dbacb392827450cdca6 absorption_res_80.out -386eb6bdea23245350d722e1f95397da absorption_res_81.out -30e63a6bf62c7ea7747d5487a6003642 absorption_res_82.out -aa1fc13ee5053d107cf548eba48fda8d absorption_res_83.out -3d2029da9f210996dbeb5bb56d4c26d1 absorption_res_84.out -178614cc4780a91ac6392940d35e89eb absorption_res_85.out -31560406504646fd0b1ff4d11832d595 absorption_res_86.out -2b85200ebdafe053deb0aec2f5e9dc63 absorption_res_87.out -177c9bf208a0d74ca486cc49b492ee00 absorption_res_88.out -62a5af963168051fe917b9560cae72fe absorption_res_89.out -d99248eb10a567a7619dceb5eb3dfe29 absorption_res_90.out -9fa4ce77ced9d040cf007494961a28f1 absorption_res_91.out -c77c5d43e9731017dd9afda49b926d94 absorption_res_92.out -2a74c3574ca783275a5915f2f294e9d2 absorption_res_93.out -7bc356661b1b2eaaad505cba1ad1642b absorption_res_94.out -3ed73811b0fb9e65b65018861e05078d absorption_res_95.out -b143b567d2185ac9d423c25663dbbf8f absorption_res_96.out -2c3499c1092c036f15f6732a30dc5548 absorption_res_97.out -2467844c3d885cce6c235057526bdcd3 absorption_res_98.out -e7e78274efcde7d1034d7c56d459ff15 absorption_res_99.out +2ae5a5b82a1ad6e350016648e9b4dc0c absorption.out +130e0c9a3644989e51288d3b7576bc1b absorption_res_00.out +c8d78f04e4202968ea3a061f51047743 absorption_res_01.out +41a36d0e243b95ac684f1bb8984e0ce3 absorption_res_02.out +d8ca8e3c27d90e043735d8430ba1fe92 absorption_res_03.out +5d007d563d846d4b85de6f0ced5bcf7c absorption_res_04.out +7e09f68f562096d3df078b4d411240cc absorption_res_05.out +84e5a1d5d19a8ef9bddce2e1c72521d6 absorption_res_06.out +3334983f4cfa85ef3099a2664b7d784f absorption_res_07.out +3f4d06600660dd4504b8e213adbd2551 absorption_res_08.out +82e674388384efd62fb837c98cb303e2 absorption_res_09.out +20bed8622b6b7791580fa42daae0afb7 absorption_res_10.out +07f388112ae50e1fa21dc36782758f30 absorption_res_11.out +12e9f7f947d18ffb6622f7335d4bac0a absorption_res_12.out +d9831dd114cae54d8c91fd44e62439c0 absorption_res_13.out +ea616b58ff9d5767264aef9874d73f67 absorption_res_14.out +f87ce48b1d476322607576f91614e751 absorption_res_15.out +4a813cd284ddc223be2f5ad5911e037c absorption_res_16.out +08afac53c047978e65010178f9a0a427 absorption_res_17.out +7e4355b506fa6faa79ed923aa977df8d absorption_res_18.out +c38c771c669f74e3e0bd3fbaa66f3bf5 absorption_res_19.out +4a98687575d19a65cf2b573127a58d08 absorption_res_20.out +6e3f48e0388b44cac8ed4dc6e14c00b0 absorption_res_21.out +1c04b26d69a2a6e4f51a9ce6af77d54e absorption_res_22.out +43a603cec35d543fae535c1efe3919ec absorption_res_23.out +f99b0ce39fd0f195ebbd421775b6c3c2 absorption_res_24.out +19eedfb57491e0ad3456608d0d1ca022 absorption_res_25.out +f10e766e34132bf9ad4234761c1c3f97 absorption_res_26.out +8592dc21362eca6e3228a77a0d402c38 absorption_res_27.out +26012365b579f115484fd8823aabb93a absorption_res_28.out +a730eb8352ad5bf8ff06e35818e692af absorption_res_29.out +1cb839467ecbc0a7b085bf1fe301cbe9 absorption_res_30.out +c780d2f9b60342fc8ca218add3cef74d absorption_res_31.out +bb99b26939479774b18789e0c7da19f3 absorption_res_32.out +4ca0c87df2968d0dc301cff742304061 absorption_res_33.out +23d7199ef91a21e135f259c25179e25e absorption_res_34.out +48ad0aa7c731657d12261e8fd9ed7cbb absorption_res_35.out +bdc21aa4170313b44b1c65757ae152ab absorption_res_36.out +e6b16425a3b348cb9792d59647aef90f absorption_res_37.out +4e987aec1d9629e9463855e683f41a9d absorption_res_38.out +14079c1a422e41e8057454060454d858 absorption_res_39.out +9ae9a85834b40c7efeed939911d397f5 absorption_res_40.out +da1fd579f088028043bf3f2b60b3c314 absorption_res_41.out +9a5c6967807fe1f718361f48f6218c5c absorption_res_42.out +b2dc8cb8bfdb9ff195bad7e25a7c42a9 absorption_res_43.out +2760d442aa64f5d561143a38f3238472 absorption_res_44.out +71b464c89d5009f7d7a7960db2cae7ab absorption_res_45.out +53c4f570defcda71cd3f11908bac0262 absorption_res_46.out +69e1c090346acf84f8d744bef5119e83 absorption_res_47.out +2356f6d559fed6f14200caf46e21d0f5 absorption_res_48.out +9c79cc5fbb9d39deb71423824e8499ba absorption_res_49.out +f1f95a5beace748a875344585d93deb6 absorption_res_50.out +0e6979a5e8a057269ec69a9e4ae49259 absorption_res_51.out +9bedaf18ef86e98d8083714ce56dd849 absorption_res_52.out +16f8d9e00274c22a3659283fc4c571a8 absorption_res_53.out +83ae93d5adc6afd7a37889e9459e3214 absorption_res_54.out +7783e616e430b2a6d759d7f56e1ea9ee absorption_res_55.out +d0c97bc9de2c0c7762e6aba7963ee77e absorption_res_56.out +1c77e7a069856262335a2b9015615213 absorption_res_57.out +4fec69dfebbf3922ed33802be6211e89 absorption_res_58.out +d4620e6d1d1983653a939cb5257fd7e1 absorption_res_59.out +8fc209dc7c8310444e733942760de3c0 absorption_res_60.out +6dac56f203a692a4afa22db7b694cf3a absorption_res_61.out +ec11eabed2105fa6d98171000dce987c absorption_res_62.out +00d903ae39a72da7166d96c168b32a38 absorption_res_63.out +f7dcbf73dae4f0175a20dac6a5d06be3 absorption_res_64.out +529bf960479780c54ae6937ebb975b0c absorption_res_65.out +5ae88fa557b007d4a66cbb3a47504de9 absorption_res_66.out +53c2843de88d0f5720136409c3616a8a absorption_res_67.out +8cfad4ef278d2533956cf141b475b56d absorption_res_68.out +3ad1b54cbd0d2e0c1e15211dc01c33b0 absorption_res_69.out +013bbb022825b6e04e55ac4098402870 absorption_res_70.out +45f91f36db08597c9d816f7cc3332a1a absorption_res_71.out +c91d731ea826c0f243eb96e63b57ccff absorption_res_72.out +64c7f9c00227e995d3c2bc9450f7c184 absorption_res_73.out +654a10d8eb21964bca53ad9bd8b889e2 absorption_res_74.out +49b74a4572f41942b4af0bb62c15da42 absorption_res_75.out +7d915b3d2864a80356dba5b6c522dec7 absorption_res_76.out +322d3545bff0b2b9e2337e0d20cf24a5 absorption_res_77.out +b6b1cd53f4b4bf65b51fa56d3ec8c9b6 absorption_res_78.out +fee7d69c363446d76087545bbd513595 absorption_res_79.out +36621f80bdcda371af5efe456d5be339 absorption_res_80.out +b6dd586d6c7b63e927b57838d36409fd absorption_res_81.out +abfe88336cf49491f70ec5143040890c absorption_res_82.out +6ced4e278dc2aa4cb1fd73b26600bac5 absorption_res_83.out +9d2033136ae967f4f33487309612a0cc absorption_res_84.out +c1bf7967d1ac6efcdc6af135332b075c absorption_res_85.out +08cbae5ee43c4e1972dbfdbcd61b02b8 absorption_res_86.out +f03851570e3b9e3861e259b7b1f91d2d absorption_res_87.out +4a19d347fb9bb33c557246d0c77cda04 absorption_res_88.out +91594df55a04073d9c4cfb5f8ffa3d7c absorption_res_89.out +122b0804c0872c89f54d0365881d1659 absorption_res_90.out +a2129b40ee06561565a8b09a5ca9627f absorption_res_91.out +46ee95563e981bde9723c4f5f99d2bd1 absorption_res_92.out +039e21272f0698183b17494de8ec7f78 absorption_res_93.out +5d78dbdde2549c1289741c2a3b1cc384 absorption_res_94.out +5c43cdd525116484c26d3346781749f5 absorption_res_95.out +bf07037fc6007130f73a88eeb2a9c954 absorption_res_96.out +c3014853e9b4918c163803eba2184c95 absorption_res_97.out +606f3f9bf8d375a1bda561201e40613a absorption_res_98.out +dc2f27104034b4f025214820dafc2f24 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -cd7d9b8340014d5bcc934e71ed6a223b deposition.out -4a5c4759d39721abe5a6ee49d31da3e6 emission.out -cc572d39e872d0104401bb4c4b0fbe92 emission_res_00.out -7bd493fd4e5c762d32d4a140d175300e emission_res_01.out -0e7d16d1a2db4742d78b2eab46c2be58 emission_res_02.out -105ed3f21aa264952c083b060361159b emission_res_03.out -f6864f61f86b1b4acd61147a5f2667df emission_res_04.out -517611008c0c318a2dd2ffde63ed63dc emission_res_05.out -fc42248fa52970762b22ee4face386ae emission_res_06.out -e120802527bb7f9c39af967db50507e0 emission_res_07.out -7fa2a19e9d2fcd7c91891a03e16da841 emission_res_08.out -6b9b541503d4a4bba2696f93862afecf emission_res_09.out -f41b88d0c5747763b0b39263bee9194f emission_res_10.out -5ec7f5ab71a81e1931135e9645e513fb emission_res_11.out -77a5ebc034e53efe24dca03b7527e107 emission_res_12.out -9ff5e8665ba28bfe42aa7f0dbd90e440 emission_res_13.out -327d902a0aebd019a246fe88f137bb51 emission_res_14.out -e4ba77dd58f4bfac1f29cd2c72014da1 emission_res_15.out -e2fc750b6b7161d40ae91ce39300e181 emission_res_16.out -3b1976f718ad58d67278d8b323bede10 emission_res_17.out -ddeb8c804520a45a3a9052683c9a661c emission_res_18.out -e536ec04fe43d80ecf999b73a3b7bf0d emission_res_19.out -67709c86acf269ae150e6fe9e3f207fc emission_res_20.out -cca17d9aec474b7774c95c7155034204 emission_res_21.out -2e7f7cdaee0ad6583bca0133a117a44c emission_res_22.out -e4eb9b7709d2969fff0123a2f7376a5f emission_res_23.out -2e010aa1dde94daf4141ebd091045387 emission_res_24.out -b87219aa7c6440d3f99ddfb120669a41 emission_res_25.out -e5e760be1eea94aa006c10ebcc0c4c6d emission_res_26.out -f31be96f0d7e0e215de61ba079a29c35 emission_res_27.out -b4e210592643bffaa0c5c4ae4e32a2f0 emission_res_28.out -4d66fc69e47b9a66ef6ac1b3e9cc210a emission_res_29.out -b3e3ea9af0ffe16be2c0b091bcb8079f emission_res_30.out -75bd85f2c4c63fb5a52e3cbe33989349 emission_res_31.out -8e0eb10a22811bad8499a782f5b9b3ef emission_res_32.out -fc25207bb79ced180f75a177093ed4a3 emission_res_33.out -d81722d5b10552f34e54cbcc33d70fa4 emission_res_34.out -040fcc8945a22105f9be9c4ebc8280b2 emission_res_35.out -61df5fd7d564441f3f8bf51cded8fd43 emission_res_36.out -1a26f2fc12671af7b0674b6aef129a42 emission_res_37.out -ebb5ed5317273a7ca9f98d1f039c7782 emission_res_38.out -b6b904b46f171b48edd7a7f51ebe4528 emission_res_39.out -8140deeafa0552d7744b04b7ad2dd667 emission_res_40.out -cb19d22e9727ffe492372ab54c25315f emission_res_41.out -a701a6db53451f120de811926dc9fc61 emission_res_42.out -2881ad70bed0d4c959d5ec8c1d51c527 emission_res_43.out -7ebda8c9b9d62ea8c1e50e8914e750ce emission_res_44.out -ff7691998e62c2b551820c01a0437634 emission_res_45.out -7fa565cfaa5031dd381e9f43c486bdc0 emission_res_46.out -e70ca2b14a85818bf17b0d8fe0a25a47 emission_res_47.out -43a51b13050b40da664b211e7b8df13f emission_res_48.out -ebd1ded8c011d5314204028e58c95bc4 emission_res_49.out -91038b64eea91f0b2c93f8ec50ea8697 emission_res_50.out -d2b4262a1a9faf8a32d811589057849f emission_res_51.out -0722ccaa187b4976240224efa365ebd3 emission_res_52.out -7a5a265a228451caed1bac42e41ff303 emission_res_53.out -8ae134a7d3a5ea9ce848c93e7b4fd4e4 emission_res_54.out -cea3be41bbeb139b6d74f32a6ec73fb6 emission_res_55.out -aed3743a86c454c7d672cc9917db222f emission_res_56.out -9c2fac120c5f4a46dff749ef170d5d58 emission_res_57.out -7dfdf248e4297a58dea69d6757d41d40 emission_res_58.out -3152d17723b7da39a56da8f28f67e02f emission_res_59.out -b398b8235c6956c6f9d1071046186c37 emission_res_60.out -ec71ba6aef599b8850c5064ba938810c emission_res_61.out -fdec8ef659eb96f2f03c1eb0717911b6 emission_res_62.out -e2d5d197d5ac590356320471bd977f0e emission_res_63.out -1213f561aca21663891309fc81d2cc30 emission_res_64.out -a9972b67ae0b4ed5217b85289f98d12c emission_res_65.out -714f59f20f2e1e66c197e18b38f7ec37 emission_res_66.out -5701feb4ec2d85c1be73bcb035354a71 emission_res_67.out -ec835a4729b4f2773ac3762a272531dd emission_res_68.out -49bb10b6895de80c3b1e0f1e2fb818b0 emission_res_69.out -3600530580ba5f49da20eeb8fd404b40 emission_res_70.out -0028c79eb1ce191e1eb8aa3ea0741dc7 emission_res_71.out -d263493bbdf347fd0ceb2ebf0759c6b8 emission_res_72.out -bcb5ec7bacd141128b0f59ec10c77c07 emission_res_73.out -cdf0999af79b8b80d422a29f7badfb25 emission_res_74.out -4c382bdafc53e258c29ea2440c3ff811 emission_res_75.out -e5cf051dbbe37c6920c22aae42c1df93 emission_res_76.out -6ee260eb40de74f181c27a7099cf8e20 emission_res_77.out -b2fa3fa154fd575f7fba680654fa6490 emission_res_78.out -3c4ef9b642470e19803e2ac5b5e051a3 emission_res_79.out -e1cc1a7caf77f2a300e3973f42aa3bb8 emission_res_80.out -f51f46d3bca818193cb17320e6bc6e42 emission_res_81.out -14b5601403fecbc8159303bd8d5473a4 emission_res_82.out -14e6d024a8fd42c52888a4ee707e06d3 emission_res_83.out -85f730ac2fc51460e999070c29a64f95 emission_res_84.out -53679f48e5d37e4a3d10365c06317908 emission_res_85.out -506ceb097ba4f3093f4e5fd3a06a58a7 emission_res_86.out -d5267ed66ae0cd646bf8aa5e810980a9 emission_res_87.out -2c5dd3ed2469736bcc4b0e7ee7ed48b7 emission_res_88.out -359c5c6abce22f742e389070465656a2 emission_res_89.out -b6ab5515f84ccb9d88458501d3ac7440 emission_res_90.out -90b25ded9658ad9932a34f42f919a528 emission_res_91.out -c0fd74a87912fe4e4bd64acbf8e668d5 emission_res_92.out -6b299c031abac6dc80ef69096000be5c emission_res_93.out -f33732a20a11af9684a4db3c0eef17b3 emission_res_94.out -664472b4310c3761b8967ea73e865219 emission_res_95.out -49ad0ddc60b06f0bad2f4ee8dce1f729 emission_res_96.out -1e7af5fe6b9e7ff6134b1599299af251 emission_res_97.out -d35808e987c7aef6b22a5416bf17c7b0 emission_res_98.out -8b3f2bd8ee37437d0f7dfdd323c1a6e5 emission_res_99.out -81e206ca6fccc71f5f15af8b85e67ec5 emissiontrue.out -b5fb06ef79ab1001e58006c827162a29 emissiontrue_res_00.out -21e3fb9e41f14362034c3025021c020d emissiontrue_res_01.out -b08e0d7dca103924d22431a79342cd84 emissiontrue_res_02.out -194ac5603dc2a0c41f272780bc161ae9 emissiontrue_res_03.out -8040e5fa9003b6c2955d28db357ceb83 emissiontrue_res_04.out -ed70e0209be4b1c70a4235f48715cd91 emissiontrue_res_05.out -6e4ebc782100a987ea85413f8b7db5a6 emissiontrue_res_06.out -9c39333b2f73f63b378214b6bff0a39b emissiontrue_res_07.out -0213c3aaa1cdf7ae2357fcd48f783fd6 emissiontrue_res_08.out -3a8030378ea116936a291b00115741dd emissiontrue_res_09.out -e3780c7ca484041cc3b59b84e4504248 emissiontrue_res_10.out -a458655ca53641c549cfdca52f83b877 emissiontrue_res_11.out -0ecb29fb03203e805a364149e04523d6 emissiontrue_res_12.out -f46c89692a7453a41a7f7e7a35fd7d06 emissiontrue_res_13.out -a49fc4929d4ebae2cdd22d121b74b061 emissiontrue_res_14.out -26d637af05f9385287ea2f02fa7d8f9b emissiontrue_res_15.out -1338ed4e2fe5447bb3b7585acf57d026 emissiontrue_res_16.out -c0174a2839545a8366ba996957d8c07b emissiontrue_res_17.out -aa919856cb214f0b8add0e01f3e788d0 emissiontrue_res_18.out -b339e492d8862313b95ad4f99a66b89e emissiontrue_res_19.out -59aacbd232b1ceb029c07829a3dd65ac emissiontrue_res_20.out -c1d66a041b4b03c2902bdcd8ac1fe33d emissiontrue_res_21.out -0b17ab8ca6fe0cd88ce8b4d64643e9e4 emissiontrue_res_22.out -abe8de0a2cc6096bfaf23c0769391ccd emissiontrue_res_23.out -6d9274d2ff1fd0b71b9cbbea2084214b emissiontrue_res_24.out -ec3875fbcb728d453ed99be585b22ddf emissiontrue_res_25.out -c5aea4f89bd310772f0d2c681fb40bfd emissiontrue_res_26.out -6f7e9eb20600e6287d4d8fadc71f85ba emissiontrue_res_27.out -754fd1862f2affc4dbd982f69de3707e emissiontrue_res_28.out -c111024f3e1184c5ac30faa959ea4fd6 emissiontrue_res_29.out -6e0dceef8b17d1a0fe1628702517f300 emissiontrue_res_30.out -8b43a167dbabd3cb68e653816fc2e4b7 emissiontrue_res_31.out -a3c3c3ad10570ca68e797feea0c23164 emissiontrue_res_32.out -4fbc6f9bf7502b90cd8360b6b5148d8a emissiontrue_res_33.out -2c7ac8715615eddc8205a08191532340 emissiontrue_res_34.out -753452c80b805d6d88606dfb90d7452f emissiontrue_res_35.out -5fbe80041ad2f8f11191016b3271dfdd emissiontrue_res_36.out -38268b799ab43aa5946498f0a27f7e3e emissiontrue_res_37.out -2b9b3b102e9948eb29d5c4f157cbacf2 emissiontrue_res_38.out -39a8c05e0d385c6c10b794bfb09857d7 emissiontrue_res_39.out -9e3b740705a9e8a9e0ab1783bff00e38 emissiontrue_res_40.out -2d5777c6a9b3718094775352330aeb62 emissiontrue_res_41.out -c264104715625233089b2ac6df291247 emissiontrue_res_42.out -4d9e84788c0bf2aada603025a88956fb emissiontrue_res_43.out -2805238c9d564cbd15247159c130579b emissiontrue_res_44.out -ff30bace38faf2cd3c9b23b6fb31d48a emissiontrue_res_45.out -112d2a753fd0d0b950f3e376bbe1563e emissiontrue_res_46.out -b8e6f601c2834a8dd0a7d1adf2c82144 emissiontrue_res_47.out -0b6c4816459aab0614439437d947d336 emissiontrue_res_48.out -4887b8ce41f4ee7d2f265e2d83218b6f emissiontrue_res_49.out -d216be13765ab0aafe41bd786b26aee2 emissiontrue_res_50.out -744e72ac70721a955522d66ae9eee3bc emissiontrue_res_51.out -4691f93494336dc680191201da3b7e22 emissiontrue_res_52.out -b13dd07587371f5db1761b23efe53940 emissiontrue_res_53.out -9525b7ffcf22e5d040a41491b2872136 emissiontrue_res_54.out -7609a67586253f6fa95cdfeb314565bd emissiontrue_res_55.out -034487f40428c3fb6ccdae85839d9b0b emissiontrue_res_56.out -500c500d5d30b1809ea47107f854a0c5 emissiontrue_res_57.out -0de771068d8c4bebf36e09f0b9881c93 emissiontrue_res_58.out -553ab62fb8f2b57a7742982ade62b043 emissiontrue_res_59.out -99ee5791f3f09c08a15d98168d713859 emissiontrue_res_60.out -dc6abb0e032a4a2cc015a9ad63096b14 emissiontrue_res_61.out -168fab67369e28df4b628602a416dff0 emissiontrue_res_62.out -e0d7d797e264cf2ae0f0d65cdb7af562 emissiontrue_res_63.out -ae573e3a59a960aee5150b72ca779d0c emissiontrue_res_64.out -63c3e3598c109f8005476876efbb2ec1 emissiontrue_res_65.out -0f3fd9d9e337a16dfca92733b53a9704 emissiontrue_res_66.out -db9fca748a0eaad85bee94937f060b11 emissiontrue_res_67.out -669c0988ec271b5cbf34eea76c0d36a4 emissiontrue_res_68.out -8142a70ab2cbe54fe1593be9c5f5265b emissiontrue_res_69.out -d800404628e346b4c604123416d0619d emissiontrue_res_70.out -d77fbfec0fb8eaa44b4ebb10aa583941 emissiontrue_res_71.out -fd396095df75c8057d1f4965787c77fc emissiontrue_res_72.out -56209362fc78524261fbbc9b287e4c66 emissiontrue_res_73.out -6691d9fc1f4125ec29f0b2ee4aacb390 emissiontrue_res_74.out -543d617d5644bcf5eec598431086ea74 emissiontrue_res_75.out -18d07da54360b10b01dcc09ba5a2b2bd emissiontrue_res_76.out -e7fdcd69e1cfb754783ab16fcf000454 emissiontrue_res_77.out -f5f64d841da92ac5cf64799902d62b52 emissiontrue_res_78.out -4b7232550f8a30462fa80ad0206f9a6d emissiontrue_res_79.out -24949075ee7070dd1fe5d0e358beeb5c emissiontrue_res_80.out -13c99407609964cf927928e266babd44 emissiontrue_res_81.out -b05c9252aba7a3257c9c06c81c9990a0 emissiontrue_res_82.out -5fe373eb02284dbedd17d5f41d92bf26 emissiontrue_res_83.out -b65866401ca0201901ea71f8d5c09157 emissiontrue_res_84.out -49176cc16a676fa807403ff1a06ad3e2 emissiontrue_res_85.out -2c8c261fdda28f8f7195cea9958b2740 emissiontrue_res_86.out -6f774234794470bb853ce14ebdcaa44a emissiontrue_res_87.out -d5f9631b947fe103497da7499b8da18f emissiontrue_res_88.out -dbc97ce31d7542505032a0fefc21138c emissiontrue_res_89.out -703832d6bcfba95085ce88a1cec9c5a4 emissiontrue_res_90.out -23d2eea0eb23f0010b7e91065505f2f4 emissiontrue_res_91.out -c050766c9cd2c7ed57fdc02b808e066a emissiontrue_res_92.out -2204a74ff67b7e458d6ee1f55d0d6d49 emissiontrue_res_93.out -e9c98f92ef74f6bc4fe7258e721a4374 emissiontrue_res_94.out -6c0a8e96d005296d35d0780f20775164 emissiontrue_res_95.out -3bb8a8663fa200efb866baaa02841fc1 emissiontrue_res_96.out -0f6a82a362f741a00821f218b6410ff1 emissiontrue_res_97.out -ae37411bb87929ebba53f7d98e028fb2 emissiontrue_res_98.out -6035bce2fcd58b263b879ca0a666437a emissiontrue_res_99.out +27cd5ff0c7e1e1e38ab53d5da75c13ec deposition.out +30f2a2cb8387b2c6591337423dec3293 emission.out +97981ea90ae9ecb035aea8ec8e8c3c65 emission_res_00.out +ab2f42f05b2f2c710e1aa15a79e543b3 emission_res_01.out +a2614cb40b930dcfa646cbdc3d8a5cc9 emission_res_02.out +3c4cc87a3e17793aba170fdd5690d3dc emission_res_03.out +02958eec3842f4f411783b9f8ab9402e emission_res_04.out +67bd0fdb82e3dc4b2e5a6cef6284a64f emission_res_05.out +9fa6f10003be8624ba5338d2b3e4e525 emission_res_06.out +8472a50ac99b7b6f5d33ba8c47cf8d97 emission_res_07.out +9922b57dda13be39d85c4986a01c0fac emission_res_08.out +017bc94558003b60f140b40925adc9ff emission_res_09.out +7fe29985712e13c40160b96a6d841913 emission_res_10.out +e86c8db28cf605854c173bcde279a1cb emission_res_11.out +9c67bfeb949ce20207048a44bddad283 emission_res_12.out +9465071c10c63599930604f6617d132c emission_res_13.out +dc78fdec647dca513683c59e524e5f51 emission_res_14.out +4a18565d976abd955f03a39c633472d1 emission_res_15.out +3c55e81d2e4db3c058b64e6252af662a emission_res_16.out +dfcce0badcfcc820c0b753db8ca42db7 emission_res_17.out +0be6137203c1f183be38065db097ae45 emission_res_18.out +91c72c83a63f5f4447874740229dbfa1 emission_res_19.out +dfa6b5a59f15adaf74f348b58f01041a emission_res_20.out +38c9c1962dec6e33b494fb62cd731d61 emission_res_21.out +9a14f828ad898f4f1bd97ecb6b81fb42 emission_res_22.out +a1f8de1a5ffe1fffbff9aa33296af576 emission_res_23.out +9f5ebc23806bccf13edddd79a356c4dc emission_res_24.out +b5570f759b168be67c113f39f9ecc09e emission_res_25.out +6bd6c05e31c640c3826b7de88b0311b7 emission_res_26.out +749928deb63b15f4ab455d8d9372203b emission_res_27.out +fe5221ba65b262b3e9e215a51a618ae3 emission_res_28.out +bee6124a93353ac298f7275fb2248fe1 emission_res_29.out +78d70967fbb898b003d5fb303f2ad34f emission_res_30.out +fcc8ccae96e1f482b8d28b77e8a845a6 emission_res_31.out +c770c0b226445e397221b70accebb081 emission_res_32.out +96e3961b64ae3e7ab6bf521432e35c1a emission_res_33.out +ebfd68f9b3d32e2c3385d91da82bdb4a emission_res_34.out +b8b146a4f3bca8426fe8db4dc1af8b33 emission_res_35.out +e8e0e0a948b0e4ff57941a0767390f7d emission_res_36.out +af9adddde40333468b7e8774095032f7 emission_res_37.out +ae1cb0224aaf97cb56f73e8713859ef6 emission_res_38.out +795fa6e786c50a42f2784e091b346ae8 emission_res_39.out +40058222444452ce7f9c844e37f47ab5 emission_res_40.out +65bd132eef03f727aeddb2ba63d5961b emission_res_41.out +3f7f2b61b821a4cdc0d2c1dca25a62d1 emission_res_42.out +efda35d1f90b5efcd0b839778cbb2f09 emission_res_43.out +8b2d43ea93548576ccb717266a6abaad emission_res_44.out +a3a385672b114b9346f1634e7b5ca786 emission_res_45.out +2204266b1f3971c6e3805a8e5df2db70 emission_res_46.out +27bc2dd9c63138c1c3823f9aed8b389f emission_res_47.out +ca3a32e2e53342eeeb2855b1394a3f83 emission_res_48.out +ee787bfc6f71f5f266d3acc585c38ea1 emission_res_49.out +e38854c1715eb57e0b8d4387fa6cf1d0 emission_res_50.out +40ca1ee2c9f66e3907b62cfb089c8763 emission_res_51.out +7ecb75101875fffdda4b983c706f6eb4 emission_res_52.out +27b8027fa8969905fd5854019767f3f8 emission_res_53.out +0b4a702b3f41b91d3e308cdda02609ab emission_res_54.out +524fe9b25763d032a65f17acabe903ea emission_res_55.out +76e5602fd1c9511a2130bb9df2b1a530 emission_res_56.out +039fe75b8bac8d153eff3fb79b214f81 emission_res_57.out +e30036454a57c932e242bc942c826944 emission_res_58.out +7b4222b00c3a47512f21f8a66437ce41 emission_res_59.out +f5468a89e1d2eef22434a30054ff37ca emission_res_60.out +541ba3e1a2ddaa72994cd8b9bd4d58f9 emission_res_61.out +77d4ba6fdb5c3b28c89ec6b0465c1dd9 emission_res_62.out +c7a5b1068cd88dc7f5a7b0767c017847 emission_res_63.out +cbcce37417987386c2bcbbbec46a7d10 emission_res_64.out +9ec0d4740124d7c48fe78c7905f767a7 emission_res_65.out +b27065eb14bf68e24390b43ce1141dac emission_res_66.out +c45a15e9e5e153200600ff15102a1abd emission_res_67.out +3463e67178f02100195a4784d0dfc0c1 emission_res_68.out +1a70a2583219d8cb2926e983630f23e1 emission_res_69.out +efa667c444bda3f2c014303c89e3a639 emission_res_70.out +8789e73c939b9e94f1084c0a80359caa emission_res_71.out +abc04fbc5c2d5a88340be4cb9ab2a59c emission_res_72.out +419360a7635c6b25e7b2adf901ed6342 emission_res_73.out +1caefcfb9dc08f3d296f699a2d0546c6 emission_res_74.out +a83f348225a1c79e509b51e6fc1e1ebd emission_res_75.out +df39d5c4aa388d0e6643fbd3ee9ee7c1 emission_res_76.out +4fb1ed39117505be0eb55f73eb0ddd20 emission_res_77.out +7ecc2d2de81f2ad9fc26acd07927df58 emission_res_78.out +cca4130690c7847e430716dd2218a5e8 emission_res_79.out +41ba9dc8d7c59f4af9ea6da56ee39e60 emission_res_80.out +1b64aaa749c59df11019a37cbd5defe5 emission_res_81.out +c7fcc11a6c141f4763d0146c94fab568 emission_res_82.out +a7eeed4e384aaa370ea328e72d3cb4a6 emission_res_83.out +de423e83c6dd0d65242b7e96a818229b emission_res_84.out +ae6fe79c9afed3af245df9e318f0e3a1 emission_res_85.out +eeb893a436db7d52d775638fc867203e emission_res_86.out +337a2b4fd6c7db0ac725d03c201ab9d2 emission_res_87.out +5cd170ec28e3f45cbfda2d038d8e1fb7 emission_res_88.out +77c5fc0d1a024125e65f0ec7a914632d emission_res_89.out +e2cfc3b5e9137a9552610308d31f69e1 emission_res_90.out +89362d414410a115c73eb596b628ff5c emission_res_91.out +630892d538d59007d81e0ef420692f6a emission_res_92.out +22d8a81a267650a3a8deecff2622dd56 emission_res_93.out +31248ba977d6dca6da0c43a4796c16d8 emission_res_94.out +b4e63c8b971f85ceb3dec2c1a1e20a88 emission_res_95.out +5e2f82fb26eee688647a0cdcbc8837dc emission_res_96.out +fd4f6eda72dfa787829c7a1932e7d548 emission_res_97.out +312f2ec4d9918ba0f0121e2d2464d2cc emission_res_98.out +1e0d2d817a3a683a531bde593d233bb1 emission_res_99.out +9efbc10f23d5204a176d84dce94d1241 emissiontrue.out +f29858256d04ece60a208e6395f31011 emissiontrue_res_00.out +215212a3fadfb727c85785e16def79c0 emissiontrue_res_01.out +c0b65e6e8ffeb7e0b665374de24170e8 emissiontrue_res_02.out +4336cdb2699ee75fd75c1461df23f374 emissiontrue_res_03.out +2beda3268eaafbb1c22b5788d4fbf2fc emissiontrue_res_04.out +ba5a3eb615ba1c920cc331486978d29d emissiontrue_res_05.out +435b9cd9f6310e446d0b0c40273f7c4b emissiontrue_res_06.out +b9b84bf50783b58c232784221be70827 emissiontrue_res_07.out +8ed88b943c25c670419c8fe679d4ba05 emissiontrue_res_08.out +8ac1bbee22fa3ed6eca1df059b90e1d5 emissiontrue_res_09.out +1f3ef6d393c2db9b4a0556cb63ee12df emissiontrue_res_10.out +0427de965ab7a474fe868ce48a4e4b20 emissiontrue_res_11.out +5a0976efa1037e9bb7d614d4263f5f8a emissiontrue_res_12.out +8d87e43cb6d8ec3f969e0dd87ac737fc emissiontrue_res_13.out +d3d22382c5e4f2b1ddd34736102ff0bc emissiontrue_res_14.out +bedca7ff86cadced972e50271437d614 emissiontrue_res_15.out +09f847c16e8d852eb699adfd300e6201 emissiontrue_res_16.out +42f0d234b040dd1c5ba744576bec39d1 emissiontrue_res_17.out +7dd412a15fb6f79948ef21c6b3cd77d7 emissiontrue_res_18.out +0db336f9c069ddefc16bf43cbe695d77 emissiontrue_res_19.out +1887f448e3a074949bbdf6365f77366d emissiontrue_res_20.out +efbf92b0e4b1a97247ad488eeb975d86 emissiontrue_res_21.out +1ff74aa662ae07e404bdb3f7f8b5ae72 emissiontrue_res_22.out +d95646194bfa09db5fb04484382e0f4e emissiontrue_res_23.out +3d3c72b251fa9bb7a04401a577de9800 emissiontrue_res_24.out +ba2e0ae934a657e686160c38de53dd7f emissiontrue_res_25.out +482745c6eb078dc26b8aeb3a10232f25 emissiontrue_res_26.out +ca4da6ecdc1229aca3bbc5d1df6f05d8 emissiontrue_res_27.out +5b02b97a8cdcb95c2b775f3af4e92198 emissiontrue_res_28.out +7b97444588f0a28b568e7f660a33b5aa emissiontrue_res_29.out +358725d8bc22e174d54d226ee6d3a971 emissiontrue_res_30.out +8a70a448045726f6284112e621ffcc01 emissiontrue_res_31.out +85fa6480da77473a851a0872a21439de emissiontrue_res_32.out +33d846d537c60514c72bb68397a47e20 emissiontrue_res_33.out +cb1d761d2ccfb5faf398c3203b32d1ff emissiontrue_res_34.out +50969783d3f54fc19af05a00d7b71614 emissiontrue_res_35.out +5c3beea194947b8eb3852b8925cbf615 emissiontrue_res_36.out +7379042a8bdc7f08c5b71516e99a2aa0 emissiontrue_res_37.out +f2c544b80fc0ea6866bfedb4736a5737 emissiontrue_res_38.out +6e40c4d2ee9571c62992e90b39342151 emissiontrue_res_39.out +50bef91bb82d991316a5d543b5fc10f1 emissiontrue_res_40.out +026b3c57f00d837e72512f90ac2696f5 emissiontrue_res_41.out +99d13525345cb2cb2300723ee64fa320 emissiontrue_res_42.out +f7d55bd6968bdbed0af68dd4e1402143 emissiontrue_res_43.out +4d61bbaf485729a0a3a52578578039ca emissiontrue_res_44.out +9b93ff2a134765ae540bd6203eadc815 emissiontrue_res_45.out +3cd7769bbb4c4336506761463f8a3854 emissiontrue_res_46.out +94516a1e58d3c6d376c8200a27dfaff1 emissiontrue_res_47.out +4a3b562475b2297affb1da63ac8e8049 emissiontrue_res_48.out +ed9af8d95612df1f3c6b78812943ed4c emissiontrue_res_49.out +be239713f351ce053ace00c7457df573 emissiontrue_res_50.out +5039c23ba39e1796bc09455f6ddf777e emissiontrue_res_51.out +d49a15c03bb0cf6df6191edff645d422 emissiontrue_res_52.out +44ff35d9c1430effc50acdf56408c1c8 emissiontrue_res_53.out +34dd1db250a7904383423fd231aee95b emissiontrue_res_54.out +0f14060d17fd370cf75b94de34d98356 emissiontrue_res_55.out +14eeca8dcf8aec291e959d9aaf8dbe52 emissiontrue_res_56.out +04cdb81991365f93b138503743164337 emissiontrue_res_57.out +974b58912e6a3590dfbc84e9e3b49de3 emissiontrue_res_58.out +701391695e302e3d57067a10f37b587b emissiontrue_res_59.out +e13d9f062b66b4a2b404eb3d69db2147 emissiontrue_res_60.out +a4f3dfa22a8795aea2a60b8130f9482f emissiontrue_res_61.out +34ef416adfc4cd37f267d14cc814e0e6 emissiontrue_res_62.out +6ba8adafdbd336d8219d2630fbe69bfb emissiontrue_res_63.out +e7828259db96148bdc7b5ad6746670c7 emissiontrue_res_64.out +16186da58eb3df4b91e015de80b5bb84 emissiontrue_res_65.out +dd805f04cd56907441d77f53b8352e40 emissiontrue_res_66.out +aed74d6f176615f0674b16e05a696fe9 emissiontrue_res_67.out +6828c01bcd24ec27c9eb0354b5fce501 emissiontrue_res_68.out +cbc7f2f5f6088a78e3574b50a208bd8c emissiontrue_res_69.out +5b6bc22dc23f5b03c2a3cb91cafdbca1 emissiontrue_res_70.out +2c1f26aa586392c20a6debaf4b1cced5 emissiontrue_res_71.out +d36ef302d3236fa1500fb07170531aa0 emissiontrue_res_72.out +e4ec9b4ead7c308af32243eec3808464 emissiontrue_res_73.out +2a89f3d3337a1102c750f7ad84b52590 emissiontrue_res_74.out +56b0110a04a7b968d6c970adbb02c32e emissiontrue_res_75.out +56134eed4c7615f1c9b350a37d4bca10 emissiontrue_res_76.out +d32f3a64e35a1d4e8a2e83d4b18fc367 emissiontrue_res_77.out +b98aa74a5f60e949494ca5e39a4fa50e emissiontrue_res_78.out +75199e447974b17329a6fe3fc122bc92 emissiontrue_res_79.out +f06fa80eba983e9444cddb393841123c emissiontrue_res_80.out +27e1df2a710f04a7b0326ee174a22579 emissiontrue_res_81.out +1a0061691822a1b21c10ba35711a46a6 emissiontrue_res_82.out +a2ae221596be148445c3c7dbd1b65c05 emissiontrue_res_83.out +55faf5c0a321b94d018e303b18c6a536 emissiontrue_res_84.out +b624b7735eaa61f637a991bf019ccf05 emissiontrue_res_85.out +bfc8cf36030a8193fcaaadafbcb2dee7 emissiontrue_res_86.out +5eeb523ec34faca6cb552c0b4c22fdcd emissiontrue_res_87.out +bc646974692db202aac331913e812d86 emissiontrue_res_88.out +391ca49deadfde5374cfef51a53cf260 emissiontrue_res_89.out +cc6112dd902627392ec4f5ead103bc2e emissiontrue_res_90.out +29d921741d2091db9a26fde858e825db emissiontrue_res_91.out +46f9e81a7b35b8c4c748a3a865a52eb1 emissiontrue_res_92.out +84ac0c41aeccf120bec54ea315a25627 emissiontrue_res_93.out +9efbd761d03c64c69157a3d57c1b81e3 emissiontrue_res_94.out +dddb13602686df67b9d9226ff8fbbef3 emissiontrue_res_95.out +2e801a0dbaec334abeda97fbc1ec1ca9 emissiontrue_res_96.out +31b0689f46a609c43e065cd8b3433f8f emissiontrue_res_97.out +b382790909c5c1da022e65e6a7712f1a emissiontrue_res_98.out +6a1d582e346927ecac6bd414751dde4d emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -26e7f83d49072c35020f3e170b91334b light_curve.out -6d8c77ab3451b894939484918b64973d light_curve_res.out +d34d568bae0f54c86cdcc223cc1046a5 light_curve.out +d3c72291c7438eafd464c49a648c3068 light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -824fa63d9d0e8a16b56e60d80ef49a1e packets00_0000.out -ea2bb9d00a595ddea110c5a1c33ba3ca packets00_0001.out -0dea2332a5243b956945abc873b41216 packets00_0002.out -36fc78247a45a5fe182ccc34ac0fc0af packets00_0003.out -6eef5da0bab37e29fd2cb3b9ae04832c spec.out -787ea9b17d6b86d3236c12b89f49c9a3 spec_res.out +40c7e21d1057371f2576401e97d7e092 packets00_0000.out +4a4b4b0b38d95e3de03e5f96fbe0d4dc packets00_0001.out +d3f3ab45d617d6c4529a2946296d1cd0 packets00_0002.out +87a6043c2fdab1ff4f0d6c4499e32506 packets00_0003.out +81cdbc53ccab06f206f90cdcfc2e07af spec.out +7a05920b97ec68394b20223b4588b039 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -266a3473fefd978b5ce3fe46bb3c14bd job1/estimators_0000.out -feacc4f2b8eeed8bfadd9aa7dc88242d job1/estimators_0001.out -ce09e41e172a11bfa0a3285dd6fd9580 job1/estimators_0002.out -81dce9f8a1eb0ec858ceccd6fac0df6f job1/estimators_0003.out +f3db81fc473257650b015bfc9f9ffac2 job1/estimators_0000.out +679d1910efa0516c70da10fc696bf3d0 job1/estimators_0001.out +ecea23e09ce025a3af4b6ace4e8f716d job1/estimators_0002.out +658f5e7dce6e8408c7b060db78e54c65 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 7c2b4e448..a2d3bec63 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -6bd54ee9700306c4f1da537fe8939aeb deposition.out -267fa0f38b2763b29eb4bebb9c3d110c gamma_light_curve.out +c3d839f1692d3b06ff2c03db64949d97 deposition.out +4e429ae0865553e3eb26f561d5fd3040 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -a5f6eed3aa3de1375784bbf175e42494 light_curve.out +2a111629a130d19611436117b6c20778 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -878862f601178dd48aa4dcf2945f3cd0 packets00_0000.out -7e2db0149c0241f41716846e5390c382 packets00_0001.out -c1977627040085c730a8ce9f41b0daa8 packets00_0002.out -37f35d601bb085b82e3bf9554d4c315f packets00_0003.out -bc999ebbcee373fd633d2f0dcdcc3b67 spec.out +0bb6a8244d354c4c185bf537367524b2 packets00_0000.out +e1686573dca2a06b00b0ca3b8ab0745c packets00_0001.out +3774a1d01f4f2a957d7a0fc0abbec2e6 packets00_0002.out +f1c0964063848c6fe9cbfce41c68a2be packets00_0003.out +d208e6c529f37bf28c70dcf13daeb0ce spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -424b6e13fe6f6d93ac13890d1a1edf71 job0/estimators_0000.out -64488872c5b47c516c6cc692c668550a job0/estimators_0001.out -a956fa38a510440ba22a60acab3b4859 job0/estimators_0002.out -c5158a986c7b9f377ce1f03c32c46ac2 job0/estimators_0003.out +f6e389b9110d41a21655c4e71f70911c job0/estimators_0000.out +b14130fcb2dd68eb370109e97147bd41 job0/estimators_0001.out +088ab99d8650965eb4ad834d4bb404b0 job0/estimators_0002.out +83567e100201853207e48cfa95147bf1 job0/estimators_0003.out From b5271382dfecf6e41227b6470b60199a4d851fa5 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 5 Jul 2024 15:13:04 +0100 Subject: [PATCH 002/117] Update spectrum_lightcurve.cc --- spectrum_lightcurve.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 9fbdbce41..a79a978b7 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -598,13 +598,11 @@ void write_partial_lightcurve_spectra(int my_rank, int nts, const Packet *pkts) TRACE_EMISSION_ABSORPTION_REGION_ON = false; - bool do_emission_res = WRITE_PARTIAL_EMISSIONABSORPTIONSPEC ? globals::do_emission_res : false; + bool do_emission_res = false; // the emission resolved spectra are slow to generate, so only allow making them for the final timestep or every n if (WRITE_PARTIAL_EMISSIONABSORPTIONSPEC && globals::do_emission_res) { - if ((nts >= globals::timestep_finish - 1) || (nts % 5 == 0)) { - do_emission_res = true; - } + do_emission_res = ((nts >= globals::timestep_finish - 1) || (nts % 5 == 0)); } init_spectra(rpkt_spectra, NU_MIN_R, NU_MAX_R, do_emission_res); From 0d7df24d6b96bc724f730827d372e685793d69f3 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 6 Jul 2024 11:08:15 +0100 Subject: [PATCH 003/117] Fix virgo jobs by adding APPTAINER_* env vars to slurm script --- scripts/artis-virgo-slurmjob.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/artis-virgo-slurmjob.sh b/scripts/artis-virgo-slurmjob.sh index 3542df568..5d9b7b9b9 100755 --- a/scripts/artis-virgo-slurmjob.sh +++ b/scripts/artis-virgo-slurmjob.sh @@ -4,6 +4,8 @@ cd $SLURM_SUBMIT_DIR +export APPTAINER_SHARENS=true +export APPTAINER_CONFIGDIR=/tmp/$USER eval `spack load --sh gsl%gcc arch=linux-debian11-x86_64` export LD_LIBRARY_PATH=$(gsl-config --prefix)/lib/:$LD_LIBRARY_PATH From 24e6ade6282c3181ef93d9b5c2580c1ab017ee34 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 6 Jul 2024 11:11:22 +0100 Subject: [PATCH 004/117] Update Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 3259ce430..1acc1f263 100644 --- a/Makefile +++ b/Makefile @@ -154,8 +154,8 @@ else # g++ -march=native -Q --help=target | grep -- '-march= ' | cut -f3 ifneq (,$(shell hostname -A | grep gsi.de)) # virgo has some AMD nodes and some Intel. - # As of Feb 2024, the login nodes are zen3, and we select the same arch for jobs - CXXFLAGS += -march=native + # As of 6th July 2024, the login nodes are cascadelake, and we select zen3 nodes to run on. + CXXFLAGS += -march=x86-64-v3 -mtune=znver3 else # for GitHub actions, checksums must match with different assigned CPUs, so avoid -march=native (use lowest common denominator) # update: all zenver3 now? From 8e592cb9bf04b32511958b75d8b9cd668969681e Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 8 Jul 2024 22:01:46 +0100 Subject: [PATCH 005/117] Track per-cell emission and deposition rates for alphas, positrons, and electrons (#86) --- .github/workflows/ci-checks.yml | 2 +- .github/workflows/ci.yml | 33 +- decay.cc | 122 ++-- decay.h | 1 + exspec.cc | 5 +- gammapkt.cc | 42 +- gammapkt.h | 3 +- globals.h | 53 +- grid.cc | 46 +- input.cc | 23 +- nonthermal.cc | 50 +- nonthermal.h | 5 +- packet.h | 6 +- sn3d.cc | 128 ++-- .../results_md5_final.txt | 54 +- .../results_md5_job0.txt | 14 +- .../results_md5_final.txt | 10 +- .../results_md5_job0.txt | 14 +- .../results_md5_final.txt | 32 +- .../results_md5_job0.txt | 30 +- .../results_md5_final.txt | 32 +- .../results_md5_job0.txt | 30 +- .../results_md5_final.txt | 632 ++++++++--------- .../results_md5_job0.txt | 24 +- .../results_md5_final.txt | 232 +++---- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 636 +++++++++--------- .../results_md5_job0.txt | 24 +- .../results_md5_final.txt | 636 +++++++++--------- .../results_md5_job0.txt | 30 +- .../results_md5_final.txt | 636 +++++++++--------- .../results_md5_job0.txt | 24 +- .../results_md5_final.txt | 20 +- .../results_md5_job0.txt | 24 +- .../results_md5_final.txt | 18 +- .../results_md5_job0.txt | 22 +- thermalbalance.h | 27 +- update_grid.cc | 10 + update_packets.cc | 71 +- 39 files changed, 1970 insertions(+), 1857 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 178de431c..92dd2e995 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -203,7 +203,7 @@ jobs: openmp: [ON, OFF] fail-fast: false - name: macOS brew clang ${{ matrix.mpi == 'ON' && ' MPI' || ''}}${{ matrix.openmp == 'ON' && ' OpenMP' || ''}} + name: macOS llvm clang ${{ matrix.mpi == 'ON' && ' MPI' || ''}}${{ matrix.openmp == 'ON' && ' OpenMP' || ''}} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41bbfd01d..54fb76841 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,10 +170,24 @@ jobs: working-directory: tests/${{ matrix.testname }}_testrun/ run: cat job1/output_0-0.txt - - name: cat job1 deposition.out - if: always() + - name: Set up Python + if: always() && matrix.testmode == 'OFF' + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install artistools + if: always() && matrix.testmode == 'OFF' + run: | + python3 -m pip install --upgrade pip uv + uv pip install --system -U artistools + + - name: show deposition.out + if: always() && matrix.testmode == 'OFF' working-directory: tests/${{ matrix.testname }}_testrun/ - run: cat deposition.out + run: | + echo -e "import artistools as at; import polars as pl;\nwith pl.Config(tbl_rows=-1,tbl_cols=-1,tbl_width_chars=300,tbl_formatting='NOTHING'):\n df = at.get_deposition('.')\n print(df.select(['timestep', 'tmid_days'] + [c for c in sorted(df.columns, key=lambda x: x.lower().lstrip('eps_')) if c not in ['timestep', 'tmid_days', 'tmid_s']]))" | python3 - + cat deposition.out - name: Run exspec if: always() @@ -218,19 +232,6 @@ jobs: name: ${{ matrix.testname }}_inputfiles path: tests/${{ matrix.testname }}_inputfiles/results_md5* - - name: Set up Python - if: always() && matrix.testmode == 'OFF' - uses: actions/setup-python@v5 - with: - python-version: '3.12' - cache: pip - - - name: Install artistools - if: always() && matrix.testmode == 'OFF' - run: | - python3 -m pip install --upgrade pip uv - uv pip install --system artistools - - name: Plot light curve if: always() && matrix.testmode == 'OFF' working-directory: tests/ diff --git a/decay.cc b/decay.cc index a1ba84ee3..917cf073d 100644 --- a/decay.cc +++ b/decay.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "artisoptions.h" @@ -30,7 +31,6 @@ #include "globals.h" #include "grid.h" #include "input.h" -#include "nonthermal.h" #include "packet.h" #include "sn3d.h" @@ -65,7 +65,7 @@ std::vector nuclides; } // anonymous namespace -constexpr auto decay_daughter_z(const int z_parent, const int /*a_parent*/, const int decaytype) -> int +[[nodiscard]] constexpr auto decay_daughter_z(const int z_parent, const int /*a_parent*/, const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { assert_always(decaytype >= 0); @@ -92,7 +92,7 @@ constexpr auto decay_daughter_z(const int z_parent, const int /*a_parent*/, cons return -1; // no daughter } -constexpr auto decay_daughter_a(const int /*z_parent*/, const int a_parent, const int decaytype) -> int +[[nodiscard]] constexpr auto decay_daughter_a(const int /*z_parent*/, const int a_parent, const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { switch (static_cast(decaytype)) { @@ -140,26 +140,32 @@ double *decaypath_energy_per_mass{}; MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; #endif -auto get_num_nuclides() -> int { return static_cast(nuclides.size()); } +[[nodiscard]] auto get_num_nuclides() -> int { return static_cast(nuclides.size()); } -auto get_elname(const int z) -> std::string { +[[nodiscard]] auto get_elname(const int z) -> std::string { assert_testmodeonly(z <= Z_MAX); return std::string(elsymbols[z]); } -auto get_nuc_z(int nucindex) -> int { +[[nodiscard]] auto get_nuc_z(int nucindex) -> int { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return nuclides[nucindex].z; } -auto get_nuc_a(int nucindex) -> int { +[[nodiscard]] auto get_nuc_a(int nucindex) -> int { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return nuclides[nucindex].a; } -static auto get_nucindex_or_neg_one(int z, int a) -> int +[[nodiscard]] auto get_nuc_z_a(int nucindex) -> std::pair { + assert_testmodeonly(nucindex >= 0); + assert_testmodeonly(nucindex < get_num_nuclides()); + return {nuclides[nucindex].z, nuclides[nucindex].a}; +} + +[[nodiscard]] static auto get_nucindex_or_neg_one(int z, int a) -> int // get the nuclide array index from the atomic number and mass number { assert_testmodeonly(get_num_nuclides() > 0); @@ -173,7 +179,7 @@ static auto get_nucindex_or_neg_one(int z, int a) -> int return -1; // nuclide not found } -auto get_nucindex(int z, int a) -> int +[[nodiscard]] auto get_nucindex(int z, int a) -> int // get the nuclide array index from the atomic number and mass number { const int nucindex = get_nucindex_or_neg_one(z, a); @@ -185,7 +191,7 @@ auto get_nucindex(int z, int a) -> int return -1; } -auto nuc_exists(int z, int a) -> bool +[[nodiscard]] auto nuc_exists(int z, int a) -> bool // check if nuclide exists in the simulation { for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) { @@ -196,7 +202,7 @@ auto nuc_exists(int z, int a) -> bool return false; } -static auto get_meanlife(int nucindex) -> double { +[[nodiscard]] static auto get_meanlife(int nucindex) -> double { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return nuclides[nucindex].meanlife; @@ -216,7 +222,7 @@ static void printout_nuclidemeanlife(const int z, const int a) { } } -static auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> double { +[[nodiscard]] static auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> double { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); assert_testmodeonly(decaytype >= 0); @@ -224,11 +230,12 @@ static auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> return nuclides[nucindex].branchprobs[decaytype]; } -static auto get_nuc_decaybranchprob(const int z_parent, const int a_parent, const int decaytype) -> double { +[[nodiscard]] static auto get_nuc_decaybranchprob(const int z_parent, const int a_parent, + const int decaytype) -> double { return get_nuc_decaybranchprob(get_nucindex(z_parent, a_parent), decaytype); } -static auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool +[[nodiscard]] static auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool // check if (z_parent, a_parent) is a parent of (z, a) { assert_testmodeonly(nuc_exists(z_parent, a_parent)); @@ -238,12 +245,13 @@ static auto nuc_is_parent(const int z_parent, const int a_parent, const int z, c }); } -auto nucdecayenergygamma(int nucindex) -> double +[[nodiscard]] auto nucdecayenergygamma(int nucindex) -> double // average energy per decay in the form of gamma rays [erg] { return nuclides[nucindex].endecay_gamma; } -auto nucdecayenergygamma(int z, int a) -> double { return nucdecayenergygamma(get_nucindex(z, a)); } + +[[nodiscard]] auto nucdecayenergygamma(int z, int a) -> double { return nucdecayenergygamma(get_nucindex(z, a)); } void set_nucdecayenergygamma(int nucindex, double value) // set average energy per decay in the form of gamma rays [erg] @@ -251,7 +259,7 @@ void set_nucdecayenergygamma(int nucindex, double value) nuclides[nucindex].endecay_gamma = value; } -static auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double +[[nodiscard]] static auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double // decay energy in the form of kinetic energy of electrons, positrons, or alpha particles, // depending on the relevant decay type (but not including neutrinos) { @@ -277,7 +285,7 @@ static auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> d } } -static auto nucdecayenergytotal(const int z, const int a) -> double +[[nodiscard]] static auto nucdecayenergytotal(const int z, const int a) -> double // average energy (erg) per decay in the form of gammas and particles [erg] { const int nucindex = get_nucindex(z, a); @@ -289,7 +297,7 @@ static auto nucdecayenergytotal(const int z, const int a) -> double return nuclides[nucindex].endecay_gamma + endecay_particles; } -static auto nucdecayenergy(int nucindex, int decaytype) -> double +[[nodiscard]] static auto nucdecayenergy(int nucindex, int decaytype) -> double // contributed energy release per decay [erg] for decaytype (e.g. decaytypes::DECAYTYPE_BETAPLUS) // (excludes neutrinos!) { @@ -298,16 +306,20 @@ static auto nucdecayenergy(int nucindex, int decaytype) -> double return endecay; } -static auto nucdecayenergyqval(int nucindex, int decaytype) -> double { +[[nodiscard]] static auto nucdecayenergyqval(int nucindex, int decaytype) -> double { return nuclides[nucindex].endecay_q[decaytype]; } -static auto get_num_decaypaths() -> int { return static_cast(decaypaths.size()); } +[[nodiscard]] static auto get_num_decaypaths() -> int { return static_cast(decaypaths.size()); } -static auto get_decaypathlength(const DecayPath &dpath) -> int { return static_cast(dpath.z.size()); } -static auto get_decaypathlength(int decaypathindex) -> int { return get_decaypathlength(decaypaths[decaypathindex]); } +[[nodiscard]] static auto get_decaypathlength(const DecayPath &dpath) -> int { + return static_cast(dpath.z.size()); +} +[[nodiscard]] static auto get_decaypathlength(int decaypathindex) -> int { + return get_decaypathlength(decaypaths[decaypathindex]); +} -static auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> double { +[[nodiscard]] static auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> double { // return the product of all branching factors in the decay path double branchprod = 1.; @@ -318,7 +330,7 @@ static auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> dou return branchprod; } -static auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { +[[nodiscard]] static auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { // a decaypath's energy is the decay energy of the last nuclide and decaytype in the chain const int nucindex_end = dpath.nucindex.back(); @@ -326,7 +338,7 @@ static auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { return nucdecayenergy(nucindex_end, decaytype_end); } -static auto get_decaypath_lastnucdecayenergy(const int decaypathindex) -> double { +[[nodiscard]] static auto get_decaypath_lastnucdecayenergy(const int decaypathindex) -> double { return get_decaypath_lastnucdecayenergy(decaypaths[decaypathindex]); } @@ -892,8 +904,6 @@ static auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const int z_top = decaypaths[decaypathindex].z[0]; const int a_top = decaypaths[decaypathindex].a[0]; const int nucindex_top = decaypaths[decaypathindex].nucindex[0]; - // if it's a single-nuclide decay chain, then contribute the initial abundance, otherwise contribute - // all ancestors const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); if (top_initabund <= 0.) { @@ -911,13 +921,6 @@ static auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, calculate_decaychain(top_initabund, decaypaths[decaypathindex].lambdas, decaypathlength + 1, t_afterinit, false); const double ndecays_remaining = decaypaths[decaypathindex].branchproduct * (top_initabund - abund_endplusone); - // // alternative: add up the ancestor abundances that will eventually cause decays at the end of chain - // double ndecays_remaining = 0.; - // for (int c = 1; c <= decaypathlength; c++) - // { - // ndecays_remaining += calculate_decaychain(top_initabund, decaypaths[decaypathindex].lambdas, c, t_afterinit); - // } - const double endecay = ndecays_remaining * get_decaypath_lastnucdecayenergy(decaypathindex); return endecay; @@ -1138,14 +1141,14 @@ void free_decaypath_energy_per_mass() { #endif } -auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) -> double +[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) -> double // energy release rate in form of kinetic energy of positrons, electrons, and alpha particles in [erg/s/g] { double dep_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { - const int z = get_nuc_z(nucindex); - const int a = get_nuc_a(nucindex); + const auto [z, a] = get_nuc_z_a(nucindex); + const double meanlife = get_meanlife(nucindex); if (meanlife < 0.) { continue; @@ -1154,7 +1157,7 @@ auto get_particle_injection_rate(const int modelgridindex, const double t, const if (en_particles > 0.) { const double nucdecayrate = get_nuc_massfrac(modelgridindex, z, a, t) / meanlife * get_nuc_decaybranchprob(nucindex, decaytype); - assert_always(nucdecayrate >= 0); + assert_testmodeonly(nucdecayrate >= 0); dep_sum += nucdecayrate * en_particles / nucmass(z, a); } } @@ -1164,14 +1167,38 @@ auto get_particle_injection_rate(const int modelgridindex, const double t, const return dep_sum; } -auto get_qdot_modelcell(const int modelgridindex, const double t, const int decaytype) -> double +[[nodiscard]] auto get_gamma_emission_rate(const int modelgridindex, const double t) -> double +// energy release rate in form of gamma-rays in [erg/s/g] +{ + double eps_gamma_sum = 0.; + const auto num_nuclides = get_num_nuclides(); + for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { + const auto [z, a] = get_nuc_z_a(nucindex); + + const double meanlife = get_meanlife(nucindex); + if (meanlife < 0.) { + continue; + } + const double en_gamma = nucdecayenergygamma(nucindex); + if (en_gamma > 0.) { + const double nucdecayrate = get_nuc_massfrac(modelgridindex, z, a, t) / meanlife; + assert_testmodeonly(nucdecayrate >= 0); + eps_gamma_sum += nucdecayrate * en_gamma / nucmass(z, a); + } + } + + assert_always(std::isfinite(eps_gamma_sum)); + + return eps_gamma_sum; +} + +[[nodiscard]] auto get_qdot_modelcell(const int modelgridindex, const double t, const int decaytype) -> double // energy release rate [erg/s/g] including everything (even neutrinos that are ignored elsewhere) { double qdot = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { - const int z = get_nuc_z(nucindex); - const int a = get_nuc_a(nucindex); + const auto [z, a] = get_nuc_z_a(nucindex); const double meanlife = get_meanlife(nucindex); if (meanlife < 0.) { continue; @@ -1217,8 +1244,7 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl double isomassfrac_on_nucmass_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { - const int nuc_z = get_nuc_z(nucindex); - const int a = get_nuc_a(nucindex); + const auto [nuc_z, a] = get_nuc_z_a(nucindex); if (nuc_z == atomic_number) { // this nucleus is an isotope of the element if (!a_isotopes.contains(a)) { @@ -1281,8 +1307,7 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl // double nucfracsum = 0.; // for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) // { - // const int z = get_nuc_z(nucindex); - // const int a = get_nuc_a(nucindex); + // const auto [z, a] = get_nuc_z_a(nucindex); // initnucfracsum += grid::get_modelinitradioabund(modelgridindex, z, a); // nucfracsum += get_nuc_massfrac(modelgridindex, z, a, t_current); // @@ -1309,8 +1334,6 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl // printout("nucfracsum %g\n", nucfracsum); // assert_always(fabs(nucfracsum - initnucfracsum) < 0.001); // decays shouldn't change nuclear mass fraction sum - - nonthermal::calculate_deposition_rate_density(modelgridindex, timestep); } void fprint_nuc_abundances(FILE *estimators_file, const int modelgridindex, const double t_current, const int element) { @@ -1320,8 +1343,7 @@ void fprint_nuc_abundances(FILE *estimators_file, const int modelgridindex, cons std::set a_isotopes; // ensure we don't repeat isotopes const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { - const int nuc_z = get_nuc_z(nucindex); - const int nuc_a = get_nuc_a(nucindex); + const auto [nuc_z, nuc_a] = get_nuc_z_a(nucindex); if (nuc_z == atomic_number) { // isotope of this element is on the network if (!a_isotopes.contains(nuc_a)) { a_isotopes.insert(nuc_a); diff --git a/decay.h b/decay.h index 2f7b89c23..47ff5e24e 100644 --- a/decay.h +++ b/decay.h @@ -44,6 +44,7 @@ void setup_decaypath_energy_per_mass(); void free_decaypath_energy_per_mass(); [[nodiscard]] auto get_qdot_modelcell(int modelgridindex, double t, int decaytype) -> double; [[nodiscard]] auto get_particle_injection_rate(int modelgridindex, double t, int decaytype) -> double; +[[nodiscard]] auto get_gamma_emission_rate(int modelgridindex, double t) -> double; [[nodiscard]] auto get_global_etot_t0_tinf() -> double; void fprint_nuc_abundances(FILE *estimators_file, int modelgridindex, double t_current, int element); void setup_radioactive_pellet(double e0, int mgi, Packet &pkt); diff --git a/exspec.cc b/exspec.cc index a56983460..ba680ffaa 100644 --- a/exspec.cc +++ b/exspec.cc @@ -1,8 +1,5 @@ #include "exspec.h" -#include -#include - #include #include #include @@ -59,7 +56,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra snprintf(pktfilename, MAXFILENAMELENGTH, "packets%.2d_%.4d.out", 0, p); printout("reading %s (file %d of %d)\n", pktfilename, p + 1, globals::nprocs_exspec); - if (access(pktfilename, F_OK) == 0) { + if (std::filesystem::exists(pktfilename)) { read_packets(pktfilename, pkts_start); } else { printout(" WARNING %s does not exist - trying temp packets file at beginning of timestep %d...\n", diff --git a/gammapkt.cc b/gammapkt.cc index 3072bb576..d3da0d9e6 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -241,24 +241,6 @@ void init_gamma_data() { } } -void normalise(int nts) { - const double dt = globals::timesteps[nts].width; - globals::timesteps[nts].gamma_dep_pathint = 0.; - for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - - const double dV = grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts].mid / globals::tmin, 3); - - globals::timesteps[nts].gamma_dep_pathint += globals::dep_estimator_gamma[nonemptymgi] / globals::nprocs; - - globals::dep_estimator_gamma[nonemptymgi] = - globals::dep_estimator_gamma[nonemptymgi] * ONEOVER4PI / dV / dt / globals::nprocs; - - assert_testmodeonly(globals::dep_estimator_gamma[nonemptymgi] >= 0.); - assert_testmodeonly(std::isfinite(globals::dep_estimator_gamma[nonemptymgi])); - } -} - static auto choose_gamma_ray(const int nucindex) -> double { // Routine to choose which gamma ray line it'll be. @@ -557,7 +539,7 @@ static void compton_scatter(Packet &pkt) pkt.last_cross = BOUNDARY_NONE; // allow it to re-cross a boundary } else { // It's converted to an e-minus packet. - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -3; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } @@ -794,7 +776,7 @@ void pair_prod(Packet &pkt) { if (rng_uniform() > prob_gamma) { // Convert it to an e-minus packet - actually it could be positron EK too, but this works // for consistency with compton_scatter. - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -5; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } else { @@ -944,7 +926,7 @@ void transport_gamma(Packet &pkt, double t2) compton_scatter(pkt); } else if ((chi_compton + chi_photo_electric) > chi_rnd) { // Photo electric effect - makes it a k-packet for sure. - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -4; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } else if ((chi_compton + chi_photo_electric + chi_pair_prod) > chi_rnd) { @@ -995,7 +977,7 @@ void barnes_thermalisation(Packet &pkt) // either absorb packet or let it escape if (rng_uniform() < f_gamma) { // packet is absorbed and contributes to the heating as a k-packet - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -4; } else { // let packet escape, i.e. make it inactive @@ -1035,8 +1017,9 @@ void wollaeger_thermalisation(Packet &pkt) { // either absorb packet or let it escape if (rng_uniform() < f_gamma) { // packet is absorbed and contributes to the heating as a k-packet - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -4; + } else { // let packet escape, i.e. make it inactive pkt.type = TYPE_ESCAPE; @@ -1044,7 +1027,7 @@ void wollaeger_thermalisation(Packet &pkt) { } } -void do_gamma(Packet &pkt, double t2) { +void do_gamma(Packet &pkt, const int nts, double t2) { if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::DETAILED) { transport_gamma(pkt, t2); } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::BARNES) { @@ -1054,6 +1037,17 @@ void do_gamma(Packet &pkt, double t2) { } else { __builtin_unreachable(); } + + if (pkt.type != TYPE_GAMMA && pkt.type != TYPE_ESCAPE) { + atomicadd(globals::timesteps[nts].gamma_dep_discrete, pkt.e_cmf); + + if constexpr (GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILED) { + // no transport, so the path-based gamma deposition estimator won't get updated unless we do it here + const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + atomicadd(globals::dep_estimator_gamma[nonemptymgi], pkt.e_cmf); + } + } } } // namespace gammapkt diff --git a/gammapkt.h b/gammapkt.h index d38c4497f..fbe1f50c1 100644 --- a/gammapkt.h +++ b/gammapkt.h @@ -7,8 +7,7 @@ namespace gammapkt { void init_gamma_data(); void pellet_gamma_decay(Packet &pkt); -void do_gamma(Packet &pkt, double t2); -void normalise(int nts); +void do_gamma(Packet &pkt, int nts, double t2); } // namespace gammapkt diff --git a/globals.h b/globals.h index 11d162378..97dddd7ea 100644 --- a/globals.h +++ b/globals.h @@ -15,25 +15,29 @@ #include "artisoptions.h" struct TimeStep { - double start; // time at start of this timestep. [s] - double width; // Width of timestep. [s] - double mid; // Mid time in step - computed logarithmically. [s] - double gamma_dep; // cmf gamma ray energy deposition from absorption events [erg] - double gamma_dep_pathint; // cmf gamma ray energy deposition from packet trajectories [erg] - double positron_dep; // cmf positron energy deposition [erg] - double eps_positron_ana_power; // cmf positron KE energy generation rate analytical [erg/s] - double electron_dep; // cmf electron energy deposition [erg] - double electron_emission; // cmf electron KE energy generation [erg] - double eps_electron_ana_power; // cmf electron KE energy generation rate analytical [erg/s] - double alpha_dep; // cmf alpha energy deposition [erg] - double alpha_emission; // cmf alpha KE energy generation [erg] - double eps_alpha_ana_power; // cmf alpha KE energy generation rate analytical [erg/s] - double gamma_emission; // gamma decay energy generation in this timestep [erg] - double qdot_betaminus; // energy generation from beta-minus decays (including neutrinos) [erg/s/g] - double qdot_alpha; // energy generation from alpha decays (including neutrinos) [erg/s/g] - double qdot_total; // energy generation from all decays (including neutrinos) [erg/s/g] - double cmf_lum; // cmf luminosity light curve [erg] - int pellet_decays; // Number of pellets that decay in this time step. + double start{0.}; // time at start of this timestep. [s] + double width{0.}; // Width of timestep. [s] + double mid{0.}; // Mid time in step - computed logarithmically. [s] + double gamma_dep{0.}; // cmf gamma ray energy deposition from packet trajectories [erg] + double gamma_dep_discrete{0.}; // cmf gamma ray energy deposition from absorption events [erg] + double positron_dep{0.}; // cmf positron energy deposition from packet trajectories [erg] + double positron_dep_discrete{0.}; // cmf positron energy deposition from absorption events [erg] + double positron_emission{0.}; // cmf positron KE energy generation [erg] + double eps_positron_ana_power{0.}; // cmf positron KE energy generation rate analytical [erg/s] + double electron_dep{0.}; // cmf electron energy deposition from packet trajectories [erg] + double electron_dep_discrete{0.}; // cmf electron energy deposition from absorption events [erg] + double electron_emission{0.}; // cmf electron KE energy generation [erg] + double eps_electron_ana_power{0.}; // cmf electron KE energy generation rate analytical [erg/s] + double alpha_dep{0.}; // cmf alpha energy deposition from packet trajectories [erg] + double alpha_dep_discrete{0.}; // cmf alpha energy deposition from absorption events [erg] + double alpha_emission{0.}; // cmf alpha KE energy generation [erg] + double eps_alpha_ana_power{0.}; // cmf alpha KE energy generation rate analytical [erg/s] + double gamma_emission{0.}; // gamma decay energy generation in this timestep [erg] + double qdot_betaminus{0.}; // energy generation from beta-minus decays (including neutrinos) [erg/s/g] + double qdot_alpha{0.}; // energy generation from alpha decays (including neutrinos) [erg/s/g] + double qdot_total{0.}; // energy generation from all decays (including neutrinos) [erg/s/g] + double cmf_lum{0.}; // cmf luminosity light curve [erg] + int pellet_decays{0}; // Number of pellets that decay in this time step. }; struct BFListEntry { @@ -83,9 +87,9 @@ struct EnergyLevel { int nuptrans{0}; int ndowntrans{0}; PhotoionTarget *phixstargets{}; /// pointer to table of target states and probabilities - float *photoion_xs{}; /// Pointer to a lookup-table providing photoionisation cross-sections for this level. - int nphixstargets{0}; /// length of phixstargets array: - float stat_weight{0}; /// Statistical weight of this level. + float *photoion_xs{}; /// Pointer to a lookup-table providing photoionisation cross-sections for this level. + int nphixstargets{0}; /// length of phixstargets array: + float stat_weight{0.}; /// Statistical weight of this level. int cont_index{-1}; /// Index of the continuum associated to this level. Negative number. int closestgroundlevelcont{-1}; @@ -208,7 +212,12 @@ inline std::array syn_dir{}; // vector pointing from origin to obser inline std::vector timesteps; +// deposition estimators index by non-empty modelgridindex +// after normalisation factor has been applied, units will be erg/s/cm3 inline std::vector dep_estimator_gamma; +inline std::vector dep_estimator_positron; +inline std::vector dep_estimator_electron; +inline std::vector dep_estimator_alpha; inline int bfestimcount{0}; diff --git a/grid.cc b/grid.cc index aa379027d..3ddc27b4c 100644 --- a/grid.cc +++ b/grid.cc @@ -991,16 +991,19 @@ static void allocate_nonemptymodelcells() { allocate_expansionopacities(); } - globals::dep_estimator_gamma.resize(get_nonempty_npts_model(), 0.); + globals::dep_estimator_gamma.resize(nonempty_npts_model, 0.); + globals::dep_estimator_positron.resize(nonempty_npts_model, 0.); + globals::dep_estimator_electron.resize(nonempty_npts_model, 0.); + globals::dep_estimator_alpha.resize(nonempty_npts_model, 0.); - auto ionestimsize = get_nonempty_npts_model() * globals::nbfcontinua_ground * sizeof(double); + auto ionestimsize = nonempty_npts_model * globals::nbfcontinua_ground * sizeof(double); if (USE_LUT_PHOTOION && ionestimsize > 0) { #ifdef MPI_ON - auto my_rank_cells = get_nonempty_npts_model() / globals::node_nprocs; + auto my_rank_cells = nonempty_npts_model / globals::node_nprocs; // rank_in_node 0 gets any remainder if (globals::rank_in_node == 0) { - my_rank_cells += get_nonempty_npts_model() - (my_rank_cells * globals::node_nprocs); + my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); } auto size = static_cast(my_rank_cells * globals::nbfcontinua_ground * sizeof(double)); @@ -1038,11 +1041,11 @@ static void allocate_nonemptymodelcells() { #endif } - globals::ffheatingestimator = static_cast(malloc(get_nonempty_npts_model() * sizeof(double))); - globals::colheatingestimator = static_cast(malloc(get_nonempty_npts_model() * sizeof(double))); + globals::ffheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::colheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); #ifdef DO_TITER - globals::ffheatingestimator_save = static_cast(malloc(get_nonempty_npts_model() * sizeof(double))); - globals::colheatingestimator_save = static_cast(malloc(get_nonempty_npts_model() * sizeof(double))); + globals::ffheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::colheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); #endif #ifdef MPI_ON @@ -1774,15 +1777,18 @@ static void read_grid_restart_data(const int timestep) { for (int nts = 0; nts < globals::ntimesteps; nts++) { int pellet_decays = 0.; - assert_always(fscanf(gridsave_file, "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", - &globals::timesteps[nts].gamma_dep, &globals::timesteps[nts].gamma_dep_pathint, - &globals::timesteps[nts].positron_dep, &globals::timesteps[nts].eps_positron_ana_power, - &globals::timesteps[nts].electron_dep, &globals::timesteps[nts].electron_emission, - &globals::timesteps[nts].eps_electron_ana_power, &globals::timesteps[nts].alpha_dep, + assert_always(fscanf(gridsave_file, + "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", + &globals::timesteps[nts].gamma_dep, &globals::timesteps[nts].gamma_dep_discrete, + &globals::timesteps[nts].positron_dep, &globals::timesteps[nts].positron_dep_discrete, + &globals::timesteps[nts].positron_emission, &globals::timesteps[nts].eps_positron_ana_power, + &globals::timesteps[nts].electron_dep, &globals::timesteps[nts].electron_dep_discrete, + &globals::timesteps[nts].electron_emission, &globals::timesteps[nts].eps_electron_ana_power, + &globals::timesteps[nts].alpha_dep, &globals::timesteps[nts].alpha_dep_discrete, &globals::timesteps[nts].alpha_emission, &globals::timesteps[nts].eps_alpha_ana_power, &globals::timesteps[nts].qdot_betaminus, &globals::timesteps[nts].qdot_alpha, &globals::timesteps[nts].qdot_total, &globals::timesteps[nts].gamma_emission, - &globals::timesteps[nts].cmf_lum, &pellet_decays) == 16); + &globals::timesteps[nts].cmf_lum, &pellet_decays) == 20); globals::timesteps[nts].pellet_decays = pellet_decays; } @@ -1851,11 +1857,13 @@ void write_grid_restart_data(const int timestep) { fprintf(gridsave_file, "%d ", globals::nprocs); for (int nts = 0; nts < globals::ntimesteps; nts++) { - fprintf(gridsave_file, "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", - globals::timesteps[nts].gamma_dep, globals::timesteps[nts].gamma_dep_pathint, - globals::timesteps[nts].positron_dep, globals::timesteps[nts].eps_positron_ana_power, - globals::timesteps[nts].electron_dep, globals::timesteps[nts].electron_emission, - globals::timesteps[nts].eps_electron_ana_power, globals::timesteps[nts].alpha_dep, + fprintf(gridsave_file, "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", + globals::timesteps[nts].gamma_dep, globals::timesteps[nts].gamma_dep_discrete, + globals::timesteps[nts].positron_emission, globals::timesteps[nts].positron_dep, + globals::timesteps[nts].positron_dep_discrete, globals::timesteps[nts].eps_positron_ana_power, + globals::timesteps[nts].electron_dep, globals::timesteps[nts].electron_dep_discrete, + globals::timesteps[nts].electron_emission, globals::timesteps[nts].eps_electron_ana_power, + globals::timesteps[nts].alpha_dep, globals::timesteps[nts].alpha_dep_discrete, globals::timesteps[nts].alpha_emission, globals::timesteps[nts].eps_alpha_ana_power, globals::timesteps[nts].qdot_betaminus, globals::timesteps[nts].qdot_alpha, globals::timesteps[nts].qdot_total, globals::timesteps[nts].gamma_emission, globals::timesteps[nts].cmf_lum, diff --git a/input.cc b/input.cc index 8cb92b3fb..7e8a4c32a 100644 --- a/input.cc +++ b/input.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1991,6 +1992,9 @@ void time_init() /// globals::ntimesteps is the number of time steps globals::timesteps.resize(globals::ntimesteps + 1); + for (auto &ts : globals::timesteps) { + ts = TimeStep{}; + } /// Now set the individual time steps switch (TIMESTEP_SIZE_METHOD) { @@ -2120,25 +2124,6 @@ void time_init() globals::tmax) - 1 < 0.001); - - for (int n = 0; n < globals::ntimesteps; n++) { - globals::timesteps[n].positron_dep = 0.; - globals::timesteps[n].eps_positron_ana_power = 0.; - globals::timesteps[n].electron_dep = 0.; - globals::timesteps[n].electron_emission = 0.; - globals::timesteps[n].eps_electron_ana_power = 0.; - globals::timesteps[n].alpha_dep = 0.; - globals::timesteps[n].alpha_emission = 0.; - globals::timesteps[n].eps_alpha_ana_power = 0.; - globals::timesteps[n].gamma_dep = 0.; - globals::timesteps[n].gamma_dep_pathint = 0.; - globals::timesteps[n].qdot_betaminus = 0.; - globals::timesteps[n].qdot_alpha = 0.; - globals::timesteps[n].qdot_total = 0.; - globals::timesteps[n].gamma_emission = 0.; - globals::timesteps[n].cmf_lum = 0.; - globals::timesteps[n].pellet_decays = 0; - } } void write_timestep_file() { diff --git a/nonthermal.cc b/nonthermal.cc index 0016da9f3..3c0960846 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -37,6 +37,7 @@ #include "packet.h" #include "sn3d.h" #include "stats.h" +#include "thermalbalance.h" namespace nonthermal { @@ -2039,44 +2040,53 @@ void init(const int my_rank, const int ndo_nonempty) { printout("Finished initializing non-thermal solver\n"); } -void calculate_deposition_rate_density(const int modelgridindex, const int timestep) -// should be in erg / s / cm^3 +void calculate_deposition_rate_density(const int modelgridindex, const int timestep, + HeatingCoolingRates *heatingcoolingrates) +// set total non-thermal deposition rate from individual gamma/positron/electron/alpha rates. This should be called +// after packet propagation is finished for this timestep and normalise_deposition_estimators() has been done { const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - const double gamma_deposition = globals::dep_estimator_gamma[nonemptymgi] * FOURPI; + heatingcoolingrates->dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; const double tmid = globals::timesteps[timestep].mid; const double rho = grid::get_rho(modelgridindex); - // TODO: calculate thermalisation ratio from the previous timestep either globally (easy) or per cell - // f = E_dep / E_rad + // if INSTANT_PARTICLE_DEPOSITION, use the analytic rate at t_mid since it will have no Monte Carlo noise (although + // strictly, it should be an integral from the timestep start to the end) + // with time-dependent deposition, we don't have an analytic rate, so we use the Monte Carlo rate + assert_always(heatingcoolingrates != nullptr); - // convert from [erg/s/g] to [erg/s/cm3] - const double positron_deposition = + heatingcoolingrates->eps_gamma_ana = rho * decay::get_gamma_emission_rate(modelgridindex, tmid); + + heatingcoolingrates->eps_positron_ana = rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_BETAPLUS); - const double electron_deposition = - rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_BETAMINUS); + heatingcoolingrates->eps_electron_ana = + (rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_BETAMINUS)); - const double alpha_deposition = + heatingcoolingrates->eps_alpha_ana = rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_ALPHA); - deposition_rate_density[modelgridindex] = - (gamma_deposition + positron_deposition + electron_deposition + alpha_deposition); + if (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::INSTANT) { + heatingcoolingrates->dep_positron = heatingcoolingrates->eps_positron_ana; + heatingcoolingrates->dep_electron = heatingcoolingrates->eps_electron_ana; + heatingcoolingrates->dep_alpha = heatingcoolingrates->eps_alpha_ana; + } else { + heatingcoolingrates->dep_positron = globals::dep_estimator_positron[nonemptymgi]; + heatingcoolingrates->dep_electron = globals::dep_estimator_electron[nonemptymgi]; + heatingcoolingrates->dep_alpha = globals::dep_estimator_alpha[nonemptymgi]; + } - printout( - "deposition rates [eV/s/cm^3] for timestep %d mgi %d: gamma %8.2e (Monte Carlo), positron %8.2e elec %8.2e alpha " - "%8.2e (analytic t_mid)\n", - timestep, modelgridindex, gamma_deposition / EV, positron_deposition / EV, electron_deposition / EV, - alpha_deposition / EV); + deposition_rate_density[modelgridindex] = (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + + heatingcoolingrates->dep_electron + heatingcoolingrates->dep_alpha); deposition_rate_density_timestep[modelgridindex] = timestep; } auto get_deposition_rate_density(const int modelgridindex) -> double -// should be in erg / s / cm^3 +// get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() { - assert_always(deposition_rate_density_timestep[modelgridindex] == globals::timestep); + assert_testmodeonly(deposition_rate_density_timestep[modelgridindex] == globals::timestep); assert_always(deposition_rate_density[modelgridindex] >= 0); return deposition_rate_density[modelgridindex]; } @@ -2294,7 +2304,7 @@ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const return ratecoeffperdeposition * deposition_rate_density; } -void do_ntlepton(Packet &pkt) { +void do_ntlepton_deposit(Packet &pkt) { atomicadd(nt_energy_deposited, pkt.e_cmf); const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); diff --git a/nonthermal.h b/nonthermal.h index e898779bc..e54bcec12 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -5,6 +5,7 @@ #include #include "packet.h" +#include "thermalbalance.h" namespace nonthermal { void init(int my_rank, int ndo_nonempty); @@ -15,12 +16,12 @@ void solve_spencerfano(int modelgridindex, int timestep, int iteration); bool energyweighted) -> double; [[nodiscard]] auto nt_ionisation_maxupperion(int element, int lowerion) -> int; [[nodiscard]] auto nt_random_upperion(int modelgridindex, int element, int lowerion, bool energyweighted) -> int; -void calculate_deposition_rate_density(int modelgridindex, int timestep); +void calculate_deposition_rate_density(int modelgridindex, int timestep, HeatingCoolingRates *heatingcoolingrates); [[nodiscard]] auto get_deposition_rate_density(int modelgridindex) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; [[nodiscard]] auto nt_excitation_ratecoeff(int modelgridindex, int element, int ion, int lowerlevel, int uptransindex, double epsilon_trans, int lineindex) -> double; -void do_ntlepton(Packet &pkt); +void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); void nt_MPI_Bcast(int modelgridindex, int root, int my_rank); diff --git a/packet.h b/packet.h index cc1f8a8c4..45ad07e14 100644 --- a/packet.h +++ b/packet.h @@ -12,8 +12,10 @@ enum packet_type : int { TYPE_RPKT = 11, TYPE_KPKT = 12, TYPE_MA = 13, - TYPE_NTLEPTON = 20, - TYPE_NONTHERMAL_PREDEPOSIT = 21, + TYPE_NTLEPTON_DEPOSITED = 20, + TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS = 21, + TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS = 22, + TYPE_NONTHERMAL_PREDEPOSIT_ALPHA = 23, TYPE_PRE_KPKT = 120, }; diff --git a/sn3d.cc b/sn3d.cc index 0ecd0565d..5d05f189e 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -17,10 +17,10 @@ #endif #include -#include #include #include +#include #include #include #include @@ -37,7 +37,6 @@ #include "atomic.h" #include "constants.h" #include "decay.h" -#include "gammapkt.h" #include "globals.h" #include "grid.h" #include "input.h" @@ -176,11 +175,11 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c if (my_rank == 0) { FILE *dep_file = fopen_required("deposition.out.tmp", "w"); - fprintf( - dep_file, - "#ts tmid_days tmid_s total_dep_Lsun gammadep_Lsun gammadeppathint_Lsun positrondep_Lsun eps_positron_ana_Lsun " - "elecdep_Lsun eps_elec_Lsun eps_elec_ana_Lsun alphadep_Lsun eps_alpha_Lsun eps_alpha_ana_Lsun eps_gamma_Lsun " - "Qdot_betaminus_ana_erg/s/g Qdotalpha_ana_erg/s/g eps_erg/s/g Qdot_ana_erg/s/g\n"); + fprintf(dep_file, + "#ts tmid_days tmid_s total_dep_Lsun gammadep_discrete_Lsun gammadep_Lsun positrondep_Lsun " + "eps_positron_ana_Lsun elecdep_Lsun eps_elec_Lsun eps_elec_ana_Lsun alphadep_Lsun eps_alpha_Lsun " + "eps_alpha_ana_Lsun eps_gamma_Lsun Qdot_betaminus_ana_erg/s/g Qdotalpha_ana_erg/s/g eps_erg/s/g " + "Qdot_ana_erg/s/g positrondep_discrete_Lsun elecdep_discrete_Lsun alphadep_discrete_Lsun\n"); for (int i = 0; i <= nts; i++) { const double t_mid = globals::timesteps[i].mid; @@ -188,21 +187,22 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c const double total_dep = (globals::timesteps[i].gamma_dep + globals::timesteps[i].positron_dep + globals::timesteps[i].electron_dep + globals::timesteps[i].alpha_dep); - // dep is used here for positrons and alphas because it is the same as the emission rate - const double epsilon_mc = (globals::timesteps[i].gamma_emission + globals::timesteps[i].positron_dep + - globals::timesteps[i].electron_emission + globals::timesteps[i].alpha_emission) / - mtot / t_width; + const double epsilon = (globals::timesteps[i].gamma_emission + globals::timesteps[i].positron_emission + + globals::timesteps[i].electron_emission + globals::timesteps[i].alpha_emission) / + mtot / t_width; - fprintf(dep_file, "%d %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n", i, t_mid / DAY, t_mid, - total_dep / t_width / LSUN, globals::timesteps[i].gamma_dep / t_width / LSUN, - globals::timesteps[i].gamma_dep_pathint / t_width / LSUN, - globals::timesteps[i].positron_dep / t_width / LSUN, globals::timesteps[i].eps_positron_ana_power / LSUN, - globals::timesteps[i].electron_dep / t_width / LSUN, + fprintf(dep_file, "%d %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n", i, t_mid / DAY, t_mid, + total_dep / t_width / LSUN, globals::timesteps[i].gamma_dep_discrete / t_width / LSUN, + globals::timesteps[i].gamma_dep / t_width / LSUN, globals::timesteps[i].positron_dep / t_width / LSUN, + globals::timesteps[i].eps_positron_ana_power / LSUN, globals::timesteps[i].electron_dep / t_width / LSUN, globals::timesteps[i].electron_emission / t_width / LSUN, globals::timesteps[i].eps_electron_ana_power / LSUN, globals::timesteps[i].alpha_dep / t_width / LSUN, globals::timesteps[i].alpha_emission / t_width / LSUN, globals::timesteps[i].eps_alpha_ana_power / LSUN, globals::timesteps[i].gamma_emission / t_width / LSUN, globals::timesteps[i].qdot_betaminus / mtot, - globals::timesteps[i].qdot_alpha / mtot, epsilon_mc, globals::timesteps[i].qdot_total / mtot); + globals::timesteps[i].qdot_alpha / mtot, epsilon, globals::timesteps[i].qdot_total / mtot, + globals::timesteps[i].positron_dep_discrete / t_width / LSUN, + globals::timesteps[i].electron_dep_discrete / t_width / LSUN, + globals::timesteps[i].alpha_dep_discrete / t_width / LSUN); } fclose(dep_file); @@ -396,26 +396,44 @@ void mpi_reduce_estimators(int nts) { assert_always(static_cast(globals::dep_estimator_gamma.size()) == nonempty_npts_model); MPI_Allreduce(MPI_IN_PLACE, globals::dep_estimator_gamma.data(), nonempty_npts_model, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + assert_always(static_cast(globals::dep_estimator_positron.size()) == nonempty_npts_model); + MPI_Allreduce(MPI_IN_PLACE, globals::dep_estimator_positron.data(), nonempty_npts_model, MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); + assert_always(static_cast(globals::dep_estimator_electron.size()) == nonempty_npts_model); + MPI_Allreduce(MPI_IN_PLACE, globals::dep_estimator_electron.data(), nonempty_npts_model, MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); + assert_always(static_cast(globals::dep_estimator_alpha.size()) == nonempty_npts_model); + MPI_Allreduce(MPI_IN_PLACE, globals::dep_estimator_alpha.data(), nonempty_npts_model, MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); /// Communicate gamma and positron deposition and write to file MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].cmf_lum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].gamma_dep, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].positron_dep, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].electron_dep, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].electron_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].alpha_dep, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].alpha_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].gamma_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - globals::timesteps[nts].cmf_lum /= globals::nprocs; - globals::timesteps[nts].gamma_dep /= globals::nprocs; - globals::timesteps[nts].positron_dep /= globals::nprocs; - globals::timesteps[nts].electron_dep /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].gamma_dep_discrete, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + globals::timesteps[nts].gamma_dep_discrete /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].positron_dep_discrete, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + globals::timesteps[nts].positron_dep_discrete /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].positron_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + globals::timesteps[nts].positron_emission /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].electron_dep_discrete, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + globals::timesteps[nts].electron_dep_discrete /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].electron_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); globals::timesteps[nts].electron_emission /= globals::nprocs; - globals::timesteps[nts].alpha_dep /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].alpha_dep_discrete, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + globals::timesteps[nts].alpha_dep_discrete /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].alpha_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); globals::timesteps[nts].alpha_emission /= globals::nprocs; + + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].gamma_emission, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); globals::timesteps[nts].gamma_emission /= globals::nprocs; if constexpr (TRACK_ION_STATS) { @@ -458,7 +476,7 @@ void remove_temp_packetsfile(const int timestep, const int my_rank) { char filename[MAXFILENAMELENGTH]; snprintf(filename, MAXFILENAMELENGTH, "packets_%.4d_ts%d.tmp", my_rank, timestep); - if (access(filename, F_OK) == 0) { + if (std::filesystem::exists(filename)) { std::remove(filename); printout("Deleted %s\n", filename); } @@ -468,7 +486,7 @@ void remove_grid_restart_data(const int timestep) { char prevfilename[MAXFILENAMELENGTH]; snprintf(prevfilename, MAXFILENAMELENGTH, "gridsave_ts%d.tmp", timestep); - if (access(prevfilename, F_OK) == 0) { + if (std::filesystem::exists(prevfilename)) { std::remove(prevfilename); printout("Deleted %s\n", prevfilename); } @@ -606,6 +624,40 @@ void zero_estimators() { #endif } +void normalise_deposition_estimators(int nts) { + const double dt = globals::timesteps[nts].width; + const auto nprocs = globals::nprocs; + + globals::timesteps[nts].gamma_dep = 0.; + globals::timesteps[nts].positron_dep = 0.; + globals::timesteps[nts].electron_dep = 0.; + globals::timesteps[nts].alpha_dep = 0.; + + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); + + const double dV = + grid::get_modelcell_assocvolume_tmin(mgi) * std::pow(globals::timesteps[nts].mid / globals::tmin, 3); + + // contribute the energy deposited (in erg) by each process in this cell to the timestep total + globals::timesteps[nts].gamma_dep += globals::dep_estimator_gamma[nonemptymgi] / nprocs; + globals::timesteps[nts].positron_dep += globals::dep_estimator_positron[nonemptymgi] / nprocs; + globals::timesteps[nts].electron_dep += globals::dep_estimator_electron[nonemptymgi] / nprocs; + globals::timesteps[nts].alpha_dep += globals::dep_estimator_alpha[nonemptymgi] / nprocs; + + // normalise the estimators to units of erg/s/cm^3 + const double estimator_normfactor = 1 / dV / dt / nprocs; + + globals::dep_estimator_gamma[nonemptymgi] *= estimator_normfactor; + globals::dep_estimator_positron[nonemptymgi] *= estimator_normfactor; + globals::dep_estimator_electron[nonemptymgi] *= estimator_normfactor; + globals::dep_estimator_alpha[nonemptymgi] *= estimator_normfactor; + + assert_testmodeonly(globals::dep_estimator_gamma[nonemptymgi] >= 0.); + assert_testmodeonly(std::isfinite(globals::dep_estimator_gamma[nonemptymgi])); + } +} + auto do_timestep(const int nts, const int titer, const int my_rank, const int nstart, const int ndo, Packet *packets, const int walltimelimitseconds) -> bool { bool do_this_full_loop = true; @@ -676,20 +728,20 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns mpi_reduce_estimators(nts); #endif +#ifdef MPI_ON + printout("timestep %d: time after estimators have been communicated %ld (took %ld seconds)\n", nts, + std::time(nullptr), std::time(nullptr) - time_communicate_estimators_start); +#endif + // The estimators have been summed across all proceses and distributed. - // They will now be normalised independently on all processes + // They will now be normalised independently on all processes. - gammapkt::normalise(nts); + normalise_deposition_estimators(nts); write_deposition_file(nts, my_rank, nstart, ndo); write_partial_lightcurve_spectra(my_rank, nts, packets); -#ifdef MPI_ON - printout("timestep %d: time after estimators have been communicated %ld (took %ld seconds)\n", nts, - std::time(nullptr), std::time(nullptr) - time_communicate_estimators_start); -#endif - printout("During timestep %d on MPI process %d, %d pellets decayed and %d packets escaped. (t=%gd)\n", nts, my_rank, globals::timesteps[nts].pellet_decays, globals::nesc, globals::timesteps[nts].mid / DAY); diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index 7d93b222f..2cd473629 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,37 +1,37 @@ -18d2e10f3bf71ef539852b5b2df4b439 absorption.out -d9c288195276a22408d15a75a657362c absorptionpol.out +26d9e13ad6a94de247a288c9644914b0 absorption.out +d36a2323f4839c3ebbdaf9d5b549fc24 absorptionpol.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -c6d7319bb7136e9cae5874ee9efcc85d deposition.out -379b13704b6476814283bdd7d2ea4e47 emission.out -99235e55736cd52286bd74aa0fd07edc emissionpol.out -12cf80e6b48fe1f47b7647da1753f5eb emissiontrue.out -27f75c87d4cd766eb941db8bb54f1f81 gamma_light_curve.out -68f0fe43be3ff423a4a8b00e85dd79b7 gamma_spec.out +e86b69d3cbd8e4d991d6f75d8c0e2f79 deposition.out +d94c2c032796a777f58581ba1992cc59 emission.out +15e76a5e16da47f58b42ea954a9c7be5 emissionpol.out +8bae638acb0f0ee5b86a860024563fed emissiontrue.out +302f37ac870c22d6b4a633448b7faac4 gamma_light_curve.out +e2d7b162e1f39df386a71126ef3dd348 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -5c963868869e8d438927c54ec152551e light_curve.out +70dadec17fb2fa987f2df88dddfcd930 light_curve.out 5740f40190d45653e5fce57ddf577dc8 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -7bc2b07de9ebbc0bf802f17869da4a2d packets00_0000.out -ada898682332d885d8d4a1761c9591ed packets00_0001.out -6e53813bd40eeea80e16b261b99dcf3d packets00_0002.out -eec6b07e4c617c4a90e2b6e11a734c67 packets00_0003.out -c7852ce0d437fa2d69d281752b573a0e spec.out -406f0d143133f6f5acf6c3b918b30f70 specpol.out +3033f81191b0dc5c764a0086a94ac1b1 packets00_0000.out +270524ecbd3a9664bda29accdfc5b7be packets00_0001.out +eba236e2a397c84a10356257392652f8 packets00_0002.out +3b128c5a7f9b4ccf14c94202a74dbae0 packets00_0003.out +a7e49331cdab38ceac10a8bde2b4adf4 spec.out +e95aef64ed098f825506f7ad26a13770 specpol.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -8602d0fc86e1ffdbd9362e025765032c vpackets_0000.out -2ddd0669aa42e86e4c3c33af336afabc vpackets_0001.out -221c7a09f5c875bb31d433d564ca0452 vpackets_0002.out -bb3135cb3ec944a611172c3d04fb033e vpackets_0003.out +f279081d33f6b57de84558197314502e vpackets_0000.out +5a43becdc1d7e71b4ffd7cebafcaf6c6 vpackets_0001.out +f121ea01d207139c93ce7be5ac31e4a5 vpackets_0002.out +9c24724778aae1528f3d0b56155d8a20 vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -c0f9d5656d2d155cd19bd98e45e2aecf vspecpol_0000.out -1d54f9876a95a759f41793d7afceea6e vspecpol_0001.out -6e4c992d669a05eaff47f310004b5a19 vspecpol_0002.out -22394b555269063ef22203785baf1da6 vspecpol_0003.out -96ed0b0aee737ee68753f9303226a2eb job1/estimators_0000.out -97d50c87e1932cb6ec152913792fe4e0 job1/estimators_0001.out -aa4ace2d555d3d24719d772f4d7f4ae5 job1/estimators_0002.out -04657cb83f1cb6e530c7203c667cd548 job1/estimators_0003.out +4c5306f6e0600965c64054681e4e7cb7 vspecpol_0000.out +475c10e47987945227a085d5c1e1be8c vspecpol_0001.out +6b00a1ea7b27e5526d6b4111b8ac649c vspecpol_0002.out +4a9877bedb2280ae456c03fddc3f3e9c vspecpol_0003.out +6c52257f858067599cb5558fc3ecee9d job1/estimators_0000.out +4f4a2b7b0372574946c27b72970c0079 job1/estimators_0001.out +0b018d853ee5558f2c3e00c8812704ea job1/estimators_0002.out +654ee46032abcb5642770eaba93800a4 job1/estimators_0003.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index 5d029e80a..a2c84f41d 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,12 +1,12 @@ f6f254e9f1381dc7b7f7ef8f8cd12b19 absorption.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -495e4053eb59ea072fa250fd7e0e92eb deposition.out +b189c2a2ae7647df01a340c9d2b19200 deposition.out 618536f8df9ce91e3215ef59cdd1d55e emission.out 5c757e01a7473b96512490153df67102 emissiontrue.out -bfe96e8a4db19cd45dff11ce3d3975d7 gamma_light_curve.out +5ee5397adc055cb62b922ea98e50245c gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -8cb02f7c95a34b4a9b5b813e5e24017b light_curve.out +ff34c9bfa70483263ed6eccbeb38e93d light_curve.out 5740f40190d45653e5fce57ddf577dc8 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out 7faaca35800ae2c3ad9d3f4960d48692 packets00_0000.out @@ -27,7 +27,7 @@ ef9e1f821d4920e44053e909fdc51fe4 vspecpol_0000.out abc6598657cda5f5a3be63bcaf519043 vspecpol_0001.out d582dafe3ea571fe7473cc4c0be03455 vspecpol_0002.out 5b7fc753283aa641885d587c2f9518e6 vspecpol_0003.out -99ddf74f709d9eef3d62429416346220 job0/estimators_0000.out -68d13c6c4da76d29db65f6ce18a8e161 job0/estimators_0001.out -01a6901b977aca4d845c3cdafa75921c job0/estimators_0002.out -d802e8c65aea8c8005f39485bcc2e7c7 job0/estimators_0003.out +2fae638309c009c16f37d118fd5c5cfd job0/estimators_0000.out +b21cc560e486dee405f63c6f1566ccac job0/estimators_0001.out +7ed70e373237a2baa5b6fccb1c2f9bd0 job0/estimators_0002.out +1b95178675f2f06bca85ed41093e9a9a job0/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_final.txt b/tests/classicmode_3d_inputfiles/results_md5_final.txt index 79a5ec047..16a513b76 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_final.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_final.txt @@ -201,7 +201,7 @@ ed92da0ecbc1042c5a35cf982013daad absorptionpol_res_95.out 4f3d23c7065f4d24cb846018ce0944d0 absorptionpol_res_98.out 368fdf068e5f32f68a016ff8429ae44b absorptionpol_res_99.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -910503f95dea5a5ba0ae5154436fc004 deposition.out +10aa52e7049599280e304985c7f29098 deposition.out 0dee27af7ac2a4176a058d344969847a emission.out 12c19b24250988600f92387f7a9ee8a8 emission_res_00.out 3c42846db64af7bfab776bb5288ea107 emission_res_01.out @@ -522,7 +522,7 @@ b4f5eace8e9349a3a6b702c811ebaef8 packets00_0003.out 443ff2f26a56a1b577035096e17e6546 specpol.out e594395c996007e366d8191a4fc54488 specpol_res.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -751a03e01ce2d9148a2dcd77dcf05576 job1/estimators_0000.out -9573f0a8a83dd494d1f6238d690ebc16 job1/estimators_0001.out -a21e0884dda7b21835da74054ed5a98e job1/estimators_0002.out -21160a59d95307c9dc879e733d3910bf job1/estimators_0003.out +390501396ec721bd855347cdfb31e708 job1/estimators_0000.out +1ed27e467f2cf74d5cce76585a5395b8 job1/estimators_0001.out +d6d3fbeb58ab90cb576fa4ca02def050 job1/estimators_0002.out +03c32e5a40092f192b4fad4be798bc42 job1/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_job0.txt b/tests/classicmode_3d_inputfiles/results_md5_job0.txt index 5b6afcc4a..15e5f0cbe 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_job0.txt @@ -1,12 +1,12 @@ 6a5510f9d5126f62fe65ea11f76af72b absorption.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -908b5a71a0fc1121935273b5a9e7ab8c deposition.out +fd04d11f6960f0f99e31fe243051084e deposition.out 558ee7d654a300cc3ad478fd74b20c11 emission.out 680cc0d3c4ecee72bea9a2e0c2454df8 emissiontrue.out -827d710010ae243eb29395b468d91440 gamma_light_curve.out +357bc2aa8c2d69a38f1c189a998c935f gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out e08bbb965fac36412810b8769a13ab9d grid.out -35006afc4fd038ac1843dae8531bb1e4 light_curve.out +f2cb121d9941d7c3ebd59eee25a8c9d2 light_curve.out 6a60c8e204b6679e37d10f30386d4948 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out 40c324ca17f8fccec763cfb7ce81ddbc packets00_0000.out @@ -15,7 +15,7 @@ a254dfb37db9eb536d40948b140cf80b packets00_0002.out 56de76c244b04137473bb437052fd18f packets00_0003.out fdb3d9de60da03e358b37bac30907ff2 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -047cee1126fec1c031af6218cc1a7549 job0/estimators_0000.out -ffbc88b7b7769ab17640fe6cc6eab391 job0/estimators_0001.out -4e2867e694940dc38911f049b983d0fb job0/estimators_0002.out -756b76a5d25b306127219443f459c903 job0/estimators_0003.out +cf7571c11e38e451b6bec5c6564654c8 job0/estimators_0000.out +6315c47801e2168b64d38b38e119253d job0/estimators_0001.out +320846c205e4674f69d2abb3db5d6eaa job0/estimators_0002.out +8e94b8ab52e5f89fca0135cfdae24bf6 job0/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt index d68e8010f..229c01f78 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -b8bb4ec33055c0533e85a030b888c0bb absorption.out +9043a925b102e512a4854a3de880e32f absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -da224a7c93bafb9d65fd8c60de4875b9 deposition.out -57152d87e775fac387aedbe2da63565f emission.out -28e11260373f18ceb90dbc7a51fd4d1b emissiontrue.out -c2dd25e167199fd8259801ed44307aad gamma_light_curve.out -9d32cad9f8c7a81c302cd0e54ffa9cf9 gamma_spec.out +f3a3b8c53df5e147216c247cc0de35d4 deposition.out +5414af7cfe6d1dc9f49396f5fc8c0b82 emission.out +77867e60ce94101ea9b046337ee39e04 emissiontrue.out +d2bcae2c099b1c3fc5c25452065c4bee gamma_light_curve.out +f271da3efc68490cad51460aa8b53e23 gamma_spec.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -0c4caa9c47d0c8c03ba7782661b4d454 light_curve.out +37aaa6ce6743ab57a41ca10db799fa39 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -97099188ebd7f840dfe86cbf973b526a packets00_0000.out -626b66d6579d9b4d0092e3e224c1e5cc packets00_0001.out -95aedbb99244264bcb569851c2808d92 packets00_0002.out -63ac2dd4ef4a01115cacfb4f56142aaa packets00_0003.out -0d71dd643700788b34c6cc0e6e16b249 spec.out +4a917b12e8982e278b5f4ad21fc1ba98 packets00_0000.out +621d58b8703b403e0829759180a69b82 packets00_0001.out +48973a1bb0d0ca6b74540577be4dfa08 packets00_0002.out +6ed4839f8392a86f916fad01457c6259 packets00_0003.out +e1de2bfebbe2a4ec4bc026c94c259fe2 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -8887f9816dee5adfbf9e7fcfb7322f96 job1/estimators_0000.out -e8a07489101da8c29e32a93f9a632ccd job1/estimators_0001.out -13fd3fa04d1b2591e38f0b1fded7c24f job1/estimators_0002.out -a1e22e2ab6d2e12086e4a7c89bc23107 job1/estimators_0003.out +772e04600688399f64b456d57fc9d589 job1/estimators_0000.out +9c577d9f7d6ba26fe08a000bdef2112a job1/estimators_0001.out +728703475de78f7cd6b19ed25804d6fc job1/estimators_0002.out +cafcd8af12880610a081607341659f4f job1/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index 1eebf01c8..f8f9a9050 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -d4e0ad3b9282fd7d355e59fedd9ca524 absorption.out +6612e0e192ebaa7222ea80c135b07240 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -fe31a2fabe038df41f5e5c11c96d54a3 deposition.out -2f8d16bf3a72e4cccab4b31d8bac6433 emission.out -d71f446aa4f40eb3075096f74ac10d32 emissiontrue.out -76e2a2d6efa64ba43940acafaf1bded1 gamma_light_curve.out +0c49c4cfa8d8ebdd3d75db268849dd01 deposition.out +6770426d4cf091b8defdc2a9f466d047 emission.out +e89d0ad5e1b346ec9f1de260e483fd99 emissiontrue.out +ef28712aa9caffa21463d40732bf88ce gamma_light_curve.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -3f7d485a712e6ccd161286055665d5cf light_curve.out +6cdf515af89c069795fa10fd26d54924 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -8bb4b6f07fc34142439bd8f4ebb0bcb9 packets00_0000.out -0494ff2946480c3f202e783e96febf18 packets00_0001.out -38c35feeb2562209fc032a5d2b4214aa packets00_0002.out -391eabcea04d522b3737bbad2b7a8ae8 packets00_0003.out -5578753ba7bd469be0351accab13098a spec.out +13ffbcfde4e3420b941240ddd74df716 packets00_0000.out +5bee476ad9f4eb613b15395b7588d9e9 packets00_0001.out +3114af660a585f68fdff7a0971e69d38 packets00_0002.out +8f79a881190938de1bb7c79601592727 packets00_0003.out +23fcbf4f2756078ea8b022fd9f6bd7fb spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -248d0cf29942868d28a1ae0d356be77d job0/estimators_0000.out -fc900ecb9d79011718cd7ae52fb3a380 job0/estimators_0001.out -912058d7398ef507ee1cdf68b03d5343 job0/estimators_0002.out -4b7a4256554dfbdf9a175744eda5ab3e job0/estimators_0003.out +198363b716e60ba18c6a83338230f77d job0/estimators_0000.out +284a9e68c0a5a3a16ba2e1b97128e1de job0/estimators_0001.out +9466da87988a7a31786899edc936f688 job0/estimators_0002.out +d0faa900ea61cfac965045ebff22c5e7 job0/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index 0fb800378..d81d6078f 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -afddb3dfcd4820f26b386e4c109bf290 absorption.out +107e1739bd28d7d7a9c0c3bc018858f5 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -cab02bd10e1c7fe69fed3b2900cb259d deposition.out -4b6cdd402c56e1fb42bbcab2da2798ba emission.out -fb46627a27e8b5c60a7c19e8afa899ba emissiontrue.out -b2574e7b86bd084f4099e71457d31d61 gamma_light_curve.out -9b45ff5c668ac3e676b337643fe69de8 gamma_spec.out +62ec3028277a61411fb4878f33417790 deposition.out +6342d0dfe6524ee53bb3123c8ebd4a62 emission.out +8109358398a905d45c72709788195cfd emissiontrue.out +d0dde0dcbd5ec7e0593875e87328d94c gamma_light_curve.out +2bb73a7de8958d9dd3192469a379e021 gamma_spec.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -1ec0e115098575b6c3772a165b364b7b light_curve.out +14bc0d07d9e35a645ea19c14d0957e71 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -786989f46d846cb92aaeed1095e13e0b packets00_0000.out -85052248726d4392c31bede29a9bbea1 packets00_0001.out -ceade568de559a7fcfb0f5237334916a packets00_0002.out -e7cbd8bf315b0c240e41b03d68494748 packets00_0003.out -533109b016dccf2ac1c01a8dad972a1a spec.out +8b7123e0603cd3ebb6b140af44648fe3 packets00_0000.out +9df44a85702594839856228fc6d8107e packets00_0001.out +52bb407bda6ca5c969decdd535541eb8 packets00_0002.out +2069061a9bb06052fe9b24c2beac0e47 packets00_0003.out +6dfd3b8134b8a1996664e3051910ddf1 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -4a0efcfacf204a8b9871e4d2bc859a31 job1/estimators_0000.out -eb91d0a23333ee4e17f49fb3803b2602 job1/estimators_0001.out -5667e1a17d165b74d83239c50a8ca8a2 job1/estimators_0002.out -24df7096085b6a13a4caa99530570b6e job1/estimators_0003.out +fc47ad3d373c59ae40140cf34956042f job1/estimators_0000.out +e1e45681fdaa388b8f737e2d6afaf262 job1/estimators_0001.out +878b571cdb92c02b2cbe3d4dc2c45a73 job1/estimators_0002.out +0241e8ab3bedce1570cfd44f982a5b0c job1/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index 15b94afb2..704ba4360 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -0d160e90f51c01c2409981ccb9259631 absorption.out +51cffad535f5f1f7048b98a20328c387 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -c9dd16b245bd5acd7f8bffc806f5b170 deposition.out -4880162d2de1707a307aead7ab553f0a emission.out -e245e07bb000a542b4c42b909c829a66 emissiontrue.out -87243e77a401ec46e86aff78dbe3a5ce gamma_light_curve.out +cd05d16e058461560492918152cc74c9 deposition.out +d8e908d32c96818b7b61cdc6d30aa0e4 emission.out +be12a56b07b334d266766b98d8122226 emissiontrue.out +21e3d0c1c663ba466729e1a49e8cb23b gamma_light_curve.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -0929d932cd01be6ee3ed3d867c7723d4 light_curve.out +972b71d48c29e32b421f543abc7e9bcd light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -8a2b74a4d447c9d9f68cb6abaa72dafc packets00_0000.out -4504927b31d88820e80de6231517f5f4 packets00_0001.out -b5075578608a73090483c067cb86c3e6 packets00_0002.out -07498486311d07baca18d9746f3b0ebe packets00_0003.out -c23c2d7807e88f7d8501494e22d16735 spec.out +0cb977265ca330b6a6aa4c9e438b26de packets00_0000.out +3e1158741de20ad475a7c72524104348 packets00_0001.out +dee42e74dee1a2d5138c3f4f15861dae packets00_0002.out +87490a35fae65ca82ecd0ade87260f44 packets00_0003.out +04681ed38a39014bc297bd7c60d67cfb spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -a7aa64ff12cc5e0b683066dacc660912 job0/estimators_0000.out -3eb076b0a6c858705c7c9b39c94ddba4 job0/estimators_0001.out -c7226c689ee1d0ba380bc73d94930054 job0/estimators_0002.out -8684f27afd45ce681d2003e1be75504d job0/estimators_0003.out +35fefbf79caba333c8573956dbae4ada job0/estimators_0000.out +d2434a26bbecda34b2b051f7f9b4a171 job0/estimators_0001.out +d25a6da8da74e97ad24c05f9572763e4 job0/estimators_0002.out +080ad1056c855233c76cbaaee0699569 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index b6c02ae15..2c05b6696 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -2ae5a5b82a1ad6e350016648e9b4dc0c absorption.out -130e0c9a3644989e51288d3b7576bc1b absorption_res_00.out -c8d78f04e4202968ea3a061f51047743 absorption_res_01.out -41a36d0e243b95ac684f1bb8984e0ce3 absorption_res_02.out -d8ca8e3c27d90e043735d8430ba1fe92 absorption_res_03.out -5d007d563d846d4b85de6f0ced5bcf7c absorption_res_04.out -7e09f68f562096d3df078b4d411240cc absorption_res_05.out -84e5a1d5d19a8ef9bddce2e1c72521d6 absorption_res_06.out -3334983f4cfa85ef3099a2664b7d784f absorption_res_07.out -3f4d06600660dd4504b8e213adbd2551 absorption_res_08.out -82e674388384efd62fb837c98cb303e2 absorption_res_09.out -20bed8622b6b7791580fa42daae0afb7 absorption_res_10.out -07f388112ae50e1fa21dc36782758f30 absorption_res_11.out -12e9f7f947d18ffb6622f7335d4bac0a absorption_res_12.out -d9831dd114cae54d8c91fd44e62439c0 absorption_res_13.out -ea616b58ff9d5767264aef9874d73f67 absorption_res_14.out -f87ce48b1d476322607576f91614e751 absorption_res_15.out -4a813cd284ddc223be2f5ad5911e037c absorption_res_16.out -08afac53c047978e65010178f9a0a427 absorption_res_17.out -7e4355b506fa6faa79ed923aa977df8d absorption_res_18.out -c38c771c669f74e3e0bd3fbaa66f3bf5 absorption_res_19.out -4a98687575d19a65cf2b573127a58d08 absorption_res_20.out -6e3f48e0388b44cac8ed4dc6e14c00b0 absorption_res_21.out -1c04b26d69a2a6e4f51a9ce6af77d54e absorption_res_22.out -43a603cec35d543fae535c1efe3919ec absorption_res_23.out -f99b0ce39fd0f195ebbd421775b6c3c2 absorption_res_24.out -19eedfb57491e0ad3456608d0d1ca022 absorption_res_25.out -f10e766e34132bf9ad4234761c1c3f97 absorption_res_26.out -8592dc21362eca6e3228a77a0d402c38 absorption_res_27.out -26012365b579f115484fd8823aabb93a absorption_res_28.out -a730eb8352ad5bf8ff06e35818e692af absorption_res_29.out -1cb839467ecbc0a7b085bf1fe301cbe9 absorption_res_30.out -c780d2f9b60342fc8ca218add3cef74d absorption_res_31.out -bb99b26939479774b18789e0c7da19f3 absorption_res_32.out -4ca0c87df2968d0dc301cff742304061 absorption_res_33.out -23d7199ef91a21e135f259c25179e25e absorption_res_34.out -48ad0aa7c731657d12261e8fd9ed7cbb absorption_res_35.out -bdc21aa4170313b44b1c65757ae152ab absorption_res_36.out -e6b16425a3b348cb9792d59647aef90f absorption_res_37.out -4e987aec1d9629e9463855e683f41a9d absorption_res_38.out -14079c1a422e41e8057454060454d858 absorption_res_39.out -9ae9a85834b40c7efeed939911d397f5 absorption_res_40.out -da1fd579f088028043bf3f2b60b3c314 absorption_res_41.out -9a5c6967807fe1f718361f48f6218c5c absorption_res_42.out -b2dc8cb8bfdb9ff195bad7e25a7c42a9 absorption_res_43.out -2760d442aa64f5d561143a38f3238472 absorption_res_44.out -71b464c89d5009f7d7a7960db2cae7ab absorption_res_45.out -53c4f570defcda71cd3f11908bac0262 absorption_res_46.out -69e1c090346acf84f8d744bef5119e83 absorption_res_47.out -2356f6d559fed6f14200caf46e21d0f5 absorption_res_48.out -9c79cc5fbb9d39deb71423824e8499ba absorption_res_49.out -f1f95a5beace748a875344585d93deb6 absorption_res_50.out -0e6979a5e8a057269ec69a9e4ae49259 absorption_res_51.out -9bedaf18ef86e98d8083714ce56dd849 absorption_res_52.out -16f8d9e00274c22a3659283fc4c571a8 absorption_res_53.out -83ae93d5adc6afd7a37889e9459e3214 absorption_res_54.out -7783e616e430b2a6d759d7f56e1ea9ee absorption_res_55.out -d0c97bc9de2c0c7762e6aba7963ee77e absorption_res_56.out -1c77e7a069856262335a2b9015615213 absorption_res_57.out -4fec69dfebbf3922ed33802be6211e89 absorption_res_58.out -d4620e6d1d1983653a939cb5257fd7e1 absorption_res_59.out -8fc209dc7c8310444e733942760de3c0 absorption_res_60.out -6dac56f203a692a4afa22db7b694cf3a absorption_res_61.out -ec11eabed2105fa6d98171000dce987c absorption_res_62.out -00d903ae39a72da7166d96c168b32a38 absorption_res_63.out -f7dcbf73dae4f0175a20dac6a5d06be3 absorption_res_64.out -529bf960479780c54ae6937ebb975b0c absorption_res_65.out -5ae88fa557b007d4a66cbb3a47504de9 absorption_res_66.out -53c2843de88d0f5720136409c3616a8a absorption_res_67.out -8cfad4ef278d2533956cf141b475b56d absorption_res_68.out -3ad1b54cbd0d2e0c1e15211dc01c33b0 absorption_res_69.out -013bbb022825b6e04e55ac4098402870 absorption_res_70.out -45f91f36db08597c9d816f7cc3332a1a absorption_res_71.out -c91d731ea826c0f243eb96e63b57ccff absorption_res_72.out -64c7f9c00227e995d3c2bc9450f7c184 absorption_res_73.out -654a10d8eb21964bca53ad9bd8b889e2 absorption_res_74.out -49b74a4572f41942b4af0bb62c15da42 absorption_res_75.out -7d915b3d2864a80356dba5b6c522dec7 absorption_res_76.out -322d3545bff0b2b9e2337e0d20cf24a5 absorption_res_77.out -b6b1cd53f4b4bf65b51fa56d3ec8c9b6 absorption_res_78.out -fee7d69c363446d76087545bbd513595 absorption_res_79.out -36621f80bdcda371af5efe456d5be339 absorption_res_80.out -b6dd586d6c7b63e927b57838d36409fd absorption_res_81.out -abfe88336cf49491f70ec5143040890c absorption_res_82.out -6ced4e278dc2aa4cb1fd73b26600bac5 absorption_res_83.out -9d2033136ae967f4f33487309612a0cc absorption_res_84.out -c1bf7967d1ac6efcdc6af135332b075c absorption_res_85.out -08cbae5ee43c4e1972dbfdbcd61b02b8 absorption_res_86.out -f03851570e3b9e3861e259b7b1f91d2d absorption_res_87.out -4a19d347fb9bb33c557246d0c77cda04 absorption_res_88.out -91594df55a04073d9c4cfb5f8ffa3d7c absorption_res_89.out -122b0804c0872c89f54d0365881d1659 absorption_res_90.out -a2129b40ee06561565a8b09a5ca9627f absorption_res_91.out -46ee95563e981bde9723c4f5f99d2bd1 absorption_res_92.out -039e21272f0698183b17494de8ec7f78 absorption_res_93.out -5d78dbdde2549c1289741c2a3b1cc384 absorption_res_94.out -5c43cdd525116484c26d3346781749f5 absorption_res_95.out -bf07037fc6007130f73a88eeb2a9c954 absorption_res_96.out -c3014853e9b4918c163803eba2184c95 absorption_res_97.out -606f3f9bf8d375a1bda561201e40613a absorption_res_98.out -dc2f27104034b4f025214820dafc2f24 absorption_res_99.out +40145cba9d7b26338c83d9b29b8fca8e absorption.out +a49f6298a24abfdefadff10de4976db2 absorption_res_00.out +7ba248b7fd4de1ded733d51962cafa87 absorption_res_01.out +64d551ea1402a6b49d97036bba0de622 absorption_res_02.out +e2a27a86b5c97e80b5f5248c4e7be7ef absorption_res_03.out +e4b34c85c690d3a5e5e854827f4a2ce2 absorption_res_04.out +93bbd35d8146a32bc1790a2c662cbdf2 absorption_res_05.out +7413dccb5748bdf338a09bf164b89c80 absorption_res_06.out +3e9d56098faa2bcf4a08b21807a65f85 absorption_res_07.out +bd757553bc9e139f2b19a7fce69ff965 absorption_res_08.out +b9c459deee045af874a92120496cc99b absorption_res_09.out +721280f6d3d2ec4b49529ffd45107585 absorption_res_10.out +f46d5be9cb1047eb0f70e472ddc29593 absorption_res_11.out +f11ac66c4937457c7d7add9677bc321f absorption_res_12.out +0c41ff566810314a6c9b2e3f5c5283e9 absorption_res_13.out +8397598be6eaa5bd366e3c46ea866583 absorption_res_14.out +96161473cc93196f93fe151ce759c772 absorption_res_15.out +ebf7d755d85572e83e9231a5ab8fbb57 absorption_res_16.out +16b0ce6033611e5b4e5404b89129642b absorption_res_17.out +d790820dfe5c332f3ebff5e3fa894d33 absorption_res_18.out +076a81f09eeb01ad930ecd10b0bbdbd0 absorption_res_19.out +c3f42930e4673c088c21a31ed66b9cf2 absorption_res_20.out +bc05397bec43166b1ef78c73e30fa210 absorption_res_21.out +0af6702e614090fdd7a5826516b32d45 absorption_res_22.out +bcf739c5099518ece2f578a92d0d2244 absorption_res_23.out +c17b6bf0abf77b165fb7fce59c7b914d absorption_res_24.out +dc406332035aa69613c01f6386f8f0aa absorption_res_25.out +cbcff2c0bb5436d50d2d20fed43167b4 absorption_res_26.out +d800f243d1a47195dfd8306112b587aa absorption_res_27.out +2588ba7e0414ff9940c503e3c73e23af absorption_res_28.out +00651b80a0d7707fa114b36c0248781e absorption_res_29.out +e9d3f2b71242353a8e54f9e7d52b54dd absorption_res_30.out +92954184ac6a24b856976108c5602279 absorption_res_31.out +eed4ec7cd32ebee3af246687f79ec370 absorption_res_32.out +d0ab47b53d16d830384db7c43a31a641 absorption_res_33.out +3660974f465785ff887ac91629ca35cc absorption_res_34.out +259dc3519aef8246d9b461a7a1cdbce8 absorption_res_35.out +8cbb8227115770ece2b136366f1d3fa2 absorption_res_36.out +6cf09f9d3431124e59499e735f243ab7 absorption_res_37.out +247c6c37b35a5c43c69fd4ac03a9b4d8 absorption_res_38.out +ace28f213217bb947eda2ed5371cbeec absorption_res_39.out +319f135699776f00ee4898a1f9886246 absorption_res_40.out +5dfd7cc34a2a0efecdbf39a2009615f1 absorption_res_41.out +3b44d8ef089edef98a68a5fcf90b3d42 absorption_res_42.out +0dd51a8baa980d8015e154a908e087c1 absorption_res_43.out +ca5c453e0bdac809b3ab0e41f719bb88 absorption_res_44.out +620198b21e4e06956432a64e668f7ead absorption_res_45.out +d9ac2c3d71bea664a50f79eb0a879a1f absorption_res_46.out +88a6a91f29468473bb86f5c6288c4646 absorption_res_47.out +cd8c7bcaba62824bc4e7b6fe5b666344 absorption_res_48.out +60be9adafc9232bad5b00da9284727b1 absorption_res_49.out +8f2b86ef0b3bbd9cc6b0b02ec05cf5b5 absorption_res_50.out +d362689e69f0741bc6b00af242f574db absorption_res_51.out +e5c2491143caf619127f867e00388616 absorption_res_52.out +cf9764335245f01cab7eb0ca67bc9cb0 absorption_res_53.out +be684d0067c88b9db2089456453de1f6 absorption_res_54.out +034a1d0da8a794bd8d7e4736aa5658d0 absorption_res_55.out +abff67fa68a16e1786a331b7be04dfb9 absorption_res_56.out +bf21a9a444c8cdd41a3b1f5143df8355 absorption_res_57.out +3358408a11db025e1a7783af175f3069 absorption_res_58.out +728fe3c86242f07e75f0f4ae8bbdc93f absorption_res_59.out +0f6e63e0c3ebfd6867556db87c3d7b10 absorption_res_60.out +3f7229684eb19ca95d8c822692918bc0 absorption_res_61.out +64c16f20a6594276072f5e408dd5c641 absorption_res_62.out +fa727a47501e2f6daef5a6a0bff05145 absorption_res_63.out +faa5773186151ffc3b6c43af3427446f absorption_res_64.out +e6d591b6de9cda3a71f9583ef4a3c287 absorption_res_65.out +9b6ce7ea24f7c48ae66b6b218b3f039e absorption_res_66.out +90c96a8c65554b3889956b0ac5e6cc71 absorption_res_67.out +64a2649465998e481a95d0d4a7040e31 absorption_res_68.out +c17b9cdba6881a92bb7f2ff1a63a5077 absorption_res_69.out +7648ffb87f99b99618f7e4671eacef0d absorption_res_70.out +0cc4c9a6ff4640cd7fdb1e86dac50618 absorption_res_71.out +f47a4fb9a2462b960ade7063fd4c3945 absorption_res_72.out +5087915b9b4c6c6df61aaa319fb6da45 absorption_res_73.out +4d0ecd248984c823d3f7e3cc04f0e83d absorption_res_74.out +6186b4165c1f0a0a984075607e1d2fa2 absorption_res_75.out +1dd29982ed34481eee3ae553f0121e53 absorption_res_76.out +624c4f8fcf2a8a072ea1b1d80c2b2adc absorption_res_77.out +2bae5033f40c84dc6adb7c8dbf4b49cc absorption_res_78.out +e432f6e214f51c039fb1547a97e8abfe absorption_res_79.out +96cc721062ec1fe21680f91c4202a882 absorption_res_80.out +17fffa783ef03c9b1f431fb8ff08ce40 absorption_res_81.out +110800d3f98735fde7a6cd1713e34497 absorption_res_82.out +a7ae492d7d731e653700d754bfd5f753 absorption_res_83.out +64f4ac589ce8a0dd26970fc989bf3fca absorption_res_84.out +1a9fd7a1b9aa7b54093db672f939175f absorption_res_85.out +91b40bf6fffa0af0b2c6d6d4accc1ab9 absorption_res_86.out +ca95159ac81ece7f2be399da26041acb absorption_res_87.out +e4cffbef0eb93bcdd14fb655ea536191 absorption_res_88.out +6a608d19b578462a77c52d7fc1159fbd absorption_res_89.out +6156ddf8ec8f8e26c9259e9d1ad0f329 absorption_res_90.out +4797edee6296eb6b07def2461370e19a absorption_res_91.out +2baf7dfff59bff883788d02605eadcb6 absorption_res_92.out +3bd46408c6a0d71e0e2bf48ec3f77ebb absorption_res_93.out +ce99824fe7b8386549e3579e1027291d absorption_res_94.out +e8dd71c63b9c03616ab77e95e47acc2b absorption_res_95.out +aa37858bc0ced42d09e00220905ff20a absorption_res_96.out +837eec544cdbe4532c5456156efa502c absorption_res_97.out +66662413629c6419bfd6f8c5ed107704 absorption_res_98.out +ddb3cbc3d487abd00df87be7c68d706e absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -27cd5ff0c7e1e1e38ab53d5da75c13ec deposition.out -30f2a2cb8387b2c6591337423dec3293 emission.out -97981ea90ae9ecb035aea8ec8e8c3c65 emission_res_00.out -ab2f42f05b2f2c710e1aa15a79e543b3 emission_res_01.out -a2614cb40b930dcfa646cbdc3d8a5cc9 emission_res_02.out -3c4cc87a3e17793aba170fdd5690d3dc emission_res_03.out -02958eec3842f4f411783b9f8ab9402e emission_res_04.out -67bd0fdb82e3dc4b2e5a6cef6284a64f emission_res_05.out -9fa6f10003be8624ba5338d2b3e4e525 emission_res_06.out -8472a50ac99b7b6f5d33ba8c47cf8d97 emission_res_07.out -9922b57dda13be39d85c4986a01c0fac emission_res_08.out -017bc94558003b60f140b40925adc9ff emission_res_09.out -7fe29985712e13c40160b96a6d841913 emission_res_10.out -e86c8db28cf605854c173bcde279a1cb emission_res_11.out -9c67bfeb949ce20207048a44bddad283 emission_res_12.out -9465071c10c63599930604f6617d132c emission_res_13.out -dc78fdec647dca513683c59e524e5f51 emission_res_14.out -4a18565d976abd955f03a39c633472d1 emission_res_15.out -3c55e81d2e4db3c058b64e6252af662a emission_res_16.out -dfcce0badcfcc820c0b753db8ca42db7 emission_res_17.out -0be6137203c1f183be38065db097ae45 emission_res_18.out -91c72c83a63f5f4447874740229dbfa1 emission_res_19.out -dfa6b5a59f15adaf74f348b58f01041a emission_res_20.out -38c9c1962dec6e33b494fb62cd731d61 emission_res_21.out -9a14f828ad898f4f1bd97ecb6b81fb42 emission_res_22.out -a1f8de1a5ffe1fffbff9aa33296af576 emission_res_23.out -9f5ebc23806bccf13edddd79a356c4dc emission_res_24.out -b5570f759b168be67c113f39f9ecc09e emission_res_25.out -6bd6c05e31c640c3826b7de88b0311b7 emission_res_26.out -749928deb63b15f4ab455d8d9372203b emission_res_27.out -fe5221ba65b262b3e9e215a51a618ae3 emission_res_28.out -bee6124a93353ac298f7275fb2248fe1 emission_res_29.out -78d70967fbb898b003d5fb303f2ad34f emission_res_30.out -fcc8ccae96e1f482b8d28b77e8a845a6 emission_res_31.out -c770c0b226445e397221b70accebb081 emission_res_32.out -96e3961b64ae3e7ab6bf521432e35c1a emission_res_33.out -ebfd68f9b3d32e2c3385d91da82bdb4a emission_res_34.out -b8b146a4f3bca8426fe8db4dc1af8b33 emission_res_35.out -e8e0e0a948b0e4ff57941a0767390f7d emission_res_36.out -af9adddde40333468b7e8774095032f7 emission_res_37.out -ae1cb0224aaf97cb56f73e8713859ef6 emission_res_38.out -795fa6e786c50a42f2784e091b346ae8 emission_res_39.out -40058222444452ce7f9c844e37f47ab5 emission_res_40.out -65bd132eef03f727aeddb2ba63d5961b emission_res_41.out -3f7f2b61b821a4cdc0d2c1dca25a62d1 emission_res_42.out -efda35d1f90b5efcd0b839778cbb2f09 emission_res_43.out -8b2d43ea93548576ccb717266a6abaad emission_res_44.out -a3a385672b114b9346f1634e7b5ca786 emission_res_45.out -2204266b1f3971c6e3805a8e5df2db70 emission_res_46.out -27bc2dd9c63138c1c3823f9aed8b389f emission_res_47.out -ca3a32e2e53342eeeb2855b1394a3f83 emission_res_48.out -ee787bfc6f71f5f266d3acc585c38ea1 emission_res_49.out -e38854c1715eb57e0b8d4387fa6cf1d0 emission_res_50.out -40ca1ee2c9f66e3907b62cfb089c8763 emission_res_51.out -7ecb75101875fffdda4b983c706f6eb4 emission_res_52.out -27b8027fa8969905fd5854019767f3f8 emission_res_53.out -0b4a702b3f41b91d3e308cdda02609ab emission_res_54.out -524fe9b25763d032a65f17acabe903ea emission_res_55.out -76e5602fd1c9511a2130bb9df2b1a530 emission_res_56.out -039fe75b8bac8d153eff3fb79b214f81 emission_res_57.out -e30036454a57c932e242bc942c826944 emission_res_58.out -7b4222b00c3a47512f21f8a66437ce41 emission_res_59.out -f5468a89e1d2eef22434a30054ff37ca emission_res_60.out -541ba3e1a2ddaa72994cd8b9bd4d58f9 emission_res_61.out -77d4ba6fdb5c3b28c89ec6b0465c1dd9 emission_res_62.out -c7a5b1068cd88dc7f5a7b0767c017847 emission_res_63.out -cbcce37417987386c2bcbbbec46a7d10 emission_res_64.out -9ec0d4740124d7c48fe78c7905f767a7 emission_res_65.out -b27065eb14bf68e24390b43ce1141dac emission_res_66.out -c45a15e9e5e153200600ff15102a1abd emission_res_67.out -3463e67178f02100195a4784d0dfc0c1 emission_res_68.out -1a70a2583219d8cb2926e983630f23e1 emission_res_69.out -efa667c444bda3f2c014303c89e3a639 emission_res_70.out -8789e73c939b9e94f1084c0a80359caa emission_res_71.out -abc04fbc5c2d5a88340be4cb9ab2a59c emission_res_72.out -419360a7635c6b25e7b2adf901ed6342 emission_res_73.out -1caefcfb9dc08f3d296f699a2d0546c6 emission_res_74.out -a83f348225a1c79e509b51e6fc1e1ebd emission_res_75.out -df39d5c4aa388d0e6643fbd3ee9ee7c1 emission_res_76.out -4fb1ed39117505be0eb55f73eb0ddd20 emission_res_77.out -7ecc2d2de81f2ad9fc26acd07927df58 emission_res_78.out -cca4130690c7847e430716dd2218a5e8 emission_res_79.out -41ba9dc8d7c59f4af9ea6da56ee39e60 emission_res_80.out -1b64aaa749c59df11019a37cbd5defe5 emission_res_81.out -c7fcc11a6c141f4763d0146c94fab568 emission_res_82.out -a7eeed4e384aaa370ea328e72d3cb4a6 emission_res_83.out -de423e83c6dd0d65242b7e96a818229b emission_res_84.out -ae6fe79c9afed3af245df9e318f0e3a1 emission_res_85.out -eeb893a436db7d52d775638fc867203e emission_res_86.out -337a2b4fd6c7db0ac725d03c201ab9d2 emission_res_87.out -5cd170ec28e3f45cbfda2d038d8e1fb7 emission_res_88.out -77c5fc0d1a024125e65f0ec7a914632d emission_res_89.out -e2cfc3b5e9137a9552610308d31f69e1 emission_res_90.out -89362d414410a115c73eb596b628ff5c emission_res_91.out -630892d538d59007d81e0ef420692f6a emission_res_92.out -22d8a81a267650a3a8deecff2622dd56 emission_res_93.out -31248ba977d6dca6da0c43a4796c16d8 emission_res_94.out -b4e63c8b971f85ceb3dec2c1a1e20a88 emission_res_95.out -5e2f82fb26eee688647a0cdcbc8837dc emission_res_96.out -fd4f6eda72dfa787829c7a1932e7d548 emission_res_97.out -312f2ec4d9918ba0f0121e2d2464d2cc emission_res_98.out -1e0d2d817a3a683a531bde593d233bb1 emission_res_99.out -9efbc10f23d5204a176d84dce94d1241 emissiontrue.out -f29858256d04ece60a208e6395f31011 emissiontrue_res_00.out -215212a3fadfb727c85785e16def79c0 emissiontrue_res_01.out -c0b65e6e8ffeb7e0b665374de24170e8 emissiontrue_res_02.out -4336cdb2699ee75fd75c1461df23f374 emissiontrue_res_03.out -2beda3268eaafbb1c22b5788d4fbf2fc emissiontrue_res_04.out -ba5a3eb615ba1c920cc331486978d29d emissiontrue_res_05.out -435b9cd9f6310e446d0b0c40273f7c4b emissiontrue_res_06.out -b9b84bf50783b58c232784221be70827 emissiontrue_res_07.out -8ed88b943c25c670419c8fe679d4ba05 emissiontrue_res_08.out -8ac1bbee22fa3ed6eca1df059b90e1d5 emissiontrue_res_09.out -1f3ef6d393c2db9b4a0556cb63ee12df emissiontrue_res_10.out -0427de965ab7a474fe868ce48a4e4b20 emissiontrue_res_11.out -5a0976efa1037e9bb7d614d4263f5f8a emissiontrue_res_12.out -8d87e43cb6d8ec3f969e0dd87ac737fc emissiontrue_res_13.out -d3d22382c5e4f2b1ddd34736102ff0bc emissiontrue_res_14.out -bedca7ff86cadced972e50271437d614 emissiontrue_res_15.out -09f847c16e8d852eb699adfd300e6201 emissiontrue_res_16.out -42f0d234b040dd1c5ba744576bec39d1 emissiontrue_res_17.out -7dd412a15fb6f79948ef21c6b3cd77d7 emissiontrue_res_18.out -0db336f9c069ddefc16bf43cbe695d77 emissiontrue_res_19.out -1887f448e3a074949bbdf6365f77366d emissiontrue_res_20.out -efbf92b0e4b1a97247ad488eeb975d86 emissiontrue_res_21.out -1ff74aa662ae07e404bdb3f7f8b5ae72 emissiontrue_res_22.out -d95646194bfa09db5fb04484382e0f4e emissiontrue_res_23.out -3d3c72b251fa9bb7a04401a577de9800 emissiontrue_res_24.out -ba2e0ae934a657e686160c38de53dd7f emissiontrue_res_25.out -482745c6eb078dc26b8aeb3a10232f25 emissiontrue_res_26.out -ca4da6ecdc1229aca3bbc5d1df6f05d8 emissiontrue_res_27.out -5b02b97a8cdcb95c2b775f3af4e92198 emissiontrue_res_28.out -7b97444588f0a28b568e7f660a33b5aa emissiontrue_res_29.out -358725d8bc22e174d54d226ee6d3a971 emissiontrue_res_30.out -8a70a448045726f6284112e621ffcc01 emissiontrue_res_31.out -85fa6480da77473a851a0872a21439de emissiontrue_res_32.out -33d846d537c60514c72bb68397a47e20 emissiontrue_res_33.out -cb1d761d2ccfb5faf398c3203b32d1ff emissiontrue_res_34.out -50969783d3f54fc19af05a00d7b71614 emissiontrue_res_35.out -5c3beea194947b8eb3852b8925cbf615 emissiontrue_res_36.out -7379042a8bdc7f08c5b71516e99a2aa0 emissiontrue_res_37.out -f2c544b80fc0ea6866bfedb4736a5737 emissiontrue_res_38.out -6e40c4d2ee9571c62992e90b39342151 emissiontrue_res_39.out -50bef91bb82d991316a5d543b5fc10f1 emissiontrue_res_40.out -026b3c57f00d837e72512f90ac2696f5 emissiontrue_res_41.out -99d13525345cb2cb2300723ee64fa320 emissiontrue_res_42.out -f7d55bd6968bdbed0af68dd4e1402143 emissiontrue_res_43.out -4d61bbaf485729a0a3a52578578039ca emissiontrue_res_44.out -9b93ff2a134765ae540bd6203eadc815 emissiontrue_res_45.out -3cd7769bbb4c4336506761463f8a3854 emissiontrue_res_46.out -94516a1e58d3c6d376c8200a27dfaff1 emissiontrue_res_47.out -4a3b562475b2297affb1da63ac8e8049 emissiontrue_res_48.out -ed9af8d95612df1f3c6b78812943ed4c emissiontrue_res_49.out -be239713f351ce053ace00c7457df573 emissiontrue_res_50.out -5039c23ba39e1796bc09455f6ddf777e emissiontrue_res_51.out -d49a15c03bb0cf6df6191edff645d422 emissiontrue_res_52.out -44ff35d9c1430effc50acdf56408c1c8 emissiontrue_res_53.out -34dd1db250a7904383423fd231aee95b emissiontrue_res_54.out -0f14060d17fd370cf75b94de34d98356 emissiontrue_res_55.out -14eeca8dcf8aec291e959d9aaf8dbe52 emissiontrue_res_56.out -04cdb81991365f93b138503743164337 emissiontrue_res_57.out -974b58912e6a3590dfbc84e9e3b49de3 emissiontrue_res_58.out -701391695e302e3d57067a10f37b587b emissiontrue_res_59.out -e13d9f062b66b4a2b404eb3d69db2147 emissiontrue_res_60.out -a4f3dfa22a8795aea2a60b8130f9482f emissiontrue_res_61.out -34ef416adfc4cd37f267d14cc814e0e6 emissiontrue_res_62.out -6ba8adafdbd336d8219d2630fbe69bfb emissiontrue_res_63.out -e7828259db96148bdc7b5ad6746670c7 emissiontrue_res_64.out -16186da58eb3df4b91e015de80b5bb84 emissiontrue_res_65.out -dd805f04cd56907441d77f53b8352e40 emissiontrue_res_66.out -aed74d6f176615f0674b16e05a696fe9 emissiontrue_res_67.out -6828c01bcd24ec27c9eb0354b5fce501 emissiontrue_res_68.out -cbc7f2f5f6088a78e3574b50a208bd8c emissiontrue_res_69.out -5b6bc22dc23f5b03c2a3cb91cafdbca1 emissiontrue_res_70.out -2c1f26aa586392c20a6debaf4b1cced5 emissiontrue_res_71.out -d36ef302d3236fa1500fb07170531aa0 emissiontrue_res_72.out -e4ec9b4ead7c308af32243eec3808464 emissiontrue_res_73.out -2a89f3d3337a1102c750f7ad84b52590 emissiontrue_res_74.out -56b0110a04a7b968d6c970adbb02c32e emissiontrue_res_75.out -56134eed4c7615f1c9b350a37d4bca10 emissiontrue_res_76.out -d32f3a64e35a1d4e8a2e83d4b18fc367 emissiontrue_res_77.out -b98aa74a5f60e949494ca5e39a4fa50e emissiontrue_res_78.out -75199e447974b17329a6fe3fc122bc92 emissiontrue_res_79.out -f06fa80eba983e9444cddb393841123c emissiontrue_res_80.out -27e1df2a710f04a7b0326ee174a22579 emissiontrue_res_81.out -1a0061691822a1b21c10ba35711a46a6 emissiontrue_res_82.out -a2ae221596be148445c3c7dbd1b65c05 emissiontrue_res_83.out -55faf5c0a321b94d018e303b18c6a536 emissiontrue_res_84.out -b624b7735eaa61f637a991bf019ccf05 emissiontrue_res_85.out -bfc8cf36030a8193fcaaadafbcb2dee7 emissiontrue_res_86.out -5eeb523ec34faca6cb552c0b4c22fdcd emissiontrue_res_87.out -bc646974692db202aac331913e812d86 emissiontrue_res_88.out -391ca49deadfde5374cfef51a53cf260 emissiontrue_res_89.out -cc6112dd902627392ec4f5ead103bc2e emissiontrue_res_90.out -29d921741d2091db9a26fde858e825db emissiontrue_res_91.out -46f9e81a7b35b8c4c748a3a865a52eb1 emissiontrue_res_92.out -84ac0c41aeccf120bec54ea315a25627 emissiontrue_res_93.out -9efbd761d03c64c69157a3d57c1b81e3 emissiontrue_res_94.out -dddb13602686df67b9d9226ff8fbbef3 emissiontrue_res_95.out -2e801a0dbaec334abeda97fbc1ec1ca9 emissiontrue_res_96.out -31b0689f46a609c43e065cd8b3433f8f emissiontrue_res_97.out -b382790909c5c1da022e65e6a7712f1a emissiontrue_res_98.out -6a1d582e346927ecac6bd414751dde4d emissiontrue_res_99.out +91ff0e7c10ea98f68a04ad4e8434a837 deposition.out +83aad79cbe9d35eb3bd6f45d840b580d emission.out +022d4400c529a150df6383cbe6427ff5 emission_res_00.out +832b39613e1a2590bb606094c9fc0ea4 emission_res_01.out +7a7a23f3863dc5c6f7f8cf75cdfed414 emission_res_02.out +ef704303bb5dd818fa29488041333865 emission_res_03.out +f75f2265f24fde43505f21c7fbb06803 emission_res_04.out +aac0d418ea2de72ec208d8d594d4f69c emission_res_05.out +d9cb45191bd9bf21ca06a398f289a592 emission_res_06.out +7266c043925e5fa8b5ca0e575b540e3c emission_res_07.out +383c174d77092a0e89ef769320320d77 emission_res_08.out +e455d5f16b95e727c6b561d49d036947 emission_res_09.out +5b29ea98dd6f3d104aebefa7361f10e1 emission_res_10.out +a6c70df39db5ccdf94c97eadeb67d8b0 emission_res_11.out +7fc6ee3e018d822826719f38ed3afe11 emission_res_12.out +13ee370d97e2db4008ac4f3cc1cc5f1f emission_res_13.out +88615d99b4da7f2607967276fbe8c2ab emission_res_14.out +4fb122ed80b23be580b386e0d043a28e emission_res_15.out +447d8c3538d42aa0099b73ab841b69a1 emission_res_16.out +3da25d68602d2b1b755e9df14626072b emission_res_17.out +b1b4291edab3a0a9a5e8849d3d4edc56 emission_res_18.out +cb0cd1f6bd3b1f295f0e77ea61eb9d74 emission_res_19.out +31c3f5e65881f6aef5e6fcc472d579f9 emission_res_20.out +bf215d48e5bc31d0ba1c7a0d478a42d8 emission_res_21.out +061f6643f5feeee6b2d4660d38c3c7eb emission_res_22.out +1bc2b77716cda63def46de5cb8ea7423 emission_res_23.out +bb0b78de6c8669199fd120c3b5a6947c emission_res_24.out +d0ea08431b77b49e877a7139f2787ee8 emission_res_25.out +dd5c4acbecccc0659b844f2dcda20212 emission_res_26.out +db3cbf5ebdeac5e49878d0b3dfe63e49 emission_res_27.out +16a4e043678c5840473e2fa5c68eb2df emission_res_28.out +9ca11fac1926a9afc97b1fdd60c50234 emission_res_29.out +ab6b32c2e8824fd6dcf2d7e0515b3669 emission_res_30.out +eb372e9ad199299320a8273abcda97fc emission_res_31.out +a816d3df5c0e4380dbae74c9736e4eab emission_res_32.out +3ab3552a1977b14ad717ff911142d03b emission_res_33.out +ab3d6163d22f40e3d71911e2289d0ec6 emission_res_34.out +a9569d5affbc26e6952f9d48f38479cd emission_res_35.out +ca7881565f12e400bd195372ba95da73 emission_res_36.out +2185d57783feda69d3eee3213c8e374a emission_res_37.out +409f36ce5fd0b8edce170cc40952f8c6 emission_res_38.out +0f25bd1ff243319114b2ed22ac50cc6c emission_res_39.out +b21561c7deef8ef2766e20af184d07a2 emission_res_40.out +3ef75ea54cd49d62bdeea3f514fcdc73 emission_res_41.out +7214e38fce33d0136725c8db953ea10e emission_res_42.out +08da2c4a64a58b62597bec4c47928951 emission_res_43.out +7ab2bed5e2b9089fd7b56d58454d67c7 emission_res_44.out +7438416b8fc09af9f569f03d101e8491 emission_res_45.out +e2bcc0b7729c41034538e52e8af9dab3 emission_res_46.out +f8b365180a90bd8c585dc3cd66b7d3f2 emission_res_47.out +a31b91affd2693becb04bb15b3f3f25e emission_res_48.out +60c00dacab66fe478458621f86d6f57b emission_res_49.out +1bd04f4d5e2b26499902748628ca13d1 emission_res_50.out +221fd55b5da443913e17b0f9a589d7a0 emission_res_51.out +bfe99fa9c0affd11630df915b459a462 emission_res_52.out +9147cbeae7f856e31f4fca21f4b353be emission_res_53.out +d0a2c828830fc425276dd61a32e37a8f emission_res_54.out +b8f93469f6fbece8c9e90766ed037786 emission_res_55.out +758f85650982576f84b97b1ae06e59fd emission_res_56.out +c4755d9a12347bdc1216200c4d0a1c9a emission_res_57.out +3803c22c8502c4ce574f78b6d2e82115 emission_res_58.out +bd8271f61fed761f7ea11d210354b2aa emission_res_59.out +a8e77fd9345a083d1d0a0f69ab77f16c emission_res_60.out +c5b0a4418a59d9be90aa7795ab3c7da3 emission_res_61.out +e0df953cea43a51481469024896354eb emission_res_62.out +184d6f2b2c1570b98fda50391cdafa9c emission_res_63.out +e94c1ff76409a64a075bf0ce9f4af8e9 emission_res_64.out +7c9d76aadf41b4e46b2ec325fc66b761 emission_res_65.out +79cda130e75b781305e18ae2ebe5989a emission_res_66.out +6887500f16243a91547b1fefac5baab7 emission_res_67.out +085a0dcad45f682893d7d232faec8bff emission_res_68.out +361e78d58c31d2b0ad0cbbd0e1667248 emission_res_69.out +b7449283fff105d8f1bec48ed3f52cfa emission_res_70.out +b51b5bff9a04570bd4427bda37023612 emission_res_71.out +27de67a953d91e10542a7b40f8ad9039 emission_res_72.out +129ca0cbdf72029acd86eee9e1fc8a19 emission_res_73.out +d370f7131dfe86da2b274f67414fc677 emission_res_74.out +4f413a15da31f08eef4c876d4086901e emission_res_75.out +ab1599a934a858b049bfc2aa4843238d emission_res_76.out +56e0c5e6a7cfbfb5d8a2be0417b5b0f3 emission_res_77.out +1ae599fd83065394988453d62632e156 emission_res_78.out +55cb0cb52df03f68523b3eae452372e2 emission_res_79.out +ceec19a35d185684649d0486ad06161c emission_res_80.out +b7eff12aef0294165a224323d92120ce emission_res_81.out +cf9e624e48b2a848ceee7bed4c248028 emission_res_82.out +0f03edb825239f8e896c1978d8f3a506 emission_res_83.out +01c1c5ebf41323cc7b7776391b6502a6 emission_res_84.out +fee50d0e373d431eb4ecb33cbd0fed59 emission_res_85.out +4d740133c33311293cfad127af6727f8 emission_res_86.out +7289e2abe15aac32a58baedbbc5c8894 emission_res_87.out +f73e4d8dd1d549f50ff66883f866c377 emission_res_88.out +4c2fd689dfc152f32ee9a810c1adefa3 emission_res_89.out +5b42752a29c145c398f19da8b9837c05 emission_res_90.out +e23a57c5952eb4a8d613fcb6abe02904 emission_res_91.out +e83f1df14d6d29e95850ca5f5448ec83 emission_res_92.out +79088622f0edfab122bb71f639c3d7ab emission_res_93.out +9c2f725f8243343ab691e4ebfd7f7cc3 emission_res_94.out +3e1f2b86abf7e4e7b5a111b35388fae4 emission_res_95.out +8a34eeade7f6f02f81c8bc0c5e89e328 emission_res_96.out +66d65fec3b275839a3713f47c6974676 emission_res_97.out +065683b8690a13109e4f0f355ce917c6 emission_res_98.out +604d878a8ab1d7caa63f6db3687c2b4b emission_res_99.out +76bb60319bcb9c9347c7909904587658 emissiontrue.out +79c473e0fe20f5a9695ba986ed49987e emissiontrue_res_00.out +51c9f1a24ad2880d9e0ea3542d17841c emissiontrue_res_01.out +490d3b49bbda74557109bc9dd3a1c045 emissiontrue_res_02.out +d8dd137b5a3b487b1c2a81940d691e7d emissiontrue_res_03.out +62fd0c9874e6785657d9a960eff34b5a emissiontrue_res_04.out +f520d3d80c9398db57760d43c91ec764 emissiontrue_res_05.out +f05cf0b8b4863edfec30ce14d1e50006 emissiontrue_res_06.out +2ae42870e3ef937f89705a932709edb7 emissiontrue_res_07.out +95ee3bc984c1c0d1783d1a034dfb2d31 emissiontrue_res_08.out +b00450d5c158542029123592fa6701df emissiontrue_res_09.out +fdaaf60df073a024e24a6cbce6571894 emissiontrue_res_10.out +57378982873866fe1d58acb0938f905e emissiontrue_res_11.out +34340b5318f5b1f56393123c6ebfbbad emissiontrue_res_12.out +ac5d5d8da4d8dd6a21e90bf6827bbeed emissiontrue_res_13.out +cb5d5c2102ca7563e78e283223fd580c emissiontrue_res_14.out +32fbfcf410a8d425b55d11540f4c8e26 emissiontrue_res_15.out +ca43f9ae92e4791d9cf975d3139bbe1e emissiontrue_res_16.out +dbe70f2cbf548a66753a35f43f6d34fe emissiontrue_res_17.out +1acd2634c2258424440963a534d4479a emissiontrue_res_18.out +bdae9a83e5fba134547b87fa95f417b2 emissiontrue_res_19.out +1096d4a3cb479c3f326b5155798a0ef1 emissiontrue_res_20.out +d55fa523180ff6c3ea527f13fe3c154a emissiontrue_res_21.out +ba22113793d78398aaf25e33567847ee emissiontrue_res_22.out +7d7f7a641f3a2ec4b08b910b75e75e30 emissiontrue_res_23.out +f6af1a9f220c7061b0ca51090052f0c9 emissiontrue_res_24.out +5b9db8ac5a444a1ad646b5756dbbf70f emissiontrue_res_25.out +67e966261707e29975dc67462381370f emissiontrue_res_26.out +3ac4fe76df5410fe16317e5210f2ea82 emissiontrue_res_27.out +f3dab89e22c9dde14bd0836a42dc0eb9 emissiontrue_res_28.out +dfb294a17d799e51a465ed521d0537ee emissiontrue_res_29.out +49b1dc7cb2625658997206ca5d0c08c6 emissiontrue_res_30.out +8fab3d7e7cb4822b71262348bd173704 emissiontrue_res_31.out +3a45b04e7b4cd052108f9d1fa8561c18 emissiontrue_res_32.out +0ef3996fda0e1351a227402d3025e9c2 emissiontrue_res_33.out +85d9872528093e8867df2bd0ddf645f6 emissiontrue_res_34.out +ae02ef94549dfb04bc77463936884d13 emissiontrue_res_35.out +153df4691a6e3ef65f0e676a1482fb0a emissiontrue_res_36.out +f53199e96821d7a705e4013356c4a2c4 emissiontrue_res_37.out +6a67038ac41ea30fdde445fcaafbb789 emissiontrue_res_38.out +bf273fbe818f020f143653fc544c238d emissiontrue_res_39.out +4cc3a848ef3b3be2d9445120b0f54fb3 emissiontrue_res_40.out +2036794eba3af345423a2bf465136c6c emissiontrue_res_41.out +0656368375dc2f437d7d7ffe48488f0a emissiontrue_res_42.out +62f005b7e3df033306fa71a3c5e4ba68 emissiontrue_res_43.out +70fa398e124805b967bfbd1d9698df06 emissiontrue_res_44.out +8b5ecbf9d2a25eb479eff79e86c8632e emissiontrue_res_45.out +38c1105f8ef3c44ad81b122bbf233034 emissiontrue_res_46.out +016f8f114d67ea25f982937d9f351f1c emissiontrue_res_47.out +c698b98300b44f92f8f068ec9ddabf62 emissiontrue_res_48.out +dd98fe16e38f64c95fd3d279b00495f7 emissiontrue_res_49.out +4899314cd17d9e15c867390ed409aaf1 emissiontrue_res_50.out +8cde11b2fe0b1f778a1cb29e066c0632 emissiontrue_res_51.out +9d5bd8441a090ae1053fb7b270cf3a6b emissiontrue_res_52.out +313355007445da05067ac8233341233e emissiontrue_res_53.out +924db13ec3bc4739409b7368221eff07 emissiontrue_res_54.out +ae59f1c61e54151e845a83c8fee9bd3f emissiontrue_res_55.out +6f15692958a38d838d1c3830ab9bd437 emissiontrue_res_56.out +db89db9154f10015f79d6b3114886c6e emissiontrue_res_57.out +fd6f1a0f5b0caff9eb22f54e0bc87578 emissiontrue_res_58.out +faefabe9c4e661f3ae8cd3b2efb1f04c emissiontrue_res_59.out +8f265e513a223a5021fa9739110c787b emissiontrue_res_60.out +c5f9b6ec66f83d425f45a29b4e6ca223 emissiontrue_res_61.out +84f40ca90f541527cf8b4c8f070f16e1 emissiontrue_res_62.out +a2208c8cd43ec4a4468dad3a1f1519dd emissiontrue_res_63.out +d6aba0ab7e20d0f92cae8765933a7d5c emissiontrue_res_64.out +14874367d9ee81d06696290da92105e0 emissiontrue_res_65.out +c5e8f71e5499aa150727e9b19719235a emissiontrue_res_66.out +1e7382f8c26898ea33f22be6a23c827d emissiontrue_res_67.out +cb9ea6dedcc9250c7e3ceaf9e3a4b3e0 emissiontrue_res_68.out +f77725c3188c4010346ac32b401b8512 emissiontrue_res_69.out +93777fce7fa2b76fc89d07c45652f639 emissiontrue_res_70.out +3e14066bc26e36b25c1bc43e5da7755b emissiontrue_res_71.out +e00d4e60b1b1550d8d783ab2d9e8a6a0 emissiontrue_res_72.out +12397bedd882e6262512168fc14f6568 emissiontrue_res_73.out +31fd778269bb367df8af9a641bbe1327 emissiontrue_res_74.out +ada0d79c9ecadf95157187be1a52afa5 emissiontrue_res_75.out +21a7e6e4544be33399c595a3233d042d emissiontrue_res_76.out +d6d69814fe0ea9ce07fc67886c430539 emissiontrue_res_77.out +b8b623e485c11fada488b501f9d1a911 emissiontrue_res_78.out +8f03d05002460c21af01d6fb3fbc49b0 emissiontrue_res_79.out +0b9f6bca47495a9a585b96851000b5c9 emissiontrue_res_80.out +81b8a0ea498f4f99513615fc68bf45c9 emissiontrue_res_81.out +84a6ffcb7a598cf14f9c77d0447c8708 emissiontrue_res_82.out +09bac18180c98102303f1c33560ee517 emissiontrue_res_83.out +3d62fcbe3f3da2d3a4fb8e6903bd8dea emissiontrue_res_84.out +1c06aa36643338e7fde60db5bb03c282 emissiontrue_res_85.out +052c8801fc1ca32acfa41106af855ceb emissiontrue_res_86.out +cf1ed503f5333bdc7b6d2ea08e745082 emissiontrue_res_87.out +fd699bbe5eaa9c2f68e3f8b30d02a94d emissiontrue_res_88.out +bef21d88f2274a2ec32fdefaf522bad7 emissiontrue_res_89.out +229b6de864029903e8b3a0c51217edb1 emissiontrue_res_90.out +9c860032e5c7acdff5de4d43c2c401b7 emissiontrue_res_91.out +653b089ab8c48e4597f58b0f6b66568f emissiontrue_res_92.out +384d4510b2cfe4bd56d95b1ca5dd471a emissiontrue_res_93.out +ec2672c5064f57e76a066f3750f9bbcc emissiontrue_res_94.out +1244456435c0ab393a12fcce5d45cf96 emissiontrue_res_95.out +8dfab30828609653b700f22eb7cb2972 emissiontrue_res_96.out +0410b4bb37ae675a28ac51dff235c777 emissiontrue_res_97.out +dbb7f9bd53a06af974aabaaa9ff3890c emissiontrue_res_98.out +a741e8f176a490baf532e3d65ac6bd55 emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -d34d568bae0f54c86cdcc223cc1046a5 light_curve.out -d3c72291c7438eafd464c49a648c3068 light_curve_res.out +4e0973fb2b9e60d0eda98360d506ec5a light_curve.out +c7ae0fe8b6cc0a72b6e5c1e86f7257b0 light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -40c7e21d1057371f2576401e97d7e092 packets00_0000.out -4a4b4b0b38d95e3de03e5f96fbe0d4dc packets00_0001.out -d3f3ab45d617d6c4529a2946296d1cd0 packets00_0002.out -87a6043c2fdab1ff4f0d6c4499e32506 packets00_0003.out -81cdbc53ccab06f206f90cdcfc2e07af spec.out -7a05920b97ec68394b20223b4588b039 spec_res.out +4bac70073eb7a5ee7d9a93078a8997f0 packets00_0000.out +2dba597c8fb23e8d8e964689136ad67f packets00_0001.out +2475d8968b3ebd5b8aaa0382a69d0e30 packets00_0002.out +d9d9ffa16b340ee15706cdb78f27d8d6 packets00_0003.out +e51703a72a79f9a63ead5c524618f752 spec.out +f22c0e5e234d805a092185750e7d007b spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -f3db81fc473257650b015bfc9f9ffac2 job1/estimators_0000.out -679d1910efa0516c70da10fc696bf3d0 job1/estimators_0001.out -ecea23e09ce025a3af4b6ace4e8f716d job1/estimators_0002.out -658f5e7dce6e8408c7b060db78e54c65 job1/estimators_0003.out +c3f19d02d901184f9819bd8e0693d9c7 job1/estimators_0000.out +46286c473a411515bff972ce1fb08fbf job1/estimators_0001.out +f5b424a0bcd3df7f53c0a865d89120c3 job1/estimators_0002.out +501e31d212be9b415d83701862b26615 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index a2d3bec63..4183970f7 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -c3d839f1692d3b06ff2c03db64949d97 deposition.out -4e429ae0865553e3eb26f561d5fd3040 gamma_light_curve.out +83e24d639e428701093b8eb8ed1a31ae deposition.out +623f4f36dad23b153a05e08166960125 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -2a111629a130d19611436117b6c20778 light_curve.out +38598b5933f38e0bdec026a622153d91 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -0bb6a8244d354c4c185bf537367524b2 packets00_0000.out -e1686573dca2a06b00b0ca3b8ab0745c packets00_0001.out -3774a1d01f4f2a957d7a0fc0abbec2e6 packets00_0002.out -f1c0964063848c6fe9cbfce41c68a2be packets00_0003.out -d208e6c529f37bf28c70dcf13daeb0ce spec.out +d38d8d182dc970853bf9187add77d08a packets00_0000.out +25d68708254be7a9c1c3c4fc42643f39 packets00_0001.out +bd64af97330ee5a650af344f6e411cb8 packets00_0002.out +437bbf940cd1d0e01fd525c0fc81f31b packets00_0003.out +ebc371bf6e228ab45b07b55831747255 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -f6e389b9110d41a21655c4e71f70911c job0/estimators_0000.out -b14130fcb2dd68eb370109e97147bd41 job0/estimators_0001.out -088ab99d8650965eb4ad834d4bb404b0 job0/estimators_0002.out -83567e100201853207e48cfa95147bf1 job0/estimators_0003.out +d9ba577265c55a27d582dbe69a1decb4 job0/estimators_0000.out +9511d1207484ff6c2761b09f70944b89 job0/estimators_0001.out +919222f66b0e10ef65275e50daaec4c1 job0/estimators_0002.out +29967c802abc4c3245f93621f11d9b49 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt index f30a4b1e7..7275e99af 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt @@ -100,108 +100,108 @@ b65007ef75f1eaf1a242c7b3119086c7 absorption_res_97.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_98.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -f4b45a7a90b23b155ed1137cab99f4be deposition.out -75093ef4830d6a5bd09e65e4948050b2 emission.out -5829b7daf6fe67e37064054d6bba2453 emission_res_00.out -8fd981117ba873f994c595ed5607c730 emission_res_01.out -ddb883c2b567850819ba102a59b47e87 emission_res_02.out -7a172b5c5066d4afd3060451be51ec90 emission_res_03.out -afee5f879f95c93848b2c4519827aafa emission_res_04.out -8ae7be83102c2e0af8377ac8a9731650 emission_res_05.out -1c49124b42a383d9f85daf156a1a682b emission_res_06.out -093d349b83f46e04674920ef82ffc445 emission_res_07.out -d4fa52cca710fd5df78212cbcacd49cf emission_res_08.out -da484a611625aab8a93c61a929721fa7 emission_res_09.out -5a25fddd24c0c0ba0dcdffad25429e90 emission_res_10.out -3eda18893351ea6834ef4e02f260244c emission_res_11.out -79f27a302dad01daab624bbae0210bab emission_res_12.out -9654ae0da978280d5113f38f6be98b02 emission_res_13.out -12dd6c43f98a147a08cc187f342e1b47 emission_res_14.out -2327af48ea83f6d2eacaf532f999a796 emission_res_15.out -2c97ee6c76abbe92d4747467d7f788fb emission_res_16.out -9577beb2ecdb0fb670f362c28b95146a emission_res_17.out -9414a17d41d9da950161464125ba9416 emission_res_18.out -f2f8efb27accc4546c561b1ced02fc51 emission_res_19.out -4ffd6cd632774a87da508f2d917b6047 emission_res_20.out -185d774baea0e27ac0d6e102f87e8da1 emission_res_21.out -5c4fb5fd94a9d86089baf9c0461a67f3 emission_res_22.out -7b34fee46123061ed6e8285098682100 emission_res_23.out -b6bb63359168615fa80c77b79034e31c emission_res_24.out -c2de6353a984786879587e0291546337 emission_res_25.out -d786fb69f213c641a46a9453e9990b7f emission_res_26.out -6609d1da91b7a0065db33cf3dd9693fb emission_res_27.out -67970a13ea12ff212393a6aee89a0046 emission_res_28.out -2512a1113c766bde146f3958be1c0308 emission_res_29.out -9063b29c14c418c0d0f1afa1502d4a65 emission_res_30.out -66bffc6efa13eb3050f2013d5a67e859 emission_res_31.out -029f3a4097688808d126ea7108f5cd70 emission_res_32.out -878e6e06eecef794dd26f5d0acd4be5d emission_res_33.out -de767b374e28695d516ba861fd693180 emission_res_34.out -2f9ce28247ed1373e3a3674f084cf60f emission_res_35.out -3efc008ac1e849fa2a6ffb8540e3853c emission_res_36.out -18352a2a0507b7eb6e991d2a5aad910a emission_res_37.out -85db2300c5223e7b697038e999473b9a emission_res_38.out -7e7be9508b44583345f4687c8d70d3e2 emission_res_39.out -f55b599ba5cba7307e8193757d49c999 emission_res_40.out -5768db2c555d143094e2ffc31fa879f3 emission_res_41.out -52c8bd810135c238a0ca114810533502 emission_res_42.out -0149a4892a9eda0a15cd65b05352a4b5 emission_res_43.out -df5034cbf08de9148a95a0c63237a650 emission_res_44.out -a0edba2d37e5cdbf171389b1a112e877 emission_res_45.out -6f096c30976d3661c35a68c319f1d67d emission_res_46.out -c3eca09ff1fed051caeb501c66efb479 emission_res_47.out -47dd5586b69553ba6d67c9138660aba6 emission_res_48.out -ba723e6ef59c9b0d358ef85a09a4e30e emission_res_49.out -e0bc6298b164dd775a0051c146eff4dd emission_res_50.out -9c452bbd3dcac5aaa1841b653c61ba49 emission_res_51.out -d56311351a54c624380c8b26ade7ca48 emission_res_52.out -9994b76114540c2387e4c6b01367a5d2 emission_res_53.out -48abec5ebac19d48c40ff50373f2684d emission_res_54.out -fbc002ba78f764ee5dcb41a8ce0e5ab6 emission_res_55.out -59c3b1701b84e3c015db5b576379793d emission_res_56.out -080bcfc1adb3efb906578f2216f9003f emission_res_57.out -79c806bfc679671ab86abc56d4520ffc emission_res_58.out -24048f60405b0cc219e329b683ec858e emission_res_59.out -d50271397d951ba58dcb88886be66c99 emission_res_60.out -ce134c9fb6f20147b8600c8fa695d5a8 emission_res_61.out -09282f9f0c7d60593b4302417cae2b61 emission_res_62.out -4109e975f2b0fcc835631dd9bef2393f emission_res_63.out -f091a032bf4737533bfcdbe1f5ed6fab emission_res_64.out -b144e3b962b8f7ee1c5480bda14d9da8 emission_res_65.out -9fdee22e085e5f6831c3f48b5a02389b emission_res_66.out -d6cc3924048987e95c54ca36c634f880 emission_res_67.out -41cb0c52d21c7325d0054bca9896e619 emission_res_68.out -4c5fc863e99962ca3da371c13c0d7039 emission_res_69.out -073040553ae5b2c8a7541d2820452508 emission_res_70.out -655c03b676f8b98c9e40d37fdad9fcf5 emission_res_71.out -043a6407b09cbfce5a8a9bb1cd51dd91 emission_res_72.out -049abf32f4498f15cb6edd56de3de4e2 emission_res_73.out -c2df192c987b19a43b7a465b0eddab12 emission_res_74.out -0f718c3512f65ae0acd36d6515abb1ca emission_res_75.out -e81843bd790cab4d8dff50a225ebd2a2 emission_res_76.out -c451b5f0955de79328241d9fbbb87a07 emission_res_77.out -6de61faddc75d87824f915355af95747 emission_res_78.out -c1da33f4c48bc6f3e3f691c976513bf4 emission_res_79.out -d448f535dd077ce795a735e72f4be8a1 emission_res_80.out -ecc46572cbb47b9f055a6434c9414d6e emission_res_81.out -eb7c8fd39611c22eed067207b11775a3 emission_res_82.out -0fa0715a201b385a94c66bcacfca149a emission_res_83.out -098e7baef76f04bf749b6148a9fd8a74 emission_res_84.out -ab45b2fa3956fcc226bfbad067d94a75 emission_res_85.out -86aa9313dc5d790983b1d7df59e0f4e9 emission_res_86.out -bb4849e51f3ae96429c3592aef527501 emission_res_87.out -4451cc4cfdf037389bc6072106e474e5 emission_res_88.out -47ad9709f24823d8d65e470cdc809b0d emission_res_89.out -fe5919b21630652f4488072f7f9c2847 emission_res_90.out -f502db629f7ad3ed40bc9af0ebf58d92 emission_res_91.out -4c5b227c3924be44a332c4be186496b7 emission_res_92.out -d0d6acb2341d18bea4c96a4286e78445 emission_res_93.out -5f2766134dcc89ce606deed857d22444 emission_res_94.out -5196d107eb2b54c6c74e4687120359be emission_res_95.out -4918296dc39730569ad05a14e2fdd9e8 emission_res_96.out -b2bb5a82d8971519af4371d1867fd9f9 emission_res_97.out -8f39f5cb3763a73151185d2c26945a57 emission_res_98.out -bcec3fb0f2919fbf2cdc111d41814185 emission_res_99.out +3078795ab726da1cd2ad7dde0dbda00d deposition.out +ea08268c1362628305e9bbc908ae4034 emission.out +905597a4348f4da3a5e3c3a3c876d533 emission_res_00.out +74fcd7190fe0cdc252bb775bf1e11f53 emission_res_01.out +3e87a9653970951aca91d7710f435c7b emission_res_02.out +bfdba577c91c80632ce68084fab35210 emission_res_03.out +ffb0f3193484f024d7277f3569b0fe7c emission_res_04.out +0c4fd207b77df74bc250d1b64fd74b1c emission_res_05.out +291a7ffffb345719f05f1609e79ec9c1 emission_res_06.out +87ecb54dcd2ede5cbf726318195db350 emission_res_07.out +c09a592073812449fc97fa7a48019afb emission_res_08.out +4701a0b8e7ba619dca3650bc9f3567bf emission_res_09.out +3ebad32f168007b2594c04a834d0b3a9 emission_res_10.out +e749e698ace0433a23eccbd178ce12f9 emission_res_11.out +ef07d84a48bd8a9b79137b3551730e1d emission_res_12.out +91df4ef503695bb7d52bc10de2ddbb5f emission_res_13.out +6e317e80bd6e01032406d57399236d44 emission_res_14.out +3e5e4a24a5dc689e279f06591a263724 emission_res_15.out +ceb92b65ed3101b5f08181a3303b2136 emission_res_16.out +4746da794b2ed8381fb21efe0f616058 emission_res_17.out +e875aee315347eb5b1a613300d2b1671 emission_res_18.out +b00184892f0167846854414db0c869e0 emission_res_19.out +2569fc69ac8f5a4fdb62674ef7148f67 emission_res_20.out +6ab027cd80aea2afba167ad0e7f8bb90 emission_res_21.out +88864cea0f01298d8af69b3357302d27 emission_res_22.out +692b5e61d1ad4a1ae78066903daa16e5 emission_res_23.out +cbc805af042b268c8065f567e50e090e emission_res_24.out +df2d4033324efbe8b9ec79039f0de3ba emission_res_25.out +6f67cc8b24d472a1808612654359421f emission_res_26.out +7f10b71c2716a1ffa32f2851bc903bf7 emission_res_27.out +91419838a8095fb82f1aaf1609e7858f emission_res_28.out +bc3f955aa5eaa02baff936002bd2106c emission_res_29.out +90713318b5fdfa75c6e107f3541d2031 emission_res_30.out +47ae71e20d67708e5d002f2eea4a603c emission_res_31.out +8155a93460bdae204ab5b7096603a687 emission_res_32.out +6e38614f7fc8092d9c6721eb8261e868 emission_res_33.out +04da1f16abb410b1a2fd443b301786b2 emission_res_34.out +87d39c6fac7561a025282dd07e7f7aad emission_res_35.out +47bdbfc8d68c39e450e00bfc289e342b emission_res_36.out +cdc6f57e68de4637ed28dc25bd4321ce emission_res_37.out +5394a9bcb4d43323a1ba463222e8e967 emission_res_38.out +44fdb759f689ffd9f42323e904025770 emission_res_39.out +5f7884a3cbe963cd101d47104902c5d7 emission_res_40.out +b3aa624fa434d321b3edea47c1d23c9a emission_res_41.out +785fe6d3e6bde47f18a2702e7e4b9811 emission_res_42.out +4bb0af3c5e928f760acf36b8d93bf7c5 emission_res_43.out +e2e9b3d2b4975545518ec6c93405438e emission_res_44.out +c150c53758a77c794c604355802bdcf5 emission_res_45.out +aa226f92be61b3d4b4dc54b444a6d01b emission_res_46.out +ad3ef975ea4ff4eaf5b09922ea463bf8 emission_res_47.out +4d359ddecdac58a0d2b79157fed709d0 emission_res_48.out +a3ab52b4891b9c9814cfd7e2b1c21870 emission_res_49.out +e8e20d37a36ae69028084de65e3fe183 emission_res_50.out +abb14d65a5cd7f1dc045066b4ef0dd35 emission_res_51.out +371bd97e8f1c040ad8dcb074bb1d5536 emission_res_52.out +926c8cf1195d8157898fa56306175aac emission_res_53.out +e7a2de45c36d548d49578054622a251a emission_res_54.out +9979b7aaac99200acfc4ba60acde8102 emission_res_55.out +98551baf09ab88c967ef9f5443087fe3 emission_res_56.out +7d4eed4b7bc8779c7cb4a69ceeefc99d emission_res_57.out +314bd58254d83b2dbdb555a6ad233d75 emission_res_58.out +63da2ac7fd42fe91103c92300b89c50c emission_res_59.out +0df7e29fe26ce2b63e392748e3587a94 emission_res_60.out +b3dbbdb468c1d4c4a2e5504f3e2117b1 emission_res_61.out +debb8f31ee899788292cbf2e5dc94ad6 emission_res_62.out +d3af154d9e236f93e688b08dad51b77b emission_res_63.out +101fa233822fae598a8730a3cf0c6e19 emission_res_64.out +b39cac497e8c4b11ae6cc47461cc18e6 emission_res_65.out +a41575e3e678dd757c0ec94454300df7 emission_res_66.out +739913b10c115d0a8f5a55386a2c820a emission_res_67.out +73d8cb84f4cccf8b3c4b614270cca7b5 emission_res_68.out +16f3b8cf4d53bf337a9c53ec7c7b222d emission_res_69.out +fca5667f65111a7f8b8cb6d2d0e9ed68 emission_res_70.out +80320923208a53874bf246f1175a1c84 emission_res_71.out +b47fd0820bd1367b9bd2682e4496585d emission_res_72.out +e1b61feff861af08466095c3f6b30afd emission_res_73.out +15b0a26b333f997e55757bcc5614f0fc emission_res_74.out +3a8c6a229ff3e9585cbc24c85ecd26d8 emission_res_75.out +1268423ad8146bd91650e7ff2f493713 emission_res_76.out +e247cb777d3721e2808ff7ef2d93fac3 emission_res_77.out +44397ccffd463c0b2de1beb70d94dd30 emission_res_78.out +c14b84bda8f05c77762c51c4113f0b0e emission_res_79.out +bbdda808eb721db9566a61d7b4d8f84c emission_res_80.out +6c4dff26f01a3bebcfba54bdf07af379 emission_res_81.out +b7653aab8ed46769a06bf4cd5b378b8c emission_res_82.out +b75cefb349a4a792f413ae8d96551d48 emission_res_83.out +547403061a8b34f2c44e7187848604b4 emission_res_84.out +cf5d866db9a57313fdad6de9f65758b8 emission_res_85.out +66c6927712880e790cdd936252ab787f emission_res_86.out +a72070f629252f26c7dea2e692c23d7a emission_res_87.out +ec5e830981de5b5e0463fd7068e8b1d8 emission_res_88.out +908b47f21b0aff0a5e04f18badd9a567 emission_res_89.out +2d2535c2bcbb596493d1abe42c0a0b57 emission_res_90.out +15ad3098729e6eb6a79aebf48e9220c0 emission_res_91.out +8311a29c47cc341acb00e528a4407014 emission_res_92.out +1398d9029aa5d04d579c6c10e1b958f7 emission_res_93.out +f18e3d5b66246c17040b02e5eba57243 emission_res_94.out +8360f3221bf86aeb22a3a248b6844501 emission_res_95.out +9bad4777ec16ef504f247287517f3a44 emission_res_96.out +b2fcb29f5a8e56cbf705d4bfe2c63083 emission_res_97.out +cc7158012e5cfda79c7fdb76b5d8133e emission_res_98.out +48d970c4a44078810d413d771698883d emission_res_99.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_00.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_01.out @@ -303,22 +303,22 @@ bcec3fb0f2919fbf2cdc111d41814185 emission_res_99.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_97.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_98.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_99.out -bc969e9083dede109cf7f707b63ad9ef gamma_light_curve.out -556b6b6bbcf1ab42b061598f456c346a gamma_spec.out +613057e0b479ed4e8344053a6dea55c6 gamma_light_curve.out +1a9ee77b546d00aa6069dbe9691b0454 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -7ef6a46b4be161685da0017140a637a2 light_curve.out -641259ce7173be971ec33146b0d359cc light_curve_res.out +381991b1150dcfc0862c42b91af8dd4b light_curve.out +b214de2593a6668d4807d61566e8020f light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -f27aad6ceefcab92f4313bacb3fa66bf packets00_0000.out -04040dea069b5a0a64de49140aa9033e packets00_0001.out -263fe3a2ee4332c1f4e797933b49b99a packets00_0002.out -f1505615f6c4eb1e85d1aa24a176837a packets00_0003.out -b1c366ce5b769c056300d6315192d85b spec.out -c9e1466b37cab169b8dd356f4c85814a spec_res.out +594b4252eca354ff9819dd598d1eb3ce packets00_0000.out +ab125b9ee59730252b5818b2fd25d632 packets00_0001.out +33ca6208c9ca199366faca0c11a17c53 packets00_0002.out +2de9ba1fae243ff7d4d91076390e665d packets00_0003.out +7c20e85e0e15eeca78e93c9b4b90725b spec.out +5002b0d948af7208b4c11e9745c26ea6 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -b0edebab4c754d62f9b072c6a09ef21d job1/estimators_0000.out -930ab703410ca5c0bf6f9ea04e561a2a job1/estimators_0001.out -202e2c600ccc763c705dbb3430d86592 job1/estimators_0002.out -1643ec15bf997882ff0884053da69fc4 job1/estimators_0003.out +c60a144bdca982efb6ecc99fb4fcf6a9 job1/estimators_0000.out +5c6d9b1113f373a7aa306046e9c65e1c job1/estimators_0001.out +bce423f49527e8720bf338e1de872479 job1/estimators_0002.out +f25ba18020d577cc1b423465655fd28c job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index baee78d50..2eb1629f3 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ b92a62c73f9262be2a6f6db5294d762d absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -80029349b0bceee54f92336772d14913 deposition.out -c7965863eac5bc1658fa04b8bd79abe5 emission.out +f0e5fbfef0724ae666ccfc113b6aa715 deposition.out +8730f6303955f5357e0ea93ee77783ac emission.out f5902ae8e529c0e852df6b3614fd1597 emissiontrue.out -c05cadcbb32dc5c134e828d030195e40 gamma_light_curve.out +e859530aff21ef8e260a5b5e29f40b04 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -e77fc504b0be4f773f1a56bf626cf488 light_curve.out +e8ca5a180498cd2c6b467abbdd963f65 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -28fabd7ac047ca9f5f85b1a657989a02 packets00_0000.out -69a9179cea390346d94e9dd236e929de packets00_0001.out -881ff9d3ae638efeb80ebba61d8d34dd packets00_0002.out -a7b23ba1190f873c1dbd7db6be2e9713 packets00_0003.out -5074aa0bd22851ea4c0c27746e6e1b1c spec.out +d387df4375ca73d6f294778d3677c429 packets00_0000.out +8b987921b1f6c093c83e5c505e96f0f3 packets00_0001.out +8a4fc5edcc2040355cfe344e7d640b48 packets00_0002.out +e30535b6ac363e22e4842b659173e798 packets00_0003.out +e04955ea3322610445a358f3e9b28fff spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -4419b3e3caaae65266118841a281361e job0/estimators_0000.out -6a9b5a5c42ae4eee582c66e8843afba5 job0/estimators_0001.out -05a3d42c162ac971bb3a051e2e6c1c1a job0/estimators_0002.out -03a53cbc94e6a1fcedfd4b2c9c8e5969 job0/estimators_0003.out +da7c966014744505a37187061214db2f job0/estimators_0000.out +50c01aa18855a5347923cd2147b50b79 job0/estimators_0001.out +e7e27f1e9a6bc19b9f15bfba533f3797 job0/estimators_0002.out +84b21e3c2c16bb577e9310f8cd5e877c job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt index 03506c7c0..a76597a53 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -6390bd98f8d65aa75d86d087153e2a6c absorption.out -892fe09e0a0dd04eca37e3d62c67c75f absorption_res_00.out -d4f365316d44bc472e2e2cfd7f459a89 absorption_res_01.out -098e3671471143ebcf442722c4b7185b absorption_res_02.out -3f016bd96e3d0e4e0013ce4fb3928f4c absorption_res_03.out -cc69a617accdd99f3337fc5942a0c29e absorption_res_04.out -e2f282097a4e07629fb3f5b6f7145515 absorption_res_05.out -16217a531d1e07681df104052390c7c3 absorption_res_06.out -de4bce164e7abce1a95e0866f4e18db3 absorption_res_07.out -f19b49a0b4f19e7e2d192cea2ef68cb7 absorption_res_08.out -b1a5f997982524749ee61270a486496b absorption_res_09.out -40cbd4c0af784fb09cd9e8b459966816 absorption_res_10.out -65145b0317bf7c2c6276462572b64cf7 absorption_res_11.out -16655df8816df3eebc92a4f835e4782a absorption_res_12.out -1f7b509bc7011df3f5d1e5f9f43037eb absorption_res_13.out -ad33ffc4cbd9851e1e4a92426997fd50 absorption_res_14.out -a7a161f9e48a55b856d6e97da4811ccc absorption_res_15.out -9ff55f41a287bb6be351e989be8c41bc absorption_res_16.out -6120a669ef4afa9640509099b6ed8e61 absorption_res_17.out -84ab6b960c8dfd315c44d55e1742235e absorption_res_18.out -ae6add8406aaea59fbc7a9152aaaf4b3 absorption_res_19.out -9ad44af12242662ca88d83d8e5ac73b9 absorption_res_20.out -5cea6a2a60b5de9c83fc8fe288c38c41 absorption_res_21.out -4d9de46227cb5b57d109e159a27fab8b absorption_res_22.out -aeeeccc38dc69f9ad6c5f8418f63f73f absorption_res_23.out -706f15b6a9a0963f3f50ba674930bd2d absorption_res_24.out -d7cd8f39f141b0c7695ffb508c3f606b absorption_res_25.out -768cf6cd512686f126cad2b82d651cd5 absorption_res_26.out -a70e3f04ae3e644aa5752b0a229ac61c absorption_res_27.out -cb06904b0384e4dd8e35b947ce1b9c41 absorption_res_28.out -7501e05b6fafd3e881f601dcec0d4a4d absorption_res_29.out -c13894236389988fee16498d26e69187 absorption_res_30.out -bed8e26ccb8dd809411a3969ccac9d0a absorption_res_31.out -18b814933276d5df694e0a8a497ddca1 absorption_res_32.out -a95d140b9c2ee64414ce1bcddaa4650a absorption_res_33.out -c7b4ecd4dddee7c0de43f9d219f991a6 absorption_res_34.out -92f04569a5c4628b648846775ebed6ca absorption_res_35.out -59064130832d6b1c67c27fadda005898 absorption_res_36.out -4f4526210f3dfbf16efbf68d7b9db19d absorption_res_37.out -361ef14e0411d1b28c9ed5cd0869d936 absorption_res_38.out -8736cc7a847bcb0312c22ac2d7479982 absorption_res_39.out -086a76adb203860519a9f17cdee53a01 absorption_res_40.out -c86296cb0e243b1794d82d5071cfddbc absorption_res_41.out -225c86c6ba309ce409e48ddeeb72f203 absorption_res_42.out -7951d5a6b2bed5e6801820f44b64a8e6 absorption_res_43.out -ef772514bcb2ee096ee37d17ac08613e absorption_res_44.out -ba6bc7fffd7a0c23c11705c2ab56bd29 absorption_res_45.out -3fdb657ceca0e92ea7f505c4a5913d12 absorption_res_46.out -4e38c032caecd870a51f8ed83135edf2 absorption_res_47.out -dbec3b44e8cffb1fa07581fe0d089f27 absorption_res_48.out -5467d2da3ec50dfb76c91d786ced5d5b absorption_res_49.out -caa21f4e34d790e7ec1ef211c3be26b9 absorption_res_50.out -504b6022c5acf9f6b05144393e7f5e17 absorption_res_51.out -62d73bdcba085ff8a1dcfa8fe1b3ccab absorption_res_52.out -7d075f6a236c69330214f2dd698425f5 absorption_res_53.out -628e50b5ac1953a3d5c4fbd51adcefe6 absorption_res_54.out -6a73942a731a9180fa3a079152c5f4f9 absorption_res_55.out -a6b4f0e37a20030bc47c68f21a19a0c6 absorption_res_56.out -a1c84fea212ef6134c9de131b4cc0f05 absorption_res_57.out -aacafe75e06dabf8eee925a0c7bd1df9 absorption_res_58.out -f1b7ddea61eeba17f8735fdf296f08d5 absorption_res_59.out -adb0c3446345c3eede8ad78d7044d0a7 absorption_res_60.out -f581edff533f6c5ecf25b8bec2f393fa absorption_res_61.out -2c683281ae9b0bd0252a7f847be21776 absorption_res_62.out -173d44d2ea0f0c0896b6151bc4894ecb absorption_res_63.out -5ae48934a7882802bbc5abe68f84eb3b absorption_res_64.out -ea9f23509e968e3175c4bb2230b2190f absorption_res_65.out -045eaf088812f0f91157bb2d0f0d262e absorption_res_66.out -ef21621408bf7fa1e2d9e4f86041777f absorption_res_67.out -20ee674fa48a6372d18eb8cc771cb5e3 absorption_res_68.out -a7331029fa90202bf70772b235923921 absorption_res_69.out -f96b40ca52eacf1c8c6ece6e5922ae6c absorption_res_70.out -e7bf444fd3a8a37f0b32e00de164af50 absorption_res_71.out -781780aaf86695a7ed306bffa5300082 absorption_res_72.out -a3e1e510a46d6f2dd4fff1411aad6dce absorption_res_73.out -22df1877d9a646562c9000a8db92aa88 absorption_res_74.out -11c19b6a8252a6014880a01b2b955559 absorption_res_75.out -0cbe0e124cdd5750927a8168c2635dab absorption_res_76.out -1727c548e9287663908ea0a73d21f301 absorption_res_77.out -f402c7a8f3420bd1626da4836aae3f3e absorption_res_78.out -b679364bb5da38094787784630137bf5 absorption_res_79.out -29ae3a1805d0ef23e4181e297847590e absorption_res_80.out -b57b7c35febde028fc1f81d50164d186 absorption_res_81.out -af9abe37b298072a09428dc6ca51d753 absorption_res_82.out -c0bd6d36830263d43f4d6472fd80d5d5 absorption_res_83.out -156da59157df8b939ff9f86187c00355 absorption_res_84.out -c512c81865f15583a2a7ff02b338ee8c absorption_res_85.out -3b7c85d6ef193b4b0dcf65a8df78892d absorption_res_86.out -756ccc4ca1b9944323f04eac4cb99f16 absorption_res_87.out -29374f37c69323d19b03ca4b8d303f95 absorption_res_88.out -886abda2930b935a9d8b12ea5ec3e5ef absorption_res_89.out -7d3485422c8d0903bb136cf8dee8f156 absorption_res_90.out -fdb9e3a91382855595796d88aa531f64 absorption_res_91.out -258c85e8edc16f5aff98ac176885d177 absorption_res_92.out -9a60e247de718ab7e7ee04311c3803e1 absorption_res_93.out -ee210d7230ace784b6db858118f7adbb absorption_res_94.out -70474999885af5dc2cd90c681e62a3ef absorption_res_95.out -d634fb1ca7b494afe4ec076de7923d1d absorption_res_96.out -0a6e3923f54b4e7b95fd90323d515925 absorption_res_97.out -e929e46941140b877e14e8de751c3585 absorption_res_98.out -9d946de63b6e768dfed8d531caf24dde absorption_res_99.out +59fc9c86755a14869fda7b5853eb2a1d absorption.out +5699e513a97f35794ba4e2d1f713e9f0 absorption_res_00.out +1e4a8d7889dd8df1833ad3871e89f872 absorption_res_01.out +47361aa95c10e36cf7628ac85269ed89 absorption_res_02.out +81d2c576ce4396a78d67d99bbc2884d2 absorption_res_03.out +58d6f18d732e60baa8221466ca1f6c42 absorption_res_04.out +3d8036084a7c243aee008a41b84c82f3 absorption_res_05.out +654232f48ac5d73fae562e9827a47980 absorption_res_06.out +a65d520eedaf4ace23fe1b8aa7269c27 absorption_res_07.out +0b43a0f6217b272d8ae54b4cb930ea1b absorption_res_08.out +0b0d9c6f559a7d577dab692900c0d884 absorption_res_09.out +2cb4ef6dd5447d6992409a48a3c324a5 absorption_res_10.out +7eab021356d76d656aa4aff3c373c306 absorption_res_11.out +e53882c51c6810319762bcd13956940b absorption_res_12.out +6ca3ba6c70446c79811b80ef27593320 absorption_res_13.out +b5a4ebcbb51e1e34f18431894cc7e93a absorption_res_14.out +d547cff268b0162006ec455f52901452 absorption_res_15.out +7cf1c2b9c75f0a1b583707a21f230eeb absorption_res_16.out +d1ce889a47fe62fe335dd59eff854ef8 absorption_res_17.out +a3d7e057de5dd712e069bb778d1300d1 absorption_res_18.out +c544d484855b013381f866821262c56d absorption_res_19.out +ae965203bbf105f69ecaad09c9a39f19 absorption_res_20.out +62c7f35e22f4ce365cae8b7f1403fc7d absorption_res_21.out +af95b5e1a8492a209489771307317b40 absorption_res_22.out +eb6b1479fb4cf46104be67596767a96a absorption_res_23.out +84cf3fa24b5962d4307e006f5d414b9d absorption_res_24.out +7edeb556771ba2d0d61ab09f8be9f959 absorption_res_25.out +1a5cef5cca5aaed0c88581b5d269d3d8 absorption_res_26.out +4efe3f2d842f1a254144608a22bce5bc absorption_res_27.out +657e4efae97aa961a768806af364e513 absorption_res_28.out +cbaa6189af1727a51dcde346851232b9 absorption_res_29.out +2029b094fa281359f5a50deea2fc0133 absorption_res_30.out +3965b4cc8791a9f9c951c2d979b0ccef absorption_res_31.out +995cc52f4f96b17592ffbd2f2e852f93 absorption_res_32.out +444889bc7fa608b3cb3ad04e57b56708 absorption_res_33.out +9b2ecefcdfdd219ff8d4cf1ba5498df2 absorption_res_34.out +40cdb14149d6dfab4bd357ac1c9aa95b absorption_res_35.out +425a6477f02ba50d41fecb6f67edc9f6 absorption_res_36.out +83229ae9e485ee173cbafc73bbe4878b absorption_res_37.out +548fcaccfbbf7cb09129810efeec76c0 absorption_res_38.out +720775c08a281d1b403f66d011d99ce4 absorption_res_39.out +754d3d90c979817cafd31d6ac2792c1e absorption_res_40.out +a82035f4be74da100da07179db11baa3 absorption_res_41.out +ad2486b8014bedfb5dbb4399c463e7b5 absorption_res_42.out +bb1e67da051f0711cd81b0826eec59e6 absorption_res_43.out +1dfe251c4ad9aa6e0606556552080e38 absorption_res_44.out +c0c13e76b1d0e3dada0d051f089f1b83 absorption_res_45.out +ab7785d535acaa6bf6257afa8f42ea53 absorption_res_46.out +f859f19fdc59905332b5a1107376b8d1 absorption_res_47.out +31a8902bec89a4ca1342e2a5b9ba9571 absorption_res_48.out +23625678a2c320831e020d6fd248c17a absorption_res_49.out +e2d48d836ac96f0fa7a8cc4f4704467e absorption_res_50.out +e4aa5e135aefcc69b73ea3822c581961 absorption_res_51.out +2b40a35a6d091a141991d82c40c3b3f1 absorption_res_52.out +d5dd001c02d9bc52c3f4656378094ed9 absorption_res_53.out +28760ced295dea2282ceb1c3c8478e8f absorption_res_54.out +80b1b844001be4cff21cb93d0d048d9a absorption_res_55.out +45b798d072019a147bb90c50c01438da absorption_res_56.out +609b66ead28e62fc97df2426bf98d4b1 absorption_res_57.out +8b20e1daacf59cf053e87d9752b2975a absorption_res_58.out +f85f42f7bdb876dfa96ef2e871a2a981 absorption_res_59.out +a6ea3b2b8ee67d2070f2111148f82dff absorption_res_60.out +b4810c4759f0d5b9785318285b666367 absorption_res_61.out +709156d689efd8d44d92c0208d3bc1ea absorption_res_62.out +fe18b702a2b8289412e4bf549ec905bd absorption_res_63.out +78bd6f6765332075ef2db579de49ca2b absorption_res_64.out +cc6fecdd09b48631ea05eb197677f112 absorption_res_65.out +4f5879e6abdda283320668d43f97bb85 absorption_res_66.out +4212abd7863916e8c33a4a97d5a67f10 absorption_res_67.out +2ec16e3bb4cf424b56bfcd155c5251ae absorption_res_68.out +f3e414e7877807a8a4e4745506eab78b absorption_res_69.out +85db39543bde77666e0b7f8a4af198f0 absorption_res_70.out +71612d6a5ced5ba7b805a0895f557e94 absorption_res_71.out +328fffca68e8c6d39334f3a197b70380 absorption_res_72.out +43ac73acf6d50b951565279e1397bab7 absorption_res_73.out +a1abe61126b1b688f8ae717039b47543 absorption_res_74.out +a3d7ac2813296f7a73d609fad17b26fa absorption_res_75.out +07c4222188ea6047b6b83026460e558f absorption_res_76.out +8721b59825456b357baa7fbe8e9bb56e absorption_res_77.out +4205e4db3de15c631c641147400fcff6 absorption_res_78.out +da4be9ddb59f36a62f5301beb639dbd4 absorption_res_79.out +2998108c4ccf134e57c951c9caa1d965 absorption_res_80.out +56e0396d5d80fdf6338328e54c4bbb0c absorption_res_81.out +b56c8f45a53827e307489641704e678c absorption_res_82.out +3038012354feef1bb95d668c209bdaea absorption_res_83.out +0c01bf3ed62def5d42ea54427dbf29fc absorption_res_84.out +aea034e23712e94a0528a0c6b2610397 absorption_res_85.out +c19cd526320bdcfcaa4083c50bf765ba absorption_res_86.out +a49c7664fdc62cef9247e2c9bac86239 absorption_res_87.out +92cbca3e62951205c7009b9cffe2f3b2 absorption_res_88.out +ced000627c653bdd3a0790a00a5120da absorption_res_89.out +9a8028e63dd350776a4681a3650766f5 absorption_res_90.out +576761b845125ff0eb392130097ac41d absorption_res_91.out +8819d5c6e05dcc2a92185d383e5842af absorption_res_92.out +40f4871a128882d889ebc8cd060f0536 absorption_res_93.out +478efbf8b444723d698668abcf8470fa absorption_res_94.out +e02fc87246408d5953b2be4de890b836 absorption_res_95.out +c3637a977b102295def7d0a520cf20ee absorption_res_96.out +9b56addf11702664760724a5d5103946 absorption_res_97.out +3a7585780b344f15d8f04ecc6786d49a absorption_res_98.out +7449cb79b49f745f19a993f36a12a98f absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -d2c5fe773d55456194ba11da23c11e32 deposition.out -438228eda635aa8f73b61c652fe61ddd emission.out -198f54e411c8107cbe3db250a714a84b emission_res_00.out -879865de42aba3333e0e8d05c49b41e0 emission_res_01.out -98337a21c2ed143a6644672776078bc1 emission_res_02.out -140e18fe81a3efcefed41c5bc5e73c3d emission_res_03.out -e00b8ae4095da882e30a33145162addb emission_res_04.out -2e10fcfbb185f531601f49c47771a11e emission_res_05.out -5e79433e99cf9c22d320f1eeef229a45 emission_res_06.out -48257aa9d1ac1d9c40886bcc75800642 emission_res_07.out -dc8e8ebb9fc05fa1b6606e3dbead93bb emission_res_08.out -26e4bc5c96e6472e8cf44790e6ee4d9b emission_res_09.out -7d88adc78913d83030bffe9662264aa3 emission_res_10.out -589c0697fbe34bba11869aed97e4a40d emission_res_11.out -08ee80801a4570a68ca5fc64db061b65 emission_res_12.out -fd4f114fe3a44905025ba57cc6eb05d5 emission_res_13.out -27b78dbc1f582bbecdcb0cbf2f4a3695 emission_res_14.out -967e25f0d2245d1bd6ddaba485e2c701 emission_res_15.out -004257e2276c6046879065c692c8457a emission_res_16.out -ab1ed018137c183b81daf5b6a9fa2560 emission_res_17.out -74bcaa0530b437aecd2e52fe50aece0e emission_res_18.out -762f86ad6c276a3b49a797af3fcf1913 emission_res_19.out -d9b25447cac1f12e6c7ab40778f4c9f9 emission_res_20.out -23d65361f91bbdd91766d93e9601a7d6 emission_res_21.out -161a0e6ab4b6efff239306458d31ecb6 emission_res_22.out -864077db8658190ca0a52eee1c042eed emission_res_23.out -6c176d7ddbee190d511e02fca16d33ed emission_res_24.out -dc69bec36e65f86e5f89011655f31ea4 emission_res_25.out -593e9ede070688a4746e8c6361a2a4a3 emission_res_26.out -08dc0b73243cfc21858a35404ad39826 emission_res_27.out -dfb5e5db3e719d876fa06acb7ec1e512 emission_res_28.out -b62217e3e261b0829e7817f0de16a8f7 emission_res_29.out -019002b754271720aeee641dbb00a51d emission_res_30.out -41affc65d29af773fc3b24a8b03a2731 emission_res_31.out -44f4766c74fe6e56f4104ccb93ce3b16 emission_res_32.out -ff5d7f975554cf37a6f3eabf7a023e09 emission_res_33.out -c1dfa6dc64d8015df139feaaf83f6fd1 emission_res_34.out -a7e4bb3b42b1e6b737cf0ce3a390e708 emission_res_35.out -a25a47b7bbbeb11d043b34e569f67bfe emission_res_36.out -7578aa07fbf3a0408510c9536094d544 emission_res_37.out -e2b22fcbcd87df1c111137f837e294ba emission_res_38.out -fda5c872eb4ec6a6c36f1e5988d4d090 emission_res_39.out -028b1e00f5515deca81f8fee5e7069de emission_res_40.out -ad2810b47c8bcf2ba9d0925535268efe emission_res_41.out -38421bc37654d042da1b0984e635fa8f emission_res_42.out -8c0a029f6b72452452e6f9cab67c30d7 emission_res_43.out -4036ace941002dc550b19e77f2c0ab08 emission_res_44.out -43c288371c4fdfd4bd6a001bd37bf08d emission_res_45.out -0e91858634fa4016ea93b616d7b8f868 emission_res_46.out -99147ce85d6232f5cb41bb47662946c5 emission_res_47.out -ef3be1b68ed89b34de97e7b9c2070756 emission_res_48.out -ecb1deca7b19baf7094c9775204c4685 emission_res_49.out -fdcb9f82f92e66920d89b00988c55750 emission_res_50.out -c1b1069422bc48dadea0ea36ecbb8c3b emission_res_51.out -1a77c59a0db991c4c4b21dd5138d46d4 emission_res_52.out -e190b8e1b1ad79cff088b76dc0a59c18 emission_res_53.out -5d01f60f3fa1a840665a0c892e6f592e emission_res_54.out -5483bdf672afa3535f12bca71b618c68 emission_res_55.out -1443d78cef87747ee5d02464febb9e80 emission_res_56.out -dd2a94e1d85f0ae322e9097e50b4779e emission_res_57.out -28fb74940a4095a6d59b62cb30662b12 emission_res_58.out -f42fe2f1cd868a888aacee193f7c14f3 emission_res_59.out -5bb6d514ccf5a751c1fd40591698cbd4 emission_res_60.out -e07e4e3a48754a868d859403ff96cfae emission_res_61.out -f857ab20d5271b115557c55f35a16602 emission_res_62.out -8ea4b7402e976013ea513ffe5ec43a81 emission_res_63.out -0a998f3cf33bab1af691628fb9f8f7a2 emission_res_64.out -6a2929263cb1ee1f8fd8d724f04effdc emission_res_65.out -3fa0aa370157ed157a1175f988a8b528 emission_res_66.out -b929dcbe564977e199311de707986dc6 emission_res_67.out -a0464fe4b04f6c1331ea5824a3bfd8c6 emission_res_68.out -8e760f8fbf988d1b979458a43a901473 emission_res_69.out -1aa5dc96b3b33f3c83ef2a7f1e53460e emission_res_70.out -14afc2b655f53c0fe8ba62d2397beb2c emission_res_71.out -44bf9db049992233ab7925038b814b18 emission_res_72.out -c21ab736ac47525c2fa22864c2adcde0 emission_res_73.out -d8e91c631bc02fe0fb9a2685f768e7b5 emission_res_74.out -a583ac76447feedeaf06fc8729348f3f emission_res_75.out -3cd1620517a6af7036a53aec3fc093cd emission_res_76.out -5e9eac8c4c98da0def0e2f4815faecdc emission_res_77.out -1fb03b992fc40a7b5493fbde261bb855 emission_res_78.out -402399bed0307fd578e481c18138daa6 emission_res_79.out -e7d80bb74a0e43a59425db4d7faebde8 emission_res_80.out -f4d89cdea2234e041fd454c423e855af emission_res_81.out -48dfff34fd813d3ae6a164eb5eaa26e0 emission_res_82.out -27aed7a66bfeb0b9f84bee6c6d047fb5 emission_res_83.out -82a570de5aef86155b9379e4eb7b66c4 emission_res_84.out -973e58fef46b7063ff9c3e45d601fb7e emission_res_85.out -e763c2530af740d5da67b811783541d4 emission_res_86.out -9d4935a264a5248f4a4009b9ace7b595 emission_res_87.out -68fd3ca5db638742ade68ba423e9f8fe emission_res_88.out -e5302001d01fee615f3d6c2b42eb13bd emission_res_89.out -ec532294199664811cfb76c64506e0df emission_res_90.out -00f5f98abe7b05019189e6aed49a8dc9 emission_res_91.out -4c19892eaedf7ac781473c91889dcb60 emission_res_92.out -9e6f1c8d2b60b85e794a3f7e0a3e2cdf emission_res_93.out -547f4de769bcd9196eaf5235452b9584 emission_res_94.out -a9bc21f81a66c9b71f7dbe8f8ceaa5e3 emission_res_95.out -b04e1a3c3c367803eac0ef8e0c6f8132 emission_res_96.out -3dfcbd1b4c1531249b0a6421ea5d1156 emission_res_97.out -92d4e95b3c0772272f3c38e4748a6999 emission_res_98.out -969849db4ce8282a5e1d0a799d775576 emission_res_99.out -e72e56ee6acd98469a772c769e9e1650 emissiontrue.out -998636891fb45463865536eca5be4420 emissiontrue_res_00.out -826af94ea5cc77ea5b783ba3c23f960a emissiontrue_res_01.out -fd560c6d280a1d7da694efea12dba896 emissiontrue_res_02.out -402046c2b9ea954d947fb0e7f7348104 emissiontrue_res_03.out -00b7593e53f9535c596e6a0f2a0d3a2d emissiontrue_res_04.out -22be13d0e0bbf0039b9078b7466dca75 emissiontrue_res_05.out -f5965416fe834ea94af15adfdabdb057 emissiontrue_res_06.out -392ee8830c35a95deddc57f47d696e85 emissiontrue_res_07.out -d560f07e07e9214e5e69d463ac4c3200 emissiontrue_res_08.out -d29ff022b17ce73e41b2ffa7226b92a7 emissiontrue_res_09.out -ca0b6dd64c32c37eca5e6f4ff40a9d27 emissiontrue_res_10.out -e91f161c9cd21a4bec17a65d07faf4a3 emissiontrue_res_11.out -614a437a206b82364a2af19b3b0f7a86 emissiontrue_res_12.out -3cc1cc86a88cd5afbc4c1de23f1f87c9 emissiontrue_res_13.out -4442e192e31b4e0a6af6a6fe5e7645fc emissiontrue_res_14.out -f20613980c40bd1688eb5c60ff7a3156 emissiontrue_res_15.out -9909f2ccef27c3ab4ce6e484e741d4c1 emissiontrue_res_16.out -d5baf20f19d9e6993b8a14354745b80b emissiontrue_res_17.out -282e324c2efe5ff144f8f6fa0ba4ff59 emissiontrue_res_18.out -5654d28b5e217fc69cb7302966938eab emissiontrue_res_19.out -1f473fb5758fcc545dbd51aa6dd89156 emissiontrue_res_20.out -ed21b880c93571c7d28d96385a0afa4e emissiontrue_res_21.out -8b0721b98f33c4fde6b7681c512a184e emissiontrue_res_22.out -aef6d03a026672fdc580cf3a088ef38a emissiontrue_res_23.out -c5f082684fe87e22cc92d99f03423b4a emissiontrue_res_24.out -44ea3fb63e38f900a8723cc625d8ebf6 emissiontrue_res_25.out -450cf6ec938f7cdc31b01bd1d61366db emissiontrue_res_26.out -be236f7a426066d9b620519335d173ff emissiontrue_res_27.out -b72ac6aab0992bc760887c642236a467 emissiontrue_res_28.out -20adf1c66dd3922d60b2008e4eb566ec emissiontrue_res_29.out -5656d584c7c0bab64401b454a5ce0f55 emissiontrue_res_30.out -e0e6ed53678a270e3f50ac5d8c86e9ae emissiontrue_res_31.out -d2a6e84ff661920d6944077b5d1c95fe emissiontrue_res_32.out -8e943a374b65a3cfbf36a3f8f7352aa5 emissiontrue_res_33.out -49ef457ea0636885d9cf7403cf0d62ee emissiontrue_res_34.out -53b3a3ef7fcc09a6a41966ed5479d4fe emissiontrue_res_35.out -4cafcc2dbbcb7aefba7900ad32a2ea8f emissiontrue_res_36.out -47117d2d0cd2825dc4d2b16ebe0285ad emissiontrue_res_37.out -ee45bf7444c7ba7b5c88776c94201b19 emissiontrue_res_38.out -001b004c8ec5386f040991a22eca4b20 emissiontrue_res_39.out -1b617833857ad1489cea321337ee90a0 emissiontrue_res_40.out -71550b0c62c6ece539931dc65bef4ff9 emissiontrue_res_41.out -f5570df9f460600cda68d7e5f818db61 emissiontrue_res_42.out -b847a7243a1516d4cccd76b766ee659a emissiontrue_res_43.out -5ea9dd0f6958a8a1d8827670aad27132 emissiontrue_res_44.out -9e98feb7258dc7caca0b5f34a1f87be2 emissiontrue_res_45.out -76fbda3b3e05421a919f614924b855df emissiontrue_res_46.out -5974026832cd93618cac227c8f5abc92 emissiontrue_res_47.out -0665211c9c5434e20aa4ff566d3e5fab emissiontrue_res_48.out -907020a2c683d1e3afd5ac4a4391cbc9 emissiontrue_res_49.out -a9beca61604acaec60dceee52fc82876 emissiontrue_res_50.out -22f31bed393af7c7e544ecb8fa50755f emissiontrue_res_51.out -7f39c1646b191319449f8db4cebd2639 emissiontrue_res_52.out -52f8cc0488745005ea9f80329912b328 emissiontrue_res_53.out -dc9168702d40ccda90395d7af250211a emissiontrue_res_54.out -b24699ca330c59772318940a6d27b017 emissiontrue_res_55.out -646d48523fe25ce61cf3310dd07bbd4d emissiontrue_res_56.out -4541e9e69e057a5d79b7222afcde3b91 emissiontrue_res_57.out -b6a4ae5bd9739b7f4a037179e0d439b2 emissiontrue_res_58.out -55beece95bd8aff9623400f57b265ffa emissiontrue_res_59.out -95276215fd0fc26c88183ada9a57e89b emissiontrue_res_60.out -bb5cb322c6747a7db835be83610531c0 emissiontrue_res_61.out -416a0c48d3351310c80f6e85a668f91d emissiontrue_res_62.out -fd69c100f36b375ee7b847e3ff3520ce emissiontrue_res_63.out -c2bc09a336c954d28458e019c2d4a88c emissiontrue_res_64.out -3634fe5f128571c9b0ffe8bdd5019ec3 emissiontrue_res_65.out -62971499a6d1da8e21582b7b9c8c18b1 emissiontrue_res_66.out -8b8ca40e66b7b5042217d667fb62121e emissiontrue_res_67.out -032c7baec00d0a9e22f0b75fdabd9d5e emissiontrue_res_68.out -7a9605c903b2cd63d781db401fe9c8f3 emissiontrue_res_69.out -6d230f07e545453632574e3aef0ba13e emissiontrue_res_70.out -dbce92309e43052c23c7886ebf7714c2 emissiontrue_res_71.out -3d0c2ce6f361d2ee5ecb57ca11ae2a33 emissiontrue_res_72.out -93498021ab0861fe2418c72b0f5c66eb emissiontrue_res_73.out -5a1a1df697fca2e6301ba418a02cb227 emissiontrue_res_74.out -281c764283c51e3f6893739b790ec86e emissiontrue_res_75.out -42409c9a984a66143bb70274f6b88901 emissiontrue_res_76.out -2a92a436e4e11241200b334259d18cc9 emissiontrue_res_77.out -1da1e952e9d13e374e22c208e455a01b emissiontrue_res_78.out -27ca64d26625a34457f9ab28b37c4183 emissiontrue_res_79.out -ccc01ea5270a7c21fd02163e2a2fbe37 emissiontrue_res_80.out -17d84f3b9709165787e67a2a5d8239a8 emissiontrue_res_81.out -0605839e713f9c5e01463c6df9cb8fbe emissiontrue_res_82.out -f5458588c09d1eedc0b16e0ab9adbed3 emissiontrue_res_83.out -e23ebb3fd1cfb21a52e9743293832ee7 emissiontrue_res_84.out -435cfcf83e46d47f3e4ffb5abd925dda emissiontrue_res_85.out -c9faa56a6b760677cb0d197733b33afc emissiontrue_res_86.out -0d0917d607f3f42929e06725777a310d emissiontrue_res_87.out -0a7ed3ba449ff810c814ac6bd0fa1060 emissiontrue_res_88.out -7acffb8727e9263253bd369758020d1f emissiontrue_res_89.out -4bdb9c888e9ceee248b2aaed317ce567 emissiontrue_res_90.out -df38766d6bf64109b087c433f00d2819 emissiontrue_res_91.out -3d84694ea43e389b98ba8e98c5496c5f emissiontrue_res_92.out -253c3cc0554416adce4ad5e36adf2579 emissiontrue_res_93.out -74d08926f3e94307c130270fc4ed85e2 emissiontrue_res_94.out -144dc96998fb09104fdc0c4bc2123d02 emissiontrue_res_95.out -01816ea0149abb11cc5b5f8b7068a690 emissiontrue_res_96.out -d0d4a128238b4a8a0e7c0372d02b00d0 emissiontrue_res_97.out -c0b67cd4ff4798fdd608364f88738074 emissiontrue_res_98.out -7100c2d2676b62888059671131d9163a emissiontrue_res_99.out -9175461c6a95b09565f7acce6de8b3fa gamma_light_curve.out -3affc8427c4b707224b7c45ac203900d gamma_spec.out +3ec79426a090a009fa93f8f8c0432a09 deposition.out +04f83df4ff6d51f6b88502b2843586e8 emission.out +f6496d83192e1f669c74bb61b8af8992 emission_res_00.out +d5cc6a6e71f306104708395b5250d031 emission_res_01.out +bc11d1bf7f41c6ac34c1f9e2fd1e9c69 emission_res_02.out +4adc6ae27a77f446a0e581fa181eb74a emission_res_03.out +900e401886c64e0f390b681d51dd95e7 emission_res_04.out +ff9eec48a620d9dca2a3a2b83ca26969 emission_res_05.out +d0bab496d3b0641b6b81570281b5a84f emission_res_06.out +6ae8dd3ab9bb0ac36dc3d993e013c656 emission_res_07.out +2afff9e5739f8f561d6df3d177da92cd emission_res_08.out +8cee56671b45a3b417fd9f1e0fff4f79 emission_res_09.out +503f38ab48c2a1bfbcdf4a84966aef92 emission_res_10.out +16be1740b14dad6b4740f11b466b913a emission_res_11.out +3bdd46917f09afa6313466253704c5b5 emission_res_12.out +017b1929fca080258145b4adf8b526ea emission_res_13.out +cec02ddb139e3b1535cbf6c279c22657 emission_res_14.out +64b6a214c79dd0db81356f357dd76757 emission_res_15.out +09b2c1974c4e32399853d8730722bccc emission_res_16.out +db0fc44df6045dbc118ba5f3d68642c9 emission_res_17.out +514abc1cce484133f351bc2f4950b3d3 emission_res_18.out +6e28b782b39dc261cedec9bdb9d8a454 emission_res_19.out +e02fc9a2ff3c9601f2d7b9e72f2febaa emission_res_20.out +1acd847b6729af07d8ea14e7ffd3b178 emission_res_21.out +6dea1e7cdab40fe6840c7b19c1d6bb7d emission_res_22.out +410697fcf7f340d9d0559eb49a72e5b7 emission_res_23.out +8aaa7279c9b75227aeebf435f8bb43b9 emission_res_24.out +14f357c62905fa96eb467eb9ba2c64dc emission_res_25.out +6185aa548c3e49cf5191989ae1ec9244 emission_res_26.out +9bf6b197f58dc8c6d0cf7541d861eaba emission_res_27.out +7d9a78e0628c7705b23fc9813fe89fae emission_res_28.out +06edae0bc8ce24a57eb1543068e886d9 emission_res_29.out +e8ebc5d6c823995dafc662556b2c0cd6 emission_res_30.out +e1cf22808f4c231500dadd507d510c09 emission_res_31.out +e1084c89f679f0385caa787a31a88024 emission_res_32.out +9dd90d2975e9d117c6c594218d84d8d8 emission_res_33.out +f0e53c5e25b050b18f7b4e58e9d9a6a9 emission_res_34.out +c2a5dd4fa28b0ec032103f9d604653da emission_res_35.out +c585d248bedbfb29638bccdcd0190009 emission_res_36.out +e9a82832a680f36827bdcc062d691078 emission_res_37.out +d3fc1b3910e8f693b7173f62dcc7ea32 emission_res_38.out +1f2972e71701d51c21eb0e0966ec1558 emission_res_39.out +43c8f0406aa7b883d8bb9f309114fbfa emission_res_40.out +bfe29871723634b103e43880ee9c4d22 emission_res_41.out +5c52b4a46b0c162506c3056cf20c7ec9 emission_res_42.out +be534189bb7389e7bf49a273e4ffbcae emission_res_43.out +d624753276f51a0cb51715fb773b619f emission_res_44.out +64b1f8001b1189bc4d90d3e16af502e3 emission_res_45.out +8f9a667be3673ffd8d17e44497c0fb0b emission_res_46.out +c43d93b51f0e46cc08a828ccbdc5edea emission_res_47.out +09190f4afa871319b8073126786fd5f9 emission_res_48.out +0ff9e02b7b6dbc23455200c5a119baf2 emission_res_49.out +1a6dc0e45c73caf0591178ab84b7c659 emission_res_50.out +e6fca2208de2da21a9e1fc5ab3813e2f emission_res_51.out +c40a9d985dc71689210149a58b98bd0d emission_res_52.out +ce733a424e0fd0a28169546df73d1e45 emission_res_53.out +859de6be7b9feb6e3402297ce93c23ff emission_res_54.out +bde308448e01e2cb1baf1de8c259ea6e emission_res_55.out +37333bd85a618f62347e2187ef38d042 emission_res_56.out +ac01d46732b2aac14c44f67d3c8959dd emission_res_57.out +fd5cd638c6e28d39dbbfbf4558ba186d emission_res_58.out +8b7391cc559028ebcaf0cc87fd9fda34 emission_res_59.out +3a20f8ce520a3941e7cbfafaad408ac9 emission_res_60.out +ff20f079897f01799a935b83544fcd5e emission_res_61.out +0c0b41c6f53907dfe80470dc899d6ef2 emission_res_62.out +fac5bdc7215cd5b64f6569cce739177e emission_res_63.out +6889f2564c53a92898703dc6b8d133fa emission_res_64.out +3bd2fef8d4201088d3ea2f3c1688289f emission_res_65.out +dde184586876e0aa5e1b674fd2aca390 emission_res_66.out +70acb444a0cc73153804418057af934d emission_res_67.out +c92d46b6db718e36b45677ca2fbede66 emission_res_68.out +b6bdb44dcf2b8e64b5432d2ff2c81ddd emission_res_69.out +4cccffc25fae95dc02384add2a7640c7 emission_res_70.out +f8c1f2e96c1be3321f553396ca048671 emission_res_71.out +ed2be9c2ba57bf2411cf58266ee9c016 emission_res_72.out +5d185b7aac30f35a0539142106b43a54 emission_res_73.out +b31fd179b0b141b02dc281d9ee679e0e emission_res_74.out +16ecefcca7ce9506ad6bf609f753d125 emission_res_75.out +3914322428691f7299830c7d2cab9b4d emission_res_76.out +a27fca42e533fe8f599d7ae316671665 emission_res_77.out +76de50e037cce597ced68ceb39e86ec1 emission_res_78.out +fb918e209213dc68507472e9a7143141 emission_res_79.out +ef6ea48651ed2e6562e9a6441ffbca16 emission_res_80.out +e6216756e7ae9aed4bbbe04b7996f976 emission_res_81.out +dbe7592661cde081ddaf263d0d06cf0f emission_res_82.out +f02a682255ed0843e1991e8d0dbf725d emission_res_83.out +b9b6974ca11bd1f477176c5b202efa5e emission_res_84.out +a1718b1860708a64865e4d8c6b940a0d emission_res_85.out +0b000bc7af952a8168a2e061b980a916 emission_res_86.out +f17b92b4a121c989310a31b9a91281dd emission_res_87.out +16f9faf8a0b1b6e675538af5be21a2a8 emission_res_88.out +142f4b35133acbc77c84d090e96d3056 emission_res_89.out +7c4e9e3036dea08522832b0ac2d1d717 emission_res_90.out +77d4f33a94086da3b880e4cb20984cf2 emission_res_91.out +3634498273cd9fb742316716c64760df emission_res_92.out +58ed5d2bde98d07199ecd83f3b33e26b emission_res_93.out +1f18ea0c799b8c536db7b18a1fae9e1d emission_res_94.out +32099f6b5dd17c305b7f37ed60da5d8e emission_res_95.out +98558df6514777e8dafb9a2163099db4 emission_res_96.out +a9d4bf067b7da041df1df3f29db0cf4a emission_res_97.out +aab3f810382ec8b44651cda5773c63c1 emission_res_98.out +5c74788b815c7b27af919bcfd7282813 emission_res_99.out +8810bcbbd0846ac5e13129c2f406e19d emissiontrue.out +685864ad09fcf89341baa3eb8343fe28 emissiontrue_res_00.out +7e7d1d28c259800a1b3e8c3f351d3579 emissiontrue_res_01.out +bc5164eb6854e377110fc3e8617fc96e emissiontrue_res_02.out +8275bc03f8f4f88f6a251d59ad108836 emissiontrue_res_03.out +8d8c9a3f180ba334ffa0522d198f6d37 emissiontrue_res_04.out +965adf7973b719582cf0316357f15bb0 emissiontrue_res_05.out +dae10f17ee2dd7cedee310fa1ff9feb7 emissiontrue_res_06.out +12f6ee0d47db380ab227b46a939f9ee2 emissiontrue_res_07.out +962513fb8203e98cf1edc7cac8302416 emissiontrue_res_08.out +faff9b3b1b3c9c79dfdbc3e2070742bf emissiontrue_res_09.out +67878cad948566d43183bd4c37260dd0 emissiontrue_res_10.out +6de5c1d8807f1fb1d86ab4b5d5995255 emissiontrue_res_11.out +f6e246876a2d8c90514cc784a15fc87f emissiontrue_res_12.out +2cc3c89d66681c813991602fffdaef99 emissiontrue_res_13.out +eb352627a72de27d0937918b5c145b2d emissiontrue_res_14.out +597a46cb3e9d0b68ebc46b06ad6fd509 emissiontrue_res_15.out +8c6909c4685362eb95b83552eec4ed83 emissiontrue_res_16.out +5805b94162af981f8b91bcb4e236a02e emissiontrue_res_17.out +3d66631278e5f82c0e544045a60aa20b emissiontrue_res_18.out +2c0056a5de0974807a46e2a83fb5a6bd emissiontrue_res_19.out +32968d61be840f505c7812e6f704a8b0 emissiontrue_res_20.out +f9f315b8d0ab63b5bd5a1b961b52049f emissiontrue_res_21.out +903790dd73dae9aba55b729ee3bcf2bc emissiontrue_res_22.out +b36c479302623b7643210948a45cb88c emissiontrue_res_23.out +a2f08db31a34d783f2f8ad166288ec8d emissiontrue_res_24.out +c8e6377a522bbede11005bc4f542ebed emissiontrue_res_25.out +1d2f92451baa51b3f2e621a10e8f49da emissiontrue_res_26.out +336e81717f10899a3c6f23b5cca6e8ab emissiontrue_res_27.out +6cac5c9afa5f85d7016d842341f27082 emissiontrue_res_28.out +e92f3d5a52827f9343159297f4c4e963 emissiontrue_res_29.out +8a2ff43f4f8ee5b9e585890967048e4d emissiontrue_res_30.out +80d96b2fb0306ae5eb707b9a57d0174a emissiontrue_res_31.out +38d617140b50ab8040b06dc20bb875ca emissiontrue_res_32.out +5085f6d7e656bfafa8e9fcd2035fe709 emissiontrue_res_33.out +20ead7c8e928b6600e7b78ee6859d142 emissiontrue_res_34.out +0079456824a643d057425de3296e7d54 emissiontrue_res_35.out +901bd414e2be21bf8d2db70647b7eb35 emissiontrue_res_36.out +39803b5e2010496fa43b1e593c8374ce emissiontrue_res_37.out +6101dd8265f4f63e65f5397ac68dae0e emissiontrue_res_38.out +b91bde0f30a715ee6f27ed2d170c5e17 emissiontrue_res_39.out +cb58f4e58d76d76b431b1a908be5df73 emissiontrue_res_40.out +4e4370754bd5645651d959fd162bb379 emissiontrue_res_41.out +73be4be315b30d0b65e5fc0965bcb122 emissiontrue_res_42.out +1cf174da296b42e437c651574b9c4584 emissiontrue_res_43.out +9cff78bc00136792115aa6305222bbe1 emissiontrue_res_44.out +5814834c954ee28675c8b98e2e615dfb emissiontrue_res_45.out +0f2d7ea1ea30e13a809d34bc6016934e emissiontrue_res_46.out +f56bd55f5124e0f7235a58654ed1a716 emissiontrue_res_47.out +e6ae2088053bf938625142ea1fc737ad emissiontrue_res_48.out +368a2e0beb9e54dedfa780c0c0e57266 emissiontrue_res_49.out +5b3e2993c1bc785044b2ffd9282cf3f1 emissiontrue_res_50.out +b3321f466981fb7478ffa9b4b034ba0d emissiontrue_res_51.out +bc36ea9189185129e6cc52f2e690eb9c emissiontrue_res_52.out +121045d70b0829ad2203cd8f9ad1178f emissiontrue_res_53.out +21d890612ea48b994273d7369d03ef26 emissiontrue_res_54.out +25d7e4a138e3e25be85858b9a64aab7a emissiontrue_res_55.out +3efa5a28a0b272fd4aa4b737763e9c13 emissiontrue_res_56.out +b1436f2ac33761db2573aa2cfb4121df emissiontrue_res_57.out +755917be9c5218e2b519a05081d2c105 emissiontrue_res_58.out +1e0a3d00685a7b1b27697ec887e70569 emissiontrue_res_59.out +fd93f721361a662f7953983fbce16f79 emissiontrue_res_60.out +9fa71cac547c96e4f1d3dd184be51d7c emissiontrue_res_61.out +69d8761447c93c42177c0679ca968e33 emissiontrue_res_62.out +4f286ad799bfa72df4af4ac916bd040c emissiontrue_res_63.out +997fceb908dcc8a89ec7d12e66dc8f8b emissiontrue_res_64.out +5fc66fd687a675df747943ec1785ef65 emissiontrue_res_65.out +bb07f83212c4ebde16e9b4b6859ac40c emissiontrue_res_66.out +062e0cd4602e8a990cc9a7a0d116f800 emissiontrue_res_67.out +38ec1bb05225b2cdcddea12d9dc03e38 emissiontrue_res_68.out +d2ee8f14ed30997c7c47d578b7e84dea emissiontrue_res_69.out +f04e850a2e659317a3e3dc10f5ff9ee8 emissiontrue_res_70.out +11d94bf48955ddc8fdf29c57e9ed6d42 emissiontrue_res_71.out +2724610d4475cab7b0fa4be39cef6efb emissiontrue_res_72.out +ffd7fa89702a99d17df6685647ea5a5b emissiontrue_res_73.out +dd2b3636411a1bc779b65876f95aeed7 emissiontrue_res_74.out +5a156c8b4264f2a5909faba7a077ad38 emissiontrue_res_75.out +3888bb2cadbe8da3d353ce941d77015f emissiontrue_res_76.out +de75742beb47f1ccdec49251d5a6dd16 emissiontrue_res_77.out +61327b78f5293ca00bc89c3a0f3924f7 emissiontrue_res_78.out +232c25699d8d510165b8e30c444300ce emissiontrue_res_79.out +02348997fad4339ae85e41cf211a4e07 emissiontrue_res_80.out +e9858c158600b5e5c734102449a7e4e9 emissiontrue_res_81.out +e687789b46dd9fc65f803ac1fa7d60ef emissiontrue_res_82.out +654ffd46746fbb4a1abde0637425feb3 emissiontrue_res_83.out +29f6a5487094999bb092c67f9f6af287 emissiontrue_res_84.out +208d7958c959a03cf81db420c6eb32ea emissiontrue_res_85.out +fbcb8c930cd2ed6cf90b11c442754523 emissiontrue_res_86.out +acc55b3c58e4b3a1b39ae1b30889567a emissiontrue_res_87.out +94c12f56cb83e6026884dca7b961ffa3 emissiontrue_res_88.out +3058591c186a53f1a66af0f56e74bb16 emissiontrue_res_89.out +35dff03eacdd0e5a438202078af65e1e emissiontrue_res_90.out +2dea87c7a0f1f9a1da727439ea4f3112 emissiontrue_res_91.out +eba841a598fe4ab574f0c89279b80e3f emissiontrue_res_92.out +b6cc5c269f63edd684af76b676fc1b74 emissiontrue_res_93.out +4af6d59597c3ac41aee039cb36fb1184 emissiontrue_res_94.out +8190817f89d5997de3200afd63589829 emissiontrue_res_95.out +bfb033f78920b782fac4095143e31330 emissiontrue_res_96.out +ce2b6f5450dfad64200ad1f8444e1ea2 emissiontrue_res_97.out +e81385ea000699115f4275302c11bcd4 emissiontrue_res_98.out +f7ced96bfb7de5201b41ea401287484c emissiontrue_res_99.out +57e406ca80bfad913ad3d18fa32e4630 gamma_light_curve.out +8deab0eb42b7d0452d2dea74dd6f70b0 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -10cdff07908c4bc9adb7698713d9646b light_curve.out -af07d060fdfd105e79b70149ba71a428 light_curve_res.out +8a9aa4ea5e6eab77831a63993eb94898 light_curve.out +c61846d6ab4f3a533830451b08211652 light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -b645131349330bc35452fa9da4f37991 packets00_0000.out -65b94a93df54a4d08aebae16ec204338 packets00_0001.out -6c94debc2cc626602690a93a0d2d3a50 packets00_0002.out -e69cf796a448c88b34b4a46dfaa46b96 packets00_0003.out -94d44f3675fb98f0b9cd996c99713e20 spec.out -03a4cbaaebc44082d565ed1dbf00d2b6 spec_res.out +952e5e3daf8e38eea0bfecfc09ff7943 packets00_0000.out +7047fa1e52f3ae3bd48c81b83c93a776 packets00_0001.out +0325a37eb3a8e294b6c9c1e476ac7a1e packets00_0002.out +3f1ddf501b59a3bc567bd44b85ab8a71 packets00_0003.out +eb3020ac9f92ad77cafe08debabebef3 spec.out +976e15317990950e776b033ee7c2f024 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -fb267a530fcec685ec97417476ebea40 job1/estimators_0000.out -e9b6613d0aa70becc418af2d63c1581d job1/estimators_0001.out -57523d9b07b9ee0e653f97886e3622a9 job1/estimators_0002.out -2c42537e23a164d8bb12f07c560e3ff4 job1/estimators_0003.out +81feaa4b7b09112a50d60fa05fe60301 job1/estimators_0000.out +f5262e7ac7c1b099a8adb12131a20767 job1/estimators_0001.out +ddf4bd94c15fd89dbc5a6966a2065589 job1/estimators_0002.out +a1ca68ee3c877216dfee647a5a678f7e job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index fac9f2ae5..5e1e440e0 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -0fd95e789afc0f52b62330dcbee2e5ff deposition.out -3c0ac17f8f41073acd2cbb8ea1d78172 gamma_light_curve.out +baff4b7ad509ea85def4c9d4f07a1f95 deposition.out +ba021df2fd3e0702cc22b961d914078c gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -b7f80a48dbad390ed5331031ab81c50f light_curve.out +97ad2f8d42d6f06b7dbff2cb8f69d0ca light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -c31dbab0e5de82ebfec39317676aa086 packets00_0000.out -22707e33346eb151bdb7d3fd5c3ca37e packets00_0001.out -002d666e74a2622a92f64c2184af0277 packets00_0002.out -c4fcf480f97c8fcbe8e8931c155c55c1 packets00_0003.out -f4deceb49da4445eb1da1f5df9999126 spec.out +a78c3e8320953da52f91e67d0764f64e packets00_0000.out +2c639f325202bde2acaac93346dc2a20 packets00_0001.out +c34aa67738d56f205ebc0b5d39de2e6b packets00_0002.out +e8a435024d6648a528819c5b82773e90 packets00_0003.out +1c544cd7f0655c7c0c7b94da02adfeaa spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -86b2646539895deecc633d63d69df904 job0/estimators_0000.out -995716f4e13127c0d2b744d8a2d7514d job0/estimators_0001.out -db6eab686b068b4a23b1618f076303eb job0/estimators_0002.out -0cf01d5bd970fa9fcf727bb3733bd5e9 job0/estimators_0003.out +7c6f21a50b6ffbac7ac7f321c1aa22a6 job0/estimators_0000.out +2c481b50d1b482f875264f5b0f4eb97f job0/estimators_0001.out +96654d3446da68f668f1b9da11d5e2e2 job0/estimators_0002.out +4534eeae3da8b1c1ccf8237b263f5b25 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index 1655c0866..583de178d 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -27b28efaf991b274ccbab3901631096c absorption.out -b63e81cdfdb79a036847c6c3bf5aa506 absorption_res_00.out -469f725d00d259f681902f7e8085a8e4 absorption_res_01.out -4c91e4e72f10b8a97d9ef52f01c285cc absorption_res_02.out -81dc43a4dff76ac17f03bfb0a4e87bdc absorption_res_03.out -568d5a788396638e19a23a955e4f4f69 absorption_res_04.out -de80898c386b8194e7bf34e7e426b049 absorption_res_05.out -fb0f93a057621cee0290a246ab85ee4c absorption_res_06.out -6f70bc06bb0b6def37bc6532eb1e23ac absorption_res_07.out -058f4a2511b3e07a8c6c0d91534494b5 absorption_res_08.out -22cdfae26338e74c9908954e131c8e2e absorption_res_09.out -7522e0b5555cc9dd10b91886f965f681 absorption_res_10.out -5e2f3d925cdc0f4d95b8b2f472a34784 absorption_res_11.out -e26ff1b92328dcf5028ea2ffc564802d absorption_res_12.out -1feb9784d225c71958f206c2e3d8c30f absorption_res_13.out -ecd4f900b3ec0e5df93f90fc5d7956b2 absorption_res_14.out -ad2f6b01b865842805e92cea4036dc51 absorption_res_15.out -19b9908533f1e12baee347fd26a51511 absorption_res_16.out -f8e4a91d8237234dd30d7c11f612e542 absorption_res_17.out -5c8a9c781a37ba9084441942705f697f absorption_res_18.out -00542098bd7f4e9a39d77e7dd0fe419e absorption_res_19.out -9a5f8fb5ca71bb264ec5c3757a9be778 absorption_res_20.out -5ca5a4be5d845451aaa6a98000f38dae absorption_res_21.out -4418ccea7ddb1018db787305dbd0a2d3 absorption_res_22.out -43e74240fa0758eb4b6cb4a0b399ec98 absorption_res_23.out -856ef0986a49cf44f879075067b2ab1b absorption_res_24.out -2f73c9ab4c4710ea33f50b997c19ddd8 absorption_res_25.out -f463bc5d457ebd65f095c8ab06a67492 absorption_res_26.out -ea030b53a3eec405a3c975ca38f10b75 absorption_res_27.out -9aa1f3ed9bb67113142e58c1954a847b absorption_res_28.out -2e2c0b1e5cf4647597d65a4fea03fdd4 absorption_res_29.out -f29f4dec2cd9e1d35f0663b16a17f227 absorption_res_30.out -b9f356ca132d1c4feddfb346897cbfb8 absorption_res_31.out -b1d99955ea043b9862500e1a671eaa85 absorption_res_32.out -d7ef9c9c98fc12b8befdce6c65e27197 absorption_res_33.out -a50d32f0fa7cfd2a7a2e8ffff02efa5d absorption_res_34.out -71becf542f6abedfd2e31b87fb5a388b absorption_res_35.out -6057734b3af2fe4af972ff56c9eccce8 absorption_res_36.out -abaa5e01728bdb01ddbec7c906d10596 absorption_res_37.out -53bcbc033ddb27a4461abbb4b621419f absorption_res_38.out -b8c83277811a644a9b59c4de922c1582 absorption_res_39.out -3f03286c70927a2d576da7b58079da91 absorption_res_40.out -dfbc08792c3674be80033bee1bece989 absorption_res_41.out -0259c66390101e5148bffa584665b51d absorption_res_42.out -7041a22e72a31e0fa610019e801c59a6 absorption_res_43.out -06a35c55445560e9a85c56268165a16e absorption_res_44.out -e3cd391678cc11ce79f09eda119fea64 absorption_res_45.out -22a213d28c017047aae4cdf278d79100 absorption_res_46.out -7ec7b58d2b05b9fdb748196e87e62a8c absorption_res_47.out -83a580d09ee9156b2392fc908c4a0754 absorption_res_48.out -6b3fe85697e9a9cdd82a87f67f86cc48 absorption_res_49.out -9a75d671cfe61b1539a795b39e49a687 absorption_res_50.out -8fc0d64a9e73897ac2f133bb7aa9b7cf absorption_res_51.out -387a46dd4db09177c6c8b58a5e1d7d43 absorption_res_52.out -d75a885b4503c9ec12d14b2afefc0f22 absorption_res_53.out -a3d9b0d98ee2df7e1ea6e5ea6f7c88d7 absorption_res_54.out -21effef62142ac45878a64ac7e882d31 absorption_res_55.out -48342562db86e7055f305a81ad921cb3 absorption_res_56.out -fcdd8452a2567224f145ca97429cc302 absorption_res_57.out -55167e92b790c79e891189687722cb44 absorption_res_58.out -5e82b98030a38a761a217d8797ad7bd3 absorption_res_59.out -a595ec69f107e6a295e1138637d6f905 absorption_res_60.out -4c9c00a206906d647e30538a089b9850 absorption_res_61.out -68e9aaad5f6fb0b2b5b9b5ee081d9d91 absorption_res_62.out -9922c8e1ba0319d2f08de5030c8ad187 absorption_res_63.out -79df77fb2cd7ac36b142038c7eead6e8 absorption_res_64.out -efe762c6d68721af919c06beb030c742 absorption_res_65.out -f5632cd30e617ff24345a46ae47da86a absorption_res_66.out -af55320da397a15ef0009f1a6776ec1c absorption_res_67.out -2f66b8a58182557597ed0ab0c7fd36ff absorption_res_68.out -121fe72b4f0d96c96f5014a225a96184 absorption_res_69.out -257c9ac84b17dd2d35c41896c544fbc8 absorption_res_70.out -a52b103d99e69f0638b62b25877f7182 absorption_res_71.out -2ee844af186a52f81c5c4129f1274346 absorption_res_72.out -9c696e8741d6efe7914b1832c1f37152 absorption_res_73.out -45a9237f81e1ebbe989f08b9e454fb4a absorption_res_74.out -c54d6bc164821e8398773487ab91d08f absorption_res_75.out -3e3e76a6c38e4c0c9982ab411b3856a0 absorption_res_76.out -94dae4963f3682521c3bd14b1fb0b375 absorption_res_77.out -5ecab053ce185013a0a6e0b9ef0c63e4 absorption_res_78.out -81de4c67b0bfaf379a50b3db883379ac absorption_res_79.out -a2cb4487c8766e461f32c90961f3048a absorption_res_80.out -e166a9b8f67762c5dff178c5d8cd6730 absorption_res_81.out -81ff56b036d7bc350316c8a5ebd59d13 absorption_res_82.out -38bb7a75294758cf4a4f47ac81a3d9b3 absorption_res_83.out -ed379b030ad00516ba9b3f56782cad12 absorption_res_84.out -fb1350afe1b5631a8138aa1db32ab6fd absorption_res_85.out -98ea3df0860965763f65b520f0fb3e32 absorption_res_86.out -46a55df49c7773f45033b538256daedd absorption_res_87.out -94a7f18be6ef30ee42a9c069f8bd8974 absorption_res_88.out -f4171b62f0f58865df6dbc3183fdc498 absorption_res_89.out -70e451d2357f17420eaa582705ad6301 absorption_res_90.out -b1aff4638518b6443c487e4f0780aa17 absorption_res_91.out -c74ab9d046224d1daeb9a4daa4feacff absorption_res_92.out -951b9d140b6c5f68b612f4be06f22892 absorption_res_93.out -6fb7f2782ce119a125fd602c7a86fb03 absorption_res_94.out -e0a0b04a346d1c9c444ca10ff3df32a3 absorption_res_95.out -a7b90446a338b221e71f4c2b7a6f7dfe absorption_res_96.out -dfb19700510e0e417836c19f101a073f absorption_res_97.out -cfcca24f6bbd88525b3ed37875cd96eb absorption_res_98.out -5906e913692c3b29050bab6dc38bf8d0 absorption_res_99.out +f839c7f6a8f4d229faad887904a8a98a absorption.out +09376d1b89b5370a3e73e1824bed17ec absorption_res_00.out +b1d951cb71922d06883109171f0ce25f absorption_res_01.out +5e96f879d0587773be948d68c281903b absorption_res_02.out +027ff191c8b22ced35e82af26a694d87 absorption_res_03.out +d4887a355af979067706f6cc0bf7c6b5 absorption_res_04.out +c57918bd32f328745cf80dfd8cde5332 absorption_res_05.out +6d7e070265b1959412f494f8c8e772a0 absorption_res_06.out +2b00f4183b26acfa717a1400be344120 absorption_res_07.out +3790ea9b33ed0a9eda25638da1466e83 absorption_res_08.out +fc6aad1fc05ceb72747d78ad8a369601 absorption_res_09.out +d3adca931a6ef57d2f7f3d4d2221354a absorption_res_10.out +3a4810e2dedd9592e829c70edb95a074 absorption_res_11.out +3cbbb8dfcfe632c20ae79a8677c5a2c8 absorption_res_12.out +0a6a94041c70df5ee47fef0bb5e08433 absorption_res_13.out +8cf306e9cfb2d8a9811336d2b56b545f absorption_res_14.out +bdc0537a7e04416e89a8173948254e8c absorption_res_15.out +640e0b6025aee44ba971f97970c8a955 absorption_res_16.out +73f1a6ae84c4cb3fa4a1f2492c8a6229 absorption_res_17.out +51a661fc5b33fbe7566e0c4e12cf66a3 absorption_res_18.out +f9dfa624d0e940434c518c4e21bbc19a absorption_res_19.out +e415c6d0f8b5677ca25a13fd8b1d6005 absorption_res_20.out +58df21d4ab31b8b3b58fecd8e24f86cc absorption_res_21.out +0752575d51fcd75f1e7674763f78b08d absorption_res_22.out +bb29811ab55b0d7eca501d8bc8410d0a absorption_res_23.out +f1801d9565269012d5a90e3a8a104ee8 absorption_res_24.out +edc7d3e3f0da4efcbd5c8a9a135404b7 absorption_res_25.out +b79a42f8e3847bedbe3c34f9352fa020 absorption_res_26.out +b903fcee284126df79563bcc93b29fa6 absorption_res_27.out +8a3041c25bf267aaa3ac4b49f3bc5b6c absorption_res_28.out +03169c9a16d39bb5104cf7a59f0b0bf8 absorption_res_29.out +6dc0d2cac88980fd46304e4e81389e13 absorption_res_30.out +7daa3c1af60ded35cb82b5c5e2464b06 absorption_res_31.out +33ff23b1cf2c721ecda1fbd1dfe73eba absorption_res_32.out +5bee3043bfa77b0dca50281f7caf677b absorption_res_33.out +a2055a93efab6d5d79ab820ca55d318a absorption_res_34.out +45478f4ed25a524e0313ff2f0318a6df absorption_res_35.out +da3dc8e2d2877676570808fb304e2ec6 absorption_res_36.out +f22d36c2b2aa1d472529c5202fec99d8 absorption_res_37.out +1fcb13187ddce02895c36f33a17d6d0b absorption_res_38.out +efa612329d7481e3e3e977d9699ae5b2 absorption_res_39.out +74755fdc21a6ec305f67ffa56803fbc9 absorption_res_40.out +fec337d91aff3da8b0d56c9d1104ad80 absorption_res_41.out +acf6b4a95d3b6d3a4ea99ee510f90c03 absorption_res_42.out +7a919bfa22c3211d27203a90972ce821 absorption_res_43.out +83b86cbd6b7b5b2880dcb8111a516c13 absorption_res_44.out +52de2172ec1a1b7d9e6821e018d4534e absorption_res_45.out +2eeb44f061354ad16d2cfbaa77a0d9e1 absorption_res_46.out +c2d1faef89d7871078e6a64c702a6732 absorption_res_47.out +37dc6edee76f5aa49e85a8f945da09b9 absorption_res_48.out +2dbe414eee757bbe3249bddd5a9c2a1a absorption_res_49.out +c0e0183481160310cf7f2e4378a6e7e5 absorption_res_50.out +a84ae8b4db7576c3ed2fb7787a99300a absorption_res_51.out +692de580ea1572356ada3ec95257cea3 absorption_res_52.out +3bdac6b7568f1578419fcf1c48b1706e absorption_res_53.out +9c2b6472b7e138ac7e0af1fb71377776 absorption_res_54.out +f7a6f4c593d6199993167f097bfb2ba0 absorption_res_55.out +a0f3a107bbce5af0dc5fd9ec9d539001 absorption_res_56.out +919ebcc30bd8ea19ed93c798cc3f2336 absorption_res_57.out +50fab27c50543160b65553cef1eecf26 absorption_res_58.out +a56928c9993940e6f943d6c968b67c6f absorption_res_59.out +282c18a64c062f568f378a362209513c absorption_res_60.out +2455e5fad9388b985c8f1b581cdc79e7 absorption_res_61.out +372300b2f5b853886c6e9e1eedc916b1 absorption_res_62.out +3020202ad589fd97057abcb9e165f038 absorption_res_63.out +65b029deacee0f15eb611481e61bdc93 absorption_res_64.out +a1796c9f23e814e99be7aef9105346dd absorption_res_65.out +9aba44f0c2e575aa86d59f04d44b2746 absorption_res_66.out +0b82c59a328307d75ed0ed907e2bc6b2 absorption_res_67.out +9340bc1396d704e06b6f6e6da3af0078 absorption_res_68.out +3197b0b0c63cf6d5ee7a98349f2fa100 absorption_res_69.out +19eb37aa8edbde73cebdd4632cd04e2b absorption_res_70.out +4b3123055b89024f17fd59ab8c9606fd absorption_res_71.out +e9b56e249edf86afe1f5a507876c74de absorption_res_72.out +d3041d471a5ec3ea4cf4c2ba434563ad absorption_res_73.out +b5cc02daac2124cafbaa382d5064a3f6 absorption_res_74.out +648c751cb36c3373a0ac91531c6223e5 absorption_res_75.out +7c34ba9915cbed39b0053533e73dc1af absorption_res_76.out +5c6dac30081c39400c00855025334406 absorption_res_77.out +771a9f022fc7aa83035aea57cc7b05e5 absorption_res_78.out +298016b5a9e58ad9abbf01093744b7e7 absorption_res_79.out +68156fbb7ace590c9d9651ac249bcb23 absorption_res_80.out +d7ec8c695aa3627a105bbb3349ad4867 absorption_res_81.out +9cf62803f9341eaf0dc7fd91afb03789 absorption_res_82.out +4eb965c4a75850ed8706e14db4b4e5a4 absorption_res_83.out +6cd600eb3ec01c661d8f699a8eb33c5c absorption_res_84.out +cd39056652b881298753e13d70cebaaf absorption_res_85.out +a46498285b21f5f5d2a15aeaf94cc1d9 absorption_res_86.out +ae5f6aba6cae9804ee43af8a4f34cc69 absorption_res_87.out +158f88012a890bfdea3e973194b01f76 absorption_res_88.out +8e10b2d5012f8fd0be80bffbfe9add47 absorption_res_89.out +4690695d7ae813e5bd3abdf337458170 absorption_res_90.out +073acabf72539815623ac1f3ebfe4552 absorption_res_91.out +39e79c431f75ca51ae634e7859b5af80 absorption_res_92.out +a71ac53333b0d5c756dade66238429e7 absorption_res_93.out +d65d626017a1b3d19ea12a33dd768146 absorption_res_94.out +198833e7dc3005756099157c8bfc8fbf absorption_res_95.out +8c842dba99945556dc5c4a67598b6141 absorption_res_96.out +ae2a852c6df1afd99f0ecad5388ab3f6 absorption_res_97.out +a079f7669915997c8ae72495aca90719 absorption_res_98.out +10661c6ecee39c36510afafe70768b45 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -578a03756b149222da626523d210092e deposition.out -18fb03d1c2ca204389458f26d8415872 emission.out -84a42b6b229126902340789387de7099 emission_res_00.out -acc45892036bc6228e33ff4fe48a7a02 emission_res_01.out -f3c87fb4ecfbc525a64270c35294d664 emission_res_02.out -8f2fad240f0d32b544ae4d73e5a419ca emission_res_03.out -84b68ef2d978bee65c4ae52547fe7d7e emission_res_04.out -1d93a9f61825f3392b09160a0fd61d76 emission_res_05.out -02e8186f4c04324a509a04e0492f3ba1 emission_res_06.out -9179acab68428264121483c31dc6c4a8 emission_res_07.out -0149a8cd05d07afafa1234f0b50a7884 emission_res_08.out -44d7ad95a3f71bdee3aaf3a1de7d0143 emission_res_09.out -76e53605dd225f9286319d622f3c9a8b emission_res_10.out -f1f1bc920cb12aac6274375c0c1d75c7 emission_res_11.out -cc2c6d6308da4a7b06a9bdeed1b8ef5b emission_res_12.out -00a978e4d1af3b7a0ce489c8dc115b2d emission_res_13.out -c5592ae523892370c9da951705118999 emission_res_14.out -34cc8065fb60a4945f570b11f9eeccf1 emission_res_15.out -d8ef573b271565050f24ed428c3e916c emission_res_16.out -cf18a46bbd0d9769679faf6296872927 emission_res_17.out -053ffb9e0f62d6913212032575bd082a emission_res_18.out -195d5fedc54ddd3785bf60e4cf1c059c emission_res_19.out -a32b765cc36de8f976666678bd10f9ce emission_res_20.out -2e9a9d16c55f134c9b033920e6311d12 emission_res_21.out -2c938d93b13f1b27263b8ca601dadc06 emission_res_22.out -8421e6f52c7306f1f7c719211b22846c emission_res_23.out -dcb625e1cc929a6d00bd3a6a552eda60 emission_res_24.out -f7dbcbed7b9720f5f9b8fca2295dc4b1 emission_res_25.out -2b3f8f211f60a585ac8a9ec6966642ea emission_res_26.out -1fcedcbee8d33b209ea263ddd4064ff0 emission_res_27.out -8b03b7534e87241df704ec6b16c66b12 emission_res_28.out -726c366a5d9e381b4374aaa30d93ab22 emission_res_29.out -28003a19940ac65b94c9b97104811c55 emission_res_30.out -47f107cc92242c20ade605f031ea8999 emission_res_31.out -b8fe62d5a9efe373197f132101b502f0 emission_res_32.out -72d9b390fd7b14b5dc99e328f61f090d emission_res_33.out -45d78d982aa2a8c2f62d7b1f10cb491c emission_res_34.out -6b869530b3fb72e96a83a66deaf77838 emission_res_35.out -5b965209d3e2a61dbd00ad303c137d67 emission_res_36.out -346aa9def1f438da4ff32f5ffd57ff7d emission_res_37.out -45b7e7e8a24d5ab329a8257387fef6fd emission_res_38.out -fe0f976fa6dbb5a18ada140aff71655f emission_res_39.out -51db6d312b71ad7ac4d4afc7513369aa emission_res_40.out -39a632b0cf4737c1ab1a47ecaa6af165 emission_res_41.out -e15126f102e74a729c4859509d4ce977 emission_res_42.out -97d2a24e6f12fd6b27cd161ef0d9f54a emission_res_43.out -7304420f2f998681d837f14f0d215cb3 emission_res_44.out -162dd2cd551724a8301ec9b233df1ed6 emission_res_45.out -befa06d06d17d47fd9ff9ea47cb318d3 emission_res_46.out -ae148973965e1548529465bf532c7239 emission_res_47.out -c35a8aad5a3658744a53ca42d8005ce4 emission_res_48.out -be250cdded969f2f28f5c132b2e33c23 emission_res_49.out -4d536d719397fb39a6410436f6b62da5 emission_res_50.out -32e6702c922a9e829a382bbac3d46872 emission_res_51.out -cd537907fc0a43c907a30526b9c075f8 emission_res_52.out -3651c3727eab26f71005847ff0d41529 emission_res_53.out -4e794a25dee26d4115af5a13f4360264 emission_res_54.out -828721eadb50f422a164020540a61e86 emission_res_55.out -9236fde2d318f46abb33b78d91240538 emission_res_56.out -4d4f5fe8d4094749cb66cde180af6743 emission_res_57.out -a9e9fd68f0c98f3787fb84775fd83b8a emission_res_58.out -96bb36656ab39ed7d1d7f2bea8efa327 emission_res_59.out -287b654781b88c4a44e336f941062fef emission_res_60.out -3192e80577852bb4112cb237b728ae6d emission_res_61.out -08c43c724ae9ef6ef001fbcf1c76d7b3 emission_res_62.out -decdcfd43c699672d42687c3813a88ae emission_res_63.out -ecb0efd60e2a01fd4e1aa14d3a7f5e21 emission_res_64.out -5f95802cc8384e8b96caf54c73422b5b emission_res_65.out -3f63f982e3f86ef75b966e3e5505ca8e emission_res_66.out -a893634f17c0d4b5ad96acab96968fca emission_res_67.out -be7b999734b81ee58916974e5b8af3d0 emission_res_68.out -80c65e352e79c4462d4cd48987b02cd6 emission_res_69.out -6d3a7d77c713716a5c1d26594b5256a1 emission_res_70.out -9cf1be3efca93a5d45f376687f097b03 emission_res_71.out -039331f6558c87b6d85c2078905ad003 emission_res_72.out -88ec3e9e1c28e0e71b05c55536f3475d emission_res_73.out -49e959bdcf43e73414e0fa846bbcd713 emission_res_74.out -e8d3bf50d8bbdd87c495c9069c5d6d9e emission_res_75.out -f55985a597662069aecb4603ab8920e9 emission_res_76.out -a0aed78af766668bca4c8862406135da emission_res_77.out -306619f518ad33d0fd70dfa13c2306fe emission_res_78.out -43cf19bab4d7cd4ad478f019a8de8e01 emission_res_79.out -7157f22b65d31064fe8865f7058986f9 emission_res_80.out -c95c5156296e609b868981c1466e492d emission_res_81.out -72512a43db854ff042b794f8f31ad7fb emission_res_82.out -f1aca5397ec9acbc24a7610a5a3f1a7d emission_res_83.out -b67a9f00419f49bfff8c5dbc0f26dd1e emission_res_84.out -cedd465a1fa1e20f6b91160600366465 emission_res_85.out -405eb56bc3ab19aa7e3cc10ff30037da emission_res_86.out -b4e996d4b0cb410acb7f216b0cc57ea9 emission_res_87.out -4e15653c24dcae85bfa8dc690e932229 emission_res_88.out -6f69e0464e3496c20352bb3e775eefe5 emission_res_89.out -69e306ab5faec11984d3e34197f9d4a1 emission_res_90.out -96a84708b0b77f0e204f531599524b79 emission_res_91.out -ce74c611ea8a0ec99fc9b16cc41ab96d emission_res_92.out -bd9923cc539d3ce4bf28ce90209ab83d emission_res_93.out -0abfbba066ac750dc6d54041db87a85e emission_res_94.out -3db44a7ab08e15ec7d8d4032bddfdf37 emission_res_95.out -7cf80741f38fc2ce87788a915ff8521f emission_res_96.out -7cb62e6762852a13ad2aa75a96d859fe emission_res_97.out -e0f53be088a74693f0cc45bb2978be38 emission_res_98.out -721585c59e7ab433fa89a74f60c38fe8 emission_res_99.out -31c23e84832f1fa861c56310004b2914 emissiontrue.out -9c915377e43424ec65be8dffa96b7df9 emissiontrue_res_00.out -b07e60385ed674f8b841093ca48246f5 emissiontrue_res_01.out -d9413d93a4ef907b942ea75fe0befa13 emissiontrue_res_02.out -2c80f70ebd37506e8f7f1ed86ef31e55 emissiontrue_res_03.out -5adb1ac1e1868e718ac82c1c614d9e85 emissiontrue_res_04.out -ce29b29f809116285ed1f116c1a7d85e emissiontrue_res_05.out -df3bdb8cfbd92d23546cca7ed7afd47d emissiontrue_res_06.out -d31a1638628a64a387659a54d4e37a50 emissiontrue_res_07.out -c1237470696a1a421bed0b353afdb7f4 emissiontrue_res_08.out -a84dd69740225afa57dfc9e7ed57d0a7 emissiontrue_res_09.out -e72fca5805d4c7aecde3614b54aad3d9 emissiontrue_res_10.out -526b93e1c94750eae1fc56d31d80ef6f emissiontrue_res_11.out -c12033f695c51b3e7daea9ce30d80f6e emissiontrue_res_12.out -f70c15fcf6cd3eb963cd7d1627e2260e emissiontrue_res_13.out -1e31edb11f88d1a7e69e806f174d5f03 emissiontrue_res_14.out -a4213144a52ddaa36c898ebb2726cd4d emissiontrue_res_15.out -5dfd8484690fdb002f188cc5d47d6653 emissiontrue_res_16.out -449385460e11c3151e35606b99f87b04 emissiontrue_res_17.out -105c74705f6472b6b07990f6ecbc2aa5 emissiontrue_res_18.out -8af6d35f932b905d30621e34d3bb22ff emissiontrue_res_19.out -1d709641652b6f52fe422a118f18f8c4 emissiontrue_res_20.out -98de05cc683f4a50293f477eb6f2c805 emissiontrue_res_21.out -e5d76081db1a7519ad0c7332640b889d emissiontrue_res_22.out -883f1f74dbd31f5c5055866451f07a7b emissiontrue_res_23.out -871660652e913d09695f5e6e26834f7c emissiontrue_res_24.out -2dc7044504b348713aaf34def92c3272 emissiontrue_res_25.out -0561baf5346ade6d8ffdc494d48727ca emissiontrue_res_26.out -2d9e8a2c0031766fd90a361530a73a26 emissiontrue_res_27.out -34f9872181679473d07675ab75d2c675 emissiontrue_res_28.out -919dc98b95eb77be03b82c660221affa emissiontrue_res_29.out -5650a850a12b33016728389d7fb71009 emissiontrue_res_30.out -f95cfa6c3ef1cbbcbbd09896cf6e4466 emissiontrue_res_31.out -330e4fba970c634007e94206f4e39f81 emissiontrue_res_32.out -60f0fd59eb61adcecb3c69e1ce72a348 emissiontrue_res_33.out -d3fa0730a0a32c61a6dac27012b984cc emissiontrue_res_34.out -13b4d991263ab658d8d85d5dd674c8d0 emissiontrue_res_35.out -b2ac74ab878074b1461b130bc1c08305 emissiontrue_res_36.out -7db602e1f4498ea1cbc1b072a317eb8a emissiontrue_res_37.out -91d87baea183622cad487ab21645016f emissiontrue_res_38.out -62a23bb75fbaed1a332b2775f587acbf emissiontrue_res_39.out -ee8053b342407a8f4da1abcba98ac657 emissiontrue_res_40.out -f25b65a882e2169a8fa6b412223d6374 emissiontrue_res_41.out -5d3eec0d963da5687d81a5af78ad2dcc emissiontrue_res_42.out -2bea83dd6aa54319adc1464c94029f6d emissiontrue_res_43.out -cdcf8aeeeee405e399fb90ba5cfed187 emissiontrue_res_44.out -ed1c5df2a56a9906953091037f10951c emissiontrue_res_45.out -e29474fa08e666d4c69c9bc390ec6e28 emissiontrue_res_46.out -586cedd62894bd015cc6805ebf39c199 emissiontrue_res_47.out -74dbc16356856442931613cab4cddbf8 emissiontrue_res_48.out -99a6b739c237e07295f9a71bbba00c2f emissiontrue_res_49.out -522ff15ce7f703f2c15fab50ce4c9814 emissiontrue_res_50.out -b5a94f54cfc3aba34197ead1a6609755 emissiontrue_res_51.out -ae640f0f787eed377f51cff3e3fed095 emissiontrue_res_52.out -1e76f87be55d15d4498ca5ffde7f7bb0 emissiontrue_res_53.out -032f822b833ed36b40b7a6334687a1de emissiontrue_res_54.out -84e20f7f568b4eb71160d2c6c361b920 emissiontrue_res_55.out -7b39644722208ff9bbf7cb12bb7d7066 emissiontrue_res_56.out -a00cf374045954d2f9dc9b53801089b8 emissiontrue_res_57.out -8370498e535cb482461f64d426dfd447 emissiontrue_res_58.out -0dae108d94000fc7ead19900fa090fd8 emissiontrue_res_59.out -36a914df99e5e37c17e2c8d8eef4d16e emissiontrue_res_60.out -f3cb36fd1bf6875c90142e6636710644 emissiontrue_res_61.out -672966d1d117af21f6459716c1a0b25e emissiontrue_res_62.out -4838e76868c26cb05dabfb678b0bbfeb emissiontrue_res_63.out -04a17334bd9bb6620cd85a826a412370 emissiontrue_res_64.out -5a08835e37e7c3b26fac12c1bf8c5cb7 emissiontrue_res_65.out -ded14560e989b2050ac13768bd20e16b emissiontrue_res_66.out -8faed9a2d3949a79c3ca70c234bf7a6a emissiontrue_res_67.out -ba8d6cc14bf7ee82bc838032c156f843 emissiontrue_res_68.out -618034ba2ee8e34a8c82c94df0cebc6e emissiontrue_res_69.out -be738d3d163ba5cfe8877fc62937f5cc emissiontrue_res_70.out -3456764d34d3927e8879785ba73a36b7 emissiontrue_res_71.out -79ccd47f533cec8f895f79790e3d8bb5 emissiontrue_res_72.out -88643b42153502fa08e7fd7aaff997c2 emissiontrue_res_73.out -40620a2ca0e859f6073ec5888b4fb550 emissiontrue_res_74.out -f1540b5a231e338896e5188f84911d36 emissiontrue_res_75.out -6c55fa7e2bc1ca61a8c7e900d16e9641 emissiontrue_res_76.out -e73a2038dba39ba8bb1a3d976b3c0e7e emissiontrue_res_77.out -05f74ab0d45f77b4a974d4c06116a418 emissiontrue_res_78.out -5d74d1940afc4aab6b7688855ed0b591 emissiontrue_res_79.out -ccce0fef4f427572799299ef0c5d62ad emissiontrue_res_80.out -88c6f5af70e3573a8c7ee790f9d11648 emissiontrue_res_81.out -5727b6e6ee2ac4c20b15f944aba5780b emissiontrue_res_82.out -d51d4b565b68c8b9ffc51781244ab407 emissiontrue_res_83.out -66f0ba153955400a1b58c0ccc97a0214 emissiontrue_res_84.out -820da2e5b582c9862229cb6b167b9f37 emissiontrue_res_85.out -bd26f13de50ffad2e1edde69f4b75019 emissiontrue_res_86.out -2a251c27a58b1a9d6f94abc32b1fe63f emissiontrue_res_87.out -4746c6833b3f318704b2d8907a404468 emissiontrue_res_88.out -e6f7f1fc9dcb4909a2d56e61f358b695 emissiontrue_res_89.out -3bea3700244d79928084d549e77dffac emissiontrue_res_90.out -0af91b5df34145ea5f9182ac2edea602 emissiontrue_res_91.out -0a81610cefbe332fc2d6504802d667c4 emissiontrue_res_92.out -5e2b512123d49d0b613c4579ddfcff06 emissiontrue_res_93.out -27b470e781e4f315f49ef1f6507d5bb0 emissiontrue_res_94.out -eb54d4d7405344fe54da56203ae57ff4 emissiontrue_res_95.out -b8b2592ba4d998284eef1a0cf86fb84b emissiontrue_res_96.out -c2d392130b4372aca9b2b01cedfd8937 emissiontrue_res_97.out -b4ff12e7ae1286ac17ee3233109b2c34 emissiontrue_res_98.out -46f14dbb082dafb5c493d05666c955a7 emissiontrue_res_99.out -a7c08bbe28a865f19954c289c030947c gamma_light_curve.out -d83de228b1ab8b7f0893c8b08ac7ba66 gamma_spec.out +01bd19928247966645cdab9708de5c8d deposition.out +9780aea2fd971ea4e1ee9a0d66ae2707 emission.out +caf05b95bd6772642e7e467c899cf8f3 emission_res_00.out +df9ac20536b70058b8fa4679fbf08606 emission_res_01.out +09c6a89a3b33223e2a69d0df4b99b093 emission_res_02.out +12fe67dc3032204699f51fbdb1806d53 emission_res_03.out +35732aeaf56b27c56d8f5b30c9633a46 emission_res_04.out +226a4bda44e62c9cca766a73cb9c501f emission_res_05.out +fa3188ff36f65874e56a322ac330311a emission_res_06.out +21464872febb9195bcdb66613b84e166 emission_res_07.out +668d85e2d919e2a1cae4aacf6501a4b2 emission_res_08.out +e91d258d006db1d2f51e8ae2e30b970f emission_res_09.out +023512b7f2e40bde11740a06689588d7 emission_res_10.out +64e4b2fb6bb47e5f5b235441b1a4b789 emission_res_11.out +dc8c39f78c63d579b776ec7a579df0f1 emission_res_12.out +29040606466f26b839c4b2f5acd338dc emission_res_13.out +3ab6699f20dbb04d1f89eeaae7dc1fe5 emission_res_14.out +fe3468ef859bb54d4273f97196b9b2bb emission_res_15.out +d0bbe2e7e55e2b54557c67bda941bd0a emission_res_16.out +3b95ffc2dfb1aa4ddcdbdeb0bf3f0f91 emission_res_17.out +7f1eb035efc1830a0fc3ebd3f514f49b emission_res_18.out +09267f83d1196dbb15c1365c6ff8aa39 emission_res_19.out +d0dad331fe85cdf946af5bbff98d369c emission_res_20.out +8f645ae2a40ceeee3d838b0af0d8e5b3 emission_res_21.out +f79a3500f7296f86b800825cc09ff3ad emission_res_22.out +3b3dba0b9c45504fd803f63cb6b71931 emission_res_23.out +e03dc38ef37974d03372c404ee504257 emission_res_24.out +382da61dfa307a55fe5dde92df5ab35a emission_res_25.out +f2f12586e3d87f3f29a3e954fdc1c234 emission_res_26.out +38cb2fd2b7054e4c1572cb9f681d53e1 emission_res_27.out +a2671b19f0e6c9de23179cd8c5736a1b emission_res_28.out +42532fb05de7be59501e21cc4ec7ea2e emission_res_29.out +b87a595605ed848035ebb79a1847dd01 emission_res_30.out +52848ddd22a05abe9a20e66e98ffd3e1 emission_res_31.out +8a320bd7fb77adbbbd9412a925ba89c3 emission_res_32.out +88d1bc6fa346515d9056f480fd23c377 emission_res_33.out +abef896caba9755b18bed9a2ce4a6a90 emission_res_34.out +2a7dc57e1a9ca00f188370eaac1b7abc emission_res_35.out +f7c0439c3991c91490f2402133e24466 emission_res_36.out +09f3168600c7d0ef2d43afd7a5988244 emission_res_37.out +e5615f2e3172437e750cae0b17b27fa2 emission_res_38.out +3cd195770363e95a385e85f451573ee1 emission_res_39.out +bfefcc2268797447f38110fc938a6eb9 emission_res_40.out +8001e649d72a9afbc29a18eb15e4a510 emission_res_41.out +aed0b8ce47ab904aef6092bd8f63b907 emission_res_42.out +8a2be3a718deb8a009990c898526c1d3 emission_res_43.out +9e5712b2a668c36c43a2b5756a5985ef emission_res_44.out +4c022af08d2e195e8ae59420c55a792e emission_res_45.out +d914e3985bee435f44bdc577b9b5f820 emission_res_46.out +bfa417c908125bf3d48b5aa3256ed19e emission_res_47.out +a006b5e107ed874c486643de6b4da1cf emission_res_48.out +851a75b7cb7c25f4988b3bcf704d303c emission_res_49.out +99960ec8f5846709f89703d9773632ab emission_res_50.out +69a5277175c1b48890155af9b16fa66d emission_res_51.out +46bf934085bbbeb78a469af225f2a657 emission_res_52.out +12e5a3139c9bf5105d31a1a6ecd9539f emission_res_53.out +037ded84ddb3965503d86555c6389185 emission_res_54.out +897e3eb47377be8d48f9f60ef4d89b64 emission_res_55.out +fd3beb5a3585d862b12278a130a36fd6 emission_res_56.out +406ca966ece1fca3b5cba75e879f19ed emission_res_57.out +a8e1386d4874adbb8b306fec261338bd emission_res_58.out +b4231858d71ca3f70bea0aec1cbd1f35 emission_res_59.out +99bb49085d60c46c0142e6fc26100624 emission_res_60.out +30769281ccd77429859a5b180b0a1d20 emission_res_61.out +a8255c957bfe52c8d049cedb5c1e9708 emission_res_62.out +1c74510371f838215664f3058cd69f22 emission_res_63.out +954fcca5b630d787c52fc006905651fe emission_res_64.out +fef8a6d3a9f8d6344a70fc6fed257666 emission_res_65.out +346f62c2b9616eded9bbf9fcd42206bb emission_res_66.out +d3ffff9d12f552f2f8dbac9bf74aec0e emission_res_67.out +29eafca02d1c2fc38277b86bbc45af51 emission_res_68.out +a94d137d9ad3fe2403ec4f6944a10c50 emission_res_69.out +99b0895319275c54f6046fd52d4904e5 emission_res_70.out +ace0291b16189c2671d16e08c7dc8c09 emission_res_71.out +179bc71be2a2550bb1e7e661e2bdc30f emission_res_72.out +cd40d1e44d32ab457758d2ae267581bf emission_res_73.out +7b3c9edc78f9971773104004ae443997 emission_res_74.out +e600bbcc5cb1c7eeff0107122dd27d9b emission_res_75.out +296a1a0c334ca2e9ce36aa449c9f1fde emission_res_76.out +ac6ca177fada079572e6aa06e89b4e2c emission_res_77.out +bf4ef5ab2a7f4a52f34f9c59c75e837d emission_res_78.out +2b8941764b8dfb31ee98e3e304e2c627 emission_res_79.out +50cf71cd1e1896226fdf2c4a4561c520 emission_res_80.out +27392bc340d653f3cf3ad8f42b4f0eea emission_res_81.out +a38ab6c962811f99e4406c9411a35b93 emission_res_82.out +2f1a279a68e84a05685ddb59a1cc9bf3 emission_res_83.out +6be244db2cc63c3ed8745c9f42331d7c emission_res_84.out +92f2197edc4500c802484ebcb51e27cb emission_res_85.out +2d9a2ab411bd6f0a28115b4848e1617e emission_res_86.out +fc6911e4b88d605b5082159a2e55a173 emission_res_87.out +198b8a674507f08c9ba638e80c90b3a1 emission_res_88.out +749711b5c98386ec60b55e3403af30eb emission_res_89.out +6dc5cc6f7c3500536f50940a648fee8b emission_res_90.out +6076c03ef770f62ec3ca73dc56902d03 emission_res_91.out +04850e1fdfda57c48be326f69f2093ec emission_res_92.out +4768a4b167c66009bf85b543df94387a emission_res_93.out +a2e5886381adb431175f2fe9ae873fe3 emission_res_94.out +c2f881c0c45e73df91933632c0cec3fd emission_res_95.out +1ebe123edeead15306da112f9924ed1d emission_res_96.out +8cd46d453a7d5211ee1ad39a9fb180cb emission_res_97.out +2c8eaa9a444d20d3140a6ab0155456b1 emission_res_98.out +9eb79b52b3f252f533c34e5057d45b14 emission_res_99.out +f1081c1dacf56fbe259d583797f1fb74 emissiontrue.out +a220ff31f03562422d8bd8fe6198998e emissiontrue_res_00.out +7a892dbb8e39691fb28b1178a8534a3b emissiontrue_res_01.out +9bdb0c28c52ed897a92bccb56c22cbf2 emissiontrue_res_02.out +b40151007ce13ded7ec67854b5c7dce6 emissiontrue_res_03.out +88f14d25f8bdfe9c7eb8aee769ab29a1 emissiontrue_res_04.out +b124ada26fc942a3374cf90e7f0f883f emissiontrue_res_05.out +8a5d314da8b51898d7f89ce701ca2250 emissiontrue_res_06.out +306c12713ea6dc2f291b5d494d8c9783 emissiontrue_res_07.out +a79ee29b7903846770ac7d1c033b8a16 emissiontrue_res_08.out +4e93e0bfa32d07de8fdae23b371f878c emissiontrue_res_09.out +a89e26bae369355d3c06921d5c6c0f5e emissiontrue_res_10.out +c0a40164acc0fdc1d33c6e923d3b6f17 emissiontrue_res_11.out +247f8f585cc731aa430ecb9af514838a emissiontrue_res_12.out +fe224815a1167bbeccadfda352ddaf15 emissiontrue_res_13.out +37af747f86385008b295bf08b515c000 emissiontrue_res_14.out +b43e6f8dd961bf119b1e29d7896b38d5 emissiontrue_res_15.out +8c196ed7ce87d24eb65c8aa36fca8ca4 emissiontrue_res_16.out +dac6b3d6337df4b6c55eb17c83c2cc5a emissiontrue_res_17.out +90cc2e9f476d2fcc2af52536ab21180f emissiontrue_res_18.out +1c7ca165129928f3ca9104e869149df2 emissiontrue_res_19.out +72239cc2d50d710863179bea2ec6af9c emissiontrue_res_20.out +412c88215f1a77cf89c9300e499ea1c0 emissiontrue_res_21.out +d5ac6efdaa0867006a5ea768413a92aa emissiontrue_res_22.out +d4d60f6100faa6748962627708f87d70 emissiontrue_res_23.out +468d61f3e933cec3c6cf9f1b981dbdcf emissiontrue_res_24.out +3b52e163bcfcbbcb82632bb8900d86bb emissiontrue_res_25.out +9181ce345dd6bca193bdf56148e3deea emissiontrue_res_26.out +8ba8546bec26ce912cc0ecc3b3082a81 emissiontrue_res_27.out +d2e7cbe10d325f86c0faa1ed45eed3f2 emissiontrue_res_28.out +88c100589d6d85f4971febf74b429583 emissiontrue_res_29.out +cde9d037ca75561ae57966f08e80332b emissiontrue_res_30.out +8c0c6132b6b3d64e246fcd2ea874d859 emissiontrue_res_31.out +3372b23a68f1e66682b64818eeb52e5e emissiontrue_res_32.out +cbeeeddd8ad7d2ce98929cf3296ed4d1 emissiontrue_res_33.out +51e8eca686139582e931290c686a6062 emissiontrue_res_34.out +83d3f6192234716ddd650437f1a0227c emissiontrue_res_35.out +c73b549bb7a5689de664125f9afb3a24 emissiontrue_res_36.out +b843af918636bccc7e0958b320e2cfea emissiontrue_res_37.out +a3cc993fe42d19232340214e85f3002d emissiontrue_res_38.out +d9bff692d4cf533ac2b0bef4f4be17a3 emissiontrue_res_39.out +5f3074f32b249caa9bcdd9b57bd4c152 emissiontrue_res_40.out +ead10b1884be4bb186579f5726c315e9 emissiontrue_res_41.out +2b685f9013b121b7ca535ed53a226e0b emissiontrue_res_42.out +ea3e31491cd9e628b2a16ab80332ab77 emissiontrue_res_43.out +f551e930de448385055e88d14bca1f1b emissiontrue_res_44.out +76d449bfbacd7a9387d0c240a89dfe44 emissiontrue_res_45.out +8c8d2b7a459d26566d14d52351a8c14d emissiontrue_res_46.out +42efa0fc4debb8a4c3d8872d6c152e5c emissiontrue_res_47.out +50ddf21c6a87576281b0b030a29ddcf1 emissiontrue_res_48.out +1733b5d5dacfe98bb8320bad76d448ce emissiontrue_res_49.out +748c65c25d2cc15aa32f71704a294830 emissiontrue_res_50.out +65450f789bab13329403164d5322e536 emissiontrue_res_51.out +6971857f8edb52367624d9ed7b1262f1 emissiontrue_res_52.out +8a5d3dbae5d961b8671cecb24f2fcf50 emissiontrue_res_53.out +7fa3fbcd25d6b6bbcccc996cca3b6510 emissiontrue_res_54.out +f33bd08740f855319bea4030047d6aee emissiontrue_res_55.out +d694d01d11ad9f992ed3e28189d1eb2d emissiontrue_res_56.out +c4e55ae36422dbb9e0d0ac0ccf207d3a emissiontrue_res_57.out +484746a46b614ef988d84590051cc491 emissiontrue_res_58.out +bdf07cc3fc8cb83082c23ca8a4691d65 emissiontrue_res_59.out +172465e20885114bc8ef348757a3d4af emissiontrue_res_60.out +444eba20ec3e69a08fe1b44ce869ff9c emissiontrue_res_61.out +1394de62bf847c57dbe78da5cab2c137 emissiontrue_res_62.out +52329de45516ba61dc99664452eccb9c emissiontrue_res_63.out +a59c91a64ed2613b50c59c628368aea1 emissiontrue_res_64.out +316e1eda8c4c78daad243afa59958c8d emissiontrue_res_65.out +755067a572ed040306e286d5f492410f emissiontrue_res_66.out +3507fe93fb039568856f06797ad00949 emissiontrue_res_67.out +96de22c711a53f7df36eff583c48762a emissiontrue_res_68.out +b5c35c853304818a174c5bd973b8812b emissiontrue_res_69.out +3aa2d7b8a8fe200fa155455bbb692ef1 emissiontrue_res_70.out +be8fba4f7969a10a732215f51de24bbd emissiontrue_res_71.out +532a79669862c3e872d851b6dfaee3b5 emissiontrue_res_72.out +d17e81426b9f1f7ead89f5493d27c0b9 emissiontrue_res_73.out +3f2cd49daf224c39d9f9e62e2f74c8c7 emissiontrue_res_74.out +d9aabe6ccb4e013df16c16f1183974ff emissiontrue_res_75.out +15bed6a6e5d7af4e9e930d4b376258e1 emissiontrue_res_76.out +50bdc817847170ec1f7be955e1b67fb1 emissiontrue_res_77.out +67fe3d8773e46b7552e30ea13039e39d emissiontrue_res_78.out +f460ebcd922ea65ba2bf3e0c99aa2494 emissiontrue_res_79.out +b30576ee4f61211171e63fe2b1f6c1dc emissiontrue_res_80.out +ff64e78c22a507e20a8cc6fca7afb4fb emissiontrue_res_81.out +1085db149d67e98b23d34bdaaea96256 emissiontrue_res_82.out +09bf43815d57556321fe2f13bfee8e10 emissiontrue_res_83.out +4add58f2a89af41c61214eea4142cf24 emissiontrue_res_84.out +128e57a3abafc1614696696a987b645c emissiontrue_res_85.out +ec5d8ebfb92b5bda8c96304528866bd2 emissiontrue_res_86.out +cdb8a04f39facbd2adad97cd08dacdbb emissiontrue_res_87.out +3c3517723c9f03d6a9057091226f0990 emissiontrue_res_88.out +78def8022fb15eedc9ded8a086d77928 emissiontrue_res_89.out +ff9a45b3d57042b5abad4ac147cc65d0 emissiontrue_res_90.out +e895c856243e85345c08d8dd1893ca4e emissiontrue_res_91.out +937312fe80d64a99f1e6752511e3921a emissiontrue_res_92.out +d18d0013fc6f520634c0b2b3278020a9 emissiontrue_res_93.out +02a317c51dcc4b40dacdb26af9df65af emissiontrue_res_94.out +695fcc7113f6591b340021408e593206 emissiontrue_res_95.out +442b4d85308cbf341f6ddb27f2280fef emissiontrue_res_96.out +371b99bc08acaf9e539c05ce20eaf4b3 emissiontrue_res_97.out +3b1236be8ee9fe49928379cac36cee3f emissiontrue_res_98.out +9e2b0a72d0e48ea0f15addeb717feea6 emissiontrue_res_99.out +8a370f8ac30f1b1a3fe36d8ff06bceb0 gamma_light_curve.out +2e6de551ab8d8d085497cbe9dd193b03 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -955d31fd111393b1315db81532328d31 light_curve.out -7e67512060d4e93afe5039c9b0ab8311 light_curve_res.out +ddcd979f77ce63df38a604634ed975ba light_curve.out +d2f6c90ac32be89bab395bbdb4932f0d light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -0cea5aa745a999033d44f8920f6fa3e8 packets00_0000.out -9c6dee8f63bff0dec662f29b626aa797 packets00_0001.out -ae3f8f8b28be5bf30540b5e47ff86826 packets00_0002.out -74e03aeb2260bb632b27e5f79eb0af26 packets00_0003.out -64898864c17bab3387d8b9ae3049e522 spec.out -c3b66859e11eb7313b5d339fe5ce35ea spec_res.out +d6c0219cab5fc8c9bc9766a5cca43c44 packets00_0000.out +4207225f21ecb78897122db8726e49c2 packets00_0001.out +948d43f454ddc88d63343dcdbd36bd6d packets00_0002.out +62513b5559e069fd1f24e746c6a80ff0 packets00_0003.out +4715f765a68a2f9ea81e56b8dac697df spec.out +e78908c4548a0c652c0f05b14e64cb49 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -f96be9203b24fad4c57ab6ba6827afbf job1/estimators_0000.out -a0f7cb8a4fab79a7fd5f7cfd3945386b job1/estimators_0001.out -fc2141dfcfe6a5dfe80934327b4ec301 job1/estimators_0002.out -31dadb2d933fe41ca2876a6fc73e5e7f job1/estimators_0003.out +b8e49f14003ea7359cc904cbbafc418b job1/estimators_0000.out +d893b483868defec46dcd6967d50b766 job1/estimators_0001.out +b5dca1726fc96a9987671c9f19cfbfc3 job1/estimators_0002.out +408d4ea2b9dfb505802572172ad2442a job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index bcdc39a28..053993b34 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -3337513cb60d2a287aef2b1e4e67cd07 absorption.out +091b4d802b3550712d94b40106be60e5 absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -acac95ccb956c25530fd5ed0115feca2 deposition.out -0fa5360597ed0c8af68788dbc7432672 emission.out -bb40c970ecc85e33ca48ddc88ce0d457 emissiontrue.out -ed7ce45f9e18d49cdd4126cc5d6fcfa1 gamma_light_curve.out +4d929a95df334834be2c93d1b6cd3a19 deposition.out +25e05e72e89cdb6d1dd4c5f354edd774 emission.out +aa091714028c7ed425cfb313450f7518 emissiontrue.out +029b183f609bf0765d793b01bdc6a1f1 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -d63a255192cc1e29ab78163723bc1db9 light_curve.out +785c2cdfd015a553276ca150db437315 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -22651cf94abd66c2c4d499555566281a packets00_0000.out -41436ba3515cc478a1472d5e75b6d6d9 packets00_0001.out -3c0fc6720372a76efc4a078d6df96d96 packets00_0002.out -1ae4f9d67664ce6c0cb9220d277eab58 packets00_0003.out -2bdb433bf9c9fe351323161b76f5da65 spec.out +f0b4c6fb5758defd5f6f1502dc90f039 packets00_0000.out +20210c7010add7c3a51ed103c4ebe02b packets00_0001.out +3e2467b7c46b7617db77dae9d922ca0f packets00_0002.out +f1c0736e2563eb55f4c3e9deccd0dbd6 packets00_0003.out +824b8e35b981fd2b481959e6dfde821b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -b065ff4a0cccb1af281f33d68eb10027 job0/estimators_0000.out -7b4a132b9fa6b33bf9c3602bda38e32d job0/estimators_0001.out -bb2f8fe1cb03173e6c089c36bd9a1831 job0/estimators_0002.out -32d620412c9d1c84f6a1e22ed9e291f4 job0/estimators_0003.out +de58722214caa437a3e7a3542621a8c6 job0/estimators_0000.out +806703e3c07c78b99a8990314c692a88 job0/estimators_0001.out +ce3aa8b98938ad212e511b4aae959fee job0/estimators_0002.out +a76f706fa21bb93bec0d2d2c290f6bbf job0/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt index 5b5f8a5b9..441297cb7 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -4aad47a04c0a71752a457f53faf1e000 absorption.out -0783cfa238ece80c83e9a267aaf816ec absorption_res_00.out -8ac0e4e5844dae1fe723a06451168020 absorption_res_01.out -19ffa8db29d187ed1efe3b9eae899c3f absorption_res_02.out -410894eba7147a325952204a4889d775 absorption_res_03.out -9ea42a1ae6456bde41e1f1880b5ad0f8 absorption_res_04.out -8691dbe9729ac1ab5dbd19592fd02a75 absorption_res_05.out -17fa988d9fb962297b6108c0e1081bcc absorption_res_06.out -f270cfbe290af1a7bd34e8dfd9cee56e absorption_res_07.out -7b02d31436a69fbd71d5759f6407e69e absorption_res_08.out -26673591679af16361e2f136b5f00e05 absorption_res_09.out -e168e82b7b6554c707fe4a7be2bdf634 absorption_res_10.out -585fa2ac62febe588455457bb8f351f9 absorption_res_11.out -9874cfccb0da415da7af3321b22c2859 absorption_res_12.out -8ad347d03bc2a8a4c76e4c299c3ad3e4 absorption_res_13.out -8d6b0f3cd1cd76578bd5fdccf23ecaa0 absorption_res_14.out -3e58b73e05d177d3de053f13c1aad0cc absorption_res_15.out -a4b552331538fd14f0f842efb54e90d2 absorption_res_16.out -8d59db1a13b2b36f1a9f328d554deba8 absorption_res_17.out -1d5fcaf46a80397f3adfe59f26a71112 absorption_res_18.out -9bf6ce53118487cb1260c08b0fc6bc00 absorption_res_19.out -58565c270ed1b346b585286830b39148 absorption_res_20.out -7c31ab2a810468f8a82aa00a2058c518 absorption_res_21.out -00316fbfd63c6164ccf891abe23b99da absorption_res_22.out -28ddf6a6ea43d6a5a2d1183f8d95d893 absorption_res_23.out -30907f4a91e319af9d4f191df2888eec absorption_res_24.out -e778fddc70bf3445d0d22e941d18ec1d absorption_res_25.out -4ea4644d84cedcd8e2f1e71c25cb9724 absorption_res_26.out -90ef16d9ebfdf84f9f18f3ab1a2e01ca absorption_res_27.out -1c9a94391a261fe49f26d9c8bbddae7b absorption_res_28.out -3905150ebba4e0064df96aef3dff4bb3 absorption_res_29.out -8305c639219d8bfd6479f1fc58a82fd5 absorption_res_30.out -83f9b3d55e78f3a0f74d0e9688bcf860 absorption_res_31.out -649fcb8656ceb8caf69a8e862154686d absorption_res_32.out -cfe8267629f246c253cc3ca28e60a2e1 absorption_res_33.out -2ed34f8b5f231a448a50c32c7ba141f6 absorption_res_34.out -880cce93034261453df7f447304ef088 absorption_res_35.out -83db1de278c6a58ef14baa7f093d1548 absorption_res_36.out -1595bf34286aadd33fdbfbeec8d5f14f absorption_res_37.out -39ed0e30498f74e138810a1b4c83eb31 absorption_res_38.out -4c266bda56d28f390a3287a778f4b65a absorption_res_39.out -162938ee3f8a4da922fe84d9d24b765f absorption_res_40.out -405b74f0d50b3172fa6c826f7b812677 absorption_res_41.out -a0cf6aa49a9ec1e83c9ad91702fbb83e absorption_res_42.out -5fd38e48c11c703f77764e54c78c7e4c absorption_res_43.out -e1103ca91b327377e8e74c5890236c8f absorption_res_44.out -e73a03c60fe49f9d36f6ca1c350c2318 absorption_res_45.out -7e11c1b73fe2393e623248dbba54379b absorption_res_46.out -6c27fde97575ae92f4eeed406e5bb36f absorption_res_47.out -f92c8fdedd0cf13474cb7b264d0c81c3 absorption_res_48.out -2eeab024d92c11551b006725ac386e3e absorption_res_49.out -4c9466588669d7a79db90556e7d55c54 absorption_res_50.out -f9aedc00e3dd47b7c89312d22e6284d3 absorption_res_51.out -2892a367b8712e27291f0a26fc887043 absorption_res_52.out -99d645594851b7ae232fe47a21f5e39b absorption_res_53.out -c717aeafa0210f56cbc6e323c11be06d absorption_res_54.out -29d7d470672e7063a2b007dacde7fcea absorption_res_55.out -aca4da57f39cbb61af12de351a0fcef9 absorption_res_56.out -0c010752ecca5ff40af18c263323e86a absorption_res_57.out -3cebf66581ef9627044b8e770f416556 absorption_res_58.out -53f9cc8fd108e73feb27078769fc4639 absorption_res_59.out -5ff779273c05c1a1de4812e3669c6c58 absorption_res_60.out -c66a667e1398d112643aed347f596c24 absorption_res_61.out -4fb180b04b237e3050506a47f3ac16ea absorption_res_62.out -bb2f1459c55cf94484c0c28e97c2c2a3 absorption_res_63.out -fcebd0f5c212af0c6b8e7065bae5155c absorption_res_64.out -aac2694abbc13068b833c1e8f059879d absorption_res_65.out -148542bce3db1d425dab8601a4b60c76 absorption_res_66.out -81fbbd17fa74fbe80eba01fc111702d5 absorption_res_67.out -ed95ed1c8d1382fe94d1c98f7593e171 absorption_res_68.out -2e2e39838ad5a764d7c4d0d42648d706 absorption_res_69.out -2b8287193dba7a204e0ae1fa2878cbe2 absorption_res_70.out -1406767faff351e7eacea7b20b1c966b absorption_res_71.out -e7d9ce116f2e4271fdad7384856cab5c absorption_res_72.out -4c7c801f6cbb3df267aff3cac6f6bc8f absorption_res_73.out -c06aede01c3a526a0136c236dce082bb absorption_res_74.out -035aecb84fe5e0536ac3a187203bf2c1 absorption_res_75.out -dace3462f8214bfacead042299f4327d absorption_res_76.out -a3be5fbb7baac8df6a827cdec5f5167f absorption_res_77.out -b6e4cb2051d3914155c9b8cb41a1bb25 absorption_res_78.out -2b8a7fa77b76df613e9925e3e4fb4787 absorption_res_79.out -1bec9a4594c32c289813eadef606d87d absorption_res_80.out -d56f4480ffe26a3480d011ba7e7a5171 absorption_res_81.out -b570c65a0aba020e3e1c84b05187b07f absorption_res_82.out -eab2e0b6b3b583e06bf1b614d9763fd6 absorption_res_83.out -8c7aae616ac79eebc3a4b495cba5ccea absorption_res_84.out -5770ffce567ca48337d491d15a9610c0 absorption_res_85.out -e84c9709a359818ff1887912883c946a absorption_res_86.out -9519772870aa5b638db6ba370505e2d9 absorption_res_87.out -5caa7bed04dca5ad80dc1cb2a7ea89b6 absorption_res_88.out -32f0a18ccab2487ebfd44eef46f04f98 absorption_res_89.out -1018ef33e4ea04ad208c7152d1f61a76 absorption_res_90.out -bb2fad88a0ea07f08a526355bd597772 absorption_res_91.out -c65ef30b7bf143bddd99a01f77094cc0 absorption_res_92.out -b70da5bf32e9183ba7b876d1bee61188 absorption_res_93.out -326519e2d846926ce75a53ba6117d14c absorption_res_94.out -ff3946a15c6c2847933f7f4a58476681 absorption_res_95.out -aab1f46d58c33609b04bada919c05556 absorption_res_96.out -f0c08137373459a7e9fb33d960fa7bd6 absorption_res_97.out -06a7348152016307a7bba051f6e50695 absorption_res_98.out -4f277b91cbd747fc1b73f17394429243 absorption_res_99.out +f9d9f33b0111f41d2df66ee38ce7858c absorption.out +1415c33cabda1b5b8c452cde5a3774a6 absorption_res_00.out +bfff2119309df259a4dec4437e740b5e absorption_res_01.out +1cd342aa4c5a07f20aa00d186dcd61f8 absorption_res_02.out +d4578fc93a81b6dbd1a3787b9ee72883 absorption_res_03.out +cf4df86bf09622c3f3687d6b38f06750 absorption_res_04.out +8114d6980fa76210de9895dcbfd5d7f9 absorption_res_05.out +b7ab214af73b16c99b599a301fb8824a absorption_res_06.out +2faa6db408aad5e73ee82ea69a2e03b4 absorption_res_07.out +bcb7ec08a176961fc8440c49ea6c5631 absorption_res_08.out +18771d6446e2084a91697877629b7464 absorption_res_09.out +0c5efbea3c6ea1e6e59f4c2febfff5b0 absorption_res_10.out +a9a4affcb9d1d6563a33e06fbd933c85 absorption_res_11.out +80d1fa5067b13cf53c7a8af7daecc0e5 absorption_res_12.out +b9d9e53ca11d51488e81917b17680f4e absorption_res_13.out +539989921c1f6b7fe32ad3e0da0067b6 absorption_res_14.out +e9f796f17dd040dda87e9e656c07f426 absorption_res_15.out +f874ceebd65c40d7fdc3a51016976576 absorption_res_16.out +1168013b4a37e3e35bc37d04d65c68bf absorption_res_17.out +1bdec8ee5f161110a7dbe88ff1f6d19c absorption_res_18.out +dfb14cc33008ad397dfa2e071ceb3d23 absorption_res_19.out +8ded9d4b501cccec0e019d8cc5a0e4f1 absorption_res_20.out +180e6b3ec60bd5a415c51cbf6a97d4ea absorption_res_21.out +aff008087a6cf24ea09b999ee058ce7b absorption_res_22.out +bf64a434fc8b99f96b3dcd8d1565115a absorption_res_23.out +e38e016b75c00d2de1ef556d78b9a8b9 absorption_res_24.out +55aa2eb071f9b81f18480819035b056e absorption_res_25.out +206e0fce2e46daa7a7fe0413f946a4c3 absorption_res_26.out +28bc5dc0c5f2c821c64561ce7f5a5726 absorption_res_27.out +c62b405b4a8d095eb6139de1cebc3634 absorption_res_28.out +7fc002687e2c3590e2c805bd8860deab absorption_res_29.out +71c7396e0acb04e45c0b5e8a170afa70 absorption_res_30.out +1b7a198aa9e9062ca70758429804c1c8 absorption_res_31.out +ba2c6e2211d2f3bf7fb0f9b4a19e6583 absorption_res_32.out +d4d7003abfe44ca3798adbe2b771c1eb absorption_res_33.out +8c3b099c95112c0f6d115311e8c3e9df absorption_res_34.out +e1c9f7c79bdb2b9582f4326cbe3c3313 absorption_res_35.out +7475419afb8f1c2f293b0654461d34be absorption_res_36.out +a87542ffc6abb4f5ae64e289b920fb75 absorption_res_37.out +3ab66c18494bc3540838c850f14b33e1 absorption_res_38.out +94d447efe8b0b443c3c0156d23e34ed7 absorption_res_39.out +63b294d22a70eee35e5312e4b7816350 absorption_res_40.out +d87ff57594b6dd6f2ddf4a505a0efecd absorption_res_41.out +07e025a7ac3c350c419b073fc7405e0d absorption_res_42.out +21a40a55505668ce4c3e779c7d675a9d absorption_res_43.out +b0207c3b981e5ea035ec37780fbbcb25 absorption_res_44.out +1520fa316f7f49726e0aff57a434846c absorption_res_45.out +2b5fe32aec00e7a503e651d9706f688a absorption_res_46.out +6d63f260b98feea4a7e92a91fca764fd absorption_res_47.out +6ee763c60cce9bcc038d257a987405ca absorption_res_48.out +15c42a3d72a880aa3f6400d145debec2 absorption_res_49.out +05d19de1f7a78e710ffe402796084258 absorption_res_50.out +861c66e86503dcd0a276d21da7c9ff15 absorption_res_51.out +839c70f6bef9f22aa31b095c22223867 absorption_res_52.out +feeb4fb3bd8ce672ac64bf826ad2ac30 absorption_res_53.out +bd65b6e2f80c47b55a27efa9142ba743 absorption_res_54.out +9495dd3fb5ef7994701f0a6045e155de absorption_res_55.out +cf2f2a208734e2590a63e9e7e42dc0b1 absorption_res_56.out +a904885a5aa27edb3b27876c7386945c absorption_res_57.out +e65359e96adf60b5a54be6283d239936 absorption_res_58.out +fdef337ce618b60166e6f5d251b14e79 absorption_res_59.out +9132207b8bf026ff6d9e21dbee769b6b absorption_res_60.out +aa5182794b9420eb708597378f366095 absorption_res_61.out +6366f0f5fbff04d491443fb320a07903 absorption_res_62.out +ef4f5b8431d6cad9ae329f0818252088 absorption_res_63.out +a9a983fd855bed1da22a1021353aabe2 absorption_res_64.out +d97df9893fe674a5e80b631d1e123610 absorption_res_65.out +e2a2c6c50c8f736f07244a125467f244 absorption_res_66.out +237aad18bc6ebda568a3846a4e0bb597 absorption_res_67.out +dae76fedba9a0039bf348fab86f89943 absorption_res_68.out +b0ff298f73c97a468b8b77b64e683ad5 absorption_res_69.out +2a08148ccd2f856f8c88230d360ca0fb absorption_res_70.out +f430478f7e9ae4f7a87e7260bf08cb0d absorption_res_71.out +f2051749c1f93003787d62818678d830 absorption_res_72.out +8db7b8df503243b208e37ea3b1d64062 absorption_res_73.out +550272cedd7b294ff5854c5f8bf211a3 absorption_res_74.out +cb78306f08d6b63fd369d9fd892ac2af absorption_res_75.out +732ad4238250b16c1645d81be341da6e absorption_res_76.out +59cd48baf927633be38c312670896f15 absorption_res_77.out +879e6e78767b151adc7767e3721fb224 absorption_res_78.out +5b459a7bba891e3d36084ed67d7df414 absorption_res_79.out +90e1c75c5fd16b256ddc7f7b696ba84a absorption_res_80.out +9a0a00771a603a1677acca48e218f0b1 absorption_res_81.out +50184f3d12777ef6a11bdb4f3e8099da absorption_res_82.out +2f6bcedd2fe6691631c522bdb4d830bb absorption_res_83.out +f7cf9bf4ec035dc16ce1deedbb459cb2 absorption_res_84.out +8adf717c95e9c47444f3deca9ca12838 absorption_res_85.out +142cae30b42233fde978cd2c5b06c288 absorption_res_86.out +176468d481f921f967c45417b24d062e absorption_res_87.out +7153704cf352c6d526580b351c5ab627 absorption_res_88.out +f032833487fbbedc92cd44e7a48af121 absorption_res_89.out +23c137796e6e46bbc9ca7a2b89af5d7f absorption_res_90.out +4e98bcd53e0cf200d62ca0d7c8688231 absorption_res_91.out +09b0fd22a8c02d88f4f929ada716957f absorption_res_92.out +66c851bb3c5b0ffb7e2fa7721f02df5d absorption_res_93.out +143f23a098284b711cef7f720f490112 absorption_res_94.out +42f73e52978ea74443f162f939ef3d7c absorption_res_95.out +5c22a9c74919e641e8956fc02122bd23 absorption_res_96.out +cb0a086debde9795efd7a28b71bbd341 absorption_res_97.out +16aaecd9522e2e722e87038d23bf8c8b absorption_res_98.out +5254654046c05de846138e519ff50131 absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -21e50b95f9759d3d4d785698ec6f93fa deposition.out -578c64828aad208a57f2d0e9067d9320 emission.out -cd8f55dc98f3cc724b8a852427bb0cc7 emission_res_00.out -e6f0a7ab7073f23232252691275eabc4 emission_res_01.out -715d3a67a177e68c71eb59db12d5df54 emission_res_02.out -e0c3d43adcf557f2b4ed73a6b0422445 emission_res_03.out -770dc50234a3cb396a695ef8ddf1c08a emission_res_04.out -815b2998cd1f9b19e906af9abf68be79 emission_res_05.out -6c02506879600876f015615eab5fe4fe emission_res_06.out -39c588dd2be37ea28daadb87d8e0f98d emission_res_07.out -06205aa911f888764e2ee3266e198800 emission_res_08.out -a01edfa344c9227036d8b4edf5efa996 emission_res_09.out -e015b48e50348645909ef99fe16a2f2c emission_res_10.out -b27adec9b87ed6b544394f7d922a3388 emission_res_11.out -3bc9bcadbf3589ba23ecd89f1fea0434 emission_res_12.out -2afc5b2d9b94e3f1c906dbe05fbe1b25 emission_res_13.out -6f66a652e75b636232dd66bb953b502d emission_res_14.out -4b0d3e0cbd40ade4dd9157b4165a7767 emission_res_15.out -4aeb45a1f09ce176601ec1358b9ca920 emission_res_16.out -8344bd92c1bd478dfb2b2443d0552355 emission_res_17.out -7438946d9e3dfa92f82a0519732f55fa emission_res_18.out -e8091a2aa60831fb52c4f09bff21f9a4 emission_res_19.out -9e21b7c61bc40cf0b03781caa89f591c emission_res_20.out -7c6d103f991071a4d28e7fbf26aabfbe emission_res_21.out -ed61ee06b7535a817507b5ebf95e68ab emission_res_22.out -def31bc8ea5fdd44287f90f8f2fc36f0 emission_res_23.out -e4b8f1846cd065b5f4dd89b599d81aac emission_res_24.out -3c72bc6434ab2befc71620c064000f44 emission_res_25.out -81f3f0899a6906c5f90ed5a86c3b1d26 emission_res_26.out -bdb62d1f2c15316c0a35c5260754a71c emission_res_27.out -1ca74f0d833718094b4e1f4b250dd906 emission_res_28.out -9055cb3118a356a5756a12d1286a084b emission_res_29.out -97e25d024cc346eca401055e8eaa16e4 emission_res_30.out -dcbf0d698bc38295f834dd902ab7ad9c emission_res_31.out -dbf461fcd2d42e4e854dad41710c1a01 emission_res_32.out -3d103553b9ee5450d1b5b7348b09d7f9 emission_res_33.out -1646a464794120dce498d92fc4443a0c emission_res_34.out -faeef1fc9994ad16e0c409547ad1290c emission_res_35.out -7ffa9246e17d39056180baccbd9ed5b3 emission_res_36.out -88e762b2c3f96f6f8ce076cfc11d1f85 emission_res_37.out -71060cc1be38269835d0d212fca2cc18 emission_res_38.out -444d87f681609145125e595b54a53a4e emission_res_39.out -7710c37b715266d333f938efd058f050 emission_res_40.out -1c8dc167515ae9dfe4f1646a1ae1c388 emission_res_41.out -dbe950b532951f26e818014998cb47b8 emission_res_42.out -061b4ae039417479d0f7ba58118897db emission_res_43.out -b3ad665a2bf5ac5ac396b3ed8a454b60 emission_res_44.out -729867c7806b1804b922ae78a8099b95 emission_res_45.out -574fa2dbb38657ea4689d147a2fc885f emission_res_46.out -008356ad1b979f5cfdd3a2b4682d2bbb emission_res_47.out -e56ffca34135cebc2e359315e31cb64d emission_res_48.out -dc9e9f1d27f54cb3f3a963b9d0b9ce74 emission_res_49.out -2378bd5a21a625086ad95bf3da5ac9b7 emission_res_50.out -80b825b6da2c98cd296520bbc9da4229 emission_res_51.out -9e4d2846b053588ec47e9ac42c99e83b emission_res_52.out -1f864980b286f2d29f5d077525485077 emission_res_53.out -eb133d5210d3e2955afa6cd215b756b9 emission_res_54.out -e2bc02dc7f175e1776dfcec88ba83529 emission_res_55.out -772f3b6e903f46dee3af4b17d94dd81b emission_res_56.out -63d0465ad8537357ea1245d43fb60a70 emission_res_57.out -271bcb2ca6e17fb678f3134da1837402 emission_res_58.out -6547a24efc634eaf054eac08cece7670 emission_res_59.out -6d0d4136ef8851af02345cb672951bd8 emission_res_60.out -e887093a6671e31cbaeccfaf843437e2 emission_res_61.out -904236f79e37d81937aac6d6fdaed5cf emission_res_62.out -526f89c72fb6aafc02877af86821daa4 emission_res_63.out -c1f72f84d7ee594d5f57c08b9cbe3ef3 emission_res_64.out -11053ee74f9e40e0bbe084fde0bfe79a emission_res_65.out -4bfb82a4311c6f36394f28c23345e3dd emission_res_66.out -03e29d7f2b5fa3637aeaf7185fc411b8 emission_res_67.out -66f0f93d7aced51c7ea5bc4f3533ac6f emission_res_68.out -ce299b031e6a8f2819b66b6878d5efe7 emission_res_69.out -d0eb7559dc879cb0a84bb14cb7d494df emission_res_70.out -ac18904b22b1d414fdfef0ae860b340d emission_res_71.out -d2c8b6067da883760dd4caf84319d424 emission_res_72.out -c2dbce17fc884732cdaeb9056baaa817 emission_res_73.out -185060b17490c6011101865b3724072d emission_res_74.out -6f82696c3526b3b83be209e2027d4eee emission_res_75.out -5e4ab9c25bd7de1b6604efea5b9fd7a5 emission_res_76.out -62945c1919c5fff8673f962a9fbc4b97 emission_res_77.out -8ce878a399af0ee45a7d8396e2ee2d21 emission_res_78.out -c9e9bffe258579b550762e59723abd88 emission_res_79.out -de07df8ab89314db18c075c1b105f381 emission_res_80.out -3cd04137ec3bc0a4d9891510afd6140b emission_res_81.out -ed6941d4a0641f9acd81ed5f9ba27f9b emission_res_82.out -33bfba60af36504b54f8e5db660fb595 emission_res_83.out -df66037c066922c57ae434ef72a4fa3a emission_res_84.out -7dfead5b599e397af589108f34ae23a9 emission_res_85.out -dcfb85e5944d15dcfd04b172beab3b15 emission_res_86.out -8c7646db2fbea92cae48fb667edd64c9 emission_res_87.out -3a9d4af7fbcf36a2bbc1dd9f13817da9 emission_res_88.out -bacb364b21928dfc06856b3f80263f89 emission_res_89.out -a646a44ddfa90f8055394e157dbdbd48 emission_res_90.out -2abd9bf48b9a6e59ec91da034973e95e emission_res_91.out -fd55fc1c02ff603e13275322e41eb01c emission_res_92.out -434bd3be6542345a12c306847b3c1c95 emission_res_93.out -89e66ffafa8ccabeaa00c58091229685 emission_res_94.out -be78a7a4e3248d2b61354c3055a13e51 emission_res_95.out -3364da71613b92dadfd9151aa1ebcb31 emission_res_96.out -8c483e7486004f56ebebf41c945ea765 emission_res_97.out -5cb9e2c4bb6abfb99a44621e33669ee0 emission_res_98.out -bfc4d5545686c83206a0e979ce8430e1 emission_res_99.out -93e669e4c14a7dbab9e22a56473bde98 emissiontrue.out -4f08d8a94c1a7f63aa5d21e894203e58 emissiontrue_res_00.out -2cb85b1c7f8e2a3d6ade3227d631c4dd emissiontrue_res_01.out -464dd194cff27415760c53ae8c31f582 emissiontrue_res_02.out -9c8dc956cffbbbce558f0b1c3015a058 emissiontrue_res_03.out -7fec06b1505dff2f3d06f203c93279d4 emissiontrue_res_04.out -93fe47617db26c7ea53644edca8d7c18 emissiontrue_res_05.out -7bbd2ba5b5ab0153e5e03158dc212303 emissiontrue_res_06.out -70d72d7596648272d06a9dfe9896061c emissiontrue_res_07.out -48a745e380bb34cee63da4ab11a71de8 emissiontrue_res_08.out -35824084afa5499198212dd44dff808b emissiontrue_res_09.out -7fde0ee19b92ecbbd34f93e5218379df emissiontrue_res_10.out -840e0f79c55c3ee1b4be213955656f21 emissiontrue_res_11.out -84bc542975e97c214cdff5e2f566131e emissiontrue_res_12.out -3f90e65417ba00f07047b6193b680c80 emissiontrue_res_13.out -141cd7d7a1778e82f9c7e924cfadec55 emissiontrue_res_14.out -bc6fdaa05866afd5b5b2bd74f6f7d6a2 emissiontrue_res_15.out -8ce1301d5e0a34eed4ebace7a1ca4da5 emissiontrue_res_16.out -ec5448310178b9570666e464833096ec emissiontrue_res_17.out -0ec050179606977d49b97816a550a686 emissiontrue_res_18.out -708fdaa76b23bdfcd43317e10bb88e39 emissiontrue_res_19.out -64e71bc461f0ba14f634010c0b301eff emissiontrue_res_20.out -efb408a4834cfbd6e5e0668e11ab1979 emissiontrue_res_21.out -bcfd21848d888f7332083162334f4280 emissiontrue_res_22.out -877534024304f8c74bc6a3e7ab3728e6 emissiontrue_res_23.out -cd01228128998bccd2c839281c0c7109 emissiontrue_res_24.out -884aae09c0eb09da89389de75ace5249 emissiontrue_res_25.out -82d50486b4e603f45cb67fb7deb1c393 emissiontrue_res_26.out -7b23dfa7544768152bedcaa7d5e5fb41 emissiontrue_res_27.out -55c537716fa423dbaa8b32063ed6afaa emissiontrue_res_28.out -20ed17f5b47e6d35697cea753e40826c emissiontrue_res_29.out -154eee4b7154707ce2f1c3af37636f53 emissiontrue_res_30.out -f3090ef43317a120972b3dbab9ce8417 emissiontrue_res_31.out -8a6a7e46c8a9d1f0a2c11f49cd6707b8 emissiontrue_res_32.out -3006736866c9ba17726913b70c1645b0 emissiontrue_res_33.out -5bfae3fbff8bdc313d2a69cd051150a8 emissiontrue_res_34.out -1f9ddc9a36f8a1d35642f2d4a4b8b9d4 emissiontrue_res_35.out -c597ad828f037f1de52d7aaf4bf6be95 emissiontrue_res_36.out -4b6404540ff67815dd5831b7e1f5ef64 emissiontrue_res_37.out -0edf0b2f13aa1fc595a986b099ed3760 emissiontrue_res_38.out -0c66ca760d4553a51b5d40f535926819 emissiontrue_res_39.out -c2c349edccc1eba9b81b92f789fa855e emissiontrue_res_40.out -8d7adb2210b40dd5d0d8597988aaa4e0 emissiontrue_res_41.out -17a34eb9405096de1040e58854a51f7e emissiontrue_res_42.out -b42a6764619bc761965341ddeda7e439 emissiontrue_res_43.out -f4761daba53549a1196331aca56baabc emissiontrue_res_44.out -12ef20ebd10dba6101cf076d763efbf8 emissiontrue_res_45.out -b4c5a934131312abea51d45c24d762cf emissiontrue_res_46.out -2b0995cfdd4c740cec5f5d36ea3b25d5 emissiontrue_res_47.out -3074d69c2ab458d059565ffc9754b44b emissiontrue_res_48.out -d9c0e0bd16709863f00416c5938ef10f emissiontrue_res_49.out -c2b4f6f2060d04f7d2da8a3ad4abe74c emissiontrue_res_50.out -ee3ec787c2f28a444f15e2569039d9af emissiontrue_res_51.out -04b67e59b3cb105518d8f28300b13d88 emissiontrue_res_52.out -9e668a2fb1dca9bd06d571f9a7b60eaa emissiontrue_res_53.out -99469e3a616ece46dfe2a76c407104f7 emissiontrue_res_54.out -63ef771a713ad72331e5dea8692d0a11 emissiontrue_res_55.out -63c90a22e270867bb17cf8cdfaa64587 emissiontrue_res_56.out -1fda820d9bcddd1165632bc0fa6cba71 emissiontrue_res_57.out -e43218e72cf3fe35ed8ec317548e39aa emissiontrue_res_58.out -26da737d4114e84e5e474e0c9def3487 emissiontrue_res_59.out -a54d98aca8efba12c03aa6fb5ee2209a emissiontrue_res_60.out -4248c197f0a6e65e7af936c27b93b9ad emissiontrue_res_61.out -051a343855fa9c099f1b48bd549c0f13 emissiontrue_res_62.out -52e025a27b0df22cc5f90f855c88a56a emissiontrue_res_63.out -4e27b35d9a07379baae516f9ce5f6b9e emissiontrue_res_64.out -360d5b4c7bab4a0bc567f7a63694bd3c emissiontrue_res_65.out -ece196472468cbb09a5be54322164f70 emissiontrue_res_66.out -b971632cbb69d63b32475550d20d0739 emissiontrue_res_67.out -6cb8eaea5be49ffff03944705f21a895 emissiontrue_res_68.out -9b343aa3a4cdd4bfcbb486b0f1389fcb emissiontrue_res_69.out -ecb30e85cbfc63e002003cbe341271c9 emissiontrue_res_70.out -ccabcf5dae9c4ad09a0c30f90cad181f emissiontrue_res_71.out -d77c1d964d7474f90209667081d9cfb8 emissiontrue_res_72.out -bb3895a7febd818a79707294f7b76fa7 emissiontrue_res_73.out -3e4bb658a366a59d802b716021d684d2 emissiontrue_res_74.out -a514842a4c4359128c4dc5d76d15b9cf emissiontrue_res_75.out -53cc12818d7bb5bd8ed32da8957a4bd3 emissiontrue_res_76.out -79ab25ef45b81c075b8b1fd3853d8132 emissiontrue_res_77.out -03a6b8bc3fc3d87e3c84e34a42b2f1db emissiontrue_res_78.out -9fd64f4fa59da042012ec2fc44d0ae00 emissiontrue_res_79.out -7f74ddcec1b4134499e5611b76b83ae5 emissiontrue_res_80.out -6da9ff27c046b8bca48e09c8058bbab4 emissiontrue_res_81.out -79143513e3da61280fe544b6c2a7b7c9 emissiontrue_res_82.out -0d13e16972b94193f25ee86b3da65048 emissiontrue_res_83.out -3205f7fd20fb957bf7f56d6b6d9b465b emissiontrue_res_84.out -d5113b2e13990e5110a611b11a56c8df emissiontrue_res_85.out -e3680a3afb02f0a783644231d165f226 emissiontrue_res_86.out -8eab62d1cbaf35c929c8afffd9ac0b8b emissiontrue_res_87.out -fef0f4e88011ad5bfc5cf29d32f0cf67 emissiontrue_res_88.out -2040a0eb8b9c25d9b84b2b90a2e0f56f emissiontrue_res_89.out -00c85934d7f25b4a15668c21d10c0689 emissiontrue_res_90.out -c1f20e0a8bb9afce5550bc9bf9e19065 emissiontrue_res_91.out -f1b0196758be2515b9468b601b3ebb86 emissiontrue_res_92.out -68e24500aaa3cb809c6e1f0bf31bbf68 emissiontrue_res_93.out -b6598ed87d03ca3f51e131dc52527485 emissiontrue_res_94.out -9a30724131314209675dde794cfe2d69 emissiontrue_res_95.out -901c9571fa159adc156be72c50f58700 emissiontrue_res_96.out -8a15750775ac7c0e9ac9f4571572d857 emissiontrue_res_97.out -e31eec573dc4434532d7e82f0aaf84ca emissiontrue_res_98.out -e09f8cf0d23a9fb772b627cd3cf3ac4f emissiontrue_res_99.out -7be290623cbfe8cff563766751f57a34 gamma_light_curve.out -15e54b37a5b94b04dacb437ae6785ff7 gamma_spec.out +275491f5acc91a7230bc351c0b7346a4 deposition.out +9fbb2f1301742d73d55224506e1ebf93 emission.out +f9fb255f00a9f33c6135b4e35e42e368 emission_res_00.out +5dad6776368f276e1a8b2b825ce76fd1 emission_res_01.out +b4699b8982efb1f3984af1203831a346 emission_res_02.out +4e918f52d3d2736cc2a6befd0383635d emission_res_03.out +afc925f1c45f6eba0026243243d330c9 emission_res_04.out +a40346ab0af94f8e4f39410d7b1a240a emission_res_05.out +73005292d39a2e72dc4fb21d365545e5 emission_res_06.out +884a82edd72678b4dca5400fb5ced095 emission_res_07.out +4ff444cfd84769ea64f93c7adc77938a emission_res_08.out +565b925b3e7b917bbc05f8a62205d7b1 emission_res_09.out +bbd9590e9ca230332f61f04027ce9ced emission_res_10.out +d07dcd09ce9b29518d431b140598d724 emission_res_11.out +e9024f2252d25d42cac565a06bfd6e49 emission_res_12.out +32a0222a3e506001b3eb415bea3a8bff emission_res_13.out +241c0c82d37c55f096bfe7c699689308 emission_res_14.out +40e5e11a0bb01a0cac4f9b785d54b7f0 emission_res_15.out +8f6e4830ee0d6310ef395d4e6567faa4 emission_res_16.out +2b85e34732816961eea195274ec4bee6 emission_res_17.out +babea64f2327ed03ae73e7f8808e985c emission_res_18.out +9351b6d784d8316986cd7f67e4ec4e01 emission_res_19.out +310c45e1f0863cef3a9a090bfe9e3353 emission_res_20.out +8b66394bd3f347b2119cf5de76dce461 emission_res_21.out +28bb31ae28d77558c90011ac933d2373 emission_res_22.out +41d147df49319895dbfc873a9d540b77 emission_res_23.out +fe3db1c8aba1b4586307c02a1eedaa6a emission_res_24.out +9f05b69af260444a9c9ce56442aee88e emission_res_25.out +1cd7738255ba925c38cd18268764657e emission_res_26.out +7d4029bfd6fdfaa0738e65578fd5c52c emission_res_27.out +d2cc0db19d961ebb01b07e75266c598f emission_res_28.out +375ebf17886774ede8bc1b0f5962e992 emission_res_29.out +7141c45fcf41da01605260ded3973329 emission_res_30.out +a940cde30e636005d77ff8cc85757300 emission_res_31.out +f249c6a82333a8ed543a0710ee7a4534 emission_res_32.out +541b4d27a07ae1959b3797648e65dee5 emission_res_33.out +9fc88390d03371bf49c19eef906074f6 emission_res_34.out +645f0005f040b81fc46aff228a5eb1b7 emission_res_35.out +40db661a76b8f70dbe4cd11da9a504c6 emission_res_36.out +70cdf7faac4685d56e37f92daf0500c4 emission_res_37.out +3a8460b9cd38770014e63445877d8187 emission_res_38.out +596b43dbad1645f6f0498d4c13c5e0ba emission_res_39.out +6b6401875f5114ccaf76f425ed809eb7 emission_res_40.out +fe7bb5b3b809ff59423672ae1b3bc9d1 emission_res_41.out +186848dca7cd4d055b6e8cfc60205c1d emission_res_42.out +5957a27327253edcd36be19726c27232 emission_res_43.out +00e44c14be3cb5daddf7d2c7e05b19b3 emission_res_44.out +d02b8c6aab3190a8237994b834d7939e emission_res_45.out +779c8640cd813158aa845d132df0e0b0 emission_res_46.out +e37fe2eeabd1b9ab633d83c94260a4b5 emission_res_47.out +e970d499a8b257b0d8071a7cad9dbe12 emission_res_48.out +01a7b8579dc028e3a505157950d952b5 emission_res_49.out +3a5fd46ffcccb52992d7d35bbcbd168b emission_res_50.out +fda73e796850203c57d56115ee6aa763 emission_res_51.out +08546e5ebcb4c5b733f21970cf26d774 emission_res_52.out +e0c8153037f827af20cfe1a4b26a9b74 emission_res_53.out +f3930d8d6e998b163b7ca09db6c89bc6 emission_res_54.out +41692236735e2f07d3d133c365ec4005 emission_res_55.out +e096f73b63b060ccc5f79db7bf317c8b emission_res_56.out +4596fe7c35e24bafdf943aab4dcd5c8a emission_res_57.out +dd3b87ca11eeab44155412647ca11f3d emission_res_58.out +643ab97cbafeb72947878109c49aadce emission_res_59.out +576e3479369e52a07b23d3d2c96ecab8 emission_res_60.out +17c94789f052b387e62b11bd8db7930f emission_res_61.out +065d7bc2bdbcd21298a0d32c260e0c56 emission_res_62.out +9d39c7ee52ead788d40cb5e20cdddf8b emission_res_63.out +eab7a5ae905a30e4c8b76f4460a92029 emission_res_64.out +8bff96106ffd20b8566b08f1f008442f emission_res_65.out +e03171cbe55f191f3892de44007fd687 emission_res_66.out +e4420b0549a5e00955eda566dcdd3a89 emission_res_67.out +f9b94eeb4a19b05fd9655976e9af78a2 emission_res_68.out +2ef173fe9b15f3d861f12bd232c1fd25 emission_res_69.out +b7f674d4dec8275fe451ff5a34f25a8a emission_res_70.out +d52257100dfe8ff26cf2d9613128fed1 emission_res_71.out +1bcc077e56b8fdd159383db841aeab98 emission_res_72.out +f25f3e0df6d3eb85e5add70782a47088 emission_res_73.out +f0c2dad7ef3b7f3d67009d339f51bb5e emission_res_74.out +91f7a2a68c2bc6e2046f0cab3f8adf9c emission_res_75.out +44c80f80d3555b32f68460992171652c emission_res_76.out +1eeb996c0edfb625249e9384b61735b3 emission_res_77.out +89aec949f80dd011705d9fafbcff0e24 emission_res_78.out +0e2dfa316fe807ab46a6aa02a060adcc emission_res_79.out +52f413ce63ce50130554158d51f11de7 emission_res_80.out +c39c9b0d51309b456165c7e4a898ce21 emission_res_81.out +b07eb0fdc78eaf59eb78aef5b8e1526d emission_res_82.out +1eac0b2c5e1ba81125657c35415c702e emission_res_83.out +b9af853e40af788cc57500ea43e152db emission_res_84.out +e8c1eeb8bab87747a6e1d73c00c731a5 emission_res_85.out +bfbac09ce2d1b49aa38cef1d6287f633 emission_res_86.out +7f0048285b2011f0461e3a0997c89883 emission_res_87.out +6c4324121be752867cdeb779c9f03b5f emission_res_88.out +8c4e3ddb3966889ba20f446f8b977fb1 emission_res_89.out +7d1d8af860f6ca9a43d3a959d1a00103 emission_res_90.out +ab7a9ab66325b6235e8dbc2ae049be59 emission_res_91.out +51abdcec5100bcb9c593c92034fcce22 emission_res_92.out +83be3d0c293e3fe28966c47bb758da42 emission_res_93.out +4436133befe9ca7bc91526cc8141c963 emission_res_94.out +f1eba0c1eb2d89548b7c052f471bf40f emission_res_95.out +526bf216786d815ee5d48c78cb586e90 emission_res_96.out +26f777a345f1a5bb4ee86f282e8e8645 emission_res_97.out +3159046472d2828db40a48dc9b0bbeee emission_res_98.out +ee19633730963f0f6854225e6128aa87 emission_res_99.out +950ecb16197766824e08e0171663792b emissiontrue.out +fd1b8b88329ec0da176d99da6f64f779 emissiontrue_res_00.out +af080f439470c59d8355eca48a5d10f7 emissiontrue_res_01.out +9afc365f26beb919e82422be34ac0284 emissiontrue_res_02.out +8f45b11e292a03a719a809bb8027fb90 emissiontrue_res_03.out +c3deaf1c269e0cd23ace4bc7949d85b8 emissiontrue_res_04.out +617ff7fd1960f48effa90ce5ad4cc8e9 emissiontrue_res_05.out +090c7687d0c4fa2b38dc09a3a5d9e792 emissiontrue_res_06.out +aeaf78b1bf9c31824439711d0468769b emissiontrue_res_07.out +1d2c40c54e1f51823d16c501c9e9717b emissiontrue_res_08.out +7eba70f6edb1ed7fa58359e594ecefe7 emissiontrue_res_09.out +1814bc26d5e1da60c7d5c3ac241b295e emissiontrue_res_10.out +566e48f30d2cbf0076d6aa944406031e emissiontrue_res_11.out +b22843844e3f893cb4ffe395a32396a6 emissiontrue_res_12.out +00f84bf13580ebd6872dd3a880d68ada emissiontrue_res_13.out +1995d20b96438577a369aba43ecd608f emissiontrue_res_14.out +f7454aac1bfaa01206db0a97686c1d9e emissiontrue_res_15.out +857f647db7f7e67243f66a8136291d89 emissiontrue_res_16.out +0fae346cb7d1fe86a8402e6b4d60da82 emissiontrue_res_17.out +33f780c697c3da8d1b1fbab5cae34534 emissiontrue_res_18.out +c305c7992e58df1234b8d8fa506a4fbc emissiontrue_res_19.out +d5db8c35af14da9757eee3fc75a9c413 emissiontrue_res_20.out +42c03310318d58fa67f835542336c689 emissiontrue_res_21.out +c1cbe5cdf760c09d66e6f6dd935ace00 emissiontrue_res_22.out +8fd9054a56a63381a650d5ce4c17c6d9 emissiontrue_res_23.out +7555e96991d7af1d2a4ce5949353f2b7 emissiontrue_res_24.out +56d76818729acf576e2a99b65ffd54b8 emissiontrue_res_25.out +4ef3ae3ebdf718b4cb807676e01d1388 emissiontrue_res_26.out +1fdade8885225390a16d7eeb90939d48 emissiontrue_res_27.out +822eefde3b9d364d284a6b9f6a0df6a1 emissiontrue_res_28.out +721f7ebc658bf429bd28e15c612d54e8 emissiontrue_res_29.out +fb12df7ba1c71089eb4432b3a2b5709a emissiontrue_res_30.out +6dc7da1560f0aa42e0d61a0c5e19027e emissiontrue_res_31.out +ff47d27f4e3348de0269b69f735a16b2 emissiontrue_res_32.out +d5b6b1db6fb6ec75f78674e3c91ef804 emissiontrue_res_33.out +e1082f7cd8c45a33e9b48a84f81c2b66 emissiontrue_res_34.out +43ebba3e6f29e644176be8745d8be8ec emissiontrue_res_35.out +7ce02121c64c9df750078936d975129f emissiontrue_res_36.out +1535663870570a236e07966dc801a9b6 emissiontrue_res_37.out +f7bb83165617c85f7e3086c295f4ce65 emissiontrue_res_38.out +46a432e439448c6912bac0150aa35e11 emissiontrue_res_39.out +00f9523217e20634847b274b996379c2 emissiontrue_res_40.out +256bb8f30bd6ba1d3b468ed9ccf3d0b6 emissiontrue_res_41.out +231fbf8868c5b3c95e690f783787df05 emissiontrue_res_42.out +331c80353bb564dfc01720b4a10e223c emissiontrue_res_43.out +2df7d66282856923deff11a432351b82 emissiontrue_res_44.out +053e85388e063b2b2ebe3dcf20da2642 emissiontrue_res_45.out +3f8651e1f5f3789ef917bc2248b3cc09 emissiontrue_res_46.out +4b098a0e892130edbb3a7c7e7c45aae7 emissiontrue_res_47.out +94c2321b7c26b332f5d40f6120426611 emissiontrue_res_48.out +bca82dfcd79bde3a864468209d6dfff0 emissiontrue_res_49.out +7f3e0e7e0e5b6d92731be38d0130ffbb emissiontrue_res_50.out +e7f00adc3c311cc4126f690cb3e1613f emissiontrue_res_51.out +6e6aefeaa6c853c4639a9fe3d18ccc2d emissiontrue_res_52.out +22f0ceaae71d85ace9fd43acc1a275ce emissiontrue_res_53.out +dfa8e5101ff46eb4120593076280d9a4 emissiontrue_res_54.out +2b280187d1ecccb131277e40d6c696af emissiontrue_res_55.out +33fede083ea6ec9030be16c8d7b53395 emissiontrue_res_56.out +fbf1d93b16bc65dc4683a2803ca14b39 emissiontrue_res_57.out +7865c8f5853c958e24e652ae524bd70e emissiontrue_res_58.out +e5543b1f88e874a493a0b3563e2c7ad9 emissiontrue_res_59.out +4dd879a94ae043b9484b935ad4ec67d5 emissiontrue_res_60.out +3c408cea760807a979107b458c82b2f9 emissiontrue_res_61.out +6ad0ddf23738056b0a6f29306dfa5e2f emissiontrue_res_62.out +9c374cef90a3e8c48066f9e434c77ffb emissiontrue_res_63.out +e81ff278ad9a2981876d142b35338fb0 emissiontrue_res_64.out +9bd21f0db424e62d56dfb51d919da308 emissiontrue_res_65.out +91d6573508bcbf80635b541568518416 emissiontrue_res_66.out +16c82a685c50580a65174a83266a7ef1 emissiontrue_res_67.out +d8640a73819284efc7a88fbf54c87445 emissiontrue_res_68.out +1ce9dda44b95d8d306770b6ff4ebaa09 emissiontrue_res_69.out +e8bb9cf03c00897a98c4eedf2422b3f3 emissiontrue_res_70.out +71b6f8a2bd9ef5d4f4e300eddfbb7c61 emissiontrue_res_71.out +b92e1eb931228356a0743945100b38f6 emissiontrue_res_72.out +9583512d18b5b34ba660e9c0059d6600 emissiontrue_res_73.out +23118adeb2aa9386db8282e997490b08 emissiontrue_res_74.out +843def2e9023f811f10b1ac318feda1f emissiontrue_res_75.out +885062925e51ac47f7e95dbb6c53cbe6 emissiontrue_res_76.out +d7c7278adf3efe34a221161d5ad2baf4 emissiontrue_res_77.out +4b2e3829b3ca32f5ae69ecc858996042 emissiontrue_res_78.out +3401fe62ac2f1e7976f1c0b987e82823 emissiontrue_res_79.out +2a0dd602c544cddb8284cd4420190ebe emissiontrue_res_80.out +ad93a94b6ceea35e10ff896d2ecd3cb4 emissiontrue_res_81.out +6191add32a2cf9262f0638688634bd9c emissiontrue_res_82.out +9940d2eacda861af505d8b897e1ed45d emissiontrue_res_83.out +bf76c3e077c1152f3a38de0d248826e8 emissiontrue_res_84.out +0ef48e27f2bf7645021dd443c75e32c0 emissiontrue_res_85.out +4abcb009235e642fc6444eca0a92829d emissiontrue_res_86.out +e8d625c5614e625aa823c5587f95c3cd emissiontrue_res_87.out +9c0dc917bc797e33242214964b482b20 emissiontrue_res_88.out +658436ef191cfd877f39822581d485df emissiontrue_res_89.out +704264ebdd36aa0fd2cc01c6f5cf1d55 emissiontrue_res_90.out +90b24a1bded838366a6dde23a01d6ac7 emissiontrue_res_91.out +59fc86b0bfac9b321fccf5b153f4905a emissiontrue_res_92.out +47f8158dc26f36ca12a6ef6ffdc79435 emissiontrue_res_93.out +cf42065ab5d7be29f11fa12b5479149d emissiontrue_res_94.out +600d6fca285cc4aa612c200f277b91c6 emissiontrue_res_95.out +20e782f89ca8dac83e1a793f24425eac emissiontrue_res_96.out +5dae3ffe4109ce799596b95e36a736f3 emissiontrue_res_97.out +765e33b6e7d0935e6f2bdde08be05129 emissiontrue_res_98.out +d6d0bde7d1bddae7e3438651c6946b18 emissiontrue_res_99.out +cdc683de61a29dba0af18694ab055f99 gamma_light_curve.out +afce5b78cd100311d653137dd182ee29 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -59d4e63b24a46d89cc19995a4bbfa9a6 light_curve.out -3e3927250cf10270dee0d2e29e846ba1 light_curve_res.out +de7b04ab1824e74feb7cfee6ba03cac1 light_curve.out +8dd30f7e21f771d9b66c9ec187c5a1cb light_curve_res.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -058637596c32e8c6bdd6b15fc3ab9491 packets00_0000.out -6833be5d39a8c9e61437e6cec5108d94 packets00_0001.out -e438ccc343efbf3e33cc2a3b0ba3d03f packets00_0002.out -8cac5d7ec612112d2db49fa6e2642555 packets00_0003.out -fefbb2e13fb77978eb282b360970dc3e spec.out -c1baf1876b8084f9e6026f107358aaab spec_res.out +7b20881009d844044b8a88b800dc5d47 packets00_0000.out +219e009891c5bfb4afecf25d17f7aa42 packets00_0001.out +e59b4d823e7d2ccb684fac9b84c09145 packets00_0002.out +762e8c94de5c230d4898f9832cf74394 packets00_0003.out +0dc93f648321d9740506c95a890f0694 spec.out +a73f647e0654520b1319aef34e7a1887 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -e644a723d9198610e5512cd60d36243e job1/estimators_0000.out -2cda179b034eb9e7fcab21a49eccf7f8 job1/estimators_0001.out -aae4e57600fa366c4dac1854d9687d9f job1/estimators_0002.out -8034893dde531c11dfbd3d6b797c54f6 job1/estimators_0003.out +baefa6f0e15123920c0938ab294779f4 job1/estimators_0000.out +d0320f73d2807e18891f9efd57bf1f8e job1/estimators_0001.out +00f3d1db98086d2f4dd34a2c30be0ef4 job1/estimators_0002.out +8dc6701d17295ae74d5b0e123371ce4d job1/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index 4b97e8e8d..a1bafac54 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -0cd0a493679114a220b0621680bc532c deposition.out -6f1004591fceaa1d5ca9189980932075 gamma_light_curve.out +5fc79fe6b3326ac0f90d76a5b385f903 deposition.out +2c29aed8c4f22148a1609d0d33f24bf6 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -0424d7bbe86c0db3b58817bd800e159e light_curve.out +9c265a4eb5104b0e6cb469121120dbb9 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -e23e312f8b0070f8a83f0bca9583b1ae packets00_0000.out -08fd730ffcdd0a56b754184cb524e6a4 packets00_0001.out -bdb8608de1561af021c7c670009f76d0 packets00_0002.out -751417675baa159245b0e667d5f914f1 packets00_0003.out -6d2808e463c2250c53be08c2d6b59e92 spec.out +f5e7edc0a8b489551300f2f55d354ef4 packets00_0000.out +7de15c2f5e80f511e78b7f74d9b9f131 packets00_0001.out +cd298d033a103ad160b66ebd2d02fc73 packets00_0002.out +4690dcd41fa19a1da9deae38e979d057 packets00_0003.out +8915e92a7c3bee5388ca4805ab75a45e spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -37e1259e7d845efeaac6fa851143d655 job0/estimators_0000.out -3b6d88914795a2213ed90924b6a08835 job0/estimators_0001.out -952c0eb856084016b97d0123a2ec2d67 job0/estimators_0002.out -690f779fd1f174bff190036c33adf727 job0/estimators_0003.out +e66c556773f7788e7c4c8e3e6319955e job0/estimators_0000.out +8d39154197b0b3eb47f0176aeaf878bf job0/estimators_0001.out +c78a879cce8a59dc7024d4455d6ed1dc job0/estimators_0002.out +91d37441617933156a1ae3d8e3f9467b job0/estimators_0003.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 838339ea0..2304f34d8 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,6 +1,6 @@ a0a9957fe56f07b30fd667bbc8862c43 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -0b7686ff1fab9c4bacc5486aabc5c421 deposition.out +50f22638abddae941d86e18d15e851a9 deposition.out 82e9cc26719f53714737065dda43da79 emission.out 2fca8b6df84bfec802c623725b584294 emissiontrue.out bbc12a10475fb7a801a04f06e56861ed gamma_light_curve.out @@ -10,18 +10,18 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out ab459cc8e8540d5f4352bfbda140a469 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -541602a1b9c5ac8be6372dbff57e97b0 packets00_0000.out -ad732ad19eb47535e731413261716e81 packets00_0001.out -6791dfcc8b3fb600864e007f0fde5020 packets00_0002.out -ba11000fc9f3e22c361905e5c88d1e70 packets00_0003.out +916d4e06cb3ce8dec7ffc2cd26c23813 packets00_0000.out +c1d45735e4ea8f456f432eaed16a576b packets00_0001.out +cec5745c1c74df35eba3aae44e245c65 packets00_0002.out +06eb1b90a2f5b4758cb2268920f954b5 packets00_0003.out b9f314f9a296a32b1732c4ac163088e7 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -d2af692fa171802c2735c6c2cb3d21e6 job1/estimators_0000.out -9409e1a11e01e0ae494257f145d7047f job1/estimators_0001.out -f737dca3a18a377d4af6d594e2e1753c job1/estimators_0002.out +f6dbb21ee3f2d1b270bca6207de07ad2 job1/estimators_0000.out +3315ea1ed7d294aa93c75de8b2d42bf2 job1/estimators_0001.out +e313b30095557e70332faa0dc3ea84ed job1/estimators_0002.out 3939046c8f072fbcafb2825969713398 job1/nlte_0000.out -01d0f41f84fcb57145a3eb7111cf6ccc job1/nlte_0001.out -4f9e04505f266651af15e057be690ed1 job1/nlte_0002.out +0ba1f4ba0599789a13b31a213be8da1a job1/nlte_0001.out +57379e4bf2c927b19432577266515439 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index b17fdf386..7293b961f 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,26 +1,26 @@ 0214118b0d1f2bcf1ea70600d1e2c236 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -fbb89ee95b9323d3c1f843482935977b deposition.out +83baaf0e40350f5228742c0b62f99e19 deposition.out 806f2bac5f9839b7d5dde80872d2335b emission.out f47c36a3905e6baac50624adbf781d15 emissiontrue.out -b103a8b8a93234f6ed4ec9f7134d7b74 gamma_light_curve.out +326082c70b15571eac4ee4804cf49f7e gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -7f9f624aff57c77ba267d188bd8f3b76 light_curve.out +439ccc3d173c5aa186dd5e94cec510eb light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -c59add030d3c8b251e74086f771407ef packets00_0000.out -c20fb13f1ec7b4e0367b38d48e291f61 packets00_0001.out -b0dc28be8d00ecd40e260e605131fb1a packets00_0002.out -4fff710f3c66b07d072473d263704b4c packets00_0003.out +30d9c4633451e6f3bfb434cfcb266401 packets00_0000.out +0900e8ebaa69550ff2cb3d07bb52f028 packets00_0001.out +a3e11f4e07025d0b63646f147bbe6da5 packets00_0002.out +f261efe2b09c6e55d382b49718560eeb packets00_0003.out c98d7b9bc20e210c34c1d9d18cdcd30b spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -cb6d40184608eb4234e60a84b96cdcd6 job0/estimators_0000.out -154f21df593ed869a683b41ecf0394da job0/estimators_0001.out -5f2e08e628b4c98afc1ac4b11fb7b65f job0/estimators_0002.out +fd429c9db02f7d0917608ffd949a50cc job0/estimators_0000.out +84f1a8955e08a43dfeeea183e90bbb45 job0/estimators_0001.out +d1360d523b32630082fdf65dd3307c42 job0/estimators_0002.out 074b0b9cdc06c0f8d35c6c92d546652d job0/nlte_0000.out -df8fa742dbff3e284be4e515292d23a5 job0/nlte_0001.out -d9deec48eb6c0ff9fd5bf43da26f396e job0/nlte_0002.out +0c4abb5cc11ed764d1a5eb59cf928437 job0/nlte_0001.out +83a67ce6f367b1155c3545cbfd80f28b job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 8ad2f6f24..5f45634f8 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -1,6 +1,6 @@ 5db21c9087270dfe4f04ffd619b3e2c0 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -fdc00c3d6294a6d7b996083346a783e9 deposition.out +5a701de02f8d29c3440703b239f76da7 deposition.out ddc58b8fb083aa5ce0eb363b5a8c7557 emission.out 69a76d0f782b4387f72872d1e49fa75c emissiontrue.out c06d57c1b70d100869e924c42a852d2e gamma_light_curve.out @@ -10,18 +10,18 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out 647bab9757d1a50f0a7ee2803af2ece8 light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -b51eedf3e722859eb830177e27507671 packets00_0000.out -468c969498032835cd8e859ea8219b1d packets00_0001.out -71cfd2461f65efd657a163ef106603e3 packets00_0002.out -b8230042a737fe51ee01924d745ca602 packets00_0003.out +53f0eb86a14d1878972506c6820e22ac packets00_0000.out +8d9eef504f09763b2527be4ada18c938 packets00_0001.out +e26a2efbc2e720a8af45978e8a2f26a0 packets00_0002.out +a2142aed3cb852bd2154f29c38607a8e packets00_0003.out 42c12cc4e318ea5450e71e27261798c3 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -ef0febabcb72f9414f8ced8cc5c98384 job1/estimators_0000.out -e5ebb3cabceb6dcef7f1a322b64f4435 job1/estimators_0001.out -2ebac101c6a3e4f0db8ce36d3c179e04 job1/estimators_0002.out +b34c9abd72bf77ef15e70b3cae5c5a01 job1/estimators_0000.out +54ca53c073550a0d07addd5aa0dc2caf job1/estimators_0001.out +a1462f00ec8c84af6643abf349ba549d job1/estimators_0002.out 6038cb41537b773a9fd659af21e04a41 job1/nlte_0000.out 5f3d791a08c7ee9142e883275db74b33 job1/nlte_0001.out -8c4ea4b2d7fd417b9aa4d65cf0751cf3 job1/nlte_0002.out +b8527165c6a02c223fe1b2e8e2f554a7 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index 949c058b8..7ad82eb65 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -1,26 +1,26 @@ 2bab28e6c44dc5f73ce68bd1e9792e2b absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -c2188ca7df89b8a6b40006dc32ed8c8b deposition.out +9f443fef6a1bd8ea9ce3fb796f713c06 deposition.out d7852586693f119d71c452553abac594 emission.out 66e15feb69cdcdba0f477301a3c15db1 emissiontrue.out -93bf0f184c75652ba532acb05013b2bb gamma_light_curve.out +6883b2c110209525613b23caf2a38631 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -5ac9cb2c4967e6156bd73cbf510483c9 light_curve.out +7c328b45adf004d1e23d9e97befdb2af light_curve.out 9773becefdfe4afffb041b703210c67c linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -38f43634a42ef185adab06be6c555684 packets00_0000.out -267c5ecf781af9fa2b6575160e8da225 packets00_0001.out -b43a4b88e59ee6d370dbd1e74f48e5bc packets00_0002.out -ffb281555aa9b97c67710b305dadc8ad packets00_0003.out +21d24f8cf6bbe362a4458e3c61981365 packets00_0000.out +4fcea2d6a448c5d1102de8b6eab523ad packets00_0001.out +0ba50b79e12743d56f8397d7e9ebbdc6 packets00_0002.out +8255f260fdab8e7079473293c0df424e packets00_0003.out 6359d469d801b3eda814b0cc4a5eb196 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -20276e33ca8f3dfc4aadc378c043b5bf job0/estimators_0000.out -79725dee21a0aa8cd019391f496f8e77 job0/estimators_0001.out -159836770680e7457bc47e37947a0f92 job0/estimators_0002.out +037eca48b4120f8f100285d4d03492fe job0/estimators_0000.out +f034f2846fb5b5e84e554de0c1cff479 job0/estimators_0001.out +d64821f262bc506a4e2cbfdf9428bc69 job0/estimators_0002.out 70745363977227f69b62785cf6773acd job0/nlte_0000.out c49c7ccf68d648435a82116406c8d6eb job0/nlte_0001.out -38aab2a3c5650a86117213fba89b5175 job0/nlte_0002.out +800cb6ec93bb650868774f6f03b72dbd job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out diff --git a/thermalbalance.h b/thermalbalance.h index 6150d5e96..d59b369ce 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -5,15 +5,24 @@ #include struct HeatingCoolingRates { - double cooling_collisional; - double cooling_fb; - double cooling_ff; - double cooling_adiabatic; - double heating_collisional; - double heating_bf; - double heating_ff; - double heating_dep; - double nt_frac_heating; + double cooling_collisional{0}; + double cooling_fb{0}; + double cooling_ff{0}; + double cooling_adiabatic{0}; + double heating_collisional{0}; + double heating_bf{0}; + double heating_ff{0}; + double heating_dep{0}; + double nt_frac_heating{0}; + double dep_gamma{0}; + double dep_positron{0}; + double dep_electron{0}; + double dep_alpha{0}; + // analytic rates at the middle of the timestep (t_mid) + double eps_gamma_ana{0}; + double eps_positron_ana{0}; + double eps_electron_ana{0}; + double eps_alpha_ana{0}; }; void call_T_e_finder(int modelgridindex, int timestep, double t_current, double T_min, double T_max, diff --git a/update_grid.cc b/update_grid.cc index a7e9a2cce..dd95df759 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -649,6 +649,15 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } } + // power densities in erg / s / cm^3 + // ana means analytical at t_mid, i.e. the rates calculated from the nuclear abundances and decay data, not from + // Monte Carlo + fprintf(estimators_file, "emission_ana: gamma %11.5e positron %11.5e electron %11.5e alpha %11.5e\n", + heatingcoolingrates->eps_gamma_ana, heatingcoolingrates->eps_positron_ana, + heatingcoolingrates->eps_electron_ana, heatingcoolingrates->eps_alpha_ana); + fprintf(estimators_file, "deposition: gamma %11.5e positron %11.5e electron %11.5e alpha %11.5e\n", + heatingcoolingrates->dep_gamma, heatingcoolingrates->dep_positron, heatingcoolingrates->dep_electron, + heatingcoolingrates->dep_alpha); fprintf(estimators_file, "heating: ff %11.5e bf %11.5e coll %11.5e dep %11.5e heating_dep/total_dep %.3f\n", heatingcoolingrates->heating_ff, heatingcoolingrates->heating_bf, heatingcoolingrates->heating_collisional, heatingcoolingrates->heating_dep, heatingcoolingrates->nt_frac_heating); @@ -897,6 +906,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in /// Update elemental abundances with radioactive decays decay::update_abundances(mgi, nts, globals::timesteps[nts].mid); + nonthermal::calculate_deposition_rate_density(mgi, nts, heatingcoolingrates); if (globals::opacity_case == 6) { grid::calculate_kappagrey(); diff --git a/update_packets.cc b/update_packets.cc index 1d375cf71..98593bdb6 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -30,11 +30,14 @@ namespace { void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { double en_deposited = pkt.e_cmf; + const auto mgi = grid::get_cell_modelgridindex(pkt.where); + const auto nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const auto priortype = pkt.type; const double ts = pkt.prop_time; if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::INSTANT) { // absorption happens - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::BARNES) { const double E_kin = grid::get_ejecta_kinetic_energy(); const double v_ej = std::sqrt(E_kin * 2 / grid::mtot_input); @@ -46,7 +49,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; } else { en_deposited = 0.; pkt.type = TYPE_ESCAPE; @@ -63,7 +66,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; } else { en_deposited = 0.; pkt.type = TYPE_ESCAPE; @@ -75,7 +78,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { // endot is energy loss rate (positive) in [erg/s] // endot [erg/s] from Barnes et al. (2016). see their figure 6. - const double endot = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 5.e11 * MEV * rho : 4.e10 * MEV * rho; + const double endot = (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? 5.e11 * MEV * rho : 4.e10 * MEV * rho; const double ts = pkt.prop_time; const double particle_en = H * pkt.nu_cmf; // energy of the particles in the packet @@ -104,7 +107,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const auto t_new = std::min(t_absorb, t2); if (t_absorb <= t2) { - pkt.type = TYPE_NTLEPTON; + pkt.type = TYPE_NTLEPTON_DEPOSITED; } else { pkt.nu_cmf = (particle_en - endot * (t_new - ts)) / H; } @@ -113,12 +116,21 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { pkt.prop_time = t_new; } - if (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) { - atomicadd(globals::timesteps[nts].alpha_dep, en_deposited); - } else if (pkt.pellet_decaytype == decay::DECAYTYPE_BETAMINUS) { - atomicadd(globals::timesteps[nts].electron_dep, en_deposited); - } else if (pkt.pellet_decaytype == decay::DECAYTYPE_BETAPLUS) { - atomicadd(globals::timesteps[nts].positron_dep, en_deposited); + if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS) { + atomicadd(globals::dep_estimator_electron[nonemptymgi], en_deposited); + if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + atomicadd(globals::timesteps[nts].electron_dep_discrete, pkt.e_cmf); + } + } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS) { + atomicadd(globals::dep_estimator_positron[nonemptymgi], en_deposited); + if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + atomicadd(globals::timesteps[nts].positron_dep_discrete, pkt.e_cmf); + } + } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) { + atomicadd(globals::dep_estimator_alpha[nonemptymgi], en_deposited); + if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + atomicadd(globals::timesteps[nts].alpha_dep_discrete, pkt.e_cmf); + } } } @@ -147,23 +159,26 @@ void update_pellet(Packet &pkt, const int nts, const double t2) { if (pkt.originated_from_particlenotgamma) // will decay to non-thermal particle { if (pkt.pellet_decaytype == decay::DECAYTYPE_BETAPLUS) { - atomicadd(globals::timesteps[nts].positron_dep, pkt.e_cmf); - pkt.type = TYPE_NTLEPTON; - pkt.absorptiontype = -10; + pkt.type = TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS; + atomicadd(globals::timesteps[nts].positron_emission, pkt.e_cmf); } else if (pkt.pellet_decaytype == decay::DECAYTYPE_BETAMINUS) { + pkt.type = TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS; atomicadd(globals::timesteps[nts].electron_emission, pkt.e_cmf); - pkt.em_time = pkt.prop_time; - pkt.type = TYPE_NONTHERMAL_PREDEPOSIT; - pkt.absorptiontype = -10; } else if (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) { atomicadd(globals::timesteps[nts].alpha_emission, pkt.e_cmf); - pkt.em_time = pkt.prop_time; - pkt.type = TYPE_NONTHERMAL_PREDEPOSIT; - pkt.absorptiontype = -10; + pkt.type = TYPE_NONTHERMAL_PREDEPOSIT_ALPHA; + } else if constexpr (TESTMODE) { + printout("ERROR: pellet marked as particle emission is for decaytype %d != any of (alpha, beta+, beta-)\n", + pkt.pellet_decaytype); + std::abort(); + } else { + __builtin_unreachable(); } + pkt.em_time = pkt.prop_time; + pkt.absorptiontype = -10; } else { + // decay to gamma-ray packet atomicadd(globals::timesteps[nts].gamma_emission, pkt.e_cmf); - // decay to gamma-ray, kpkt, or ntlepton gammapkt::pellet_gamma_decay(pkt); } } else if ((tdecay > 0) && (nts == 0)) { @@ -198,11 +213,7 @@ void do_packet(Packet &pkt, const double t2, const int nts) } case TYPE_GAMMA: { - gammapkt::do_gamma(pkt, t2); - - if (pkt.type != TYPE_GAMMA && pkt.type != TYPE_ESCAPE) { - atomicadd(globals::timesteps[nts].gamma_dep, pkt.e_cmf); - } + gammapkt::do_gamma(pkt, nts, t2); break; } @@ -215,13 +226,15 @@ void do_packet(Packet &pkt, const double t2, const int nts) break; } - case TYPE_NONTHERMAL_PREDEPOSIT: { + case TYPE_NONTHERMAL_PREDEPOSIT_ALPHA: + case TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS: + case TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS: { do_nonthermal_predeposit(pkt, nts, t2); break; } - case TYPE_NTLEPTON: { - nonthermal::do_ntlepton(pkt); + case TYPE_NTLEPTON_DEPOSITED: { + nonthermal::do_ntlepton_deposit(pkt); break; } From 57905a71a3031b892dc758fdacc155dbc99765a7 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 13 Jul 2024 14:04:17 +0100 Subject: [PATCH 006/117] Update artis-cosma8.sh --- scripts/artis-cosma8.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/artis-cosma8.sh b/scripts/artis-cosma8.sh index 6f395e3bc..ffbe1b891 100644 --- a/scripts/artis-cosma8.sh +++ b/scripts/artis-cosma8.sh @@ -14,10 +14,10 @@ module purge #load the modules used to build your program. module load cosma -module load gsl/2.4 -module load gnu_comp/13.1.0 -module load openmpi/4.1.4 -module load python/3.10.12 +module load gsl +module load gnu_comp +module load openmpi +module load python module list From e63aa97bf77c3a7b79d93db50969b9a8dbb79c08 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 17 Jul 2024 11:41:05 +0100 Subject: [PATCH 007/117] Update artis-virgo-slurmjob.sh --- scripts/artis-virgo-slurmjob.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/artis-virgo-slurmjob.sh b/scripts/artis-virgo-slurmjob.sh index 5d9b7b9b9..59dc5366b 100755 --- a/scripts/artis-virgo-slurmjob.sh +++ b/scripts/artis-virgo-slurmjob.sh @@ -6,7 +6,9 @@ cd $SLURM_SUBMIT_DIR export APPTAINER_SHARENS=true export APPTAINER_CONFIGDIR=/tmp/$USER +eval `spack load --sh openmpi%gcc arch=linux-debian11-x86_64` eval `spack load --sh gsl%gcc arch=linux-debian11-x86_64` +eval `spack load --sh gcc arch=linux-debian11-x86_64` export LD_LIBRARY_PATH=$(gsl-config --prefix)/lib/:$LD_LIBRARY_PATH From 63cf6559dec89b244e403ec9b1caf6dcc2628b09 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 29 Jul 2024 17:12:11 +0100 Subject: [PATCH 008/117] CI: Compile for -stdpar=gpu with nvc++ (#97) --- .github/workflows/ci-checks.yml | 44 ++++++++++++++++++++++++--------- input.cc | 2 +- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 92dd2e995..c1b59c2e6 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -109,11 +109,10 @@ jobs: {name: nvc++, ver: '24.5'}, ] mpi: [ON, OFF] - openmp: [ON, OFF] fail-fast: false runs-on: ubuntu-24.04 - name: ${{ matrix.compiler.name }} ${{ matrix.compiler.ver }}${{ matrix.mpi == 'ON' && ' MPI' || ''}}${{ matrix.openmp == 'ON' && ' OpenMP' || ''}} + name: ${{ matrix.compiler.name }} ${{ matrix.compiler.ver }}${{ matrix.mpi == 'ON' && ' MPI' || ''}} steps: - uses: actions/checkout@v4 @@ -161,7 +160,6 @@ jobs: sudo apt install -y openmpi-bin libopenmpi-dev - name: install OpenMP - if: matrix.openmp == 'ON' run: | sudo apt-get install -y libomp5 libomp-dev @@ -170,28 +168,52 @@ jobs: $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile classic mode OPENMP=ON + run: | + make clean + make MPI=${{matrix.mpi}} OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile classic mode STDPAR=ON - if: matrix.openmp != 'ON' run: | $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile classic mode STDPAR=ON GPU=ON + if: matrix.compiler.name == 'nvc++' + run: | + $CXX -v + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make MPI=${{matrix.mpi}} STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode OPENMP=ON + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make MPI=${{matrix.mpi}} OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode STDPAR=ON - if: matrix.openmp != 'ON' run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode STDPAR=ON GPU=ON + if: matrix.compiler.name == 'nvc++' + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make MPI=${{matrix.mpi}} STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec mac-llvm: runs-on: macos-14 @@ -267,7 +289,7 @@ jobs: $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode run: | @@ -280,4 +302,4 @@ jobs: run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec diff --git a/input.cc b/input.cc index 7e8a4c32a..35a2512e5 100644 --- a/input.cc +++ b/input.cc @@ -1702,7 +1702,7 @@ void read_parameterfile(int rank) pre_zseed = std::random_device{}(); #ifdef MPI_ON // broadcast randomly-generated seed from rank 0 to all ranks - MPI_Bcast(&pre_zseed, 1, MPI_LONG_LONG_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&pre_zseed, 1, MPI_INT64_T, 0, MPI_COMM_WORLD); #endif printout("randomly-generated random number seed is %" PRId64 "\n", pre_zseed); } From d56b2c3a90217127454b54da0335647b63ccaae4 Mon Sep 17 00:00:00 2001 From: gleck97 <86471143+gleck97@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:52:35 +0200 Subject: [PATCH 009/117] Add Guttman Gamma Thermalisation (#93) Co-authored-by: Luke Shingles --- constants.h | 2 +- gammapkt.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/constants.h b/constants.h index 3b9c81dfe..d515cf386 100644 --- a/constants.h +++ b/constants.h @@ -67,6 +67,6 @@ enum timestepsizemethods { TIMESTEP_SIZES_CONSTANT_THEN_LOGARITHMIC = 3, }; -enum class ThermalisationScheme { INSTANT, DETAILED, BARNES, WOLLAEGER }; +enum class ThermalisationScheme { INSTANT, DETAILED, BARNES, WOLLAEGER, GUTTMAN }; #endif diff --git a/gammapkt.cc b/gammapkt.cc index d3da0d9e6..3f49c1726 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -987,6 +988,8 @@ void barnes_thermalisation(Packet &pkt) } void wollaeger_thermalisation(Packet &pkt) { + // corresponds to a local version of the Barnes scheme, i.e. it takes into account the local mass + // density rather than a value averaged over the ejecta constexpr double mean_gamma_opac = 0.1; // integration: requires distances within single cells in radial direction and the corresponding densities // need to create a packet copy which is moved during the integration @@ -1027,6 +1030,82 @@ void wollaeger_thermalisation(Packet &pkt) { } } +void guttman_thermalisation(Packet &pkt) { + // Guttman+2024, arXiv:2403.08769v1 + // extension of the Wollaeger scheme. Rather than calculating a single optical depth in radial outward + // direction, it calculates a spherical average in all possible gamma-ray emission directions. + + // toy value for the mean gamma ray opacity for a start, the paper discuss this some more detail, too + constexpr double mean_gamma_opac = + 0.03; // mean gamma opacity from section 3.2, taken the lower one due to almost symmetrical matter at late times + + const double t_0 = globals::tmin; + const double t = pkt.prop_time; + + // calculate average optical w.r.t. to emission direction + // discretize the two sphere into octants, i.e. four values in phi and two in theta + constexpr int numb_rnd_dirs = 100; + auto column_densities = std::array{}; + for (int i = 0; i < numb_rnd_dirs; i++) { + // compute column density by moving an artificial packet outwards and integrating over local density + // WARNING: This simple implementation relies on a relatively large number of random directions + // as it assumes that the directions are distributed equally which is likely not the case with low statistics. + + // step 1: draw a random direction + Packet pkt_copy = pkt; + // phi rotation: around z-axis + std::array random_dir = get_rand_isotropic_unitvec(); + pkt_copy.dir = random_dir; // fix new direction + + // step 2: move packet into the calculated direction and integrate the density + bool end_packet = false; + while (!end_packet) { + // distance to the next cell + const auto [sdist, snext] = + grid::boundary_distance(pkt_copy.dir, pkt_copy.pos, pkt_copy.prop_time, pkt_copy.where, &pkt_copy.last_cross); + const double s_cont = sdist * std::pow(t, 3.) / std::pow(pkt_copy.prop_time, 3.); + const int mgi = grid::get_cell_modelgridindex(pkt_copy.where); + if (mgi != grid::get_npts_model()) { + column_densities[i] += grid::get_rho_tmin(mgi) * s_cont; // contribution to the integral + } + // move packet copy now + move_pkt_withtime(pkt_copy, sdist); + + grid::change_cell(pkt_copy, snext); + end_packet = (pkt_copy.type == TYPE_ESCAPE); + } + } + const double avg_column_density = + std::accumulate(column_densities.cbegin(), column_densities.cend(), 0.) / std::ssize(column_densities); + const double t_gamma = sqrt(mean_gamma_opac * avg_column_density * t_0 * t_0); + + // compute the (discretized) integral + double f_gamma = 0.; + const double width = 4 * PI / numb_rnd_dirs; + for (int i = 0; i < numb_rnd_dirs; i++) { + double summand = + width * (1 - std::exp(-std::pow(t_gamma, 2.) / std::pow(t, 2.) * column_densities[i] / avg_column_density)); + printout("width: %f t_gamma: %f t: %f column_densities[i]: %f avg_column_density: %f summand: %f", width, t_gamma, + t, column_densities[i], avg_column_density, summand); + f_gamma += summand; + } + f_gamma /= (4 * PI); + + assert_always(f_gamma >= 0.); + assert_always(f_gamma <= 1.); + + // either absorb packet or let it escape + if (rng_uniform() < f_gamma) { + // packet is absorbed and contributes to the heating as a k-packet + pkt.type = TYPE_NTLEPTON_DEPOSITED; + pkt.absorptiontype = -4; + } else { + // let packet escape, i.e. make it inactive + pkt.type = TYPE_ESCAPE; + grid::change_cell(pkt, -99); + } +} + void do_gamma(Packet &pkt, const int nts, double t2) { if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::DETAILED) { transport_gamma(pkt, t2); @@ -1034,6 +1113,8 @@ void do_gamma(Packet &pkt, const int nts, double t2) { barnes_thermalisation(pkt); } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::WOLLAEGER) { wollaeger_thermalisation(pkt); + } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::GUTTMAN) { + guttman_thermalisation(pkt); } else { __builtin_unreachable(); } From 8ee88d0028191208782b7ccfb38aeb98ad6a0fbe Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 1 Aug 2024 10:30:15 +0100 Subject: [PATCH 010/117] Add missing semicolon after assert_always macro invocation --- decay.cc | 5 ++++- kpkt.cc | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/decay.cc b/decay.cc index 917cf073d..a44a4001a 100644 --- a/decay.cc +++ b/decay.cc @@ -1043,7 +1043,10 @@ static auto get_decaypath_power_per_ejectamass(const int decaypathindex, const i const int nucindex_top = decaypaths[decaypathindex].nucindex[0]; const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top); - assert_always(top_initabund >= 0.) if (top_initabund <= 0.) { return 0.; } + assert_always(top_initabund >= 0.); + if (top_initabund <= 0.) { + return 0.; + } const int nucindex_end = decaypaths[decaypathindex].nucindex[get_decaypathlength(decaypathindex) - 1]; diff --git a/kpkt.cc b/kpkt.cc index 2659da724..4b0926b97 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -55,7 +55,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co const auto T_e = grid::get_Te(modelgridindex); if constexpr (update_cooling_contrib_list) { - assert_always(indexionstart >= 0) + assert_always(indexionstart >= 0); } double C_ion = 0.; From b41315d7bee0af7160104798ffb6742c28cd07c3 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 5 Aug 2024 12:55:34 +0100 Subject: [PATCH 011/117] Fix compilation on clang 19.1.0-rc2 --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1acc1f263..da69983ba 100644 --- a/Makefile +++ b/Makefile @@ -206,12 +206,10 @@ else # ifeq ($(TESTMODE),ON) # CXXFLAGS += -Og # else + CXXFLAGS += -O3 ifeq ($(FASTMATH),OFF) - CXXFLAGS += -O3 BUILD_DIR := $(BUILD_DIR)_nofastmath else - CXXFLAGS += -Ofast - ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -fast else From bf09f41e0c765631487dd5da557df91969389e4b Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 7 Aug 2024 10:02:34 +0100 Subject: [PATCH 012/117] Replace std::distance with pointer arithmetic (slight improvement to compile times and readability) (#100) --- atomic.h | 2 +- decay.cc | 4 ++-- grid.cc | 6 +++--- input.cc | 10 +++++----- kpkt.cc | 6 +++--- macroatom.cc | 8 ++++---- nonthermal.cc | 14 +++++++++----- packet.cc | 4 ++-- radfield.cc | 32 ++++++++++++++++---------------- rpkt.cc | 43 ++++++++++++++++++++----------------------- update_packets.cc | 4 ++-- 11 files changed, 67 insertions(+), 66 deletions(-) diff --git a/atomic.h b/atomic.h index 5f2e08792..7fc63e015 100644 --- a/atomic.h +++ b/atomic.h @@ -274,7 +274,7 @@ inline auto get_elementindex(const int Z) -> int const auto elem = std::ranges::find_if(globals::elements, [Z](const Element &element) { return element.anumber == Z; }); if (elem != globals::elements.end()) { - return std::distance(globals::elements.begin(), elem); + return elem - globals::elements.begin(); } // printout("[debug] get_elementindex: element Z=%d was not found in atomic data ... skip readin of cross sections diff --git a/decay.cc b/decay.cc index a44a4001a..e0acc53d4 100644 --- a/decay.cc +++ b/decay.cc @@ -1415,8 +1415,8 @@ void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { const double zrand_en = rng_uniform() * cumulative_en_sum[num_decaychannels - 1]; // first decaychannelindex such that cumulative_en_sum[decaychannelindex] > zrand_en - const int decaychannelindex = std::distance( - cumulative_en_sum.cbegin(), std::upper_bound(cumulative_en_sum.cbegin(), cumulative_en_sum.cend(), zrand_en)); + const int decaychannelindex = + std::upper_bound(cumulative_en_sum.cbegin(), cumulative_en_sum.cend(), zrand_en) - cumulative_en_sum.cbegin(); assert_always(decaychannelindex >= 0); assert_always(decaychannelindex < num_decaychannels); diff --git a/grid.cc b/grid.cc index 3ddc27b4c..b1fb944b6 100644 --- a/grid.cc +++ b/grid.cc @@ -1068,9 +1068,9 @@ static void map_1dmodelto3dgrid() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; - const int mgi = - std::distance(vout_model, std::find_if_not(vout_model, vout_model + get_npts_model(), - [cellvmid](double v_outer) { return v_outer < cellvmid; })); + const int mgi = std::find_if_not(vout_model, vout_model + get_npts_model(), + [cellvmid](double v_outer) { return v_outer < cellvmid; }) - + vout_model; if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { set_cell_modelgridindex(cellindex, mgi); diff --git a/input.cc b/input.cc index 35a2512e5..88b7f8862 100644 --- a/input.cc +++ b/input.cc @@ -1391,11 +1391,11 @@ void setup_phixs_list() { const int nions = get_nions(element); for (int ion = 0; ion < nions - 1; ion++) { if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::elements[element].ions[ion].groundcontindex = std::distance( - globals::groundcont, std::find_if(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, - [=](const auto &groundcont) { - return (groundcont.element == element) && (groundcont.ion == ion); - })); + globals::elements[element].ions[ion].groundcontindex = + std::find_if( + globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, + [=](const auto &groundcont) { return (groundcont.element == element) && (groundcont.ion == ion); }) - + globals::groundcont; if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { globals::elements[element].ions[ion].groundcontindex = -1; } diff --git a/kpkt.cc b/kpkt.cc index 4b0926b97..6d0058b86 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -497,10 +497,10 @@ void do_kpkt(Packet &pkt, double t2, int nts) const double rndcool_ion_process = rng_uniform() * C_ion_procsum; - const auto i = std::distance( - globals::cellcache[cellcacheslotid].cooling_contrib, + const auto i = std::upper_bound(globals::cellcache[cellcacheslotid].cooling_contrib + ilow, - globals::cellcache[cellcacheslotid].cooling_contrib + ihigh + 1, rndcool_ion_process)); + globals::cellcache[cellcacheslotid].cooling_contrib + ihigh + 1, rndcool_ion_process) - + globals::cellcache[cellcacheslotid].cooling_contrib; if (i > ihigh) { printout("do_kpkt: error occured while selecting a cooling channel: low %d, high %d, i %td, rndcool %g\n", ilow, diff --git a/macroatom.cc b/macroatom.cc index c6fc57ab8..fa83fd681 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -191,8 +191,8 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, const double targetval = rng_uniform() * sum_epstrans_rad_deexc[ndowntrans - 1]; // first sum_epstrans_rad_deexc[i] such that sum_epstrans_rad_deexc[i] > targetval - const auto downtransindex = std::distance( - sum_epstrans_rad_deexc, std::upper_bound(sum_epstrans_rad_deexc, sum_epstrans_rad_deexc + ndowntrans, targetval)); + const auto downtransindex = + std::upper_bound(sum_epstrans_rad_deexc, sum_epstrans_rad_deexc + ndowntrans, targetval) - sum_epstrans_rad_deexc; assert_always(downtransindex < ndowntrans); @@ -407,8 +407,8 @@ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) // first cumulative_transitions[i] such that cumulative_transitions[i] > randomrate const int selected_action = - std::distance(cumulative_transitions.cbegin(), - std::upper_bound(cumulative_transitions.cbegin(), cumulative_transitions.cend(), randomrate)); + std::upper_bound(cumulative_transitions.cbegin(), cumulative_transitions.cend(), randomrate) - + cumulative_transitions.cbegin(); assert_always(selected_action < MA_ACTION_COUNT); assert_always(cumulative_transitions[selected_action] > randomrate); diff --git a/nonthermal.cc b/nonthermal.cc index 3c0960846..ee47ea325 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -160,6 +160,7 @@ double *deposition_rate_density; int *deposition_rate_density_timestep; void read_shell_configs() { + assert_always(NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE); auto shells_file = fstream_required("electron_shell_occupancy.txt", std::ios::in); int nshells = 0; // number of shell in binding energy file @@ -889,11 +890,9 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { } const int num_shells = electron_binding[get_atomicnumber(element) - 1].size(); - const bool use_shells_file = !shells_q.empty(); - std::vector q(0); + auto q = std::array < int, NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE ? 0 : 10 > {0}; - if (!use_shells_file) { - q.resize(num_shells, 0); + if (!NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { if (q[0] < 2) // K 1s { @@ -967,7 +966,12 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { double total = 0.; for (int shellindex = 0; shellindex < num_shells; shellindex++) { - const double electronsinshell = (use_shells_file ? shells_q[get_atomicnumber(element) - 1] : q)[shellindex]; + int electronsinshell = 0; + if constexpr (NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { + electronsinshell = shells_q[get_atomicnumber(element) - 1][shellindex]; + } else if (shellindex < std::ssize(q)) { + electronsinshell = q[shellindex]; + } if (electronsinshell <= 0) { continue; diff --git a/packet.cc b/packet.cc index 95c4ced18..78b512162 100644 --- a/packet.cc +++ b/packet.cc @@ -144,8 +144,8 @@ void packet_init(Packet *pkt) const double targetval = rng_uniform() * norm; // first i such that en_cumulative[i] > targetval - const int cellindex = std::distance(en_cumulative.cbegin(), - std::upper_bound(en_cumulative.cbegin(), en_cumulative.cend(), targetval)); + const int cellindex = + std::upper_bound(en_cumulative.cbegin(), en_cumulative.cend(), targetval) - en_cumulative.cbegin(); assert_always(cellindex < grid::ngrid); place_pellet(e0, cellindex, n, pkt[n]); diff --git a/radfield.cc b/radfield.cc index 00b2821ce..4353554d6 100644 --- a/radfield.cc +++ b/radfield.cc @@ -634,17 +634,16 @@ static void update_bfestimators(const int nonemptymgi, const double distance_e_c // so the nu condition on this nu_cmf can truncate the list further compared to what was used in the calculation // of phixslist.gamma_contr - const int bfestimend = - std::distance(globals::bfestim_nu_edge.data(), - std::upper_bound(globals::bfestim_nu_edge.data(), - globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf)); - - const int bfestimbegin = std::distance(globals::bfestim_nu_edge.data(), - std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, - globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, - [](const double nu_edge, const double nu_cmf) { - return nu_edge * last_phixs_nuovernuedge < nu_cmf; - })); + const int bfestimend = std::upper_bound(globals::bfestim_nu_edge.data(), + globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf) - + globals::bfestim_nu_edge.data(); + + const int bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, + globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, + [](const double nu_edge, const double nu_cmf) { + return nu_edge * last_phixs_nuovernuedge < nu_cmf; + }) - + globals::bfestim_nu_edge.data(); const auto bfestimcount = globals::bfestimcount; for (int bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { @@ -1064,11 +1063,12 @@ void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, static auto get_bfcontindex(const int element, const int lowerion, const int lower, const int phixstargetindex) -> int { // simple linear search seems to be faster than the binary search // possibly because lower frequency transitions near start of list are more likely to be called? - const auto bfcontindex = std::distance( - globals::allcont, std::find_if(globals::allcont, globals::allcont + globals::nbfcontinua, [=](const auto &bf) { - return (bf.element == element) && (bf.ion == lowerion) && (bf.level == lower) && - (bf.phixstargetindex == phixstargetindex); - })); + const auto bfcontindex = std::find_if(globals::allcont, globals::allcont + globals::nbfcontinua, + [=](const auto &bf) { + return (bf.element == element) && (bf.ion == lowerion) && + (bf.level == lower) && (bf.phixstargetindex == phixstargetindex); + }) - + globals::allcont; if (bfcontindex < globals::nbfcontinua) { return bfcontindex; diff --git a/rpkt.cc b/rpkt.cc index f98a973e4..2db0274a2 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -122,9 +122,9 @@ auto closest_transition(const double nu_cmf, const int next_trans) -> int // will find the highest frequency (lowest index) line with nu_line <= nu_cmf // lower_bound matches the first element where the comparison function is false const int matchindex = - std::distance(globals::linelist, - std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, - [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; })); + std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, + [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - + globals::linelist; if (matchindex >= globals::nlines) [[unlikely]] { return -1; @@ -577,10 +577,9 @@ static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoe const double chi_bf_rand = rng_uniform() * chi_bf_inrest; // first chi_bf_sum[i] such that chi_bf_sum[i] > chi_bf_rand - const int allcontindex = - std::distance(phixslist.chi_bf_sum.data(), - std::upper_bound(phixslist.chi_bf_sum.data() + phixslist.allcontbegin, - phixslist.chi_bf_sum.data() + phixslist.allcontend - 1, chi_bf_rand)); + const int allcontindex = std::upper_bound(phixslist.chi_bf_sum.data() + phixslist.allcontbegin, + phixslist.chi_bf_sum.data() + phixslist.allcontend - 1, chi_bf_rand) - + phixslist.chi_bf_sum.data(); assert_always(allcontindex < phixslist.allcontend); const double nu_edge = globals::allcont[allcontindex].nu_edge; @@ -674,7 +673,7 @@ auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double const auto rnd_integral = rng_uniform() * kappa_planck_bins[expopac_nbins - 1]; const auto *selected_partintegral = std::upper_bound(kappa_planck_bins, kappa_planck_bins + expopac_nbins, rnd_integral); - const auto binindex = std::min(std::distance(kappa_planck_bins, selected_partintegral), expopac_nbins - 1); + const auto binindex = std::min(selected_partintegral - kappa_planck_bins, expopac_nbins - 1); assert_testmodeonly(binindex >= 0); assert_testmodeonly(binindex < expopac_nbins); @@ -1056,15 +1055,14 @@ static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double n // break the list into nu >= nu_edge and the remainder (nu < nu_edge) int i = 0; - const int allcontend = - std::distance(globals::allcont_nu_edge.cbegin(), - std::upper_bound(globals::allcont_nu_edge.cbegin(), globals::allcont_nu_edge.cend(), nu)); + const int allcontend = std::upper_bound(globals::allcont_nu_edge.cbegin(), globals::allcont_nu_edge.cend(), nu) - + globals::allcont_nu_edge.cbegin(); - const int allcontbegin = std::distance( - globals::allcont_nu_edge.data(), + const int allcontbegin = std::lower_bound( globals::allcont_nu_edge.data(), globals::allcont_nu_edge.data() + allcontend, nu, - [](const double nu_edge, const double nu_cmf) { return nu_edge * last_phixs_nuovernuedge < nu_cmf; })); + [](const double nu_edge, const double nu_cmf) { return nu_edge * last_phixs_nuovernuedge < nu_cmf; }) - + globals::allcont_nu_edge.data(); assert_testmodeonly(allcontbegin >= 0); assert_testmodeonly(allcontend <= globals::nbfcontinua); @@ -1074,15 +1072,14 @@ static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double n phixslist->allcontbegin = allcontbegin; phixslist->allcontend = allcontend; - phixslist->bfestimend = - std::distance(globals::bfestim_nu_edge.cbegin(), - std::upper_bound(globals::bfestim_nu_edge.cbegin(), globals::bfestim_nu_edge.cend(), nu)); + phixslist->bfestimend = std::upper_bound(globals::bfestim_nu_edge.cbegin(), globals::bfestim_nu_edge.cend(), nu) - + globals::bfestim_nu_edge.cbegin(); - phixslist->bfestimbegin = std::distance( - globals::bfestim_nu_edge.data(), + phixslist->bfestimbegin = std::lower_bound( globals::bfestim_nu_edge.data(), globals::bfestim_nu_edge.data() + phixslist->bfestimend, nu, - [](const double nu_edge, const double nu_cmf) { return nu_edge * last_phixs_nuovernuedge < nu_cmf; })); + [](const double nu_edge, const double nu_cmf) { return nu_edge * last_phixs_nuovernuedge < nu_cmf; }) - + globals::bfestim_nu_edge.data(); } for (i = allcontbegin; i < allcontend; i++) { @@ -1258,10 +1255,10 @@ void calculate_expansion_opacities(const int modelgridindex) { const auto t_mid = globals::timesteps[globals::timestep].mid; // find the first line with nu below the upper limit of the first bin - const auto *matchline = + int lineindex = std::lower_bound(&globals::linelist[0], &globals::linelist[globals::nlines], get_expopac_bin_nu_upper(0), - [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }); - int lineindex = std::distance(globals::linelist, matchline); + [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - + globals::linelist; double kappa_planck_cumulative = 0.; diff --git a/update_packets.cc b/update_packets.cc index 98593bdb6..d78e0644b 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -383,7 +383,7 @@ void update_packets(const int my_rank, const int nts, std::span packets) if (cellcache_change_cell_required) { if (packetgroupstart != &pkt) { - do_cell_packet_updates(std::span(packetgroupstart, std::distance(packetgroupstart, &pkt)), nts, ts_end); + do_cell_packet_updates(std::span(packetgroupstart, &pkt - packetgroupstart), nts, ts_end); } #ifdef _OPENMP @@ -397,7 +397,7 @@ void update_packets(const int my_rank, const int nts, std::span packets) } } } - const auto packets_remaining = std::distance(packetgroupstart, packets.data() + packets.size()); + const auto packets_remaining = packets.data() + packets.size() - packetgroupstart; if (packets_remaining > 0) { do_cell_packet_updates(std::span(packetgroupstart, packets_remaining), nts, ts_end); } From 051bc640a9c35d1a53afefb9d0a1c7c80a800ffa Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 7 Aug 2024 20:18:20 +0100 Subject: [PATCH 013/117] Fix compilation errors for nvc++ 24.5 with unified-memory GPUs and clang 19 (#98) --- .clang-format | 1 + .clang-tidy | 3 + .github/workflows/ci-checks.yml | 11 ++- Makefile | 13 +++- decay.cc | 50 ++++++------- exspec.cc | 4 ++ gammapkt.cc | 41 ++++++----- grid.cc | 124 ++++++++++++++++---------------- input.cc | 8 ++- kpkt.cc | 22 +++--- ltepop.cc | 9 +-- macroatom.cc | 12 ++-- md5.cc | 4 +- nltepop.cc | 11 ++- nonthermal.cc | 103 +++++++++++++------------- packet.cc | 5 +- radfield.cc | 92 ++++++++++++------------ ratecoeff.cc | 40 +++++++---- rpkt.cc | 62 +++++++++------- rpkt.h | 7 +- sn3d.cc | 4 ++ sn3d.h | 29 ++++++-- spectrum_lightcurve.cc | 51 ++++++------- stats.cc | 15 ++-- thermalbalance.cc | 11 ++- update_grid.cc | 10 +-- update_packets.cc | 8 +-- vpkt.cc | 20 +++--- 28 files changed, 424 insertions(+), 346 deletions(-) diff --git a/.clang-format b/.clang-format index 3442bc765..3841ad1ef 100644 --- a/.clang-format +++ b/.clang-format @@ -2,3 +2,4 @@ Language: Cpp BasedOnStyle: Google ColumnLimit: 120 +BreakAfterAttributes: Never diff --git a/.clang-tidy b/.clang-tidy index c4eb32bac..7c7a87aa8 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -12,6 +12,7 @@ Checks: > -bugprone-exception-escape, -bugprone-implicit-widening-of-multiplication-result, -bugprone-narrowing-conversions, + -boost-use-ranges, -llvmlibc-*, -cert-err33-c, -cert-err34-c, @@ -65,3 +66,5 @@ CheckOptions: value: 'true' - key: readability-identifier-naming.NamespaceCase value: lower_case + - key: bugprone-reserved-identifier.AllowedIdentifiers + value: '__host__;__device__' diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index c1b59c2e6..a219be667 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -106,7 +106,7 @@ jobs: {name: gcc, ver: 12}, {name: gcc, ver: 13}, {name: gcc, ver: 14}, - {name: nvc++, ver: '24.5'}, + {name: nvc++, ver: '24.7'}, ] mpi: [ON, OFF] fail-fast: false @@ -139,6 +139,14 @@ jobs: compiler: nvidia-hpc version: ${{ matrix.compiler.ver }} + # - name: Install CUDA Toolkit + # uses: Jimver/cuda-toolkit@master + # if: matrix.compiler.name == 'nvc++' + # with: + # log-file-suffix: '${{matrix.compiler.ver}}.txt' + # method: 'network' + # sub-packages: '"nvcc", "cudart"' + - name: Set nvc++ as compiler if: matrix.compiler.name == 'nvc++' run: | @@ -203,6 +211,7 @@ jobs: make MPI=${{matrix.mpi}} OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode STDPAR=ON + if: matrix.compiler.name != 'nvc++' run: | cp -v -p artisoptions_classic.h artisoptions.h make clean diff --git a/Makefile b/Makefile index da69983ba..0f1715b19 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,11 @@ ifeq ($(OPENMP),ON) BUILD_DIR := $(BUILD_DIR)_openmp ifeq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -mp=gpu -gpu=unified + ifeq ($(GPU),ON) + CXXFLAGS += -mp=gpu -gpu=unified + else + CXXFLAGS += -mp + endif else ifeq ($(COMPILER_NAME),CLANG) CXXFLAGS += -Xpreprocessor -fopenmp LDFLAGS += -lomp @@ -100,7 +104,12 @@ ifeq ($(STDPAR),ON) BUILD_DIR := $(BUILD_DIR)_stdpar ifeq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -stdpar=gpu -gpu=unified + ifeq ($(GPU),ON) + CXXFLAGS += -stdpar=gpu -gpu=unified + # CXXFLAGS += -gpu=cc80 + else + CXXFLAGS += -stdpar=multicore + endif else ifeq ($(COMPILER_NAME),CLANG) # CXXFLAGS += -fexperimental-library LDFLAGS += -ltbb diff --git a/decay.cc b/decay.cc index e0acc53d4..9266545b7 100644 --- a/decay.cc +++ b/decay.cc @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +64,8 @@ std::vector nuclides; } // anonymous namespace -[[nodiscard]] constexpr auto decay_daughter_z(const int z_parent, const int /*a_parent*/, const int decaytype) -> int +[[nodiscard]] constexpr static auto decay_daughter_z(const int z_parent, const int /*a_parent*/, + const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { assert_always(decaytype >= 0); @@ -92,7 +92,8 @@ std::vector nuclides; return -1; // no daughter } -[[nodiscard]] constexpr auto decay_daughter_a(const int /*z_parent*/, const int a_parent, const int decaytype) -> int +[[nodiscard]] constexpr static auto decay_daughter_a(const int /*z_parent*/, const int a_parent, + const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { switch (static_cast(decaytype)) { @@ -130,12 +131,12 @@ struct DecayPath { [[nodiscard]] auto final_daughter_z() const -> int { return decay_daughter_z(z.back(), a.back(), decaytypes.back()); } }; -std::vector decaypaths; +static std::vector decaypaths; // decaypath_energy_per_mass points to an array of length npts_model * num_decaypaths // the index [mgi * num_decaypaths + i] will hold the decay energy per mass [erg/g] released by chain i in cell mgi // during the simulation time range -double *decaypath_energy_per_mass{}; +static double *decaypath_energy_per_mass{}; #ifdef MPI_ON MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; #endif @@ -159,7 +160,7 @@ MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; return nuclides[nucindex].a; } -[[nodiscard]] auto get_nuc_z_a(int nucindex) -> std::pair { +[[nodiscard]] static auto get_nuc_z_a(int nucindex) -> std::pair { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return {nuclides[nucindex].z, nuclides[nucindex].a}; @@ -245,13 +246,15 @@ static void printout_nuclidemeanlife(const int z, const int a) { }); } -[[nodiscard]] auto nucdecayenergygamma(int nucindex) -> double +[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(int nucindex) -> double // average energy per decay in the form of gamma rays [erg] { return nuclides[nucindex].endecay_gamma; } -[[nodiscard]] auto nucdecayenergygamma(int z, int a) -> double { return nucdecayenergygamma(get_nucindex(z, a)); } +[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(int z, int a) -> double { + return nucdecayenergygamma(get_nucindex(z, a)); +} void set_nucdecayenergygamma(int nucindex, double value) // set average energy per decay in the form of gamma rays [erg] @@ -291,7 +294,7 @@ void set_nucdecayenergygamma(int nucindex, double value) const int nucindex = get_nucindex(z, a); const auto endecay_particles = std::accumulate( all_decaytypes.cbegin(), all_decaytypes.cend(), 0., [nucindex](const double ensum, const auto &decaytype) { - return ensum + nucdecayenergyparticle(nucindex, decaytype) * get_nuc_decaybranchprob(nucindex, decaytype); + return ensum + (nucdecayenergyparticle(nucindex, decaytype) * get_nuc_decaybranchprob(nucindex, decaytype)); }); return nuclides[nucindex].endecay_gamma + endecay_particles; @@ -497,13 +500,12 @@ static void find_decaypaths(const std::vector &custom_zlist, const std::vec // convert mean lifetimes to decay constants decaypath.lambdas.resize(decaypath.nucindex.size()); - std::transform(decaypath.nucindex.cbegin(), decaypath.nucindex.cend(), decaypath.lambdas.begin(), - [](const auto nucindex) { - const double meanlife = get_meanlife(nucindex); - // last nuclide might be stable (meanlife <= 0.) - const double lambda = (meanlife > 0.) ? 1. / meanlife : 0.; - return lambda; - }); + std::ranges::transform(decaypath.nucindex, decaypath.lambdas.begin(), [](const auto nucindex) { + const double meanlife = get_meanlife(nucindex); + // last nuclide might be stable (meanlife <= 0.) + const double lambda = (meanlife > 0.) ? 1. / meanlife : 0.; + return lambda; + }); // the nuclide one past the end of the path is a used as a sink, so treat it as stable (even if it's not) decaypath.lambdas.push_back(0.); @@ -739,7 +741,7 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector const int maxdecaypathlength = std::accumulate( decaypaths.cbegin(), decaypaths.cend(), 0, - [](const int maxlen, const auto decaypath) { return std::max(maxlen, get_decaypathlength(decaypath)); }); + [](const int maxlen, const auto &decaypath) { return std::max(maxlen, get_decaypathlength(decaypath)); }); printout("Number of decay paths: %d (max length %d)\n", get_num_decaypaths(), maxdecaypathlength); @@ -811,7 +813,7 @@ static constexpr auto calculate_decaychain(const double firstinitabund, const st } else { if (lambdas[j] > 0.) { const double sumtermtop = - (1 + 1 / lambdas[j] / timediff) * exp(-timediff * lambdas[j]) - 1. / lambdas[j] / timediff; + ((1 + 1 / lambdas[j] / timediff) * exp(-timediff * lambdas[j])) - (1. / lambdas[j] / timediff); sum += sumtermtop / denominator; } } @@ -926,9 +928,9 @@ static auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, return endecay; } -auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, - const int decaypathindex, - const double tstart) -> double +static auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, + const int decaypathindex, + const double tstart) -> double // just here as as check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() // this version does an Euler integration { @@ -946,7 +948,7 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const i double last_chain_endecay = -1.; double last_t = -1.; for (int i = 0; i < nsteps; i++) { - const double t = grid::get_t_model() + (tstart - grid::get_t_model()) * i / nsteps; + const double t = grid::get_t_model() + ((tstart - grid::get_t_model()) * i / nsteps); const double chain_endecay_t = get_endecay_to_tinf_per_ejectamass_at_time(modelgridindex, decaypathindex, t); if (last_chain_endecay >= 0) { const double chain_step_endecay_diff = last_chain_endecay - chain_endecay_t; @@ -1025,7 +1027,7 @@ static auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypat // get the decay energy released during the simulation time per unit mass [erg/g] { const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); - const double chainendecay = decaypath_energy_per_mass[nonemptymgi * get_num_decaypaths() + decaypathindex]; + const double chainendecay = decaypath_energy_per_mass[(nonemptymgi * get_num_decaypaths()) + decaypathindex]; assert_testmodeonly(chainendecay >= 0.); assert_testmodeonly(std::isfinite(chainendecay)); return chainendecay; @@ -1116,7 +1118,7 @@ void setup_decaypath_energy_per_mass() { if (nonemptymgi % globals::node_nprocs == globals::rank_in_node) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); for (size_t decaypathindex = 0; decaypathindex < num_decaypaths; decaypathindex++) { - decaypath_energy_per_mass[nonemptymgi * num_decaypaths + decaypathindex] = + decaypath_energy_per_mass[(nonemptymgi * num_decaypaths) + decaypathindex] = calculate_simtime_endecay_per_ejectamass(mgi, decaypathindex); } } diff --git a/exspec.cc b/exspec.cc index ba680ffaa..4c371e243 100644 --- a/exspec.cc +++ b/exspec.cc @@ -8,7 +8,9 @@ #ifdef MPI_ON #include #endif +#ifndef GPU_ON #include +#endif #include #include "artisoptions.h" @@ -22,7 +24,9 @@ #include "spectrum_lightcurve.h" #include "version.h" +#ifndef GPU_ON std::mt19937 stdrng{std::random_device{}()}; +#endif std::ofstream output_file; diff --git a/gammapkt.cc b/gammapkt.cc index 3f49c1726..4966cc9cd 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -45,12 +45,12 @@ static constexpr int numb_xcom_elements = USE_XCOM_GAMMAPHOTOION ? 100 : 0; static std::array, numb_xcom_elements> photoion_data; -struct gammaline { +struct NucGammaLine { int nucindex; // is it a Ni56, Co56, a fake line, etc int nucgammaindex; // which of the lines of that nuclide is it double energy; // in erg - auto operator<(const gammaline &g2) const -> bool { + auto operator<(const NucGammaLine &g2) const -> bool { // true if d1 < d2 if (energy < g2.energy) { return true; @@ -65,7 +65,7 @@ struct gammaline { } }; -static std::vector allnuc_gamma_line_list; +static std::vector allnuc_gamma_line_list; static void read_gamma_spectrum(const int nucindex, const char filename[50]) // reads in gamma_spectra and returns the average energy in gamma rays per nuclear decay @@ -127,8 +127,7 @@ static void read_decaydata() { } auto strelname = decay::get_elname(z); - std::transform(strelname.begin(), strelname.end(), strelname.begin(), - [](unsigned char c) { return std::tolower(c); }); + std::ranges::transform(strelname, strelname.begin(), [](unsigned char c) { return std::tolower(c); }); // look in the current folder char filename[MAXFILENAMELENGTH]; @@ -178,7 +177,7 @@ static void init_gamma_linelist() { } printout("total gamma-ray lines %td\n", total_lines); - allnuc_gamma_line_list = std::vector(); + allnuc_gamma_line_list = std::vector(); allnuc_gamma_line_list.reserve(total_lines); for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { @@ -189,7 +188,7 @@ static void init_gamma_linelist() { } allnuc_gamma_line_list.shrink_to_fit(); assert_always(static_cast(allnuc_gamma_line_list.size()) == total_lines); - std::sort(allnuc_gamma_line_list.begin(), allnuc_gamma_line_list.end()); + std::stable_sort(allnuc_gamma_line_list.begin(), allnuc_gamma_line_list.end()); FILE *const line_list = fopen_required("gammalinelist.out", "w"); @@ -242,7 +241,7 @@ void init_gamma_data() { } } -static auto choose_gamma_ray(const int nucindex) -> double { +__host__ __device__ static auto choose_gamma_ray(const int nucindex) -> double { // Routine to choose which gamma ray line it'll be. const double E_gamma = decay::nucdecayenergygamma(nucindex); // Average energy per gamma line of a decay @@ -260,7 +259,7 @@ static auto choose_gamma_ray(const int nucindex) -> double { assert_always(false); } -void pellet_gamma_decay(Packet &pkt) { +__host__ __device__ void pellet_gamma_decay(Packet &pkt) { // Subroutine to convert a pellet to a gamma ray (or kpkt if no gamma spec loaded) // pkt is a pointer to the packet that is decaying. @@ -320,7 +319,7 @@ void pellet_gamma_decay(Packet &pkt) { // printout("pkt direction %g, %g, %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); } -constexpr auto sigma_compton_partial(const double x, const double f_max) -> double +constexpr static auto sigma_compton_partial(const double x, const double f_max) -> double // Routine to compute the partial cross section for Compton scattering. // xx is the photon energy (in units of electron mass) and f // is the energy loss factor up to which we wish to integrate. @@ -627,8 +626,8 @@ static auto get_chi_photo_electric_rf(const Packet &pkt) -> double { const double log10_sigma_lower = log10(photoion_data[Z - 1][E_smaller_idx].sigma_xcom); const double log10_sigma_gtr = log10(photoion_data[Z - 1][E_gtr_idx].sigma_xcom); // interpolate or extrapolate, both linear in log10-log10 space - const double log10_intpol = log10_E_smaller + (log10_sigma_gtr - log10_sigma_lower) / - (log10_E_gtr - log10_E_smaller) * (log10_E - log10_E_smaller); + const double log10_intpol = log10_E_smaller + ((log10_sigma_gtr - log10_sigma_lower) / + (log10_E_gtr - log10_E_smaller) * (log10_E - log10_E_smaller)); const double sigma_intpol = pow(10., log10_intpol) * 1.0e-24; // now in cm^2 const double chi_cmf_contrib = sigma_intpol * n_i; chi_cmf += chi_cmf_contrib; @@ -707,7 +706,7 @@ static auto sigma_pair_prod_rf(const Packet &pkt) -> double { return chi_rf; } -constexpr auto meanf_sigma(const double x) -> double +constexpr static auto meanf_sigma(const double x) -> double // Routine to compute the mean energy converted to non-thermal electrons times // the Klein-Nishina cross section. { @@ -758,7 +757,7 @@ static void update_gamma_dep(const Packet &pkt, const double dist, const int mgi atomicadd(globals::dep_estimator_gamma[nonemptymgi], heating_cont); } -void pair_prod(Packet &pkt) { +static void pair_prod(Packet &pkt) { // Routine to deal with pair production. // In pair production, the original gamma makes an electron positron pair - kinetic energy equal to @@ -806,7 +805,7 @@ void pair_prod(Packet &pkt) { } } -void transport_gamma(Packet &pkt, double t2) +static void transport_gamma(Packet &pkt, double t2) // Now routine for moving a gamma packet. Idea is that we have as input // a gamma packet with known properties at time t1 and we want to follow it // until time t2. @@ -952,7 +951,7 @@ void transport_gamma(Packet &pkt, double t2) } } -void barnes_thermalisation(Packet &pkt) +static void barnes_thermalisation(Packet &pkt) // Barnes treatment: packet is either getting absorbed immediately and locally // creating a k-packet or it escapes. The absorption probability matches the // Barnes thermalization efficiency, for expressions see the original paper: @@ -987,7 +986,7 @@ void barnes_thermalisation(Packet &pkt) } } -void wollaeger_thermalisation(Packet &pkt) { +static void wollaeger_thermalisation(Packet &pkt) { // corresponds to a local version of the Barnes scheme, i.e. it takes into account the local mass // density rather than a value averaged over the ejecta constexpr double mean_gamma_opac = 0.1; @@ -1030,7 +1029,7 @@ void wollaeger_thermalisation(Packet &pkt) { } } -void guttman_thermalisation(Packet &pkt) { +static void guttman_thermalisation(Packet &pkt) { // Guttman+2024, arXiv:2403.08769v1 // extension of the Wollaeger scheme. Rather than calculating a single optical depth in radial outward // direction, it calculates a spherical average in all possible gamma-ray emission directions. @@ -1054,7 +1053,7 @@ void guttman_thermalisation(Packet &pkt) { // step 1: draw a random direction Packet pkt_copy = pkt; // phi rotation: around z-axis - std::array random_dir = get_rand_isotropic_unitvec(); + const std::array random_dir = get_rand_isotropic_unitvec(); pkt_copy.dir = random_dir; // fix new direction // step 2: move packet into the calculated direction and integrate the density @@ -1083,7 +1082,7 @@ void guttman_thermalisation(Packet &pkt) { double f_gamma = 0.; const double width = 4 * PI / numb_rnd_dirs; for (int i = 0; i < numb_rnd_dirs; i++) { - double summand = + const double summand = width * (1 - std::exp(-std::pow(t_gamma, 2.) / std::pow(t, 2.) * column_densities[i] / avg_column_density)); printout("width: %f t_gamma: %f t: %f column_densities[i]: %f avg_column_density: %f summand: %f", width, t_gamma, t, column_densities[i], avg_column_density, summand); @@ -1106,7 +1105,7 @@ void guttman_thermalisation(Packet &pkt) { } } -void do_gamma(Packet &pkt, const int nts, double t2) { +__host__ __device__ void do_gamma(Packet &pkt, const int nts, double t2) { if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::DETAILED) { transport_gamma(pkt, t2); } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::BARNES) { diff --git a/grid.cc b/grid.cc index b1fb944b6..688eb75af 100644 --- a/grid.cc +++ b/grid.cc @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -86,6 +85,37 @@ std::vector ranks_ndo; std::vector ranks_ndo_nonempty; int maxndo = -1; +void set_rho_tmin(const int modelgridindex, const float x) { modelgrid[modelgridindex].rhoinit = x; } + +void set_initelectronfrac(const int modelgridindex, const double electronfrac) { + modelgrid[modelgridindex].initelectronfrac = electronfrac; +} + +void read_possible_yefile() { + if (!std::filesystem::exists("Ye.txt")) { + printout("Ye.txt not found\n"); + return; + } + + FILE *filein = fopen_required("Ye.txt", "r"); + int nlines_in = 0; + assert_always(fscanf(filein, "%d", &nlines_in) == 1); + + for (int n = 0; n < nlines_in; n++) { + int mgiplusone = -1; + double initelecfrac = 0.; + assert_always(fscanf(filein, "%d %lg", &mgiplusone, &initelecfrac) == 2); + const int mgi = mgiplusone - 1; + if (mgi >= 0 && mgi < get_npts_model()) { + set_initelectronfrac(mgi, initelecfrac); + // printout("Ye.txt: setting mgi %d init_ye %g\n", mgi, initelecfrac); + } else { + // printout("Ye.txt: ignoring mgi %d init_ye %g\n", mgi, initelecfrac); + } + } + fclose(filein); +} + } // anonymous namespace auto wid_init(const int cellindex, const int axis) -> double @@ -253,9 +283,9 @@ auto get_cellcoordpointnum(const int cellindex, const int axis) -> int auto get_rho_tmin(const int modelgridindex) -> float { return modelgrid[modelgridindex].rhoinit; } -auto get_rho(const int modelgridindex) -> float { return modelgrid[modelgridindex].rho; } +__host__ __device__ auto get_rho(const int modelgridindex) -> float { return modelgrid[modelgridindex].rho; } -auto get_nne(const int modelgridindex) -> float { +__host__ __device__ auto get_nne(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); @@ -264,7 +294,7 @@ auto get_nne(const int modelgridindex) -> float { return nne; } -auto get_nnetot(const int modelgridindex) -> float { +__host__ __device__ auto get_nnetot(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); @@ -273,7 +303,7 @@ auto get_nnetot(const int modelgridindex) -> float { return nnetot; } -auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } +__host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) // mass fraction of an element (all isotopes combined) @@ -281,45 +311,43 @@ void set_elem_abundance(const int modelgridindex, const int element, const float modelgrid[modelgridindex].composition[element].abundance = newabundance; } -auto get_elem_numberdens(const int modelgridindex, const int element) -> double +__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double // mass fraction of an element (all isotopes combined) { const double elem_meanweight = grid::get_element_meanweight(modelgridindex, element); return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); } -auto get_kappagrey(const int modelgridindex) -> float { +__host__ __device__ auto get_kappagrey(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex <= get_npts_model()); return modelgrid[modelgridindex].kappagrey; } -auto get_Te(const int modelgridindex) -> float { +__host__ __device__ auto get_Te(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex <= get_npts_model()); return modelgrid[modelgridindex].Te; } -auto get_TR(const int modelgridindex) -> float { +__host__ __device__ auto get_TR(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex <= get_npts_model()); return modelgrid[modelgridindex].TR; } -auto get_TJ(const int modelgridindex) -> float { +__host__ __device__ auto get_TJ(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex <= get_npts_model()); return modelgrid[modelgridindex].TJ; } -auto get_W(const int modelgridindex) -> float { +__host__ __device__ auto get_W(const int modelgridindex) -> float { assert_testmodeonly(modelgridindex >= 0); assert_testmodeonly(modelgridindex <= get_npts_model()); return modelgrid[modelgridindex].W; } -static void set_rho_tmin(const int modelgridindex, const float x) { modelgrid[modelgridindex].rhoinit = x; } - void set_rho(const int modelgridindex, float rho) { assert_always(rho >= 0.); assert_always(std::isfinite(rho)); @@ -364,7 +392,7 @@ auto get_model_type() -> enum gridtypes { return model_type; } void set_model_type(enum gridtypes model_type_value) { model_type = model_type_value; } -auto get_npts_model() -> int +__host__ __device__ auto get_npts_model() -> int // number of model grid cells { assert_testmodeonly(npts_model > 0); @@ -441,7 +469,7 @@ auto get_t_model() -> double return t_model; } -auto get_cell_modelgridindex(const int cellindex) -> int { +__host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { assert_testmodeonly(cellindex >= 0); assert_testmodeonly(cellindex < ngrid); const int mgi = cell[cellindex].modelgridindex; @@ -456,14 +484,14 @@ static void set_cell_modelgridindex(const int cellindex, const int new_modelgrid cell[cellindex].modelgridindex = new_modelgridindex; } -auto get_numassociatedcells(const int modelgridindex) -> int +__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int // number of propagation cells associated with each modelgrid cell { assert_testmodeonly(modelgridindex <= get_npts_model()); return mg_associated_cells[modelgridindex]; } -auto get_modelcell_nonemptymgi(const int mgi) -> int +__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int // get the index in the list of non-empty cells for a given model grid cell { assert_testmodeonly(get_nonempty_npts_model() > 0); @@ -477,7 +505,7 @@ auto get_modelcell_nonemptymgi(const int mgi) -> int return nonemptymgi; } -auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int +__host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int // get the index in the list of non-empty cells for a given model grid cell { assert_testmodeonly(get_nonempty_npts_model() > 0); @@ -551,10 +579,6 @@ auto get_electronfrac(const int modelgridindex) -> double { auto get_initelectronfrac(const int modelgridindex) -> double { return modelgrid[modelgridindex].initelectronfrac; } -static void set_initelectronfrac(const int modelgridindex, const double electronfrac) { - modelgrid[modelgridindex].initelectronfrac = electronfrac; -} - auto get_initenergyq(const int modelgridindex) -> double { // q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] @@ -565,31 +589,6 @@ static void set_initenergyq(const int modelgridindex, const double initenergyq) modelgrid[modelgridindex].initenergyq = initenergyq; } -void read_possible_yefile() { - if (!std::filesystem::exists("Ye.txt")) { - printout("Ye.txt not found\n"); - return; - } - - FILE *filein = fopen_required("Ye.txt", "r"); - int nlines_in = 0; - assert_always(fscanf(filein, "%d", &nlines_in) == 1); - - for (int n = 0; n < nlines_in; n++) { - int mgiplusone = -1; - double initelecfrac = 0.; - assert_always(fscanf(filein, "%d %lg", &mgiplusone, &initelecfrac) == 2); - const int mgi = mgiplusone - 1; - if (mgi >= 0 && mgi < get_npts_model()) { - set_initelectronfrac(mgi, initelecfrac); - // printout("Ye.txt: setting mgi %d init_ye %g\n", mgi, initelecfrac); - } else { - // printout("Ye.txt: ignoring mgi %d init_ye %g\n", mgi, initelecfrac); - } - } - fclose(filein); -} - static void set_elem_stable_abund_from_total(const int mgi, const int element, const float elemabundance) { // set the stable mass fraction of an element from the total element mass fraction // by subtracting the abundances of radioactive isotopes. @@ -674,7 +673,7 @@ void calculate_kappagrey() { if (globals::opacity_case == 3) { if (get_rho_tmin(mgi) > 0.) { - double kappagrey = (0.9 * get_ffegrp(mgi) + 0.1); + double kappagrey = ((0.9 * get_ffegrp(mgi)) + 0.1); if (get_rho_tmin(mgi) > globals::rho_crit) { kappagrey *= globals::rho_crit / get_rho_tmin(mgi); @@ -1068,9 +1067,9 @@ static void map_1dmodelto3dgrid() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; - const int mgi = std::find_if_not(vout_model, vout_model + get_npts_model(), - [cellvmid](double v_outer) { return v_outer < cellvmid; }) - - vout_model; + const int mgi = static_cast(std::find_if_not(vout_model, vout_model + get_npts_model(), + [cellvmid](double v_outer) { return v_outer < cellvmid; }) - + vout_model); if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { set_cell_modelgridindex(cellindex, mgi); @@ -1601,7 +1600,7 @@ static void read_3d_model() for (int axis = 0; axis < 3; axis++) { const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; - const double cellpos_expected = -xmax_tmodel + cellwidth * get_cellcoordpointnum(mgi, axis); + const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid // %d\n", // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, @@ -1830,7 +1829,7 @@ static void read_grid_restart_data(const int timestep) { if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { - const int estimindex = nonemptymgi * globals::nbfcontinua_ground + i; + const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; assert_always(fscanf(gridsave_file, " %la %la", &globals::corrphotoionrenorm[estimindex], &globals::gammaestimator[estimindex]) == 2); } @@ -1881,7 +1880,7 @@ void write_grid_restart_data(const int timestep) { if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { - const int estimindex = nonemptymgi * globals::nbfcontinua_ground + i; + const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; fprintf(gridsave_file, " %la %la", globals::corrphotoionrenorm[estimindex], globals::gammaestimator[estimindex]); } @@ -2161,7 +2160,7 @@ static void setup_grid_cylindrical_2d() { } } -auto get_grid_type_name() -> std::string { +static auto get_grid_type_name() -> std::string { switch (GRID_TYPE) { case GRID_SPHERICAL1D: return "spherical"; @@ -2383,7 +2382,7 @@ template const double b = 2 * (dot(dir, pos) - pow(shellradiuststart, 2) / tstart / speed); const double c = dot(pos, pos) - pow(shellradiuststart, 2); - const double discriminant = pow(b, 2) - 4 * a * c; + const double discriminant = pow(b, 2) - (4 * a * c); if (discriminant < 0) { // no intersection @@ -2488,8 +2487,8 @@ static auto get_coordboundary_distances_cylindrical2d( const double d_rcyl_coordminboundary = expanding_shell_intersection(posnoz, dirnoz, xyspeed, r_inner, true, tstart); if (d_rcyl_coordminboundary >= 0) { const double d_z_coordminboundary = d_rcyl_coordminboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; - d_coordminboundary[0] = - std::sqrt(d_rcyl_coordminboundary * d_rcyl_coordminboundary + d_z_coordminboundary * d_z_coordminboundary); + d_coordminboundary[0] = std::sqrt((d_rcyl_coordminboundary * d_rcyl_coordminboundary) + + (d_z_coordminboundary * d_z_coordminboundary)); } } @@ -2499,7 +2498,7 @@ static auto get_coordboundary_distances_cylindrical2d( if (d_rcyl_coordmaxboundary >= 0) { const double d_z_coordmaxboundary = d_rcyl_coordmaxboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; d_coordmaxboundary[0] = - std::sqrt(d_rcyl_coordmaxboundary * d_rcyl_coordmaxboundary + d_z_coordmaxboundary * d_z_coordmaxboundary); + std::sqrt((d_rcyl_coordmaxboundary * d_rcyl_coordmaxboundary) + (d_z_coordmaxboundary * d_z_coordmaxboundary)); } // z boundaries are the same as Cartesian @@ -2517,9 +2516,10 @@ static auto get_coordboundary_distances_cylindrical2d( return {d_coordminboundary, d_coordmaxboundary}; } -[[nodiscard]] auto boundary_distance(const std::array dir, const std::array pos, - const double tstart, const int cellindex, - enum cell_boundary *pkt_last_cross) -> std::tuple +[[nodiscard]] __host__ __device__ auto boundary_distance(const std::array dir, + const std::array pos, const double tstart, + const int cellindex, + enum cell_boundary *pkt_last_cross) -> std::tuple /// Basic routine to compute distance to a cell boundary. { if constexpr (FORCE_SPHERICAL_ESCAPE_SURFACE) { diff --git a/input.cc b/input.cc index 88b7f8862..e3399de08 100644 --- a/input.cc +++ b/input.cc @@ -22,7 +22,9 @@ #include #include #include +#ifndef GPU_ON #include +#endif #include #include #include @@ -939,7 +941,7 @@ void read_atomicdata_files() { if (globals::rank_in_node == 0) { // sort the lineline in descending frequency std::sort(EXEC_PAR_UNSEQ temp_linelist.begin(), temp_linelist.end(), - [](const auto &a, const auto &b) { return static_cast(a.nu > b.nu); }); + [](const auto &a, const auto &b) { return a.nu > b.nu; }); for (int i = 0; i < globals::nlines - 1; i++) { const double nu = temp_linelist[i].nu; @@ -1699,7 +1701,9 @@ void read_parameterfile(int rank) if (pre_zseed > 0) { printout("using input.txt specified random number seed of %" PRId64 "\n", pre_zseed); } else { +#ifndef GPU_ON pre_zseed = std::random_device{}(); +#endif #ifdef MPI_ON // broadcast randomly-generated seed from rank 0 to all ranks MPI_Bcast(&pre_zseed, 1, MPI_INT64_T, 0, MPI_COMM_WORLD); @@ -1716,7 +1720,9 @@ void read_parameterfile(int rank) /// to the thread-ID tid. const auto tid = get_thread_num(); auto rngseed = pre_zseed + static_cast(13 * (rank * get_max_threads() + tid)); +#ifndef GPU_ON stdrng.seed(rngseed); +#endif printout("rank %d: thread %d has rngseed %" PRId64 "\n", rank, tid, rngseed); printout("rng is a std::mt19937 generator\n"); diff --git a/kpkt.cc b/kpkt.cc index 6d0058b86..5c80957f0 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -4,7 +4,6 @@ #include #include #include -#include #include "artisoptions.h" #include "atomic.h" @@ -352,7 +351,7 @@ static auto sample_planck_analytic(const double T) -> double double bin_nu_lower = NU_MIN_R; for (ptrdiff_t i = 1; i < nubins; i++) { bin_nu_lower = NU_MIN_R + (i - 1) * delta_nu; - const double nu_upper = NU_MIN_R + i * delta_nu; + const double nu_upper = NU_MIN_R + (i * delta_nu); prev_partintegral = part_integral; part_integral = radfield::planck_integral_analytic(T, NU_MIN_R, nu_upper, false); if (rand_partintegral >= part_integral) { @@ -377,7 +376,7 @@ static auto sample_planck_montecarlo(const double T) -> double const double B_peak = radfield::dbb(nu_peak, T, 1); while (true) { - const double nu = NU_MIN_R + rng_uniform() * (NU_MAX_R - NU_MIN_R); + const double nu = NU_MIN_R + (rng_uniform() * (NU_MAX_R - NU_MIN_R)); if (rng_uniform() * B_peak <= radfield::dbb(nu, T, 1)) { return nu; } @@ -385,7 +384,7 @@ static auto sample_planck_montecarlo(const double T) -> double } } -void do_kpkt_blackbody(Packet &pkt) +__host__ __device__ void do_kpkt_blackbody(Packet &pkt) /// handle a k-packet (e.g., in a thick cell) by emitting according to the planck function { const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); @@ -414,7 +413,7 @@ void do_kpkt_blackbody(Packet &pkt) pkt.nscatterings = 0; } -void do_kpkt(Packet &pkt, double t2, int nts) +__host__ __device__ void do_kpkt(Packet &pkt, double t2, int nts) /// handle a k-packet (kinetic energy of the free electrons) { const double t1 = pkt.prop_time; @@ -547,8 +546,9 @@ void do_kpkt(Packet &pkt, double t2, int nts) pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; pkt.nscatterings = 0; - - vpkt_call_estimators(pkt, TYPE_KPKT); + if constexpr (VPKT_ON) { + vpkt_call_estimators(pkt, TYPE_KPKT); + } } else if (rndcoolingtype == COOLINGTYPE_FB) { /// The k-packet converts directly into a r-packet by free-bound-emission. @@ -587,7 +587,9 @@ void do_kpkt(Packet &pkt, double t2, int nts) pkt.em_time = pkt.prop_time; pkt.nscatterings = 0; - vpkt_call_estimators(pkt, TYPE_KPKT); + if constexpr (VPKT_ON) { + vpkt_call_estimators(pkt, TYPE_KPKT); + } } else if (rndcoolingtype == COOLINGTYPE_COLLEXC) { /// the k-packet activates a macro-atom due to collisional excitation // printout("[debug] do_kpkt: k-pkt -> collisional excitation of MA\n"); @@ -643,7 +645,7 @@ void do_kpkt(Packet &pkt, double t2, int nts) pkt.trueemissiontype = EMTYPE_NOTSET; pkt.trueemissionvelocity = -1; - do_macroatom(pkt, {element, ion, upper, -99}); + do_macroatom(pkt, {.element = element, .ion = ion, .level = upper, .activatingline = -99}); } else if (rndcoolingtype == COOLINGTYPE_COLLION) { /// the k-packet activates a macro-atom due to collisional ionisation // printout("[debug] do_kpkt: k-pkt -> collisional ionisation of MA\n"); @@ -663,7 +665,7 @@ void do_kpkt(Packet &pkt, double t2, int nts) pkt.trueemissiontype = EMTYPE_NOTSET; pkt.trueemissionvelocity = -1; - do_macroatom(pkt, {element, upperion, upper, -99}); + do_macroatom(pkt, {.element = element, .ion = upperion, .level = upper, .activatingline = -99}); } else if constexpr (TESTMODE) { printout("ERROR: Unknown rndcoolingtype type %d\n", rndcoolingtype); assert_testmodeonly(false); diff --git a/ltepop.cc b/ltepop.cc index 46ef30f38..92d94231e 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -41,7 +41,7 @@ auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const d const double f_upper = globals::elements[element].ions[ion].Alpha_sp[upperindex]; const double f_lower = globals::elements[element].ions[ion].Alpha_sp[lowerindex]; - return f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower); + return f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower)); } return globals::elements[element].ions[ion].Alpha_sp[TABLESIZE - 1]; } @@ -332,7 +332,7 @@ auto calculate_levelpop(int modelgridindex, int element, int ion, int level) -> return nn; } -auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double +__host__ __device__ auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double /// Calculates the population of a level from either LTE or NLTE information { double nn = 0.; @@ -411,7 +411,8 @@ void calculate_cellpartfuncts(const int modelgridindex, const int element) } } -auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, double E_threshold) -> double +__host__ __device__ auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, + double E_threshold) -> double /// calculates saha factor in LTE: Phi_level,ion,element = nn_level,ion,element/(nne*nn_upper,ion+1,element) { const double g_lower = stat_weight(element, ion, level); @@ -429,7 +430,7 @@ auto calculate_sahafact(int element, int ion, int level, int upperionlevel, doub return sf; } -auto get_nnion(int modelgridindex, int element, int ion) -> double +[[nodiscard]] __host__ __device__ auto get_nnion(int modelgridindex, int element, int ion) -> double /// Use the ground level population and partition function to get an ion population { return get_groundlevelpop(modelgridindex, element, ion) * diff --git a/macroatom.cc b/macroatom.cc index fa83fd681..ecd65ceed 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -6,7 +6,6 @@ #include #include #include -#include #if defined(STDPAR_ON) || defined(_OPENMP_ON) #include #endif @@ -317,7 +316,7 @@ void do_macroatom_ionisation(const int modelgridindex, const int element, int *i } // anonymous namespace -void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) +__host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) /// Material for handling activated macro atoms. { const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); @@ -371,7 +370,7 @@ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) auto &chlevel = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level]; { -#if defined(STDPAR_ON) || defined(_OPENMP_ON) +#if (defined(STDPAR_ON) || defined(_OPENMP_ON)) && !defined(GPU_ON) const auto lock = std::lock_guard(globals::mutex_cellcachemacroatom[get_uniquelevelindex(element, ion, level)]); #endif @@ -407,8 +406,7 @@ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) // first cumulative_transitions[i] such that cumulative_transitions[i] > randomrate const int selected_action = - std::upper_bound(cumulative_transitions.cbegin(), cumulative_transitions.cend(), randomrate) - - cumulative_transitions.cbegin(); + std::ranges::upper_bound(cumulative_transitions, randomrate) - cumulative_transitions.cbegin(); assert_always(selected_action < MA_ACTION_COUNT); assert_always(cumulative_transitions[selected_action] > randomrate); @@ -637,7 +635,9 @@ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) } if (pkt.type == TYPE_RPKT) { - vpkt_call_estimators(pkt, TYPE_MA); + if constexpr (VPKT_ON) { + vpkt_call_estimators(pkt, TYPE_MA); + } } } diff --git a/md5.cc b/md5.cc index 873722172..233d4f3f5 100644 --- a/md5.cc +++ b/md5.cc @@ -209,7 +209,7 @@ void md5_final(MD5_CTX *ctx, BYTE hash[]) { } // added by Luke Shingles -void md5_file(const char filename[], char hashout[2 * MD5_BLOCK_SIZE + 1]) { +void md5_file(const char filename[], char hashout[(2 * MD5_BLOCK_SIZE) + 1]) { MD5_CTX ctx; md5_init(&ctx); @@ -231,7 +231,7 @@ void md5_file(const char filename[], char hashout[2 * MD5_BLOCK_SIZE + 1]) { md5_final(&ctx, hashbytes); for (int j = 0; j < MD5_BLOCK_SIZE; j++) { - snprintf(&hashout[2 * j], 2 * MD5_BLOCK_SIZE + 1 - 2 * j, "%02x", hashbytes[j]); + snprintf(&hashout[2 * j], (2 * MD5_BLOCK_SIZE) + 1 - (2 * j), "%02x", hashbytes[j]); } hashout[2 * MD5_BLOCK_SIZE] = '\0'; diff --git a/nltepop.cc b/nltepop.cc index 6f7b8773e..1c0140dec 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -91,17 +91,13 @@ static void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_v double row_max = 0.; for (int column = 0; column < nlte_dimension; column++) { const double element_value = fabs(gsl_matrix_get(rate_matrix, index, column)); - if (element_value > row_max) { - row_max = element_value; - } + row_max = std::max(element_value, row_max); } double col_max = 0.; for (int row = 1; row < nlte_dimension; row++) // skip the normalisation row 0 { const double element_value = fabs(gsl_matrix_get(rate_matrix, row, index)); - if (element_value > col_max) { - col_max = element_value; - } + col_max = std::max(element_value, col_max); } int ion = -1; int level = -1; @@ -1072,7 +1068,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } } -auto superlevel_boltzmann(const int modelgridindex, const int element, const int ion, const int level) -> double { +__host__ __device__ auto superlevel_boltzmann(const int modelgridindex, const int element, const int ion, + const int level) -> double { const int superlevel_index = get_nlevels_nlte(element, ion) + 1; const double T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(modelgridindex) : grid::get_Te(modelgridindex); const double E_level = epsilon(element, ion, level); diff --git a/nonthermal.cc b/nonthermal.cc index ee47ea325..9ff6b599b 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1,5 +1,6 @@ #include "nonthermal.h" +#include #include #ifdef MPI_ON @@ -13,7 +14,6 @@ #include #include -#include #include #include #include @@ -235,13 +235,13 @@ void read_binding_energies() { auto get_auger_probability(int modelgridindex, int element, int ion, int naugerelec) -> double { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + naugerelec]; + return nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; } auto get_ion_auger_enfrac(int modelgridindex, int element, int ion, int naugerelec) -> double { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + naugerelec]; + return nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; } void check_auger_probabilities(int modelgridindex) { @@ -323,7 +323,7 @@ void read_auger_data() { float n_auger_elec_avg = 0; double prob_num_auger[NT_MAX_AUGER_ELECTRONS + 1]; for (int a = 0; a < 9; a++) { - linepos = line + static_cast(26 + a * 5); + linepos = line + static_cast(26 + (a * 5)); // have to read out exactly 5 characters at a time because the columns are sometimes not separated by a space char strprob[6] = "00000"; assert_always(sscanf(linepos, "%5c%n", strprob, &offset) == 1); @@ -465,8 +465,8 @@ void zero_all_effionpot(const int modelgridindex) { nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)] = 1.; nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)] = 1.; for (int a = 1; a <= NT_MAX_AUGER_ELECTRONS; a++) { - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 0.; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 0.; + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; } const auto [element, ion] = get_ionfromuniqueionindex(uniqueionindex); @@ -538,7 +538,7 @@ auto get_y(const int modelgridindex, const double energy_ev) -> double { const double ybelow = get_y_sample(modelgridindex, index); const double yabove = get_y_sample(modelgridindex, index + 1); const double x = (energy_ev - enbelow) / (enabove - enbelow); - return (1 - x) * ybelow + x * yabove; + return ((1 - x) * ybelow) + (x * yabove); // or return the nearest neighbour // return get_y_sample(modelgridindex, index); @@ -602,7 +602,7 @@ auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &collio for (int i = startindex; i < SFPTS; i++) { const double u = gsl_vector_get(envec, i) / ionpot_ev; const double xs_ioniz = - 1e-14 * (A * (1 - 1 / u) + B * pow((1 - 1 / u), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); + 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); gsl_vector_set(xs_vec, i, xs_ioniz); } @@ -668,7 +668,7 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, // const double g_bar = 0.2; const double A = 0.28; const double B = 0.15; - const double g_bar = A * log(U) + B; + const double g_bar = (A * log(U)) + B; const double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) // Eq 4 of Mewe 1972, possibly from Seaton 1962? @@ -716,7 +716,7 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col const double C = colliondata.C; const double D = colliondata.D; - return 1e-14 * (A * (1 - 1 / u) + B * pow((1 - 1 / u), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); + return 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); } auto N_e(const int modelgridindex, const double energy) -> double @@ -784,7 +784,7 @@ auto N_e(const int modelgridindex, const double energy) -> double } // integral from 2E + I up to E_max - const int integral2startindex = get_energyindex_ev_lteq(2 * energy_ev + ionpot_ev); + const int integral2startindex = get_energyindex_ev_lteq((2 * energy_ev) + ionpot_ev); for (int i = integral2startindex; i < SFPTS; i++) { const double endash = gsl_vector_get(envec, i); const double delta_endash = DELTA_E; @@ -1173,29 +1173,30 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen const int upperion = ion + 1 + a; if (upperion <= topion) // not too many Auger electrons to exceed the top ion of this element { - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = eta_nauger_ionize_sum[a] / eta_sum; } else { // the following ensures that multiple ionisations can't send you to an ion stage that is not in // the model. Send it to the highest ion stage instead const int a_replace = topion - ion - 1; - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a_replace] += + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a_replace] += eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a_replace] += + nt_solution[modelgridindex] + .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a_replace] += eta_nauger_ionize_sum[a] / eta_sum; - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 0; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 0.; + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0; + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; } } } } else { const int a = 0; - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 1.; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a] = 1.; + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 1.; + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 1.; } if (matching_nlsubshell_count > 0) { @@ -1296,7 +1297,7 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele for (int j = en_startindex; j < SFPTS; j++) { const double logU = gsl_vector_get(logenvec, j) - log(epsilon_trans_ev); - const double g_bar = A * logU + B; + const double g_bar = (A * logU) + B; gsl_vector_set(xs_excitation_vec, j, constantfactor * g_bar / gsl_vector_get(envec, j)); } @@ -1571,9 +1572,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo if constexpr (NT_EXCITATION_ON && (MAX_NT_EXCITATIONS_STORED > 0)) { // sort by descending frac_deposition - std::sort(EXEC_PAR_UNSEQ nt_solution[modelgridindex].frac_excitations_list.begin(), - nt_solution[modelgridindex].frac_excitations_list.end(), - [](const auto &a, const auto &b) { return static_cast(a.frac_deposition > b.frac_deposition); }); + std::stable_sort(nt_solution[modelgridindex].frac_excitations_list.begin(), + nt_solution[modelgridindex].frac_excitations_list.end(), + [](const auto &a, const auto &b) { return a.frac_deposition > b.frac_deposition; }); // the excitation list is now sorted by frac_deposition descending const double deposition_rate_density = get_deposition_rate_density(modelgridindex); @@ -1630,9 +1631,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::sort(EXEC_PAR_UNSEQ nt_solution[modelgridindex].frac_excitations_list.begin(), + std::sort(nt_solution[modelgridindex].frac_excitations_list.begin(), nt_solution[modelgridindex].frac_excitations_list.end(), - [](const auto &a, const auto &b) { return static_cast(a.lineindex < b.lineindex); }); + [](const auto &a, const auto &b) { return a.lineindex < b.lineindex; }); } // NT_EXCITATION_ON @@ -1793,7 +1794,7 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int // endash ranges from 2 * en + ionpot_ev to SF_EMAX if (2 * en + ionpot_ev <= SF_EMAX) { - const int secondintegralstartindex = std::max(xsstartindex, get_energyindex_ev_lteq(2 * en + ionpot_ev)); + const int secondintegralstartindex = std::max(xsstartindex, get_energyindex_ev_lteq((2 * en) + ionpot_ev)); for (int j = secondintegralstartindex; j < SFPTS; j++) { // epsilon_lower = en + ionpot_ev; // epsilon_upper = (endash + ionpot_ev) / 2; @@ -2007,7 +2008,7 @@ void init(const int my_rank, const int ndo_nonempty) { const int sourcelowerindex = SFPTS - source_spread_pts; for (int s = 0; s < SFPTS; s++) { - const double energy_ev = SF_EMIN + s * DELTA_E; + const double energy_ev = SF_EMIN + (s * DELTA_E); gsl_vector_set(envec, s, energy_ev); gsl_vector_set(logenvec, s, log(energy_ev)); @@ -2087,7 +2088,7 @@ void calculate_deposition_rate_density(const int modelgridindex, const int times deposition_rate_density_timestep[modelgridindex] = timestep; } -auto get_deposition_rate_density(const int modelgridindex) -> double +__host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double // get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() { assert_testmodeonly(deposition_rate_density_timestep[modelgridindex] == globals::timestep); @@ -2137,8 +2138,9 @@ auto get_nt_frac_heating(const int modelgridindex) -> float { return frac_heating; } -auto nt_ionization_upperion_probability(const int modelgridindex, const int element, const int lowerion, - const int upperion, const bool energyweighted) -> double { +__host__ __device__ auto nt_ionization_upperion_probability(const int modelgridindex, const int element, + const int lowerion, const int upperion, + const bool energyweighted) -> double { assert_always(upperion > lowerion); assert_always(upperion < get_nions(element)); assert_always(upperion <= nt_ionisation_maxupperion(element, lowerion)); @@ -2149,19 +2151,19 @@ auto nt_ionization_upperion_probability(const int modelgridindex, const int elem if (numaugerelec < NT_MAX_AUGER_ELECTRONS) { if (energyweighted) { return nt_solution[modelgridindex] - .ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + numaugerelec]; + .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]; } - return nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + numaugerelec]; + return nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]; } if (numaugerelec == NT_MAX_AUGER_ELECTRONS) { double prob_remaining = 1.; for (int a = 0; a < NT_MAX_AUGER_ELECTRONS; a++) { if (energyweighted) { prob_remaining -= - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a]; + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]; } else { prob_remaining -= - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a]; + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]; } } if (energyweighted) { @@ -2170,9 +2172,9 @@ auto nt_ionization_upperion_probability(const int modelgridindex, const int elem .ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + numaugerelec]) < 0.001); } else { - if (fabs(prob_remaining - nt_solution[modelgridindex] - .prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + numaugerelec]) >= - 0.001) { + if (fabs(prob_remaining - + nt_solution[modelgridindex] + .prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]) >= 0.001) { printout("Auger probabilities issue for cell %d Z=%02d ionstage %d to %d\n", modelgridindex, get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, upperion)); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { @@ -2191,7 +2193,7 @@ auto nt_ionization_upperion_probability(const int modelgridindex, const int elem return (upperion == lowerion + 1) ? 1.0 : 0.; } -auto nt_ionisation_maxupperion(const int element, const int lowerion) -> int { +__host__ __device__ auto nt_ionisation_maxupperion(const int element, const int lowerion) -> int { const int nions = get_nions(element); assert_always(lowerion < nions - 1); int maxupper = lowerion + 1; @@ -2200,15 +2202,13 @@ auto nt_ionisation_maxupperion(const int element, const int lowerion) -> int { maxupper += NT_MAX_AUGER_ELECTRONS; } - if (maxupper > nions - 1) { - maxupper = nions - 1; - } + maxupper = std::min(maxupper, nions - 1); return maxupper; } -auto nt_random_upperion(const int modelgridindex, const int element, const int lowerion, - const bool energyweighted) -> int { +__host__ __device__ auto nt_random_upperion(const int modelgridindex, const int element, const int lowerion, + const bool energyweighted) -> int { assert_testmodeonly(lowerion < get_nions(element) - 1); if (NT_SOLVE_SPENCERFANO && NT_MAX_AUGER_ELECTRONS > 0) { while (true) { @@ -2234,7 +2234,7 @@ auto nt_random_upperion(const int modelgridindex, const int element, const int l } } -auto nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion) -> double { +__host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion) -> double { assert_always(NT_ON); assert_always(grid::get_numassociatedcells(modelgridindex) > 0); @@ -2264,8 +2264,9 @@ auto nt_ionization_ratecoeff(const int modelgridindex, const int element, const return nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion); } -auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lowerlevel, - const int uptransindex, const double epsilon_trans, const int lineindex) -> double { +__host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, + const int lowerlevel, const int uptransindex, + const double epsilon_trans, const int lineindex) -> double { if constexpr (!NT_EXCITATION_ON) { return 0.; } @@ -2308,7 +2309,7 @@ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const return ratecoeffperdeposition * deposition_rate_density; } -void do_ntlepton_deposit(Packet &pkt) { +__host__ __device__ void do_ntlepton_deposit(Packet &pkt) { atomicadd(nt_energy_deposited, pkt.e_cmf); const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); @@ -2354,7 +2355,7 @@ void do_ntlepton_deposit(Packet &pkt) { // printout("NTLEPTON packet in cell %d selected ionization of Z=%d ionstage %d to %d\n", // modelgridindex, get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, // upperion)); - do_macroatom(pkt, {element, upperion, 0, -99}); + do_macroatom(pkt, {.element = element, .ion = upperion, .level = 0, .activatingline = -99}); return; } @@ -2385,7 +2386,7 @@ void do_ntlepton_deposit(Packet &pkt) { // printout("NTLEPTON packet selected in cell %d excitation of Z=%d ionstage %d level %d upperlevel %d\n", // modelgridindex, get_atomicnumber(element), get_ionstage(element, ion), lower, upper); - do_macroatom(pkt, {element, ion, upper, -99}); + do_macroatom(pkt, {.element = element, .ion = ion, .level = upper, .activatingline = -99}); return; } zrand -= frac_deposition_exc; @@ -2618,8 +2619,8 @@ void write_restart_data(FILE *gridsave_file) { for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { fprintf(gridsave_file, "%a %a ", - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a], - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a]); + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a], + nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]); } } diff --git a/packet.cc b/packet.cc index 78b512162..f313fc057 100644 --- a/packet.cc +++ b/packet.cc @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -41,7 +40,7 @@ static void place_pellet(const double e0, const int cellindex, const int pktnumb const double r_inner = grid::get_cellcoordmin(cellindex, 0); const double r_outer = grid::get_cellcoordmax(cellindex, 0); // use equal volume probability distribution to select radius - const double radius = pow(zrand * pow(r_inner, 3) + (1. - zrand) * pow(r_outer, 3), 1 / 3.); + const double radius = pow((zrand * pow(r_inner, 3)) + ((1. - zrand) * pow(r_outer, 3)), 1 / 3.); // assert_always(radius >= r_inner); // assert_always(radius <= r_outer); @@ -52,7 +51,7 @@ static void place_pellet(const double e0, const int cellindex, const int pktnumb const double rcyl_inner = grid::get_cellcoordmin(cellindex, 0); const double rcyl_outer = grid::get_cellcoordmax(cellindex, 0); // use equal area probability distribution to select radius - const double rcyl_rand = std::sqrt(zrand * std::pow(rcyl_inner, 2) + (1. - zrand) * std::pow(rcyl_outer, 2)); + const double rcyl_rand = std::sqrt((zrand * std::pow(rcyl_inner, 2)) + ((1. - zrand) * std::pow(rcyl_outer, 2))); const double theta_rand = rng_uniform() * 2 * PI; pkt.pos[0] = std::cos(theta_rand) * rcyl_rand; pkt.pos[1] = std::sin(theta_rand) * rcyl_rand; diff --git a/radfield.cc b/radfield.cc index 4353554d6..f7ed25c9c 100644 --- a/radfield.cc +++ b/radfield.cc @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "artisoptions.h" @@ -112,7 +111,7 @@ constexpr auto get_bin_nu_upper(int binindex) -> double { if (binindex == RADFIELDBINCOUNT - 1) { return nu_upper_superbin; } - return nu_lower_first_initial + (binindex + 1) * radfieldbins_delta_nu; + return nu_lower_first_initial + ((binindex + 1) * radfieldbins_delta_nu); } constexpr auto get_bin_nu_lower(int binindex) -> double { @@ -204,7 +203,7 @@ auto get_bin_J(int modelgridindex, int binindex) -> double assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); assert_testmodeonly(binindex < RADFIELDBINCOUNT); - return radfieldbins[nonemptymgi * RADFIELDBINCOUNT + binindex].J_raw * J_normfactor[nonemptymgi]; + return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].J_raw * J_normfactor[nonemptymgi]; } auto get_bin_nuJ(int modelgridindex, int binindex) -> double { @@ -213,7 +212,7 @@ auto get_bin_nuJ(int modelgridindex, int binindex) -> double { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); assert_testmodeonly(binindex < RADFIELDBINCOUNT); - return radfieldbins[nonemptymgi * RADFIELDBINCOUNT + binindex].nuJ_raw * J_normfactor[nonemptymgi]; + return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].nuJ_raw * J_normfactor[nonemptymgi]; } auto get_bin_nu_bar(int modelgridindex, int binindex) -> double @@ -226,17 +225,30 @@ auto get_bin_nu_bar(int modelgridindex, int binindex) -> double auto get_bin_contribcount(int modelgridindex, int binindex) -> int { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - return radfieldbins[nonemptymgi * RADFIELDBINCOUNT + binindex].contribcount; + return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].contribcount; } auto get_bin_W(int modelgridindex, int binindex) -> float { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - return radfieldbin_solutions[nonemptymgi * RADFIELDBINCOUNT + binindex].W; + return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].W; } auto get_bin_T_R(int modelgridindex, int binindex) -> float { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - return radfieldbin_solutions[nonemptymgi * RADFIELDBINCOUNT + binindex].T_R; + return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].T_R; +} + +constexpr auto gsl_integrand_planck(const double nu, void *voidparas) -> double { + const auto *paras = static_cast(voidparas); + const auto T_R = paras->T_R; + + double integrand = TWOHOVERCLIGHTSQUARED * std::pow(nu, 3) / (std::expm1(HOVERKB * nu / T_R)); + + if (paras->times_nu) { + integrand *= nu; + } + + return integrand; } } // anonymous namespace @@ -410,7 +422,7 @@ void init(int my_rank, int ndo_nonempty) if (globals::rank_in_node == 0) { for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; radfieldbin_solutions[mgibinindex].W = -1.; radfieldbin_solutions[mgibinindex].T_R = -1.; } @@ -602,7 +614,7 @@ void zero_estimators() assert_always(radfieldbins != nullptr); for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; radfieldbins[mgibinindex].J_raw = 0.; radfieldbins[mgibinindex].nuJ_raw = 0.; radfieldbins[mgibinindex].contribcount = 0; @@ -634,26 +646,27 @@ static void update_bfestimators(const int nonemptymgi, const double distance_e_c // so the nu condition on this nu_cmf can truncate the list further compared to what was used in the calculation // of phixslist.gamma_contr - const int bfestimend = std::upper_bound(globals::bfestim_nu_edge.data(), - globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf) - - globals::bfestim_nu_edge.data(); + const auto bfestimend = std::upper_bound(globals::bfestim_nu_edge.data(), + globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf) - + globals::bfestim_nu_edge.data(); - const int bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, - globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, - [](const double nu_edge, const double nu_cmf) { - return nu_edge * last_phixs_nuovernuedge < nu_cmf; - }) - - globals::bfestim_nu_edge.data(); + const auto bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, + globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, + [](const double nu_edge, const double nu_cmf) { + return nu_edge * last_phixs_nuovernuedge < nu_cmf; + }) - + globals::bfestim_nu_edge.data(); const auto bfestimcount = globals::bfestimcount; - for (int bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { - atomicadd(bfrate_raw[nonemptymgi * bfestimcount + bfestimindex], + for (auto bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { + atomicadd(bfrate_raw[(nonemptymgi * bfestimcount) + bfestimindex], phixslist.gamma_contr[bfestimindex] * distance_e_cmf_over_nu); } } -void update_estimators(const int nonemptymgi, const double distance_e_cmf, const double nu_cmf, - const double doppler_nucmf_on_nurf, const Phixslist &phixslist, const bool thickcell) { +__host__ __device__ void update_estimators(const int nonemptymgi, const double distance_e_cmf, const double nu_cmf, + const double doppler_nucmf_on_nurf, const Phixslist &phixslist, + const bool thickcell) { if (distance_e_cmf == 0) { return; } @@ -673,7 +686,7 @@ void update_estimators(const int nonemptymgi, const double distance_e_cmf, const const int binindex = select_bin(nu_cmf); if (binindex >= 0) { - const ptrdiff_t mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const ptrdiff_t mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; atomicadd(radfieldbins[mgibinindex].J_raw, distance_e_cmf); atomicadd(radfieldbins[mgibinindex].nuJ_raw, distance_e_cmf * nu_cmf); atomicadd(radfieldbins[mgibinindex].contribcount, 1); @@ -681,7 +694,7 @@ void update_estimators(const int nonemptymgi, const double distance_e_cmf, const } } -void update_lineestimator(const int modelgridindex, const int lineindex, const double increment) { +__host__ __device__ void update_lineestimator(const int modelgridindex, const int lineindex, const double increment) { if constexpr (!DETAILED_LINE_ESTIMATORS_ON) { return; } @@ -693,7 +706,7 @@ void update_lineestimator(const int modelgridindex, const int lineindex, const d } } -auto radfield(double nu, int modelgridindex) -> double +__host__ __device__ auto radfield(double nu, int modelgridindex) -> double // returns mean intensity J_nu [ergs/s/sr/cm2/Hz] { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { @@ -701,7 +714,7 @@ auto radfield(double nu, int modelgridindex) -> double const int binindex = select_bin(nu); if (binindex >= 0) { const auto &bin = - radfieldbin_solutions[grid::get_modelcell_nonemptymgi(modelgridindex) * RADFIELDBINCOUNT + binindex]; + radfieldbin_solutions[(grid::get_modelcell_nonemptymgi(modelgridindex) * RADFIELDBINCOUNT) + binindex]; if (bin.W >= 0.) { const double J_nu = dbb(nu, bin.T_R, bin.W); return J_nu; @@ -717,19 +730,6 @@ auto radfield(double nu, int modelgridindex) -> double return J_nu_fullspec; } -constexpr auto gsl_integrand_planck(const double nu, void *voidparas) -> double { - const auto *paras = static_cast(voidparas); - const auto T_R = paras->T_R; - - double integrand = TWOHOVERCLIGHTSQUARED * std::pow(nu, 3) / (std::expm1(HOVERKB * nu / T_R)); - - if (paras->times_nu) { - integrand *= nu; - } - - return integrand; -} - static auto planck_integral(double T_R, double nu_lower, double nu_upper, const bool times_nu) -> double { double integral = 0.; @@ -1018,7 +1018,7 @@ void fit_parameters(int modelgridindex, int timestep) W_bin = 0.; } - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; radfieldbin_solutions[mgibinindex].T_R = T_R_bin; radfieldbin_solutions[mgibinindex].W = W_bin; } @@ -1051,7 +1051,7 @@ void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, const double estimator_normfactor = 1 / deltaV / deltat / globals::nprocs; assert_always(nonemptymgi >= 0); for (int i = 0; i < globals::bfestimcount; i++) { - const auto mgibfindex = nonemptymgi * globals::bfestimcount + i; + const auto mgibfindex = (nonemptymgi * globals::bfestimcount) + i; prev_bfrate_normed[mgibfindex] = bfrate_raw[mgibfindex] * (estimator_normfactor / H); } } @@ -1085,7 +1085,7 @@ auto get_bfrate_estimator(const int element, const int lowerion, const int lower const auto bfestimindex = globals::allcont[allcontindex].bfestimindex; if (bfestimindex >= 0) { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - return prev_bfrate_normed[nonemptymgi * globals::bfestimcount + bfestimindex]; + return prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + bfestimindex]; } } } @@ -1255,7 +1255,7 @@ void write_restart_data(FILE *gridsave_file) { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); fprintf(gridsave_file, "%d\n", modelgridindex); for (int i = 0; i < bfestimcount; i++) { - fprintf(gridsave_file, "%a ", prev_bfrate_normed[nonemptymgi * bfestimcount + i]); + fprintf(gridsave_file, "%a ", prev_bfrate_normed[(nonemptymgi * bfestimcount) + i]); } } } @@ -1277,7 +1277,7 @@ void write_restart_data(FILE *gridsave_file) { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; fprintf(gridsave_file, "%la %la %a %a %d\n", radfieldbins[mgibinindex].J_raw, radfieldbins[mgibinindex].nuJ_raw, radfieldbin_solutions[mgibinindex].W, radfieldbin_solutions[mgibinindex].T_R, radfieldbins[mgibinindex].contribcount); @@ -1364,7 +1364,7 @@ void read_restart_data(FILE *gridsave_file) { assert_always(fscanf(gridsave_file, "%a ", &bfrate_normed) == 1); if (globals::rank_in_node == 0) { - prev_bfrate_normed[nonemptymgi * globals::bfestimcount + i] = bfrate_normed; + prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + i] = bfrate_normed; } } } @@ -1398,7 +1398,7 @@ void read_restart_data(FILE *gridsave_file) { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; float W = 0; float T_R = 0; assert_always(fscanf(gridsave_file, "%la %la %a %a %d\n", &radfieldbins[mgibinindex].J_raw, diff --git a/ratecoeff.cc b/ratecoeff.cc index 7958de91c..2753274c3 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -4,7 +4,9 @@ #include #endif +#if !USE_SIMPSON_INTEGRATOR #include +#endif #include #include @@ -547,7 +549,8 @@ static void precalculate_rate_coefficient_integrals() { } } -auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel, float T_e) -> double { +__host__ __device__ auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel, + float T_e) -> double { const int phixstargetindex = get_phixtargetindex(element, lowerion, lower, upperionlevel); const double E_threshold = get_phixs_threshold(element, lowerion, lower, phixstargetindex); const double nu_threshold = ONEOVERH * E_threshold; @@ -566,7 +569,9 @@ auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel const double deltanu = (nu_max_phixs - nu_threshold) / npieces; double error{NAN}; +#if !USE_SIMPSON_INTEGRATOR gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); +#endif double total_alpha_sp = 0.; integrator(intparas, nu_threshold, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, @@ -578,7 +583,7 @@ auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel int i = 1; for (i = 1; i < npieces; i++) { alpha_sp_old = alpha_sp; - const double xlow = nu_threshold + i * deltanu; + const double xlow = nu_threshold + (i * deltanu); // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field integrator(intparas, xlow, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, @@ -589,18 +594,21 @@ auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel } } +#if !USE_SIMPSON_INTEGRATOR gsl_set_error_handler(previous_handler); +#endif const double nuoffset = (alpha_sp != alpha_sp_old) ? (total_alpha_sp * zrand - alpha_sp_old) / (alpha_sp - alpha_sp_old) * deltanu : 0.; - const double nu_lower = nu_threshold + (i - 1) * deltanu + nuoffset; + const double nu_lower = nu_threshold + ((i - 1) * deltanu) + nuoffset; assert_testmodeonly(std::isfinite(nu_lower)); return nu_lower; } -auto get_spontrecombcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double +__host__ __device__ auto get_spontrecombcoeff(int element, int ion, int level, int phixstargetindex, + float T_e) -> double /// Returns the rate coefficient for spontaneous recombination. { double Alpha_sp{NAN}; @@ -782,8 +790,8 @@ static void read_recombrate_file() while (fscanf(recombrate_file, "%d %d %d\n", &atomicnumber, &upperionstage, &tablerows) > 0) { // printout("%d %d %d\n", atomicnumber, upperionstage, tablerows); - RRCRow T_highestbelow = {0, 0, 0}; - RRCRow T_lowestabove = {0, 0, 0}; + RRCRow T_highestbelow = {.log_Te = 0, .rrc_low_n = 0, .rrc_total = 0}; + RRCRow T_lowestabove = {.log_Te = 0, .rrc_low_n = 0, .rrc_total = 0}; T_highestbelow.log_Te = -1; T_lowestabove.log_Te = -1; for (int i = 0; i < tablerows; i++) { @@ -812,8 +820,8 @@ static void read_recombrate_file() const int nlevels = get_ionisinglevels(element, ion - 1); const double x = (log_Te_estimate - T_highestbelow.log_Te) / (T_lowestabove.log_Te - T_highestbelow.log_Te); - const double input_rrc_low_n = x * T_highestbelow.rrc_low_n + (1 - x) * T_lowestabove.rrc_low_n; - const double input_rrc_total = x * T_highestbelow.rrc_total + (1 - x) * T_lowestabove.rrc_total; + const double input_rrc_low_n = (x * T_highestbelow.rrc_low_n) + ((1 - x) * T_lowestabove.rrc_low_n); + const double input_rrc_total = (x * T_highestbelow.rrc_total) + ((1 - x) * T_lowestabove.rrc_total); const bool assume_lte = true; const bool printdebug = false; @@ -854,7 +862,7 @@ static void read_recombrate_file() printout(" rrc(superlevel): %10.3e\n", rrc_superlevel); if (rrc_superlevel > 0) { - const double phixs_multiplier_superlevel = 1.0 + (input_rrc_total - rrc) / rrc_superlevel; + const double phixs_multiplier_superlevel = 1.0 + ((input_rrc_total - rrc) / rrc_superlevel); printout(" scaling phixs of levels in the superlevel by %.3f\n", phixs_multiplier_superlevel); assert_always(phixs_multiplier_superlevel >= 0); @@ -984,7 +992,7 @@ auto interpolate_corrphotoioncoeff(int element, int ion, int level, int phixstar const double f_upper = corrphotoioncoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; const double f_lower = corrphotoioncoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - return (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower)); + return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower))); } return corrphotoioncoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; } @@ -1096,7 +1104,8 @@ auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetin return stimrecombcoeff; } -auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double { +__host__ __device__ auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, + float T_e) -> double { const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); if (lowerindex < TABLESIZE - 1) { const int upperindex = lowerindex + 1; @@ -1106,7 +1115,7 @@ auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, f const double f_upper = bfcooling_coeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; const double f_lower = bfcooling_coeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - return (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower)); + return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower))); } return bfcooling_coeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; } @@ -1122,7 +1131,7 @@ static auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *c const double corrfactor = 1.; #else const float T_e = params->T_e; - double corrfactor = 1. - params->departure_ratio * exp(-HOVERKB * nu / T_e); + double corrfactor = 1. - (params->departure_ratio * exp(-HOVERKB * nu / T_e)); if (corrfactor < 0) { corrfactor = 0.; } @@ -1196,7 +1205,8 @@ static auto calculate_corrphotoioncoeff_integral(int element, int ion, int level return gammacorr; } -auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, int modelgridindex) -> double +__host__ __device__ auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, + int modelgridindex) -> double /// Returns the photoionisation rate coefficient (corrected for stimulated emission) { /// The correction factor for stimulated emission in gammacorr is set to its @@ -1228,7 +1238,7 @@ auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex const int index_in_groundlevelcontestimator = globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; if (index_in_groundlevelcontestimator >= 0) { - gammacorr *= globals::corrphotoionrenorm[nonemptymgi * globals::nbfcontinua_ground + + gammacorr *= globals::corrphotoionrenorm[(nonemptymgi * globals::nbfcontinua_ground) + index_in_groundlevelcontestimator]; } } diff --git a/rpkt.cc b/rpkt.cc index 2db0274a2..4da70ef21 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -30,6 +30,12 @@ #include "vectors.h" #include "vpkt.h" +#ifdef GPU_ON +#define THREADLOCALONHOST +#else +#define THREADLOCALONHOST thread_local +#endif + namespace { constexpr float expopac_lambdamin = 534.5; @@ -138,7 +144,7 @@ static auto get_nu_cmf_abort(const std::array pos, const std::array abort_pos{pos[0] + (dir[0] * half_abort_dist) + (dir[0] * half_abort_dist), pos[1] + (dir[1] * half_abort_dist) + (dir[1] * half_abort_dist), @@ -152,12 +158,12 @@ static auto get_nu_cmf_abort(const std::array pos, const std::array double { - const auto lambda_lower = expopac_lambdamin + binindex * expopac_deltalambda; + const auto lambda_lower = expopac_lambdamin + (binindex * expopac_deltalambda); return 1e8 * CLIGHT / lambda_lower; } static constexpr auto get_expopac_bin_nu_lower(const size_t binindex) -> double { - const auto lambda_upper = expopac_lambdamin + (binindex + 1) * expopac_deltalambda; + const auto lambda_upper = expopac_lambdamin + ((binindex + 1) * expopac_deltalambda); return 1e8 * CLIGHT / lambda_upper; } @@ -275,7 +281,7 @@ static auto get_event(const int modelgridindex, } else { /// continuum process occurs before reaching the line - return {dist + (tau_rnd - tau) / chi_cont, next_trans - 1, false}; + return {dist + ((tau_rnd - tau) / chi_cont), next_trans - 1, false}; } } else [[unlikely]] { /// no line interaction possible - check whether continuum process occurs in cell @@ -288,7 +294,7 @@ static auto get_event(const int modelgridindex, } /// continuum process occurs at edist - return {dist + (tau_rnd - tau) / chi_cont, globals::nlines + 1, false}; + return {dist + ((tau_rnd - tau) / chi_cont), globals::nlines + 1, false}; } } @@ -327,7 +333,7 @@ static auto get_event_expansion_opacity( // const auto chi_cont = 0.; double chi_bb_expansionopac = 0.; if (binindex >= 0) { - const auto kappa = expansionopacities[nonemptymgi * expopac_nbins + binindex]; + const auto kappa = expansionopacities[(nonemptymgi * expopac_nbins) + binindex]; chi_bb_expansionopac = kappa * grid::get_rho(modelgridindex) * doppler; } @@ -336,7 +342,7 @@ static auto get_event_expansion_opacity( if (chi_tot * binedgedist > tau_rnd - tau) { // interaction occurs if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { - const auto edist = std::max(dist + (tau_rnd - tau) / chi_tot, 0.); + const auto edist = std::max(dist + ((tau_rnd - tau) / chi_tot), 0.); const bool event_is_boundbound = rng_uniform() <= chi_bb_expansionopac / chi_tot; return {edist, next_trans, event_is_boundbound}; } else { @@ -473,8 +479,8 @@ static void electron_scatter_rpkt(Packet &pkt) { const double cos2i1 = cos(2 * i1); const double sin2i1 = sin(2 * i1); - const double Qold = Qi * cos2i1 - Ui * sin2i1; - const double Uold = Qi * sin2i1 + Ui * cos2i1; + const double Qold = (Qi * cos2i1) - (Ui * sin2i1); + const double Uold = (Qi * sin2i1) + (Ui * cos2i1); // Scattering @@ -495,8 +501,8 @@ static void electron_scatter_rpkt(Packet &pkt) { const double cos2i2 = cos(2 * i2); const double sin2i2 = sin(2 * i2); - double Q = Qnew * cos2i2 + Unew * sin2i2; - double U = -Qnew * sin2i2 + Unew * cos2i2; + double Q = (Qnew * cos2i2) + (Unew * sin2i2); + double U = (-Qnew * sin2i2) + (Unew * cos2i2); // Transform Stokes Parameters from the CMF to the RF // Update rest frame direction, frequency and energy @@ -544,7 +550,9 @@ static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoe stats::increment(stats::COUNTER_ESCOUNTER); // generate a virtual packet - vpkt_call_estimators(pkt, TYPE_RPKT); + if constexpr (VPKT_ON) { + vpkt_call_estimators(pkt, TYPE_RPKT); + } // pkt.nu_cmf = 3.7474058e+14; electron_scatter_rpkt(pkt); @@ -608,7 +616,7 @@ static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoe pkt.type = TYPE_MA; const int upper = get_phixsupperlevel(element, ion, level, phixstargetindex); - do_macroatom(pkt, {element, ion + 1, upper, -99}); + do_macroatom(pkt, {.element = element, .ion = ion + 1, .level = upper, .activatingline = -99}); } /// or to the thermal pool else { @@ -733,7 +741,7 @@ static void update_estimators(const double e_cmf, const double nu_cmf, const dou // because groundcont is sorted by nu_edge descending, nu < nu_edge for all remaining items return; } - const int ionestimindex = nonemptymgi * globals::nbfcontinua_ground + i; + const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; if constexpr (USE_LUT_PHOTOION) { atomicadd(globals::gammaestimator[ionestimindex], @@ -758,19 +766,21 @@ static auto do_rpkt_step(Packet &pkt, const double t2) -> bool MacroAtomState pktmastate{}; - // TODO: these should be re-used to avoid allocations during packet prop - // but make sure r10_d2.6_Z in classic mode is not affected! - static thread_local Phixslist phixslist{ - .groundcont_gamma_contr = std::vector(globals::nbfcontinua_ground, 0.), - .chi_bf_sum = std::vector(globals::nbfcontinua, 0.), - .gamma_contr = std::vector(globals::bfestimcount, 0.), + THREADLOCALONHOST auto groundcont_gamma_contr = std::make_unique(globals::nbfcontinua_ground); + THREADLOCALONHOST auto chi_bf_sum = std::make_unique(globals::nbfcontinua); + THREADLOCALONHOST auto gamma_contr = std::make_unique(globals::bfestimcount); + + THREADLOCALONHOST Phixslist phixslist{ + .groundcont_gamma_contr = std::span(groundcont_gamma_contr.get(), globals::nbfcontinua_ground), + .chi_bf_sum = std::span(chi_bf_sum.get(), globals::nbfcontinua), + .gamma_contr = std::span(gamma_contr.get(), globals::bfestimcount), .allcontend = 1, .allcontbegin = 0, .bfestimend = 1, .bfestimbegin = 0, }; - static thread_local Rpkt_continuum_absorptioncoeffs chi_rpkt_cont{ + THREADLOCALONHOST Rpkt_continuum_absorptioncoeffs chi_rpkt_cont{ .nu = NAN, .total = NAN, .ffescat = NAN, @@ -944,7 +954,7 @@ static auto do_rpkt_step(Packet &pkt, const double t2) -> bool std::abort(); } -void do_rpkt(Packet &pkt, const double t2) { +__host__ __device__ void do_rpkt(Packet &pkt, const double t2) { while (do_rpkt_step(pkt, t2)) { { } @@ -1167,7 +1177,7 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff assert_testmodeonly(modelgridindex != grid::get_npts_model()); assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); if ((modelgridindex == chi_rpkt_cont.modelgridindex) && (globals::timestep == chi_rpkt_cont.timestep) && - (fabs(chi_rpkt_cont.nu / nu_cmf - 1.0) < 1e-4)) { + (fabs((chi_rpkt_cont.nu / nu_cmf) - 1.0) < 1e-4)) { // calculated values are a match already return; } @@ -1281,7 +1291,7 @@ void calculate_expansion_opacities(const int modelgridindex) { const float bin_kappa_bb = 1. / (CLIGHT * t_mid * rho) * bin_linesum; assert_always(std::isfinite(bin_kappa_bb)); - expansionopacities[nonemptymgi * expopac_nbins + binindex] = bin_kappa_bb; + expansionopacities[(nonemptymgi * expopac_nbins) + binindex] = bin_kappa_bb; if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { // thread_local Rpkt_continuum_absorptioncoeffs chi_rpkt_cont {}; @@ -1294,7 +1304,7 @@ void calculate_expansion_opacities(const int modelgridindex) { kappa_planck_cumulative += kappa_planck * delta_nu; - expansionopacity_planck_cumulative[nonemptymgi * expopac_nbins + binindex] = kappa_planck_cumulative; + expansionopacity_planck_cumulative[(nonemptymgi * expopac_nbins) + binindex] = kappa_planck_cumulative; } } printout("took %ld seconds\n", std::time(nullptr) - sys_time_start_calc); diff --git a/rpkt.h b/rpkt.h index 0d03a9a44..7ab646693 100644 --- a/rpkt.h +++ b/rpkt.h @@ -3,12 +3,13 @@ #define RPKT_H #include +#include #include struct Phixslist { - std::vector groundcont_gamma_contr; // for either USE_LUT_PHOTOION = true or !USE_LUT_BFHEATING = false - std::vector chi_bf_sum; - std::vector gamma_contr; // needed for DETAILED_BF_ESTIMATORS_ON + std::span groundcont_gamma_contr; // for either USE_LUT_PHOTOION = true or !USE_LUT_BFHEATING = false + std::span chi_bf_sum; + std::span gamma_contr; // needed for DETAILED_BF_ESTIMATORS_ON int allcontend{-1}; int allcontbegin{0}; int bfestimend{-1}; diff --git a/sn3d.cc b/sn3d.cc index 5d05f189e..5d041d074 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -27,7 +27,9 @@ #include #include #include +#ifndef GPU_ON #include +#endif #include #ifdef STDPAR_ON #include @@ -56,7 +58,9 @@ #include "version.h" #include "vpkt.h" +#ifndef GPU_ON std::mt19937 stdrng{std::random_device{}()}; +#endif std::ofstream output_file; diff --git a/sn3d.h b/sn3d.h index 3ac258424..639a98f74 100644 --- a/sn3d.h +++ b/sn3d.h @@ -2,12 +2,21 @@ #ifndef SN3D_H #define SN3D_H +#ifndef __host__ +#define __host__ +#endif +#ifndef __device__ +#define __device__ +#endif + #include #include #include #include #include +#include +#include #include #include #include @@ -40,18 +49,21 @@ #include #include #include -#include #include #include #include +#ifndef GPU_ON #include +#endif #include "constants.h" constexpr int cellcacheslotid = 0; inline bool use_cellcache = false; +#ifndef GPU_ON extern std::mt19937 stdrng; +#endif extern std::ofstream output_file; @@ -73,14 +85,18 @@ inline thread_local auto gslworkspace = #ifdef _OPENMP -#ifdef GPU_ON -#pragma omp requires unified_shared_memory -#else +#ifndef GPU_ON #pragma omp threadprivate(stdrng, output_file, outputlinebuf, outputstartofline, timebuf) #endif #endif +#ifdef __NVCOMPILER_CUDA_ARCH__ +#define printout(...) printf(__VA_ARGS__) + +#define __artis_assert(e) assert(e) + +#else inline void print_line_start() { if (outputstartofline) { const time_t now_time = time(nullptr); @@ -113,6 +129,7 @@ inline void print_line_start() { } \ assert(pass); \ } +#endif #define assert_always(e) __artis_assert(e) @@ -226,7 +243,11 @@ inline void gsl_error_handler_printout(const char *reason, const char *file, int inline auto rng_uniform() -> float { while (true) { +#ifndef GPU_ON const auto zrand = std::generate_canonical::digits>(stdrng); +#else + const auto zrand = 0.5; +#endif if (zrand != 1.) { return zrand; } diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index a79a978b7..cec43e740 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -52,8 +52,8 @@ void printout_tracemission_stats() { // mode is 0 for emission and 1 for absorption for (int mode = 0; mode < 2; mode++) { if (mode == 0) { - std::sort(traceemissionabsorption.begin(), traceemissionabsorption.end(), - [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); + std::ranges::sort(traceemissionabsorption, + [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); printout("lambda [%5.1f, %5.1f] nu %g %g\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_nulower, traceemissabs_nuupper); @@ -61,8 +61,8 @@ void printout_tracemission_stats() { traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceemission_totalenergy); } else { - std::sort(traceemissionabsorption.begin(), traceemissionabsorption.end(), - [](const auto &a, const auto &b) { return a.energyabsorbed > b.energyabsorbed; }); + std::ranges::sort(traceemissionabsorption, + [](const auto &a, const auto &b) { return a.energyabsorbed > b.energyabsorbed; }); printout("Top line absorption contributions in the range lambda [%5.1f, %5.1f] time [%5.1fd, %5.1fd] (%g erg)\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceabsorption_totalenergy); @@ -136,7 +136,7 @@ void printout_tracemission_stats() { auto get_proccount() -> int // number of different emission processes (bf and bb for each ion, and free-free) { - return 2 * get_nelements() * get_max_nions() + 1; + return (2 * get_nelements() * get_max_nions()) + 1; } auto columnindex_from_emissiontype(const int et) -> int { @@ -144,7 +144,7 @@ auto columnindex_from_emissiontype(const int et) -> int { /// bb-emission const int element = globals::linelist[et].elementindex; const int ion = globals::linelist[et].ionindex; - return element * get_max_nions() + ion; + return (element * get_max_nions()) + ion; } if (et == EMTYPE_FREEFREE) { /// ff-emission @@ -171,7 +171,7 @@ auto columnindex_from_emissiontype(const int et) -> int { assert_always(get_emtype_continuum(element, ion, level, upperionlevel) == et); - return get_nelements() * get_max_nions() + element * get_max_nions() + ion; + return (get_nelements() * get_max_nions()) + (element * get_max_nions()) + ion; } void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, const Spectra *stokes_i, @@ -214,22 +214,22 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co const int truenproc = columnindex_from_emissiontype(pkt.trueemissiontype); assert_always(truenproc < proccount); if (truenproc >= 0) { - spectra.timesteps[nt].trueemission[nnu * proccount + truenproc] += deltaE; + spectra.timesteps[nt].trueemission[(nnu * proccount) + truenproc] += deltaE; } const int nproc = columnindex_from_emissiontype(pkt.emissiontype); assert_always(nproc < proccount); if (nproc >= 0) { // -1 means not set - spectra.timesteps[nt].emission[nnu * proccount + nproc] += deltaE; + spectra.timesteps[nt].emission[(nnu * proccount) + nproc] += deltaE; if (stokes_i != nullptr && stokes_i->do_emission_res) { - stokes_i->timesteps[nt].emission[nnu * proccount + nproc] += pkt.stokes[0] * deltaE; + stokes_i->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[0] * deltaE; } if (stokes_q != nullptr && stokes_q->do_emission_res) { - stokes_q->timesteps[nt].emission[nnu * proccount + nproc] += pkt.stokes[1] * deltaE; + stokes_q->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[1] * deltaE; } if (stokes_u != nullptr && stokes_u->do_emission_res) { - stokes_u->timesteps[nt].emission[nnu * proccount + nproc] += pkt.stokes[2] * deltaE; + stokes_u->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[2] * deltaE; } } @@ -260,18 +260,19 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co /// bb-emission const int element = globals::linelist[at].elementindex; const int ion = globals::linelist[at].ionindex; - spectra.timesteps[nt].absorption[nnu_abs * ioncount + element * get_max_nions() + ion] += deltaE_absorption; + spectra.timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += + deltaE_absorption; if (stokes_i != nullptr && stokes_i->do_emission_res) { - stokes_i->timesteps[nt].absorption[nnu_abs * ioncount + element * get_max_nions() + ion] += + stokes_i->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += pkt.stokes[0] * deltaE_absorption; } if (stokes_q != nullptr && stokes_q->do_emission_res) { - stokes_q->timesteps[nt].absorption[nnu_abs * ioncount + element * get_max_nions() + ion] += + stokes_q->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += pkt.stokes[1] * deltaE_absorption; } if (stokes_u != nullptr && stokes_u->do_emission_res) { - stokes_u->timesteps[nt].absorption[nnu_abs * ioncount + element * get_max_nions() + ion] += + stokes_u->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += pkt.stokes[2] * deltaE_absorption; } @@ -358,17 +359,17 @@ void write_spectrum(const std::string &spec_filename, const std::string &emissio fprintf(spec_file, "%g ", spectra.timesteps[nts].flux[nnu]); if (do_emission_res) { for (int i = 0; i < proccount; i++) { - fprintf(emission_file, "%g ", spectra.timesteps[nts].emission[nnu * proccount + i]); + fprintf(emission_file, "%g ", spectra.timesteps[nts].emission[(nnu * proccount) + i]); } fprintf(emission_file, "\n"); for (int i = 0; i < proccount; i++) { - fprintf(trueemission_file, "%g ", spectra.timesteps[nts].trueemission[nnu * proccount + i]); + fprintf(trueemission_file, "%g ", spectra.timesteps[nts].trueemission[(nnu * proccount) + i]); } fprintf(trueemission_file, "\n"); for (int i = 0; i < ioncount; i++) { - fprintf(absorption_file, "%g ", spectra.timesteps[nts].absorption[nnu * ioncount + i]); + fprintf(absorption_file, "%g ", spectra.timesteps[nts].absorption[(nnu * ioncount) + i]); } fprintf(absorption_file, "\n"); } @@ -424,12 +425,12 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss if (do_emission_res) { for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_i->timesteps[p].emission[m * proccount + i]); + fprintf(emissionpol_file, "%g ", stokes_i->timesteps[p].emission[(m * proccount) + i]); } fprintf(emissionpol_file, "\n"); for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_i->timesteps[p].absorption[m * ioncount + i]); + fprintf(absorptionpol_file, "%g ", stokes_i->timesteps[p].absorption[(m * ioncount) + i]); } fprintf(absorptionpol_file, "\n"); } @@ -441,12 +442,12 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss if (do_emission_res) { for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_q->timesteps[p].emission[m * proccount + i]); + fprintf(emissionpol_file, "%g ", stokes_q->timesteps[p].emission[(m * proccount) + i]); } fprintf(emissionpol_file, "\n"); for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_q->timesteps[p].absorption[m * ioncount + i]); + fprintf(absorptionpol_file, "%g ", stokes_q->timesteps[p].absorption[(m * ioncount) + i]); } fprintf(absorptionpol_file, "\n"); } @@ -458,12 +459,12 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss if (do_emission_res) { for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_u->timesteps[p].emission[m * proccount + i]); + fprintf(emissionpol_file, "%g ", stokes_u->timesteps[p].emission[(m * proccount) + i]); } fprintf(emissionpol_file, "\n"); for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_u->timesteps[p].absorption[m * ioncount + i]); + fprintf(absorptionpol_file, "%g ", stokes_u->timesteps[p].absorption[(m * ioncount) + i]); } fprintf(absorptionpol_file, "\n"); } diff --git a/stats.cc b/stats.cc index 78a8504d6..6ecc47b4f 100644 --- a/stats.cc +++ b/stats.cc @@ -45,9 +45,9 @@ void increment_ion_stats(const int modelgridindex, const int element, const int assert_testmodeonly(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - atomicadd( - ionstats[modelgridindex * get_includedions() * ION_STAT_COUNT + uniqueionindex * ION_STAT_COUNT + ionstattype], - increment); + atomicadd(ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + + ionstattype], + increment); } void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridindex, const int element, const int ion) { @@ -81,7 +81,7 @@ void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridin { stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE, n_photons_absorbed); - const int bfindex = -1 * et - 1; + const int bfindex = (-1 * et) - 1; assert_always(bfindex >= 0); assert_always(bfindex <= globals::nbfcontinua); const int emissionelement = globals::bflist[bfindex].elementindex; @@ -117,7 +117,8 @@ auto get_ion_stats(const int modelgridindex, const int element, const int ion, assert_always(ion < get_nions(element)); assert_always(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - return ionstats[modelgridindex * get_includedions() * ION_STAT_COUNT + uniqueionindex * ION_STAT_COUNT + ionstattype]; + return ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + + ionstattype]; } void set_ion_stats(const int modelgridindex, const int element, const int ion, enum ionstattypes ionstattype, @@ -125,7 +126,7 @@ void set_ion_stats(const int modelgridindex, const int element, const int ion, e assert_always(ion < get_nions(element)); assert_always(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - ionstats[modelgridindex * get_includedions() * ION_STAT_COUNT + uniqueionindex * ION_STAT_COUNT + ionstattype] = + ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + ionstattype] = newvalue; } @@ -159,7 +160,7 @@ void normalise_ion_estimators(const int mgi, const double deltat, const double d } } -void increment(enum eventcounters i) { +__host__ __device__ void increment(enum eventcounters i) { assert_testmodeonly(i >= 0); assert_testmodeonly(i < COUNTER_COUNT); atomicadd(eventstats[i], static_cast(1)); diff --git a/thermalbalance.cc b/thermalbalance.cc index bb248dea7..1d5ae6be2 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -166,7 +167,7 @@ void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatin const int index_in_groundlevelcontestimator = globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; if (index_in_groundlevelcontestimator >= 0) { - bfheatingcoeff *= globals::bfheatingestimator[nonemptymgi * globals::nbfcontinua_ground + + bfheatingcoeff *= globals::bfheatingestimator[(nonemptymgi * globals::nbfcontinua_ground) + index_in_groundlevelcontestimator]; } } @@ -375,15 +376,11 @@ void call_T_e_finder(const int modelgridindex, const int timestep, const double if (T_e > 2 * T_e_old) { T_e = 2 * T_e_old; printout("use T_e damping in cell %d\n", modelgridindex); - if (T_e > MAXTEMP) { - T_e = MAXTEMP; - } + T_e = std::min(T_e, MAXTEMP); } else if (T_e < 0.5 * T_e_old) { T_e = 0.5 * T_e_old; printout("use T_e damping in cell %d\n", modelgridindex); - if (T_e < MINTEMP) { - T_e = MINTEMP; - } + T_e = std::max(T_e, MINTEMP); } grid::set_Te(modelgridindex, T_e); diff --git a/update_grid.cc b/update_grid.cc index dd95df759..317c1108b 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -368,7 +368,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti const double alpha_r_mc = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_MACROATOM) + get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_KPKT); const double alpha_r_mc_abs = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_ABSORBED); - fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - alpha_r_mc_abs / alpha_r_mc); + fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - (alpha_r_mc_abs / alpha_r_mc)); } fprintf(estimators_file, "\n"); @@ -379,7 +379,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti for (int ion = 0; ion < nions; ion++) { const double bb_emitted = get_ion_stats(mgi, element, ion, stats::ION_BOUNDBOUND_MACROATOM); const double bb_abs = get_ion_stats(mgi, element, ion, stats::ION_BOUNDBOUND_ABSORBED); - fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - bb_abs / bb_emitted); + fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - (bb_abs / bb_emitted)); } fprintf(estimators_file, "\n"); } @@ -787,7 +787,7 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d if (groundcontindex < 0) { continue; } - const int ionestimindex = nonemptymgi * globals::nbfcontinua_ground + groundcontindex; + const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; globals::gammaestimator[ionestimindex] *= estimator_normfactor / H; #ifdef DO_TITER @@ -829,7 +829,7 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d if (groundcontindex < 0) { continue; } - const int ionestimindex = nonemptymgi * globals::nbfcontinua_ground + groundcontindex; + const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; if constexpr (USE_LUT_PHOTOION) { globals::gammaestimator[ionestimindex] = calculate_iongamma_per_gspop(mgi, element, ion); @@ -1036,7 +1036,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in double const radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum * tratmid / assoc_cells; const double grey_optical_deptha = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * grid::wid_init(mgi, 0) * tratmid; // cube corners will have radial pos > rmax, so clamp to 0. - const double dist_to_obs = std::max(0., globals::rmax * tratmid - radial_pos); + const double dist_to_obs = std::max(0., (globals::rmax * tratmid) - radial_pos); const double grey_optical_depth = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * dist_to_obs; printout( "modelgridcell %d, compton optical depth (/propgridcell) %g, grey optical depth " diff --git a/update_packets.cc b/update_packets.cc index d78e0644b..cc0619de3 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -45,7 +45,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double prefactor = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 7.74 : 7.4; const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * std::pow((0.2 * 29979200000) / v_ej, 3. / 2.); - const double f_p = std::log(1 + 2. * ts * ts / tau_ineff / tau_ineff) / (2. * ts * ts / tau_ineff / tau_ineff); + const double f_p = std::log(1 + (2. * ts * ts / tau_ineff / tau_ineff)) / (2. * ts * ts / tau_ineff / tau_ineff); assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { @@ -85,7 +85,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { // for endot independent of energy, the next line is trival (for E dependent endot, an integral would be needed) - const double t_enzero = ts + particle_en / endot; // time at which zero energy is reached + const double t_enzero = ts + (particle_en / endot); // time at which zero energy is reached if (t_enzero > t2) { en_deposited = pkt.e_cmf * (t2 - ts) / (particle_en / endot); } else { @@ -100,7 +100,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { // Choose random en_absorb [0, particle_en] const double rnd_en_absorb = rng_uniform() * particle_en; - const double t_absorb = ts + rnd_en_absorb / endot; + const double t_absorb = ts + (rnd_en_absorb / endot); // if absorption happens beyond the end of the current timestep, // just reduce the particle energy up to the end of this timestep @@ -363,7 +363,7 @@ void update_packets(const int my_rank, const int nts, std::span packets) // printout("sorting packets..."); - std::sort(std::begin(packets), std::end(packets), std_compare_packets_bymodelgriddensity); + std::ranges::sort(packets, std_compare_packets_bymodelgriddensity); // printout("took %lds\n", std::time(nullptr) - sys_time_start_pass); diff --git a/vpkt.cc b/vpkt.cc index a641858f0..458e9a6ab 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -103,7 +103,7 @@ void add_to_vspecpol(const Packet &vpkt, const int obsdirindex, const int opacho return; } - const int ind_comb = Nspectra * obsdirindex + opachoiceindex; + const int ind_comb = (Nspectra * obsdirindex) + opachoiceindex; const double pktcontrib = vpkt.e_rf / vspecpol[nt][ind_comb].delta_t / delta_freq_vspec[nnu] / 4.e12 / PI / PARSEC / PARSEC / globals::nprocs * 4 * PI; @@ -137,8 +137,8 @@ void add_to_vpkt_grid(const Packet &vpkt, const std::array vel, const else { // Rotate velocity from (x,y,z) to (n_obs,ref1,ref2) so that x correspond to n_obs (see notes) vref1 = -obs[1] * vel[0] + (obs[0] + obs[2] * obs[2] / (1 + obs[0])) * vel[1] - - obs[1] * obs[2] * (1 - obs[0]) / sqrt(1 - obs[0] * obs[0]) * vel[2]; - vref2 = -obs[2] * vel[0] - obs[1] * obs[2] * (1 - obs[0]) / sqrt(1 - obs[0] * obs[0]) * vel[1] + + obs[1] * obs[2] * (1 - obs[0]) / sqrt(1 - (obs[0] * obs[0])) * vel[2]; + vref2 = -obs[2] * vel[0] - obs[1] * obs[2] * (1 - obs[0]) / sqrt(1 - (obs[0] * obs[0])) * vel[1] + (obs[0] + obs[1] * obs[1] / (1 + obs[0])) * vel[2]; } @@ -210,8 +210,8 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar const double cos2i1 = cos(2 * i1); const double sin2i1 = sin(2 * i1); - const double Qold = Qi * cos2i1 - Ui * sin2i1; - const double Uold = Qi * sin2i1 + Ui * cos2i1; + const double Qold = (Qi * cos2i1) - (Ui * sin2i1); + const double Uold = (Qi * sin2i1) + (Ui * cos2i1); // Scattering @@ -323,7 +323,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar break; } - const double t_line = vpkt.prop_time + ldist / CLIGHT; + const double t_line = vpkt.prop_time + (ldist / CLIGHT); const int element = globals::linelist[lineindex].elementindex; const int ion = globals::linelist[lineindex].ionindex; @@ -550,8 +550,8 @@ void init_vpkt_grid() { for (int n = 0; n < VGRID_NY; n++) { for (int m = 0; m < VGRID_NZ; m++) { - const double yvel = globals::vmax - (n + 0.5) * ybin; - const double zvel = globals::vmax - (m + 0.5) * zbin; + const double yvel = globals::vmax - ((n + 0.5) * ybin); + const double zvel = globals::vmax - ((m + 0.5) * zbin); vgrid_i[n][m].yvel = yvel; vgrid_i[n][m].zvel = zvel; @@ -950,8 +950,8 @@ auto vpkt_call_estimators(Packet &pkt, const enum packet_type type_before_rpkt) // loop over different observer directions const std::array obsdir{ - sqrt(1 - nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex]) * cos(phiobs[obsdirindex]), - sqrt(1 - nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex]) * sin(phiobs[obsdirindex]), + sqrt(1 - (nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex])) * cos(phiobs[obsdirindex]), + sqrt(1 - (nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex])) * sin(phiobs[obsdirindex]), nz_obs_vpkt[obsdirindex]}; const double t_arrive = t_current - (dot(pkt.pos, obsdir) / CLIGHT_PROP); From 989818f2d9bd941e1ff91c958be5dc3f3abaab18 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 8 Aug 2024 14:59:03 +0100 Subject: [PATCH 014/117] Use stable_sort for test reproducibility across C++ standard library implementations (#102) --- decay.cc | 2 +- input.cc | 12 +- nonthermal.cc | 6 +- radfield.cc | 2 +- spectrum_lightcurve.cc | 8 +- .../results_md5_final.txt | 56 +- .../results_md5_job0.txt | 48 +- .../results_md5_final.txt | 1046 ++++++++--------- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 34 +- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 34 +- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 634 +++++----- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 234 ++-- .../results_md5_job0.txt | 28 +- .../results_md5_final.txt | 638 +++++----- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 638 +++++----- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 638 +++++----- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 44 +- .../results_md5_job0.txt | 42 +- .../results_md5_final.txt | 44 +- .../results_md5_job0.txt | 42 +- update_packets.cc | 2 +- 28 files changed, 2219 insertions(+), 2219 deletions(-) diff --git a/decay.cc b/decay.cc index 9266545b7..a35ceec8a 100644 --- a/decay.cc +++ b/decay.cc @@ -491,7 +491,7 @@ static void find_decaypaths(const std::vector &custom_zlist, const std::vec } } - std::sort(decaypaths.begin(), decaypaths.end()); + std::stable_sort(decaypaths.begin(), decaypaths.end()); for (auto &decaypath : decaypaths) { // all nuclei in the path (except for the last one, which is allowed to be stable) must have a mean life >0 diff --git a/input.cc b/input.cc index e3399de08..480c295f0 100644 --- a/input.cc +++ b/input.cc @@ -940,8 +940,8 @@ void read_atomicdata_files() { if (globals::rank_in_node == 0) { // sort the lineline in descending frequency - std::sort(EXEC_PAR_UNSEQ temp_linelist.begin(), temp_linelist.end(), - [](const auto &a, const auto &b) { return a.nu > b.nu; }); + std::stable_sort(EXEC_PAR_UNSEQ temp_linelist.begin(), temp_linelist.end(), + [](const auto &a, const auto &b) { return a.nu > b.nu; }); for (int i = 0; i < globals::nlines - 1; i++) { const double nu = temp_linelist[i].nu; @@ -1379,8 +1379,8 @@ void setup_phixs_list() { } } assert_always(groundcontindex == globals::nbfcontinua_ground); - std::sort(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, - [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); + std::stable_sort(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, + [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); } auto *nonconstallcont = @@ -1441,8 +1441,8 @@ void setup_phixs_list() { globals::bfestimcount = 0; if (globals::nbfcontinua > 0) { // indicies above were temporary only. continum index should be to the sorted list - std::sort(nonconstallcont, nonconstallcont + globals::nbfcontinua, - [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); + std::stable_sort(nonconstallcont, nonconstallcont + globals::nbfcontinua, + [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); globals::bfestim_nu_edge.clear(); for (int i = 0; i < globals::nbfcontinua; i++) { diff --git a/nonthermal.cc b/nonthermal.cc index 9ff6b599b..c7d7540f7 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1631,9 +1631,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::sort(nt_solution[modelgridindex].frac_excitations_list.begin(), - nt_solution[modelgridindex].frac_excitations_list.end(), - [](const auto &a, const auto &b) { return a.lineindex < b.lineindex; }); + std::stable_sort(nt_solution[modelgridindex].frac_excitations_list.begin(), + nt_solution[modelgridindex].frac_excitations_list.end(), + [](const auto &a, const auto &b) { return a.lineindex < b.lineindex; }); } // NT_EXCITATION_ON diff --git a/radfield.cc b/radfield.cc index f7ed25c9c..c57e33a71 100644 --- a/radfield.cc +++ b/radfield.cc @@ -323,7 +323,7 @@ void init(int my_rank, int ndo_nonempty) // these are probably sorted anyway because the previous loop goes in ascending // lineindex. But this sorting step is quick and makes sure that the // binary searching later will work correctly - std::sort(detailed_lineindicies, detailed_lineindicies + detailed_linecount); + std::stable_sort(detailed_lineindicies, detailed_lineindicies + detailed_linecount); } printout("There are %d lines with detailed Jblue_lu estimators.\n", detailed_linecount); diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index cec43e740..38a16372f 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -52,8 +52,8 @@ void printout_tracemission_stats() { // mode is 0 for emission and 1 for absorption for (int mode = 0; mode < 2; mode++) { if (mode == 0) { - std::ranges::sort(traceemissionabsorption, - [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); + std::ranges::stable_sort(traceemissionabsorption, + [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); printout("lambda [%5.1f, %5.1f] nu %g %g\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_nulower, traceemissabs_nuupper); @@ -61,8 +61,8 @@ void printout_tracemission_stats() { traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceemission_totalenergy); } else { - std::ranges::sort(traceemissionabsorption, - [](const auto &a, const auto &b) { return a.energyabsorbed > b.energyabsorbed; }); + std::ranges::stable_sort(traceemissionabsorption, + [](const auto &a, const auto &b) { return a.energyabsorbed > b.energyabsorbed; }); printout("Top line absorption contributions in the range lambda [%5.1f, %5.1f] time [%5.1fd, %5.1fd] (%g erg)\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceabsorption_totalenergy); diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index 2cd473629..dd3c98e43 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,37 +1,37 @@ -26d9e13ad6a94de247a288c9644914b0 absorption.out -d36a2323f4839c3ebbdaf9d5b549fc24 absorptionpol.out +86c15760e6772606c0b6874da878e1e5 absorption.out +c8ddb735d68c616eb2284d027db3e77e absorptionpol.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -e86b69d3cbd8e4d991d6f75d8c0e2f79 deposition.out -d94c2c032796a777f58581ba1992cc59 emission.out -15e76a5e16da47f58b42ea954a9c7be5 emissionpol.out -8bae638acb0f0ee5b86a860024563fed emissiontrue.out -302f37ac870c22d6b4a633448b7faac4 gamma_light_curve.out -e2d7b162e1f39df386a71126ef3dd348 gamma_spec.out +484a3c7d31147c4cf9b37394f27a7e70 deposition.out +93925a0e93c735d05487d798305608ee emission.out +0aaef5e1b4a7f4bcf6177abde91d5709 emissionpol.out +0f739c9ccab71703c5314bccb0b185f1 emissiontrue.out +89b0510bce0562daad2a528748c6d805 gamma_light_curve.out +c0058c8e94c7d1da7ed18b37885fec93 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -70dadec17fb2fa987f2df88dddfcd930 light_curve.out -5740f40190d45653e5fce57ddf577dc8 linestat.out +cc7ba3712502f6d95db04b0b52432984 light_curve.out +87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -3033f81191b0dc5c764a0086a94ac1b1 packets00_0000.out -270524ecbd3a9664bda29accdfc5b7be packets00_0001.out -eba236e2a397c84a10356257392652f8 packets00_0002.out -3b128c5a7f9b4ccf14c94202a74dbae0 packets00_0003.out -a7e49331cdab38ceac10a8bde2b4adf4 spec.out -e95aef64ed098f825506f7ad26a13770 specpol.out +10b3352ead14d4e3525e53e95d4242a3 packets00_0000.out +0d08c76357f5f25c02d47e437b4d9268 packets00_0001.out +8c23e2386f8b16dc3a7c311ea29fa91e packets00_0002.out +b5656513abdc54af9f1c851f8e487cd7 packets00_0003.out +b9a122c8a62ac1bd277d23ff9a4e37dc spec.out +5d61a2b5f77895eece5f0f1c04b97dc2 specpol.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -f279081d33f6b57de84558197314502e vpackets_0000.out -5a43becdc1d7e71b4ffd7cebafcaf6c6 vpackets_0001.out -f121ea01d207139c93ce7be5ac31e4a5 vpackets_0002.out -9c24724778aae1528f3d0b56155d8a20 vpackets_0003.out +0664f016179c072e9becf4ef5786e96e vpackets_0000.out +6c5e252d38f74c76d3ed069984ad35c5 vpackets_0001.out +20ddf629166031d0b79243ba5e8c7e1f vpackets_0002.out +9183110274310703c813f3ea07d70805 vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -4c5306f6e0600965c64054681e4e7cb7 vspecpol_0000.out -475c10e47987945227a085d5c1e1be8c vspecpol_0001.out -6b00a1ea7b27e5526d6b4111b8ac649c vspecpol_0002.out -4a9877bedb2280ae456c03fddc3f3e9c vspecpol_0003.out -6c52257f858067599cb5558fc3ecee9d job1/estimators_0000.out -4f4a2b7b0372574946c27b72970c0079 job1/estimators_0001.out -0b018d853ee5558f2c3e00c8812704ea job1/estimators_0002.out -654ee46032abcb5642770eaba93800a4 job1/estimators_0003.out +b81eca147913a935a0e1b7d471314361 vspecpol_0000.out +0a5920d2f978204df5da1d643c423d50 vspecpol_0001.out +fcccf78f512bcce165decaccbdb2c174 vspecpol_0002.out +235a52ec7939631f31eaf726cd0b0af5 vspecpol_0003.out +d4ce4ca914355420ed982d84e7f25c3b job1/estimators_0000.out +ed3c84271c5684682f00bd4e96873449 job1/estimators_0001.out +17de43d8517c1a714acecd0f539adcca job1/estimators_0002.out +a2ca1cec547d64f2c194ff93f7b1a805 job1/estimators_0003.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index a2c84f41d..968fa54e7 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,33 +1,33 @@ -f6f254e9f1381dc7b7f7ef8f8cd12b19 absorption.out +0c2e65eb3c5b56407d45dff187e98bde absorption.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -b189c2a2ae7647df01a340c9d2b19200 deposition.out -618536f8df9ce91e3215ef59cdd1d55e emission.out -5c757e01a7473b96512490153df67102 emissiontrue.out -5ee5397adc055cb62b922ea98e50245c gamma_light_curve.out +4f658e7623c91bb335b3ec06cf7de303 deposition.out +1ca797b23c4f5c973e8e7c5875b64bdd emission.out +0d09a535f08fcd6c45ddf0912ed2876c emissiontrue.out +d77b71c32e2090e56f3e0f28ef8748f4 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -ff34c9bfa70483263ed6eccbeb38e93d light_curve.out -5740f40190d45653e5fce57ddf577dc8 linestat.out +e2d213f1c6d32dcf1b35b6c25768de28 light_curve.out +87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -7faaca35800ae2c3ad9d3f4960d48692 packets00_0000.out -163d6e63c3adaeb6411551f4e302dd02 packets00_0001.out -54fea7c30fe477a5c4937bed1b240749 packets00_0002.out -a3556934bd726112ef6870161515cf8a packets00_0003.out -7dbc1b825efffa6375b6a7985173a1c2 spec.out +c073309a92f8ce66d1b1d469d7025bd6 packets00_0000.out +e3bcc3def8fea786199721c307c076a9 packets00_0001.out +42869c0f5e97c0859a9cb86a83200f71 packets00_0002.out +ca84fe5225fad046a16056e3f0fbeee0 packets00_0003.out +ba123935942e38faef2713594ec6d0b5 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -071332902024a0b4ab122020eda5c66c vpackets_0000.out -133a828923780814a105f2e19d101205 vpackets_0001.out -4ce751591988fb659a3ede79237ea563 vpackets_0002.out -0a5a8ef4f9d6ca2de6e382eba730ca7f vpackets_0003.out +557de1f52f7c660e7296948360a0f34a vpackets_0000.out +93f0858030a4d7ce117ada41ea7ad5a6 vpackets_0001.out +8dd1db3d29517a743a9503047b02a4fe vpackets_0002.out +1246e178307a445f5215f438b7b6bd57 vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -ef9e1f821d4920e44053e909fdc51fe4 vspecpol_0000.out -abc6598657cda5f5a3be63bcaf519043 vspecpol_0001.out -d582dafe3ea571fe7473cc4c0be03455 vspecpol_0002.out -5b7fc753283aa641885d587c2f9518e6 vspecpol_0003.out -2fae638309c009c16f37d118fd5c5cfd job0/estimators_0000.out -b21cc560e486dee405f63c6f1566ccac job0/estimators_0001.out -7ed70e373237a2baa5b6fccb1c2f9bd0 job0/estimators_0002.out -1b95178675f2f06bca85ed41093e9a9a job0/estimators_0003.out +d16768502c1b6d9dbcc3d89839d7e2d0 vspecpol_0000.out +a356af5f230c93556bf3cd24d64b7e35 vspecpol_0001.out +b2f9b21799bb15233dfe8ecf2fd59275 vspecpol_0002.out +b0149ecbfe2907867e7d5681b5564109 vspecpol_0003.out +1f28eae4d04a9a61b2f65754324fbe15 job0/estimators_0000.out +5ccfdb4112c294fc2aae7a6bafe1313a job0/estimators_0001.out +aa511b10e2052f7b49e268e202dea1fa job0/estimators_0002.out +d269004b3029f571d164ff1b80be7207 job0/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_final.txt b/tests/classicmode_3d_inputfiles/results_md5_final.txt index 16a513b76..b2b482322 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_final.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_final.txt @@ -1,528 +1,528 @@ -54f0dc32c69a697bbd7e936b68e36c49 absorption.out -a8a9fbc9b3f4fb6c354b8b9ef52e25df absorption_res_00.out -c5c60f29e346e1042daa1f90437f668f absorption_res_01.out -0a05457abb7fc4a0048bf75fc1d14859 absorption_res_02.out -73fe4721e4929ed6cd8b34ecb01b56a3 absorption_res_03.out -3b62f0b96a040ef0d6896bf0eda751c5 absorption_res_04.out -1c4f757bde8ac316100f6812d99dfaac absorption_res_05.out -85e91ca39e7bf0185c937a22da56e17e absorption_res_06.out -dd48c0cad971b9cf8916fb917ea05baa absorption_res_07.out -54179b161a36f3438e80c52b94d035bc absorption_res_08.out -01c5fb5b13b2322f79ee93a5e632c3ce absorption_res_09.out -a1b6ca8974f659e6e5b8b1bcda99c6c9 absorption_res_10.out -898e22fe9fad9940394e9ae9498bc378 absorption_res_11.out -9c0ff6f1f2edfd291af57a4218424cf6 absorption_res_12.out -7393ad8dc48b37a31d82bd51f6169f12 absorption_res_13.out -0d07a6d4eb68eca16a139ed902fd3a99 absorption_res_14.out -c35c219baae0ffb695e5dd5dfade647a absorption_res_15.out -60b8571e34cdb73dde5031b6b16a8225 absorption_res_16.out -54f254aa55a074de8bd619ad41a5929a absorption_res_17.out -cff0c0ec7c45b463600e811aea9bc6fd absorption_res_18.out -9cc8acab2652cc7cff2e9e8900c5107a absorption_res_19.out -2f3cd34afaf6fae3fce06ee519a02ccf absorption_res_20.out -4362675909278d9987aab68700f509f3 absorption_res_21.out -89041e8dbcf9059865c1af1bc59f93d1 absorption_res_22.out -77b5922a197a82a575a60f024c770648 absorption_res_23.out -1b77da53342eb5ff45dc862930619cff absorption_res_24.out -121399c5a6d2f170c4471f6a4763eceb absorption_res_25.out -b1351e80632224323730f62a12dc7701 absorption_res_26.out -7b2f018d5ad31b9fe4bec90de6c010f3 absorption_res_27.out -78d5bc12041d44868f7ec43a4aef0db0 absorption_res_28.out -0f43f4c248f28bff9becd190cb8f3ac1 absorption_res_29.out -f3653bd1904a1903b84735e88e648d51 absorption_res_30.out -7e2f35f0d6eebc69e6c03001d49dee49 absorption_res_31.out -ef60b66c9f9ca4a509cb54490f29f003 absorption_res_32.out -49f606e65054bb290ff53ebfdd1759c5 absorption_res_33.out -064abad0219cbe1ae6598e05110bbb9c absorption_res_34.out -5bc7dc55bf8db1a7bc415fe12b5fef99 absorption_res_35.out -bc8018fa977a699eba7bd84fb17e11b9 absorption_res_36.out -2d4b3832316c07cc10d9251b9e53401c absorption_res_37.out -156de08f0c5dfcdfe230338d26cf6a54 absorption_res_38.out -c9676bb7beeb7addb4ee6a3eeff9c018 absorption_res_39.out -0f8aafaea3c2b1da4d42adff4e21ab9c absorption_res_40.out -ddeb1349ff495f8ea860249b66e5dbab absorption_res_41.out -f5f441b68363ffe7e6301bf1d4367bcb absorption_res_42.out -c9e92ae18749d2e3b84d80cce5c796b1 absorption_res_43.out -7e3024be94dd14ad94baff0241ab9a63 absorption_res_44.out -a872e82e33f23247c0083af7bd3b4284 absorption_res_45.out -042a6d8c2c140308063ffa24d8a8f44a absorption_res_46.out -8baf763260ec9fd6596f3b6a14a87d6f absorption_res_47.out -ccab69c31bd556b3e8e51a7c0475f396 absorption_res_48.out -6f2b1b226fe972be585c17323bebbc92 absorption_res_49.out -eebcfdc36966fbe45c7f8e717cadc8cd absorption_res_50.out -cd2a7838fb56b1ec717645e39af750e6 absorption_res_51.out -efbfb655ad659345bb4461a197841529 absorption_res_52.out -4e16d8b0e09eaf51332036835a5348de absorption_res_53.out -886053dc1a89af37e696632cd323d7b1 absorption_res_54.out -c2f4218e224c15134a7029dd1a6b8da0 absorption_res_55.out -6dda843fb04886e0a43fe13fe8ff71c4 absorption_res_56.out -cde5206f43309f90b5f755625d67378d absorption_res_57.out -e5daf857f341c469e646a509df33c3de absorption_res_58.out -3cb8e14bb88dbc869fad3e67fb5e6e7c absorption_res_59.out -60064b07c310e9e34e69c19be7a2b0bd absorption_res_60.out -b7f9bd84eb11f90ca0d5f0c68e709427 absorption_res_61.out -d658124c78f9dfa1e33d75e1b9c53526 absorption_res_62.out -ddd21d58cded6ed7fb8663daa7e77ab0 absorption_res_63.out -d53eb93bd9b03df4cd9fe4bbfb0b5a66 absorption_res_64.out -10914530dc47310a9849fb9fe82a89dd absorption_res_65.out -cde94d059fa0dc627366aee4de7f1441 absorption_res_66.out -dded3ad688f7b717fa53f980b5012507 absorption_res_67.out -87d5297dd642185923ebc42efe8ad70e absorption_res_68.out -c6495a9039f43881b051fa934279c182 absorption_res_69.out -3ba8dd3345cef9594208b5a24f43dc0c absorption_res_70.out -ea0628333435d06207924a02388f61a1 absorption_res_71.out -f94eaba2e2ac56068fa82cc73991a0b8 absorption_res_72.out -601885a464115b2f9eb541148812ee40 absorption_res_73.out -dbc2656f82060fe063c71bd625f800c0 absorption_res_74.out -4675aa037d8d8635ca8a049b29759a9a absorption_res_75.out -fc3b691aa0e587b3d4ac6e83d1005338 absorption_res_76.out -4b8422c953aba429ca6c29ace6265c2c absorption_res_77.out -853eec0005d2400a834ca4cf6b4836fe absorption_res_78.out -f0d75cfb918a2f90937b36ade46e81ed absorption_res_79.out -9851b939e556f6682e77784c9252be08 absorption_res_80.out -2f08284225e5c885b3141538204d7d07 absorption_res_81.out -861a3c99a23898d2a25255840ca38b54 absorption_res_82.out -363a32d0a6754cd4ea219ff85eeff3db absorption_res_83.out -ea3b6779a520ebef5ad41ff8bb3615c3 absorption_res_84.out -610fdd800eb9e0cc996e2315fbc257eb absorption_res_85.out -7b8a42ec1ae45e1754db5ae7f4af3cff absorption_res_86.out -c2493c05a9231cc9aa0c36c79e982628 absorption_res_87.out -877d501b96cc633800f5bce38f31f1e0 absorption_res_88.out -75cd0ca707d3334395ac4a29e2900bf5 absorption_res_89.out -10ecbf93bcb667b59075c3a0502443b4 absorption_res_90.out -cc045928de16db15339cf373002a9b83 absorption_res_91.out -814a3e20bbb8660f0988271b6af643f2 absorption_res_92.out -90c10f86c8421ab501ffd9531b9076d1 absorption_res_93.out -56747b9a5af45a7e4183d56386af6119 absorption_res_94.out -b506f968f586833e48b818b1564bc16a absorption_res_95.out -f75ff54d947112335e5419a7be87b341 absorption_res_96.out -767898063a16316e1ef686d0c5cab260 absorption_res_97.out -640c29ac54d38da6ca16e64a5d371e4b absorption_res_98.out -6658bedd96515a24737fcc4a076cc537 absorption_res_99.out -7dbe38bd327992640d694aa43ce1bcb6 absorptionpol.out -df33b09e988e4483a1f0e25b19fb6164 absorptionpol_res_00.out -8d0dc45a5001ec7961681d4ec7cb2bd3 absorptionpol_res_01.out -452cfea50b4b61ffa9ae862bcc98ec3c absorptionpol_res_02.out -bd4da9c8e5d102e95e2c24f7a5ec2d63 absorptionpol_res_03.out -ff20344edfce52f06babf21632f1a852 absorptionpol_res_04.out -077de4cdccf9ef9edc535e7c72ded9ef absorptionpol_res_05.out -c7ad4986fd4f8c617ccdec262852fd06 absorptionpol_res_06.out -e357374b7be3023ea88ec3f5924b9f6b absorptionpol_res_07.out -e10e31d747b86244f907bd38e77f0433 absorptionpol_res_08.out -cd2dbd865572a9a95955e4905467668d absorptionpol_res_09.out -e1a4565208c0ac29f44e47467dd18b8e absorptionpol_res_10.out -822aa9ad7a9991937667e467f5a92ff6 absorptionpol_res_11.out -7bda8e0dfdcc310a2917bf28a3bc4e10 absorptionpol_res_12.out -918aa27f2ea35d18e32fa7829ba2deab absorptionpol_res_13.out -7605f46dfd8819d1ddf1590e697be3c4 absorptionpol_res_14.out -c51d4928f33225c315f6b89272f63e75 absorptionpol_res_15.out -cfcb97ed4495fa409a8c6a03a9dacd3c absorptionpol_res_16.out -af4465aed00260395a981e5411bcc33c absorptionpol_res_17.out -e10554607f478ba1e9baeb5eed41a75c absorptionpol_res_18.out -1d90c0a7caa9afd8c023fc2592553727 absorptionpol_res_19.out -43c19726b950c192189cc5af1fae605b absorptionpol_res_20.out -bc456632dd59899d857e383a20e48f7d absorptionpol_res_21.out -543a61fcb6bf696aa5e500c40e10825b absorptionpol_res_22.out -40e5ea71d980cca8f8e9033036a19fb1 absorptionpol_res_23.out -34081696e3e949caac4352f2a001e090 absorptionpol_res_24.out -ea60edff232e19b6370151083c8798ee absorptionpol_res_25.out -b77fb5ab6ca58c37dbe90ef854a66d74 absorptionpol_res_26.out -db481a6a2750aeb060adb0139eccd3be absorptionpol_res_27.out -8beef0c3bcd89a39e781a3d61f4ef92c absorptionpol_res_28.out -32e8a1e320deadbc2638deb5103a336b absorptionpol_res_29.out -ea33659257ae95afc4a89c1ef2eb3168 absorptionpol_res_30.out -0cfe49947e705f4916455dea564bcaf2 absorptionpol_res_31.out -0a75452b3671837661f1e7c7b436c32f absorptionpol_res_32.out -3cf7ace1dd667bfa450139fb4a80e245 absorptionpol_res_33.out -32490c3f2702238e869b1f7a9c195e04 absorptionpol_res_34.out -18cc82b1bea5b3c411a7a497b4125017 absorptionpol_res_35.out -bb8cadb76db1b19ed67f01111feac878 absorptionpol_res_36.out -8fb5b285c8193d5f1fba5111761dfccb absorptionpol_res_37.out -e89646c44e8244d307728b02abb7a8ea absorptionpol_res_38.out -69182a3172ee1fbc981805e55d966709 absorptionpol_res_39.out -d110270725cd4987f7f57a13059daf69 absorptionpol_res_40.out -8af3d42e722ef70abda0f3cbc001248f absorptionpol_res_41.out -7065e26d5e3715196877e2afa0d25aa3 absorptionpol_res_42.out -46d5d0346b45043172535273829355a9 absorptionpol_res_43.out -a27dfba1d21502f914d1533e1812bbea absorptionpol_res_44.out -8c0e4f17de7df7187c759948b5a13fbf absorptionpol_res_45.out -3a598837e0a1da182fde357ab39f4a3c absorptionpol_res_46.out -1bd25eef20a68688f00332168066aee4 absorptionpol_res_47.out -e1b301ab84e7d75779775cee66160f67 absorptionpol_res_48.out -cc8214271e2e0a7d0f9d35b2c1e75668 absorptionpol_res_49.out -5ca6d21d013e7b122913fa690dc4b2a7 absorptionpol_res_50.out -e9c0bf5ff12433b96ea745d6cbdb8eee absorptionpol_res_51.out -bb07b66e60460de013103d55eb4785a8 absorptionpol_res_52.out -e5f43f0528850fa223ecce44a72e09a0 absorptionpol_res_53.out -9803e28eccf4639924bcfd0c66f95c66 absorptionpol_res_54.out -b7576aa16cb78fd533e5f33701da8e07 absorptionpol_res_55.out -fd569ef1b6ce363556c32c85f4279f2a absorptionpol_res_56.out -341a8bea629e3aa9a20a8251441c447c absorptionpol_res_57.out -d3cd9eba6d110bb9c7ffe54506f5d9d5 absorptionpol_res_58.out -8fac08a254100b6c0a1fdad186089999 absorptionpol_res_59.out -c6e6b505f4887984d1917b1d54d1f9b9 absorptionpol_res_60.out -143392edcdab466efcf1435cf9abc4d9 absorptionpol_res_61.out -f22a808d62bb90a7c76547319736914a absorptionpol_res_62.out -5a5f5cf9e1a22fe5d159287626c4788f absorptionpol_res_63.out -216a848fdc7aacb9c0a83d9092bbcc49 absorptionpol_res_64.out -845418d383e97f111a1d5928ced8d3be absorptionpol_res_65.out -375531b7d6bab1d1713458f6c97d0c6c absorptionpol_res_66.out -e92b042ab93675741c41b3ac8e97dad5 absorptionpol_res_67.out -032fb46a93bbd7fe9581dc81181a93b8 absorptionpol_res_68.out -df4a7ed52777c204e314eeff3b7c36ed absorptionpol_res_69.out -5044158f3dc6b825822efb001a0886e7 absorptionpol_res_70.out -a0a8d737f681008ed6b3772baeb1467e absorptionpol_res_71.out -489328c22a860941b3a6566fe924bfd6 absorptionpol_res_72.out -604176a933dc8d580a9cf71af4753a1e absorptionpol_res_73.out -570c5939335f8e4ce0e6e52168d979a7 absorptionpol_res_74.out -459ee295f85c990f2ec6be62b4ffe661 absorptionpol_res_75.out -ed8ea9d3f84e37bd659b55bba0c36b82 absorptionpol_res_76.out -51295affccdbaa42cb811c2dd57bb91c absorptionpol_res_77.out -b8937826cbd1500513f510e4ed4d65d1 absorptionpol_res_78.out -e47005346ee499674bae2d1a4c96ffca absorptionpol_res_79.out -8472776bb20d939772732a85b674772d absorptionpol_res_80.out -544b279587b7e21094c8d56ce4acf004 absorptionpol_res_81.out -0f65cac0c85ab90af1f92dea7a617ffb absorptionpol_res_82.out -ee2da047f88438ded6c5d3e5b29690ea absorptionpol_res_83.out -801f157171e51f85ecc8573e0086c1d8 absorptionpol_res_84.out -9f1cbe0738fb9fbd2157338adabc4d6d absorptionpol_res_85.out -dc64939c05d266a80c555a86788e93b0 absorptionpol_res_86.out -809a5c7a6324548b4455cc14e68d8c22 absorptionpol_res_87.out -a5a73a3db3aea36da51fa303f8657c27 absorptionpol_res_88.out -4f1f720c11c5dfbbf51e61df730c0367 absorptionpol_res_89.out -338b6275996f9be44d7f5889b14f97a1 absorptionpol_res_90.out -5a8c5a4d91cb0cc4288383bccff4e63a absorptionpol_res_91.out -4bb3702fd8a20e609812bb92478605a1 absorptionpol_res_92.out -01bfa427e938a2ebd04483a3fe32c3d2 absorptionpol_res_93.out -fa3f0749da1ef716a128dfc66083368e absorptionpol_res_94.out -ed92da0ecbc1042c5a35cf982013daad absorptionpol_res_95.out -86bcc1937f86e3221b0d36b08f3ce0ab absorptionpol_res_96.out -7409ca5ef98009b31d388e8649a2561a absorptionpol_res_97.out -4f3d23c7065f4d24cb846018ce0944d0 absorptionpol_res_98.out -368fdf068e5f32f68a016ff8429ae44b absorptionpol_res_99.out +ada85fd6f9450892265513ae0a8a2c0e absorption.out +da41b933064a0a0ca8bee5e224d971a7 absorption_res_00.out +08f4b5cd06e697281c2e9feb93a0b28b absorption_res_01.out +dbf08c6c5c1456cf9a226b7d24fb033e absorption_res_02.out +48b0790c403a250b99fb90721ea6f077 absorption_res_03.out +15ba7a09800cee51d5c7cf934da469fe absorption_res_04.out +6364ff2f2e28eaa0b5da5c875753aa4a absorption_res_05.out +65852173ab4ab213d1489483994c1ef1 absorption_res_06.out +20a63e5034fbbc45d00e74483dc9e877 absorption_res_07.out +502f69b2ac15a21d37502e492255ada8 absorption_res_08.out +14a2305334b874a6674f946ae2b62ff8 absorption_res_09.out +ac6d1bec94d8266240bd41f3540c9cba absorption_res_10.out +e633e2f7827e81fe83ee34d5e9538b0c absorption_res_11.out +a295da99ededd2186c9b4ff1f27775b0 absorption_res_12.out +81500bf63c349e50c8ad61b62d4bf87c absorption_res_13.out +505502297a1ca398006a4c343de8b8d8 absorption_res_14.out +6d429eb9198154390737755ab20bccca absorption_res_15.out +781699684e4ff6897ee92419d9a81ec4 absorption_res_16.out +6e7bd7925d71cb3cfcbea65832c79b00 absorption_res_17.out +2ebd6084a203a8c23fd89435d11ecf7c absorption_res_18.out +3f0d17412b759ff3963d46991007f574 absorption_res_19.out +172492423e595be5b2f11ff10bedd72c absorption_res_20.out +b1492aacdf77e7401b75f9a86f4a726d absorption_res_21.out +e0f032278182cc8d164bfcc5bf4d7a67 absorption_res_22.out +a9921e063318ff4db1f35b58488054bc absorption_res_23.out +9a0e206d3b108b49e89b37eee05d3093 absorption_res_24.out +8ec8cd12340cf5f1d487be983a7f6100 absorption_res_25.out +01a71e315f94961cdca2bf7896d97df9 absorption_res_26.out +da7cdc2d9f029d84972746e50ef5239a absorption_res_27.out +8af1553830653e78665c4da303ffac13 absorption_res_28.out +5f276542db0d144023a8ed4770ee87fd absorption_res_29.out +b3f3a7bfbcc9898fadef4fa73d9c8055 absorption_res_30.out +d3d35deee95c3f0b29f248f25ee0dee3 absorption_res_31.out +14cf3707918a6f0966584d2bdd9b884d absorption_res_32.out +51f53c395153b980e01f63e6fb5ec2bb absorption_res_33.out +0cd98920862479bb33ec426270b242ba absorption_res_34.out +5d0917546f290dbea6b4bc3c5b393e2c absorption_res_35.out +ddab98b40eb32cdec6e805afd70db0de absorption_res_36.out +ab08be2df205eea4377a7af640b22b29 absorption_res_37.out +0a43c9f26cedef357649be41be35f31c absorption_res_38.out +c3d3d277cd95d9eb7c033e9c2ac06ba2 absorption_res_39.out +edc67bcca545cd39bfef50b145908406 absorption_res_40.out +53e636362d0d227bb8d8469e0a00fff5 absorption_res_41.out +eefa7e3902474a21527709965c5154d9 absorption_res_42.out +2ca3310ba407337af5f5a89e3db2a63e absorption_res_43.out +252017c16cf993f2a1ec0f7b096e2a76 absorption_res_44.out +cfe6541f444e2165f08a2c93f72a4aab absorption_res_45.out +6a7446c45565dad3a62b0eeab4306889 absorption_res_46.out +5215643d68ae76f9ebbb6d15e35deccb absorption_res_47.out +43f547bfc21639849af94a2ed5b4e443 absorption_res_48.out +8c36b5e3a57312b1be78e434bb634d05 absorption_res_49.out +369c3142befc40517f2e64877ddddb75 absorption_res_50.out +2b739f4725f3407f004f9abea6288cc7 absorption_res_51.out +0c3167b892b8d92b051e7efe05309a0f absorption_res_52.out +e3a7b2f2dfe53e59c4ba1f0519db7a97 absorption_res_53.out +caf6cc72c34d447b71748e60be244f5d absorption_res_54.out +8aaf92ec3b504f2f029e26ac30b36ba1 absorption_res_55.out +3f2bc3b5534ebb89199ed7586a88d0cb absorption_res_56.out +676c5c19dc8f75df446daa776f438d94 absorption_res_57.out +0f22f2eb1146a04f131b5db6d09b4166 absorption_res_58.out +bd33791adcb2055e348437bafb86a6d2 absorption_res_59.out +6f155709b56b7db0c5a7102b4fa25c11 absorption_res_60.out +42e320a6f57830d924a7c3542725d60b absorption_res_61.out +2ea73859a73ce88eb9a2df7827298f0b absorption_res_62.out +9e07cf1a42c659a6f1edc1801fb8d06a absorption_res_63.out +79e3fb5c99ff4ac18ba13624a56a6de2 absorption_res_64.out +17d642a17b363647550c59dda642ae30 absorption_res_65.out +a98c37195acc6b913f88da99c9dc8688 absorption_res_66.out +1b8f0d54bb3b0d1e79c7a2abb0c49f7f absorption_res_67.out +2a3423b7f1915d701faef049ffb97f6b absorption_res_68.out +449832bbb821468967e018e36a921d96 absorption_res_69.out +00c6ee8da8b80e575bc7539c7bc38e99 absorption_res_70.out +9ffc8c820543340213b53873549389af absorption_res_71.out +dec8a20bdb55b9fb465de008750b79d5 absorption_res_72.out +33721dd49d0f70d9b1fddaa8d61e4851 absorption_res_73.out +aef316011fed9702967fd0f3ee5d1bd9 absorption_res_74.out +65ce3a6924d11c380398013198d3dccc absorption_res_75.out +76a03fc3757222081a2e1858b0466893 absorption_res_76.out +382aaa914ea543dbccd799939dd87c30 absorption_res_77.out +5e680b63c41653aab28839e66dad90ff absorption_res_78.out +9f3543eb69d96184e05e20bd461b3605 absorption_res_79.out +20f1da8a6d2cc39ee089d82b30a89dd6 absorption_res_80.out +048b05a3c4dd45c9ae313c028cf9c615 absorption_res_81.out +c004411dc1f91858eb490ae92c5925b3 absorption_res_82.out +f2c12bb9e053143d3ed0a4a84eba2487 absorption_res_83.out +4893537f5337d3e4e0ba1942b799832c absorption_res_84.out +f279450d6ecacb822c2bde201e2412ec absorption_res_85.out +fb92d2fde0aadd45c3045c05c5320302 absorption_res_86.out +fbb30caf8435ed82a6a0790e3e90e721 absorption_res_87.out +925b39172b372c398d591f1c35495e14 absorption_res_88.out +16ab34c8ad37a89d84da47313029e07f absorption_res_89.out +1deb8d66b4280751b98921696b46ecd3 absorption_res_90.out +2f2be02033b281c47d8d4bfac5b6decb absorption_res_91.out +d981dedffcb6cdbbf91c7872ab9e1f0d absorption_res_92.out +22663b284fa6ac358921d8e7dc7e7921 absorption_res_93.out +77f08a733b22bc8e6417408f2b59a3c5 absorption_res_94.out +632a9b2fe3b559ffac3ca64e0d034a9a absorption_res_95.out +84658b0f586da5810206c19e96c39b1b absorption_res_96.out +5bc2d907740854c44c27b8ff38061d36 absorption_res_97.out +8e96873f8811ba6a7a73a8697d73df67 absorption_res_98.out +40714984580071f311637bff2524fbee absorption_res_99.out +a71f943c96688131d0130a84bc7c2882 absorptionpol.out +7855c3010744913c478fc1b8008b6af2 absorptionpol_res_00.out +17e56bd16facc1e8fc264d5fd5d40052 absorptionpol_res_01.out +43e5d6a054689d043e5a44c37bd91d93 absorptionpol_res_02.out +2bb165a412f67da261071042474aea29 absorptionpol_res_03.out +29aa6c50cd6d3ffe2341ae5e48ffbda3 absorptionpol_res_04.out +7e5292d6d2eefb4f1dd5db7e3ed358b8 absorptionpol_res_05.out +378bbbacd5e2b046aa9e0454992447b6 absorptionpol_res_06.out +0f64e3074c68967f47750916f54ab98c absorptionpol_res_07.out +acea9ee28df7975b1092fc4872714c09 absorptionpol_res_08.out +2a4f54cd06700082d7be84992c5ab511 absorptionpol_res_09.out +b53bb58107eabfe155c43270b3eb6a57 absorptionpol_res_10.out +a469fe0754e79db2f2fbb84f3ad7f1b1 absorptionpol_res_11.out +a385ca18241d8a7f07ac1d0e3f3d8224 absorptionpol_res_12.out +6bea3049e7fdb3b795479ebe6140bedc absorptionpol_res_13.out +189543baec2886f4b0b1a8ef8136f132 absorptionpol_res_14.out +f6bce9746b186cb296d399a4a496a755 absorptionpol_res_15.out +56ce3adb54bab69c92385b127db33106 absorptionpol_res_16.out +02d10fc368545466ff0b32843d89c7bf absorptionpol_res_17.out +bbeadac11cf366571f5bd3b8ec06a941 absorptionpol_res_18.out +cd5277c9777ae336f1c8522b236d57d4 absorptionpol_res_19.out +35db23dc01e6f61a99ffa825e6665b61 absorptionpol_res_20.out +66be93ca1abebde2636426b23e6119f3 absorptionpol_res_21.out +b4a5f31cde2af4458eabb2e526a75e1f absorptionpol_res_22.out +63cd49ee461fd2f7b5e16234f4f7cbbe absorptionpol_res_23.out +e61275d8804612876786a82ed904c36d absorptionpol_res_24.out +fb42f8ca5d5fb0688ace46f2f17aceaf absorptionpol_res_25.out +acf6d376a442ce9de6a4f441f4c344b3 absorptionpol_res_26.out +5c624ae555cd40e3b58fa044267e3c44 absorptionpol_res_27.out +bb019a1397e8feba9852c4d8dcf4ca62 absorptionpol_res_28.out +86a3c4397672499889db9df53e07e485 absorptionpol_res_29.out +06a918137c7ba3fe3046d92b5ddcfe70 absorptionpol_res_30.out +4150421ce77628253f4babf8e8e617ad absorptionpol_res_31.out +da60fe529699cad062c085370f07f871 absorptionpol_res_32.out +d1fd56634f84a679a401022e4f84538f absorptionpol_res_33.out +a9d9f998716b1c2aa3bd7ad96ff03027 absorptionpol_res_34.out +758a99b81e0ba2a933370de9699ed787 absorptionpol_res_35.out +38ba8fb3f74bf8808304da037dde71cc absorptionpol_res_36.out +c07e8c39c7b6828046f6610644ff4c26 absorptionpol_res_37.out +1b72a5da702a1ec8babf738adf6c8765 absorptionpol_res_38.out +b0d5a826be9b181592d828909dff9b0c absorptionpol_res_39.out +646d9dfd9524bdf8b15c5b4058327b00 absorptionpol_res_40.out +621d798a8997a61b56c0565fe5f48f83 absorptionpol_res_41.out +0058e0475ff651db2855369b1b849b92 absorptionpol_res_42.out +64c0ccb0d918670e12dc6dbdbd171713 absorptionpol_res_43.out +b274a06a1e827d5c647b181fdf18945b absorptionpol_res_44.out +8cd15e741d86cccbd286c3585624e232 absorptionpol_res_45.out +9cd15e2d59b7da5049a6f1a3f876918a absorptionpol_res_46.out +0e8a0aa02730775be6ffab5faa6ec040 absorptionpol_res_47.out +02bd12e91a6994cb6a686793a52c7186 absorptionpol_res_48.out +cacf6ade7929c77ec979c3eee6d311c6 absorptionpol_res_49.out +a0dc5427dde9c241f613870e4dafceff absorptionpol_res_50.out +18078849b07e9103c946056a4c8dc203 absorptionpol_res_51.out +3b0740263e680ef71501291134353374 absorptionpol_res_52.out +b797a614ae06a585416d21d929234e57 absorptionpol_res_53.out +78ed956bbc900752f1943b7b88e0bcb5 absorptionpol_res_54.out +5e5fb793a0e450f50863c9cda3094e62 absorptionpol_res_55.out +339872ae791e9baf75a77857c2b1075c absorptionpol_res_56.out +79ad8a47b933f4718462fec5e28c9243 absorptionpol_res_57.out +c5d80c69564c78125d15c776b82c1c9e absorptionpol_res_58.out +cdb0b2c9050c0f066281f976703012b1 absorptionpol_res_59.out +c17e4ddf6e67fc52cb4ee870185faf9d absorptionpol_res_60.out +b0ca0f5dcf3addcb8755fc18978a6a85 absorptionpol_res_61.out +08585d8c8aa34ba8cc0cc564908de806 absorptionpol_res_62.out +6c7fefe75c11020f8c9fc6abce791e9e absorptionpol_res_63.out +99e3b8bcb2722ee61b840f085e6c3f3b absorptionpol_res_64.out +a679e5b247e86419989688c56d923a66 absorptionpol_res_65.out +8866dcb157757ec2d2918ef49b4b4287 absorptionpol_res_66.out +c930972f1e0e5a6384a3159f6af900d4 absorptionpol_res_67.out +7094155804228b8d3538e0b18a6d3fe1 absorptionpol_res_68.out +2eedec117a8f46d2091655277d6f5254 absorptionpol_res_69.out +798ecca9162b3be0b59c71eff0f558b7 absorptionpol_res_70.out +b3c2d6e1e960f6b15d7436a71494527b absorptionpol_res_71.out +200513df817d22dfe07315a1bf61cff2 absorptionpol_res_72.out +630fb946c68d0ff26066c6b3905c6519 absorptionpol_res_73.out +76af8175ccf141657122ea9c9a7a0ecc absorptionpol_res_74.out +5d0d3137d87e122ce19d954c1f0725cd absorptionpol_res_75.out +811f2a8f38c795816c24dc6d62e3cbb8 absorptionpol_res_76.out +5304d53ce3202ce141337524933f6a61 absorptionpol_res_77.out +440cd4b7a3fbf2843f409fb9d0c67be7 absorptionpol_res_78.out +4dbd3dae97664c0722aae2ac39edd3c1 absorptionpol_res_79.out +e31ba3ffc25daca831077c86862ccda9 absorptionpol_res_80.out +94ae83530131739a8680c57c56db4d3d absorptionpol_res_81.out +36d7d2ca15914553c2a56c6f30017be2 absorptionpol_res_82.out +679a52cb5e159de66addf865b7a2a259 absorptionpol_res_83.out +cdd39a45584c8953ab19d701ec7ba29e absorptionpol_res_84.out +fd6ace493efd6b66b3be9e352cd0308a absorptionpol_res_85.out +2774b0afd4e542fd7c81263b9c77e276 absorptionpol_res_86.out +88c71452c548890d15e67b23d41e5558 absorptionpol_res_87.out +2d99f0ba6a124eff4917e0bf3d84e9eb absorptionpol_res_88.out +7f2da82e265886979cac607719ffd814 absorptionpol_res_89.out +c8672a449664021c78dbb509164e2074 absorptionpol_res_90.out +31313f94c0ecda21d835ca615c7c9b8e absorptionpol_res_91.out +69a3cfa4bf102651c211c2ff3f71e941 absorptionpol_res_92.out +fb1cd38c659a7c3a2de2215c9e754bda absorptionpol_res_93.out +0a5704cccb24a400f23ef517daf23b1c absorptionpol_res_94.out +87653adb9ff9efce090f30534e368453 absorptionpol_res_95.out +3320d2903d16c7181bcf7d1216123334 absorptionpol_res_96.out +d188390ec3c67621947b89e6252fadaa absorptionpol_res_97.out +9238e578f88c37f07d0fc593f4ff4f83 absorptionpol_res_98.out +a8d123ce46646fc962a7589d432a307f absorptionpol_res_99.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -10aa52e7049599280e304985c7f29098 deposition.out -0dee27af7ac2a4176a058d344969847a emission.out -12c19b24250988600f92387f7a9ee8a8 emission_res_00.out -3c42846db64af7bfab776bb5288ea107 emission_res_01.out -9ba576b6c03abcded33156c75ead3ec4 emission_res_02.out -76c45b7d8c7eb72cddd7159de3d2a36e emission_res_03.out -b6c4ba67f19d8b15ac779d330f7b4ccf emission_res_04.out -263af5e91f0832e901a1d4791f5e8cb4 emission_res_05.out -bedcf795c2c1b23636db4ec32b14e76d emission_res_06.out -89c68a10d4d334820d5b23bd11d267c7 emission_res_07.out -e5ffeb05d98447af7c52698ec683703c emission_res_08.out -d2b66d0674925b1ed8e46df7202f2726 emission_res_09.out -57eb09d25544a4c34307aa55641e4779 emission_res_10.out -8d12ec45f71325e796ea75bb4710028c emission_res_11.out -6dda19163e544657ba9f2fc3400aa973 emission_res_12.out -8b967acba3c885ddce0ae783ba0212f7 emission_res_13.out -911f0851bc5badc8b92608f993593381 emission_res_14.out -6a6947e5218a7072466eb7ffb9eb4271 emission_res_15.out -cdd010c54dcb24e9d6c62e18e84407da emission_res_16.out -31f1a9a4b683a7e82366e0afc98f1079 emission_res_17.out -991faa4c173ebf532809243bbc8b3678 emission_res_18.out -3cbbc6a0f562b15d79ae96cc823d1d60 emission_res_19.out -75f1c6e728e51d0acaf647714d1d593f emission_res_20.out -aa870bade9e0a98de9827e1e269212bf emission_res_21.out -3035fa967f38071bb11e251c68d9f25a emission_res_22.out -6caa6ae9838d79e03da7b094b25bbc68 emission_res_23.out -fbce3dbbdaa98e229f4b9c61c2ecb20b emission_res_24.out -aa726582feeff44a64c9ede2f3e78d61 emission_res_25.out -d94ef4c471c7183640484debb1771e44 emission_res_26.out -0eb4ac9a650934e40adecd0f85c637b2 emission_res_27.out -452e3090de49d2d6e4551a18ac60f237 emission_res_28.out -53cd0ad3af881133db8a912e89dd9528 emission_res_29.out -8f3c4a985d8e2d11f4c6da90cf0e6846 emission_res_30.out -4262ca63dcc651075bb59617f65972bb emission_res_31.out -c6f7335aaa54a7421aef606edc2258cb emission_res_32.out -9dd9050842d61421da40dbf6bfb998a9 emission_res_33.out -636fe2645898c20a72749bb77d5d5ad3 emission_res_34.out -a2afa9ba16644b31f859d7e4297c0a00 emission_res_35.out -d4e7c707e2848aee23d619d2e46109b6 emission_res_36.out -e47f99ab81e9d3ccea9693ddc5da352b emission_res_37.out -5d3a4c2cba8495860c73798a48fb1325 emission_res_38.out -59af29f9d38640f8a76c49b59ff1e143 emission_res_39.out -2ced90af6c8df708c28688f64985acfc emission_res_40.out -2819187e87ed0b04e8fb05c634c1d4ea emission_res_41.out -b2f4aea92aa88c781cd54f2ef2d9bd11 emission_res_42.out -36fc15b750facf2f6f729451a123032e emission_res_43.out -2b8bd5230679f3c807ac13c85f094831 emission_res_44.out -f774a3f28a9be20edd861b695581b797 emission_res_45.out -1b1de404fd17020b0c099a5053044a68 emission_res_46.out -31d7f2a98b9c5bd20689d8b4dfdf574f emission_res_47.out -59baeac212919a9f44892c41721c52d5 emission_res_48.out -152a4d3bbad37cbd8ce417f303e969d2 emission_res_49.out -efbaa0aba0a4e49436bf77516525da55 emission_res_50.out -21dae876fcfa6091252adeb2e10f1503 emission_res_51.out -efc735a3b5d57838a235fbffcf6b6b13 emission_res_52.out -a3c8f4a8b1edc5b794f1f9d2f458b556 emission_res_53.out -6317be52fa56d2134e3ced18965d3410 emission_res_54.out -6dac75f4d6b3c4c1f95d7e7d9303f78c emission_res_55.out -8978d4d59bc119f8e2196ef5e175983e emission_res_56.out -96fc15fab1d197aec789c2f265166ec0 emission_res_57.out -6c5036b78aa57b9739a11b489f05e398 emission_res_58.out -fc8dec7eb9cb5720ef44edcd3f9c1168 emission_res_59.out -1ddcc244cb48e8e7048ef1837f9ee8e5 emission_res_60.out -684fbe82ae14a56cf960afbee65044a3 emission_res_61.out -da7c92dfc3b98506ed68f435f00a71cc emission_res_62.out -9180fa37fc2fdff048ffbd7e42495d3e emission_res_63.out -672eeef20a314a169b9dfcaf8f936837 emission_res_64.out -e645100518799507f938a0fdd0451f4b emission_res_65.out -45e95a27230e32ba6e291a0cb78dc1a5 emission_res_66.out -67d27a28accb24698c3ad7772ba69fc9 emission_res_67.out -ea19a76785add30a7e0b232196e1e504 emission_res_68.out -c8afbf92f760e073faf7d889533fd7f1 emission_res_69.out -0b27b231762bde5cc8975f5e255e86b4 emission_res_70.out -3b4278b2469e50171c831ea587092710 emission_res_71.out -d7dd705a9d87c517be71b46462d5c7e4 emission_res_72.out -c90d904005fed8f1ffef202ea075c281 emission_res_73.out -92c563f4381ea8eea4707f8753bb360e emission_res_74.out -d30c25bf0d7749e58029d7c91b2139ea emission_res_75.out -955f5e83f169bdf4512aedc09fc153dc emission_res_76.out -2b44377ef038e2606f6441e8262f868c emission_res_77.out -0d900572e6b0f36d88c8877d85b874fc emission_res_78.out -e4587960bc6b67e7fc125a5de40f70aa emission_res_79.out -296a4b84012fd2f4d66fc6d39313ea53 emission_res_80.out -175fa6078bee8f2a024e3277faf0ae9a emission_res_81.out -ec8e649c4ff0e636234b30cb3677cc75 emission_res_82.out -d98c0451ff994a2a1fcd34c6655b174f emission_res_83.out -3320d35967c3e9044b8a5e898ebe73a3 emission_res_84.out -eb1fa54ee6a7055f1709299feeab2460 emission_res_85.out -c685c19f6474ff59678c29f00779cb7a emission_res_86.out -972ffaf9ec2ea6a76d3819ace819e5c2 emission_res_87.out -91189c9c1c9cfefbe42c87f04d364042 emission_res_88.out -86d904a4a4d1de6b5d7533137b20034c emission_res_89.out -f199a95eba3f4f0db43d4c0d8c438380 emission_res_90.out -a85bb6f020859f8b300f774959ceac5c emission_res_91.out -ae4ff4dd21a97db19687391b1b46792d emission_res_92.out -5fb28c927c6c12a52053c44a6c4202c8 emission_res_93.out -5ce01294eca18e0abdc5d4b2a571da5e emission_res_94.out -6c1ce645ab99eab82cac89b63787297f emission_res_95.out -462023d2e193bd66ce558feba3aaa4fa emission_res_96.out -3e9c8c29fdd75cacd938abe50992be02 emission_res_97.out -403a0e32d098783bf85bcbe0d558d3a0 emission_res_98.out -c1635504e05d5385b4e4239597c0fb40 emission_res_99.out -63c08dc7b8ccabf2c269960a65f688e7 emissionpol.out -d3fd2285e70955f1cc0015f60c405d0b emissionpol_res_00.out -308871c03a47c0d7ec4b431a75f886c9 emissionpol_res_01.out -1b28b079d01630c2fcddc3e690ff8d7b emissionpol_res_02.out -a29f5ce1db61ecc18467a85f09681df1 emissionpol_res_03.out -d1f522a656a10fb38c563155f0d6a334 emissionpol_res_04.out -a92b8b6a5b013f502861bef272782a28 emissionpol_res_05.out -2aea4b40afb439e0c089803157e80578 emissionpol_res_06.out -5e43d4a332158a9a2307eac5c1d5eb67 emissionpol_res_07.out -2f512192a2492461634a0151d4f48d40 emissionpol_res_08.out -d1df861e4328abd31bba6ca310c8eeeb emissionpol_res_09.out -160b39237ad3f9d17852d10953c81e6f emissionpol_res_10.out -3047a06e170e7f1e44bc0721606e37c5 emissionpol_res_11.out -c5b41dd7b03968d2a6ed4bc49284a0b8 emissionpol_res_12.out -b9d596fddbd448a0600738401513ec82 emissionpol_res_13.out -9fe458b1cd160a5e6656fbdf3ae9f959 emissionpol_res_14.out -cdc1ad383a9f0a26ba1b9eb0a656cecd emissionpol_res_15.out -6f4fe0a33429243d383ab24b20e5d1be emissionpol_res_16.out -23443b3b8a9dac0b2ed750d0b651f70c emissionpol_res_17.out -30b17e0b0fa6b1ba688e084fe7215e60 emissionpol_res_18.out -61fbe837b3efdf9e526638589bce91f2 emissionpol_res_19.out -e17d82cb4e4c6a12549b3fbfdfbc413a emissionpol_res_20.out -5bb730b928218b158ea39f2af8d06ab0 emissionpol_res_21.out -125a6e8c1e54962c41179223087d1b4c emissionpol_res_22.out -1d33dca00dd0c57de3906cc2bbe6e955 emissionpol_res_23.out -fd752eab9f85c972ce6b23d699c7a469 emissionpol_res_24.out -e98538230b4ef5811a0c9579ab9449dc emissionpol_res_25.out -5b7fe211a49fb06527aac13a5aae1295 emissionpol_res_26.out -b5ae5f24940126629d8d4230759a7fd3 emissionpol_res_27.out -48ca345b53e95f7fc9788672fab24c3e emissionpol_res_28.out -b3a9777e7286cf80e123cf796b470001 emissionpol_res_29.out -e7ee7d0209e3385f74dd716673cbd6b3 emissionpol_res_30.out -e43f175eee4c923725daa2e3aef62c2f emissionpol_res_31.out -dacaf58b64ab2916cc85a5d1fea7c5b3 emissionpol_res_32.out -7c9a30a1b6100a8a720941b8d285c6d8 emissionpol_res_33.out -4da39a1b4d079987345a0787e9f7fda7 emissionpol_res_34.out -2669d736b94b86ac093ff48ab274107a emissionpol_res_35.out -7fd8f3efc4fae02de99599ff0a4c8488 emissionpol_res_36.out -da905542d7f3c74f2561b8466afd5bf6 emissionpol_res_37.out -8db02ae6e7dc059da06dfae896c8ceb6 emissionpol_res_38.out -fdb16ef0702e30114256867315b0e9e9 emissionpol_res_39.out -dbbe1a529a5d391bcc20b223213d92d2 emissionpol_res_40.out -5a307a524835f21333bc7f21dcccb827 emissionpol_res_41.out -6ff41374c110ed5ee6558e2a0d565493 emissionpol_res_42.out -6231afb7cf7bcca03d44f04e1e0be24a emissionpol_res_43.out -df710be0c67216ac30f89a8cf3ae31a1 emissionpol_res_44.out -af060277fb07b368adc8df1c90a5df82 emissionpol_res_45.out -cfdd6cda0a4f2dd7600f82874ec45be2 emissionpol_res_46.out -34272244db61960d7f77db3c03420301 emissionpol_res_47.out -23028d78d4476900b2346bcbd768f34c emissionpol_res_48.out -69f20b088837a2484e68b23a8e5cd4c4 emissionpol_res_49.out -9d55166d939562fb15465a7e5536a0f5 emissionpol_res_50.out -f4bc79630d422793b6be954e5e9eea01 emissionpol_res_51.out -e40fcdfe7495d4a7619894e335fa7fe9 emissionpol_res_52.out -bebd97d25b986cba842f320fe313e479 emissionpol_res_53.out -8dabaf64a84d7c028b421f4842b03e54 emissionpol_res_54.out -f90ee1758c58ed1f0daa79ced6422a14 emissionpol_res_55.out -7fb346402d64e59b065fee23d6f2c093 emissionpol_res_56.out -2a96e45a12b2846e4ebf864d0131af41 emissionpol_res_57.out -171d8d7164ae1b4846957d83fc50bb81 emissionpol_res_58.out -f80382dcdefa35c35629e97a7a2661fa emissionpol_res_59.out -23b652a19902a824fb4873ab93ff60f5 emissionpol_res_60.out -3f15e4d4c1cbdddcf867fc3d1721b2bd emissionpol_res_61.out -f843c48f229438fc67467509fafd166b emissionpol_res_62.out -df738ff1f0663bc8f7297f97aabeba57 emissionpol_res_63.out -84c0890f12df32f4086e3bb5299b8e10 emissionpol_res_64.out -6e6fe2f0e9fe07e6ea7b51d8a326f1a0 emissionpol_res_65.out -1cbe9aa9b1ceab37c599046361be9e4d emissionpol_res_66.out -6739bcb2a1384eba0f1ee416273a6fc7 emissionpol_res_67.out -bcf6b444b5a1fc52574d2f2acd672732 emissionpol_res_68.out -cd791cb0bca3414a60acd237c482548b emissionpol_res_69.out -52d7edca13a008da65c7719c1e45c042 emissionpol_res_70.out -03c3b9c7a62167ccf7db796599737bc4 emissionpol_res_71.out -8b265427b775eac2f5ca2296368e51a3 emissionpol_res_72.out -28c27816440663524f11789c752277b0 emissionpol_res_73.out -b57477500025a7738609c4b43457b075 emissionpol_res_74.out -baa345863298657cf69ccc87d5eec88b emissionpol_res_75.out -d6caa5fbe2205d9b441286fee7a15ce8 emissionpol_res_76.out -5c6e5a0537d49d8416ef36cffb985a59 emissionpol_res_77.out -f76f3935845dd71495c0aa320db40213 emissionpol_res_78.out -ba8b2592cbceb896523bb20e31cbc16d emissionpol_res_79.out -8ea3ce708190fadb07713ee0a462884e emissionpol_res_80.out -a5bcaa056953433f3139bdf1200c7845 emissionpol_res_81.out -8b8ce1ea6d7478c841d0fcb764d6eecc emissionpol_res_82.out -951f7d562d3970c750a921183e489589 emissionpol_res_83.out -c2c171d2d4eaa1c20760c2eac17e4ae6 emissionpol_res_84.out -6a3ef62f0573372d5e931a895c5aea96 emissionpol_res_85.out -1aff143ff0c68a6b970a596133bf1d67 emissionpol_res_86.out -a1c4caf74d536c25a11e403170e91889 emissionpol_res_87.out -dc1e8ae8942ff39dd9c8cc8a4112cce5 emissionpol_res_88.out -3d0146cf4da1f9209cf9d39792c1f7ee emissionpol_res_89.out -4adc0dbaade7dede08c07b51255a0cea emissionpol_res_90.out -c135e3ffcd2b65453bbbc705abdf0d71 emissionpol_res_91.out -cb92202404806fb540fbe80a3092ab93 emissionpol_res_92.out -3e2d05849569255d9cc9be0ab38bb1dc emissionpol_res_93.out -75004b60232bdf1d5ded29a663cb2baa emissionpol_res_94.out -2574dec506ea4fd1ed98797c11082e39 emissionpol_res_95.out -cf6faa03ada10659d055b18036ed5c47 emissionpol_res_96.out -dcc893dde414a617da8ae21c26298823 emissionpol_res_97.out -e2616c2707a124759ab2a7e7e341027e emissionpol_res_98.out -2b7ea674ba157a05b68aad597eb538d1 emissionpol_res_99.out -d50eb2c8f19a7fccfc2f6090105f0e3b emissiontrue.out -1e92115d50507c60620628fc11a1464e emissiontrue_res_00.out -d649e88a19ecf500bd8ee84b60c68632 emissiontrue_res_01.out -0f1144da52f8f95a781829c65b5ddf83 emissiontrue_res_02.out -eefd6224965de03b47a7ac4ecac8812a emissiontrue_res_03.out -fff1db4bc03ffe50b8766d1771a64019 emissiontrue_res_04.out -74e5a9216e1dcfb60aee217c8edc4028 emissiontrue_res_05.out -aea912b1f0beb8f0c82d9d4a624f9c2a emissiontrue_res_06.out -d81789a4ba3fb9f7495c26d2340dd545 emissiontrue_res_07.out -37b40b1488be754d65a6aa8e8daf766c emissiontrue_res_08.out -d0137d4de37ea587c8f763f58ddd106d emissiontrue_res_09.out -0277276df0132a3b853c0916501cb1e4 emissiontrue_res_10.out -0f268e7cea4697bbe22834da18da79f5 emissiontrue_res_11.out -15e36d8cd5d079d965da1853e9e40447 emissiontrue_res_12.out -48e793814f3726c194cf29894049c49b emissiontrue_res_13.out -8a9efdd895e21a79e9d3306d219ffd62 emissiontrue_res_14.out -af7fbd2e9f002dc262e22f94d17728ab emissiontrue_res_15.out -b411905c57e32269ca1eb5f3e881cccb emissiontrue_res_16.out -72a350f04aabac272c1d430d2c3db29a emissiontrue_res_17.out -df561ccd66719afdeca6c6e8f25847e9 emissiontrue_res_18.out -d49f624e7648c4c113aa148272a2d4d7 emissiontrue_res_19.out -9a016d0d050157c0f8f178551cc6e1ca emissiontrue_res_20.out -98170aa4146836d601c195a33e6bec46 emissiontrue_res_21.out -57cac89a6423e7a6c6d3ee395a1f42ee emissiontrue_res_22.out -034d8d261c7335d79c6db0cf9baf778f emissiontrue_res_23.out -5a59c04e19e9c3226f2673d1935f0a2f emissiontrue_res_24.out -0a9976cdf053680dd35b62e075916e54 emissiontrue_res_25.out -a15f6dc5d574746dffd502592061e645 emissiontrue_res_26.out -58ab7259aaf1d74aa5586ac292b7439a emissiontrue_res_27.out -ba3734a17779eb2b46da1f92adcd52d6 emissiontrue_res_28.out -5d1150b5747755af15bcbb9436160a2b emissiontrue_res_29.out -5110f929f7b1c24bcda4a8e37595897c emissiontrue_res_30.out -b21460e6236b9d5c2f17925cdfdee50a emissiontrue_res_31.out -95b0740e02e15a281fde648bb03d1efc emissiontrue_res_32.out -878dd6d8742c4f28c5c58bfd68f0ed0d emissiontrue_res_33.out -f0de49cd1c24e4d57210904100cf9b22 emissiontrue_res_34.out -da99b2ee13898266d421b48a0f32307b emissiontrue_res_35.out -17f25ed0c432b34539b6f2c1d9d43a29 emissiontrue_res_36.out -d6f495075c2aee0df0fb045525749562 emissiontrue_res_37.out -9e2ffba99ffb101436a8735df3690517 emissiontrue_res_38.out -4968d9bbba7f7f3844eb1ab6b3c63a8b emissiontrue_res_39.out -f42d2d55c5ea4a28df02d22fbdf06866 emissiontrue_res_40.out -62adaa3d710357a1b1fd0eca6d4cc23c emissiontrue_res_41.out -dada4040bafad3b3cdc89fff6fc1d00a emissiontrue_res_42.out -32b8bd0e76827f0df6e7493410a66084 emissiontrue_res_43.out -0dcb0154cb953aad90de57c0a3528dd6 emissiontrue_res_44.out -a1673355821f662ff829fd4e73f7d16d emissiontrue_res_45.out -7555dc4b9868579a2e50b82638007132 emissiontrue_res_46.out -f50eda4124d384a872fad74709c9bf44 emissiontrue_res_47.out -06d9062680dbf48f3fd21ffff8aa0788 emissiontrue_res_48.out -7354204886023dc53e34acac1e7ab37e emissiontrue_res_49.out -f8e53f50f848d2072298998b7d78ffe5 emissiontrue_res_50.out -d5ba49d9f040e8e719fc5e03119e2a5d emissiontrue_res_51.out -9c2c1e044d643b9fd78fe2a55d11cf9e emissiontrue_res_52.out -baac709e05d5da6e512acc4e4dca3483 emissiontrue_res_53.out -449d568ed837bb6aa42ef4c8715c6c50 emissiontrue_res_54.out -1265465f170467cbe085be2739440ba1 emissiontrue_res_55.out -360c6ee3ae2baa83a3addb5f75bb84a3 emissiontrue_res_56.out -91b63f27de41fe8578fc4a05acf230d1 emissiontrue_res_57.out -7cce491878af1b8a761136f3575ea201 emissiontrue_res_58.out -0ceac066860965035dbcd2855ceb700d emissiontrue_res_59.out -77a0c4afb1f84b7aa8acd019db97f283 emissiontrue_res_60.out -ffce409c8cf7c0dff3fcdd9b2a7fffae emissiontrue_res_61.out -5be10b6b8131df8756f41783ebb5ace5 emissiontrue_res_62.out -2476222a4af7f8c684afa1bff9da510e emissiontrue_res_63.out -fb11bb0673cfbd71c0eb1019c9133ee7 emissiontrue_res_64.out -a1fe9c6a38655dcabaf2489257579e03 emissiontrue_res_65.out -a98050c4d5864145da4e5bc9821881d0 emissiontrue_res_66.out -c9fbffd1a159a208d46589a7a80f8660 emissiontrue_res_67.out -b15ba302d9f1f65eaf79db639561a6d8 emissiontrue_res_68.out -24c20af09e8d8af5ec6d1c4221f90974 emissiontrue_res_69.out -9f6f723545121bd9feeea27bad056858 emissiontrue_res_70.out -94a39b44fe6138f82f3d2b678d8a03ef emissiontrue_res_71.out -f0d1c8878a302d179e4212f51e7f145a emissiontrue_res_72.out -16739e447162cf73a6fee5df4807bd9a emissiontrue_res_73.out -53eca6ae88fb931baf24cab4f0a7c09f emissiontrue_res_74.out -ee952a72b53e5fe524cf2a3c8e17747c emissiontrue_res_75.out -029833142dd5c91f2ddd8abaaa6385e3 emissiontrue_res_76.out -ad0b3da7de53714412f2e1448cc40a14 emissiontrue_res_77.out -49d59175340b32f139b71270ca41e5ff emissiontrue_res_78.out -eb5d69b069a48483220b2cf9eab0732f emissiontrue_res_79.out -a267a31e0607bda6970b2e0eb41a7198 emissiontrue_res_80.out -a006b7d3ee57276874e7e60b0c4c66ae emissiontrue_res_81.out -0c243a59955c6afdda15bf05c5cd9e43 emissiontrue_res_82.out -5c0c92d77423343fc92630697fc4ef69 emissiontrue_res_83.out -3f1e34a86081713b368eae6abbdbb08c emissiontrue_res_84.out -51e1416f5331265a93c31b652d28a0f0 emissiontrue_res_85.out -89c38188b4bbe837c46f77580d3520a9 emissiontrue_res_86.out -f3fa70dc6163c45fdfed0114b854ce6a emissiontrue_res_87.out -64e311c5a24ff00d7ceb69d2f7eec16f emissiontrue_res_88.out -9a14f046a86bde7d72b03710a0bfd58e emissiontrue_res_89.out -5f32882659ea3a63e7a4e31254958e05 emissiontrue_res_90.out -15f9b96b330820be6a9b0124cbec3027 emissiontrue_res_91.out -138b284592098f03faac978ddb262bd2 emissiontrue_res_92.out -fbea179c87a616a73ea3c79937b39a65 emissiontrue_res_93.out -a91424e942988147a4d68a9d69733381 emissiontrue_res_94.out -a851650ef8aaef3ae29b365e68ed366d emissiontrue_res_95.out -be5dbaf98327cb5b972933646827664e emissiontrue_res_96.out -8e7c1ed5ecc5b01712bc18f83cb6c202 emissiontrue_res_97.out -26bb274771f3b703a287fa416d519c6d emissiontrue_res_98.out -64b8ec32403fa6739e4300427cb98f95 emissiontrue_res_99.out -a1c1ffe14b43ecccfd0f1d5d7e185bf1 gamma_light_curve.out -88dcfb985ea9a8e75acf3f88acceb9ff gamma_spec.out +e530204f33b7968990d8f45041cc9d47 deposition.out +5a399fb3c54f7ab61519709a24da7f29 emission.out +d6c1f8e9df983928979acfe4c24db36c emission_res_00.out +30b82c590e02d6224f9279da36a41287 emission_res_01.out +c6ca913f13bf5d5e3f5e854b0661cd99 emission_res_02.out +cb128e883bd22e4a5549f429aaadb918 emission_res_03.out +66a5663bedfcff6befd36fb949ab5115 emission_res_04.out +c3627206f409456ccdfefa93bad15329 emission_res_05.out +a4b4d60a05a5c347a6ec7a105f5877b2 emission_res_06.out +9c5d9d768be3775e4dfd35a8c207d095 emission_res_07.out +986895acb8539eda6c4116f74668015b emission_res_08.out +568faad0358b9e64e0311876e8a7e576 emission_res_09.out +83c70fac07f5225b73ff24ff60c19a7c emission_res_10.out +855c9ed82fb344e6f4529586f12c4cd6 emission_res_11.out +70850ddef161ab8041b1228eeeac901c emission_res_12.out +26bb682f00a5109b695e731fe87786f7 emission_res_13.out +a78c71bd2aa5e547f92d166aaf41b90a emission_res_14.out +9b9422653caab7ba3ad5528960bbf5d5 emission_res_15.out +00e99894520bbeb8e0c1b69cfbbdb019 emission_res_16.out +64597cbe54d7e276f914f089192fabbb emission_res_17.out +d030bb80b9bc4937780127c580745a50 emission_res_18.out +4fee83796ac60b7d2221f01105e01e1d emission_res_19.out +14f4a911e8f189a17a90836954d8ecae emission_res_20.out +5b1bdd9427ee9dcb63a05a688b16d4c0 emission_res_21.out +4c4e8758f9a24d1835c1e0eab4cf9065 emission_res_22.out +b0cda59a6bd3d3e3c87568ce6c6a5279 emission_res_23.out +15868460f72ea34c34977031c9d4c1b9 emission_res_24.out +879e0383a97aea284de7d714f277990e emission_res_25.out +93bd56a37bae2724c45fa47b79df5561 emission_res_26.out +ed07636809cbec0f0a7a8fa78f9ffae3 emission_res_27.out +f86ef98b8b95f73c32e9fb57551bd86a emission_res_28.out +7e436e0a5d8dff8f880273987240138c emission_res_29.out +922342865809afbbc79618b1bf891042 emission_res_30.out +8de01f27acf7f310d21c2d37ea678e4d emission_res_31.out +31ecd03506e6686980528c4f990e6faf emission_res_32.out +4da933c77838f899e9724709032081c2 emission_res_33.out +aed2306c177d37705820810c81c3d11d emission_res_34.out +e90aceca6f82afb5908e64873f60151b emission_res_35.out +06f4210b954f3bf1024ea81f824b0e8a emission_res_36.out +2b2a495c941cfc1b6d91392bd77d31a4 emission_res_37.out +e39a917dbbcdfac9648fd31620156b81 emission_res_38.out +92824f76d017903f51fd180f953d85a9 emission_res_39.out +1c96ed5cd3bceb5d0df55328f73634a9 emission_res_40.out +06f2983fb56acf267117e71b5e0f66b6 emission_res_41.out +3b8115dc7e58fa21a109452c09e56a4e emission_res_42.out +441814a73d52835a4463cb88394961a1 emission_res_43.out +5405b804d0c54f708299b228339a5042 emission_res_44.out +d33b262fe43da96c19b8666d85177a82 emission_res_45.out +66037b3f2ec5bbeb15e73adfbb956c10 emission_res_46.out +834743ee81e93fd1ed05cc05c503db09 emission_res_47.out +c9626bc9d72a87c92d14fca368092d29 emission_res_48.out +cc1e1f203056f91b993e4fe320440718 emission_res_49.out +b709e3643030d5dc24d583b73ab580c0 emission_res_50.out +f8f1b7609afbfd1163236eb4aef96643 emission_res_51.out +ab27319fe65e7e58958a7e54e04aeac5 emission_res_52.out +95a07675ea422dc0dd70f1e533893f35 emission_res_53.out +49c6e65f84ebef81a31a590346bb5560 emission_res_54.out +6322a393ab5770a302a376148c6184d5 emission_res_55.out +8ab324801dcba31c0cb64422476ee963 emission_res_56.out +7e8f7e68b388499cddef733abf30284e emission_res_57.out +8876216c7b19ade1cf05903acb8820fa emission_res_58.out +edd79a426be787df6ed29a681fe1a08d emission_res_59.out +bf65ff2e3c51b48e229d5adcfd839600 emission_res_60.out +96479c3807df4b1f84f52f563d70ced2 emission_res_61.out +e61ad78bf499bb182d59dddd39ca0d93 emission_res_62.out +72d812d4a7337ead22bc827a77e4a3a3 emission_res_63.out +4f94c37eb1a080abb89543b240088115 emission_res_64.out +a22be0413df847e54c6abae452a84cb7 emission_res_65.out +4c60d084ec7e1b4ae8d405e26eea7910 emission_res_66.out +6ef6e83000d4e475428fe0b22708b75c emission_res_67.out +c27c315f3a0f8e4411118a9444044e34 emission_res_68.out +1ac42f7aa33a7f4e97d2cf14f153d962 emission_res_69.out +0626d14f867847ec59871e9a181e68e8 emission_res_70.out +8c444826a8288658086e3bcfacefa564 emission_res_71.out +367b887adec2cbd35a50b2954099a6fb emission_res_72.out +c2c8c2b482efeec66e460fccb48c5e14 emission_res_73.out +65d4edd1075cf81eaadc64de7c18870e emission_res_74.out +77a1af6bd2a30c76f45a83bf98d70074 emission_res_75.out +2e8772740b06b174715373ba5afe03cb emission_res_76.out +f30bd1d506f4ca9de4a484c0ce6e0d80 emission_res_77.out +fa291be4912517be0b03f41819617c0a emission_res_78.out +6e0d081beb36f3ee6fcbf0c8cf442b06 emission_res_79.out +45c8743a8daa7d70074a3008feb4f8dc emission_res_80.out +d44872ffa92a01c46ebcce0b50dd6510 emission_res_81.out +1bd061b75d261aa10db7933f1cc0551a emission_res_82.out +164fe0836684634d6b18fe1da932c927 emission_res_83.out +43d2f90c2d87bf62e158cb31f1d80449 emission_res_84.out +9cfe95a6f65b6e30b9ec64886bb2d056 emission_res_85.out +6056a3de70e5c6ec66fdccc11a404ee5 emission_res_86.out +e9fa7beb1acb16eb0db6572850976e1a emission_res_87.out +de7e9340fa5aed9009dc03c26c9aab6c emission_res_88.out +2db8883fe9d066deb152bf8f3af1543f emission_res_89.out +05935ba1456e74b13a004f0060b7a472 emission_res_90.out +931dd7d962982317d9eeba7f6872c29f emission_res_91.out +45c85a78188be75b7b7ad2fadf46956c emission_res_92.out +db246ebcebb8030a74de8ad2c523daee emission_res_93.out +0999b944328f5ddc685237735bdd4f22 emission_res_94.out +e1e7b71a5a1a008f632785fa0b2312dc emission_res_95.out +2c9cf708452dc7bf76102243e43207c1 emission_res_96.out +e363fac8ee22843d6e4c64b65f7ff8a4 emission_res_97.out +914c395cd135d64d7b23ae0ef948aa0f emission_res_98.out +4b94b9b8f301a136a0e2ef3e5297331b emission_res_99.out +5c02b066d7619ac531d6d34ca56f2d1f emissionpol.out +d2e4e3326c6b3a96ad612a28a8f74845 emissionpol_res_00.out +74474b71d2db51b946f551698da6b0e7 emissionpol_res_01.out +4044b6e6b7380f0a8c6418655a2a187e emissionpol_res_02.out +d285d72a96f18247b1b34372292bb528 emissionpol_res_03.out +1c153c6aecf49c7144ae543c9ea57df3 emissionpol_res_04.out +78f9f692f163e38de2dc5889882d77f3 emissionpol_res_05.out +85cac259ff916ca53f3885ce70d18baf emissionpol_res_06.out +ceea522985c6916550903f112a019a71 emissionpol_res_07.out +67c3bf92326bf7e768dce89d15aabd8d emissionpol_res_08.out +a93b1131623f140ef3cb65716688047e emissionpol_res_09.out +7d430caea2578a12a815741bdca2e49e emissionpol_res_10.out +296c19b46395089adbfb3750ec072e85 emissionpol_res_11.out +f2178f86ba3ae5413140e40834b5536a emissionpol_res_12.out +6493571c7012cdc59ed373c761ada329 emissionpol_res_13.out +4996318249ca7cad4244ab1347ffd540 emissionpol_res_14.out +b0cd3e4f53d2eee41fc911e311803581 emissionpol_res_15.out +0f680c2dea673d2a06f621a215471d78 emissionpol_res_16.out +60d80c82473bb22496f575bcb6548907 emissionpol_res_17.out +19fbb0431b7951c00211acb527b4ef86 emissionpol_res_18.out +a8e9c886ba78ea8fdb50be8b91e9e3e6 emissionpol_res_19.out +c319bff0a1095cecf5957e2421a4ed6b emissionpol_res_20.out +0647130bee43b15340971494676d8896 emissionpol_res_21.out +97de905b8eb90cda1a0f2fe9e10d9e6e emissionpol_res_22.out +28dad708ae5a0f95a971cf6bc814baec emissionpol_res_23.out +5cf8631202907db2df53e827ab7860e0 emissionpol_res_24.out +0f3ed29a53b1014a75a5a94ffb7751c9 emissionpol_res_25.out +15f364a59a86f7c83c7e01ce30716cae emissionpol_res_26.out +22cbe31443810a10d95156f89646710b emissionpol_res_27.out +78d69f8eaf62febc7b7038bc03833bed emissionpol_res_28.out +62aa60c3fc96fa78c62942d0d41713ba emissionpol_res_29.out +3db430871b1d5ec2886a53c99db8e8af emissionpol_res_30.out +89d854c930017d1c93bd139b31d1b041 emissionpol_res_31.out +747b24f70b4fd769771243581fa1a9b1 emissionpol_res_32.out +ad978aec3d17324a8d39c935a3b87595 emissionpol_res_33.out +b4d807dbc01007f2a5342da182257a43 emissionpol_res_34.out +0d5216142f0d9b5a0438c4352c5f12df emissionpol_res_35.out +06f76e84a34bc6dc2074d9ab42e7bd85 emissionpol_res_36.out +8715ede9663ff9f370cc93f23c9dd467 emissionpol_res_37.out +4573bc9666100969f7c97281a068118d emissionpol_res_38.out +b8f76bb26d58f21b45ec4a8c4e85a4aa emissionpol_res_39.out +2ff85c71fa29f08c6d7a88e184dd665d emissionpol_res_40.out +b2dd0b5a7925fcb5cef96b5e22f30f3b emissionpol_res_41.out +4f9076d6960254b3bedd077ceadaead7 emissionpol_res_42.out +47a26ad66436417010546454b98b0cdd emissionpol_res_43.out +93a5fef79756d22f7a447ee9b4df591f emissionpol_res_44.out +8d7c3a5ee0b828deed31fc47afc6c0d2 emissionpol_res_45.out +706ba63b1b4ed53c5ebe19bb2f69c1de emissionpol_res_46.out +c6642492a4abd69f8929c0f29655cccd emissionpol_res_47.out +5a6973e0939fc76f1e05e192f390378f emissionpol_res_48.out +1deb7bf3eec4c25a3ab1e9b1a85f1ec7 emissionpol_res_49.out +7ce0c873ce32f9ebaa311ca4794d4cc8 emissionpol_res_50.out +c1b9eead8370584bdb54c0bc13b8256e emissionpol_res_51.out +fe7e91fb64177d02cc6ef4c3230e7b6c emissionpol_res_52.out +793becc11e9ad0f0daa8de5fd24c2223 emissionpol_res_53.out +594da9f4527390dd7461514b64edf829 emissionpol_res_54.out +7783732974078d65aa98e4af56454a91 emissionpol_res_55.out +a857ad6ed02308da2792a1c88438cbff emissionpol_res_56.out +900b8f0164ccd658f48d2a5e0fd26338 emissionpol_res_57.out +9a878eea746e6fc520d975e9ad6979ca emissionpol_res_58.out +7a9eeaabd6874efcf83124f23f157894 emissionpol_res_59.out +545a40ea47a144251e2d601e57bc3fe3 emissionpol_res_60.out +11e9403c566cf88f843d745bc89abd92 emissionpol_res_61.out +67bcecda4577d16cfb86dc1404b8cf63 emissionpol_res_62.out +7dbb9bee053f3bc5fd3b6256ba60cdb6 emissionpol_res_63.out +a52cdbc66f0fb267641c4691a188d0d4 emissionpol_res_64.out +89648b0e2337fb88f2d649b25541c063 emissionpol_res_65.out +20878fe945c8615e22cc150ea45896f6 emissionpol_res_66.out +4336b3f9f9e6d2feda1c37f396ff303f emissionpol_res_67.out +dc6ab3fcc1859b69626bfc61283fa048 emissionpol_res_68.out +71482e40bc57df8edfc855d3cad53398 emissionpol_res_69.out +e12a9e7027c5328a9b0487400234b9a8 emissionpol_res_70.out +8b034d8afbd7f6e3839bc2570f18ef4d emissionpol_res_71.out +3fde41dc868a6458eeed29b535b596c1 emissionpol_res_72.out +1174467c837c6c8ffcdb9c76970b65e4 emissionpol_res_73.out +f9718b58940339539e2df746492a0a23 emissionpol_res_74.out +5f47acf327c6eb60526adb1c2bc2f5eb emissionpol_res_75.out +fbd1b46b8ecc852d610ae014d8776c27 emissionpol_res_76.out +f7bc2c8bedefa457d1806afdac37aec9 emissionpol_res_77.out +a29a6d478fec57fa3188d3c4bc7761e9 emissionpol_res_78.out +5eec68f7c1954a42a0cdb24904470660 emissionpol_res_79.out +226e459b3d316851e959012554256951 emissionpol_res_80.out +91d026b17870e73bc40b6806fbc07a37 emissionpol_res_81.out +240d825efa2f277676b3d464f5854477 emissionpol_res_82.out +764cc31d6634a3fb8d29812f0b65fab6 emissionpol_res_83.out +079f5a6f27d9cfb90d6d9099276e63ff emissionpol_res_84.out +ae3d5e359d615083969ed6fc72aa3d71 emissionpol_res_85.out +708753abb7b7089f8263ca1e8cd0a481 emissionpol_res_86.out +e92f73c9479db51cf38efb5b169a95c5 emissionpol_res_87.out +25f578c6ce60cc99764e32f1e98b74e4 emissionpol_res_88.out +5cdee734e32026dbcbb93331fd3d5449 emissionpol_res_89.out +920263c867e880f349f772a803eed247 emissionpol_res_90.out +020c0fa315bc1ce46c8172caf5d2c977 emissionpol_res_91.out +2d2e54664f847baf882816954bc33e8a emissionpol_res_92.out +7f35517d52d7877b3bf03ec30f84ce1f emissionpol_res_93.out +ea72ffecaaff6187ec916e6c72d4af32 emissionpol_res_94.out +eb9a06d129991d2ff35e8049818dbe9e emissionpol_res_95.out +ffb1aa29f7d1281257a6ef34758c5490 emissionpol_res_96.out +e557aa8587797dc331bd0f8e626b474c emissionpol_res_97.out +88294e9c2f3912347bc3fd2d7ed1ca4a emissionpol_res_98.out +8b8d93838d6afff3a6eab640d55c47f9 emissionpol_res_99.out +bda5e8fe0059ceb043103109aaaf03b9 emissiontrue.out +10015d457488d87352656b65d9948e5b emissiontrue_res_00.out +3518d3bd20c91b126ce6d8fe66e6cfaf emissiontrue_res_01.out +4878c78bf3f9a58599fffc4e934fd30e emissiontrue_res_02.out +a12eb06cd714798a34f8e028a356d319 emissiontrue_res_03.out +9b0c81db6c94aae12baff2192069cf45 emissiontrue_res_04.out +33482141c2d1f09a1800f14a5ef37750 emissiontrue_res_05.out +5bc7ba213c0b0256ca89e74da65f18c0 emissiontrue_res_06.out +40258e6a8c5d5f29834d1dc3bb66b655 emissiontrue_res_07.out +899e90f705080573f8d7fe174c19f06e emissiontrue_res_08.out +258e9ea55b73a622a05d7f6b437b2b01 emissiontrue_res_09.out +718895f942cffda3ac13d32948c9129b emissiontrue_res_10.out +eb980982d85d7a72e5c188a21a8e29d5 emissiontrue_res_11.out +a4b0c8484380433d0ac5192dc2a000df emissiontrue_res_12.out +09195f081bceb71dcf1f04b71aab99db emissiontrue_res_13.out +00210f885a7b6c48d6856cd24a674fbb emissiontrue_res_14.out +ace6cc74a8fc82bd47d49da41b611f65 emissiontrue_res_15.out +cbdc404f432c33333597c05fa8ee5148 emissiontrue_res_16.out +4c42a48ede46da1f2bb6857512171377 emissiontrue_res_17.out +0ae7b841bf8450b9f685264fa4d0c450 emissiontrue_res_18.out +5dbcf73079561394914d8b486e477484 emissiontrue_res_19.out +e81314d5f5636e4a5dd37c4249fbe42f emissiontrue_res_20.out +d6b721d4e009e70d4cc465e518fce244 emissiontrue_res_21.out +ecdcfc1d3055b139303fb9d0b4a3c2a9 emissiontrue_res_22.out +2a9769639902c664def96258275e1a7e emissiontrue_res_23.out +82a5b639e06cd6e4c65dfd398c10bf8a emissiontrue_res_24.out +3dc10f1ecb1ca0d73debed57a0a6d1da emissiontrue_res_25.out +d19c5e4c4d85402466117a0482675cae emissiontrue_res_26.out +566ba991ec8bfd73284d4c54eae60ca2 emissiontrue_res_27.out +5efdf60174eb6f700e4143c65c525f09 emissiontrue_res_28.out +03098cbfde976a824567bd75a43c5205 emissiontrue_res_29.out +a2be8d4a9f88e74a94e15d4e2b2d2937 emissiontrue_res_30.out +fc9f3247dfa33251cd623fe7c485efe7 emissiontrue_res_31.out +f5228a5ebbf816bc6ed24df3437de43d emissiontrue_res_32.out +ea24b3101199e856243fd617b29d0bfc emissiontrue_res_33.out +f43e3cb09d7f40785549f78217f759e0 emissiontrue_res_34.out +579d6ca8c3c6c2fa2177bf37f808e0b5 emissiontrue_res_35.out +c7d6d3145fefef3be751ab993c1eb632 emissiontrue_res_36.out +fb3f20af1596ca5f7cc3f29e8c711d3f emissiontrue_res_37.out +10823952aa67d66c81ff7a46a0fdde8b emissiontrue_res_38.out +0a44152178a545d671066767735b6e8e emissiontrue_res_39.out +b43edf7f057a58a851554a7dd181e64f emissiontrue_res_40.out +2b772be76db2e3ba8462f346a23b7504 emissiontrue_res_41.out +44b743e0e459e265facb46125fee4d84 emissiontrue_res_42.out +470d7ef6aa5dab5d9f27a7d563b138cf emissiontrue_res_43.out +3b6c551207a22b9b351d2a612fb3cd67 emissiontrue_res_44.out +3cda0b7dcabb4161f9c0ae94278dc8f9 emissiontrue_res_45.out +64e6edddffcb1507bfe1a927350af7ce emissiontrue_res_46.out +0a2975d0ec3c004a94087461732d4cde emissiontrue_res_47.out +179222c09007d9d0c27354849ca3b83a emissiontrue_res_48.out +669cd44fd9e37f4ba79ec4c1d8115f9e emissiontrue_res_49.out +3c88bafc953c49374984466f37935052 emissiontrue_res_50.out +a60403b91390d4469b5ead7884247b26 emissiontrue_res_51.out +74fb43be64d60378991a208ed6a4daf7 emissiontrue_res_52.out +06b3a898579a882c48c38703e2920d16 emissiontrue_res_53.out +472731d6ab60db7fbc57b09c951b64eb emissiontrue_res_54.out +effdd7040df803098b275a3b75243483 emissiontrue_res_55.out +708abe0321f202ee87171d6c1814526b emissiontrue_res_56.out +ecb267c84fef84e8eaab956b552671e6 emissiontrue_res_57.out +69ec063cee3b4e03d0a052806a118e53 emissiontrue_res_58.out +47348c9342bd8e400bf0ae49bd695583 emissiontrue_res_59.out +f6da2a42f8b41d33066d18de5309675a emissiontrue_res_60.out +ce37fa01aa02ac4bb58b557a510f5afc emissiontrue_res_61.out +44bfd0d91b6ce896c79d51742d672e19 emissiontrue_res_62.out +5f3ac663f60bd42da7ed7d9a2c5d9036 emissiontrue_res_63.out +9601631774f1c523a57bec286a53c6d4 emissiontrue_res_64.out +04d70ee686fac6c7ce614cbbaa7c600f emissiontrue_res_65.out +92f9b7d428130e1d9f3349c2f003b5de emissiontrue_res_66.out +5380d7422c2bb87e416436b9007b9784 emissiontrue_res_67.out +1a8a565d8b96fbe5be3d09e8c1b4bbde emissiontrue_res_68.out +587dc1ad2ef40163ed3c5b13aea1beb8 emissiontrue_res_69.out +69acea024096385b518bdbe57f744541 emissiontrue_res_70.out +4bed1413fcbf4e73feae57be1d52c0dc emissiontrue_res_71.out +bc2a9604690da007711d40cc8f3a7aec emissiontrue_res_72.out +8a616fa846b62d06f6201d91754c4f05 emissiontrue_res_73.out +2c1bbc51d0b9816eb3a02c35b76748f2 emissiontrue_res_74.out +28f455e6732f2f88daa2ca3afd6bcca6 emissiontrue_res_75.out +1cf52e925d7d7461ee0d51ac42cc73a9 emissiontrue_res_76.out +5e9c340ec6bc1fc5cd08f137ee837ecf emissiontrue_res_77.out +a8159143805a8a5433e5677e12403d2b emissiontrue_res_78.out +acec97d8f51c79a33a8fb72fc3b8c9dd emissiontrue_res_79.out +27126fca44eec2d78b89382e3d2ddbd2 emissiontrue_res_80.out +da47b7c8ee0556807720f0c2675a4232 emissiontrue_res_81.out +cdaf9344bcb9cd94c8386083467d23ea emissiontrue_res_82.out +8a726970ca90316eb89ef41fb358a02e emissiontrue_res_83.out +e80f626fc160e672e81cfd10b1ee8f59 emissiontrue_res_84.out +87be626ca782f53ca20fc2b7cad516f2 emissiontrue_res_85.out +dc645b33748e4f7cc3a0c24e36de5dd6 emissiontrue_res_86.out +45ad3c555adf24e82409371f4c9c620c emissiontrue_res_87.out +f2bb5a8bddfd6095d7b25f19bd0cfe25 emissiontrue_res_88.out +12120d50b7576d829a56249b3f3063d4 emissiontrue_res_89.out +2d987202b1af2a68b2245db9cdd975d0 emissiontrue_res_90.out +255116ee8a84196bc10603a1fdb4149f emissiontrue_res_91.out +fe9b17b020486f7c010450ac594950c9 emissiontrue_res_92.out +bc604b5ae563dca2727c9a2e8950be0f emissiontrue_res_93.out +0b983ec787e72602e109363e5761b230 emissiontrue_res_94.out +b09e8e63a1d35464ff5f3c7d18ca8f0d emissiontrue_res_95.out +5b45bfeeb891780a5a7354dfdcd2517d emissiontrue_res_96.out +4c21660abb605b1bd2fb5c4da8b636d8 emissiontrue_res_97.out +4e4160afba57e1d618e9d48dade344ad emissiontrue_res_98.out +26d829e122364cdfd37925a6b5c445dc emissiontrue_res_99.out +d5dcb365f4d8bc8fadc8aa7052918411 gamma_light_curve.out +adaf870be36864429d59a4bffc28358b gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out e08bbb965fac36412810b8769a13ab9d grid.out -e4b9d67028cba6de64e15a6efd66de22 light_curve.out -013b8c0b4d4f66974509ddb414f084bf light_curve_res.out -6a60c8e204b6679e37d10f30386d4948 linestat.out +48e3911cfdfb1cd01de3e209941e4340 light_curve.out +433c08f5cf1c37d36af7981b57f41961 light_curve_res.out +c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -c218a3271275405fdc57457c654bd0a8 packets00_0000.out -551e89fea18ab69c43980892d896e301 packets00_0001.out -a74695d325ec723d38e8a035dc5c8b50 packets00_0002.out -b4f5eace8e9349a3a6b702c811ebaef8 packets00_0003.out -93eedb1ce3a2c2bc8dcfb0d4f581a56d spec.out -82da8d63bc135f7c5098b335a1bbba31 spec_res.out -443ff2f26a56a1b577035096e17e6546 specpol.out -e594395c996007e366d8191a4fc54488 specpol_res.out +333d6dac1469f5c12ed18166ad510091 packets00_0000.out +11d05abcd28bb29b9746c41ec7ff0bf5 packets00_0001.out +43bfc8f9890c6bf376bed6ac29b16692 packets00_0002.out +fb28ce31c9e18d2cfc19893b50ae39dd packets00_0003.out +e5b85d37c6e4f132501b9307c3badccb spec.out +7adeeb59b305cc5ac524f5ff36dc2adc spec_res.out +60a61f3785c25696148120f55b346fd1 specpol.out +cac2d26160630a03e404124358209697 specpol_res.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -390501396ec721bd855347cdfb31e708 job1/estimators_0000.out -1ed27e467f2cf74d5cce76585a5395b8 job1/estimators_0001.out -d6d3fbeb58ab90cb576fa4ca02def050 job1/estimators_0002.out -03c32e5a40092f192b4fad4be798bc42 job1/estimators_0003.out +be0d877dba38047748d2e08828e724e4 job1/estimators_0000.out +6568d3f123c47bc076dab17a98dbd45a job1/estimators_0001.out +c512d08767e7bf97dded2d2d3f67e264 job1/estimators_0002.out +ba5f21b2b35fe8b1afb8605b1b8d7cba job1/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_job0.txt b/tests/classicmode_3d_inputfiles/results_md5_job0.txt index 15e5f0cbe..8e70cd689 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -6a5510f9d5126f62fe65ea11f76af72b absorption.out +22584520a4d8df15bb83d78638fa2779 absorption.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -fd04d11f6960f0f99e31fe243051084e deposition.out -558ee7d654a300cc3ad478fd74b20c11 emission.out -680cc0d3c4ecee72bea9a2e0c2454df8 emissiontrue.out -357bc2aa8c2d69a38f1c189a998c935f gamma_light_curve.out +5aef6a0b0a65a324be1fa964e0243e98 deposition.out +28def04b3442a9e047b10d65516d9491 emission.out +661cfec77a5074aa7d894844ec166207 emissiontrue.out +278c45900488ee4bc457f36b1ff413b0 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out e08bbb965fac36412810b8769a13ab9d grid.out -f2cb121d9941d7c3ebd59eee25a8c9d2 light_curve.out -6a60c8e204b6679e37d10f30386d4948 linestat.out +0440dc46a5b58d64e60f6c1df8f4b43d light_curve.out +c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -40c324ca17f8fccec763cfb7ce81ddbc packets00_0000.out -503658330ea8a3d1faae20d952eaee55 packets00_0001.out -a254dfb37db9eb536d40948b140cf80b packets00_0002.out -56de76c244b04137473bb437052fd18f packets00_0003.out -fdb3d9de60da03e358b37bac30907ff2 spec.out +0aa35be1178e74ba049bab976cd4a53a packets00_0000.out +241511f53ee7368b8bf212de0a08f924 packets00_0001.out +0bab8771cc794e813e2c6fbad0555862 packets00_0002.out +62732c40e733011f354a8c44ad3b79f1 packets00_0003.out +98c95bf501f2fb6311e4f06a705052ab spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -cf7571c11e38e451b6bec5c6564654c8 job0/estimators_0000.out -6315c47801e2168b64d38b38e119253d job0/estimators_0001.out -320846c205e4674f69d2abb3db5d6eaa job0/estimators_0002.out -8e94b8ab52e5f89fca0135cfdae24bf6 job0/estimators_0003.out +fb5f4328af54eeed1c14fbac339e7cb5 job0/estimators_0000.out +79730a9e4fa9814eac0f66f00a776c86 job0/estimators_0001.out +4e4de9e1b6c204d2ec8d7a6b99a68fe8 job0/estimators_0002.out +6653b09650df3dca8f231b48d4211b91 job0/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt index 229c01f78..d9a7b5d2a 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -9043a925b102e512a4854a3de880e32f absorption.out +a68ab8919d91afb5c3a4b28bb98b75b8 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -f3a3b8c53df5e147216c247cc0de35d4 deposition.out -5414af7cfe6d1dc9f49396f5fc8c0b82 emission.out -77867e60ce94101ea9b046337ee39e04 emissiontrue.out -d2bcae2c099b1c3fc5c25452065c4bee gamma_light_curve.out -f271da3efc68490cad51460aa8b53e23 gamma_spec.out +1dd3dd203c508b5f9e5020988a8694c0 deposition.out +065c01cd760d54a888a939dfe00378c4 emission.out +f345c0a8d5ae60ec17b7bfa78d61abb9 emissiontrue.out +dd314f8317220adaee8b48aa1b60f2a3 gamma_light_curve.out +9148bc2382bb01fe9ffa140ff86a5707 gamma_spec.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -37aaa6ce6743ab57a41ca10db799fa39 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +f0b726a4dfbbbe17d71e182cfc251e72 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -4a917b12e8982e278b5f4ad21fc1ba98 packets00_0000.out -621d58b8703b403e0829759180a69b82 packets00_0001.out -48973a1bb0d0ca6b74540577be4dfa08 packets00_0002.out -6ed4839f8392a86f916fad01457c6259 packets00_0003.out -e1de2bfebbe2a4ec4bc026c94c259fe2 spec.out +4c54bcd871084746f43ad26453c039eb packets00_0000.out +0c872ac2a44f70d6d3fc9ffaf9c64338 packets00_0001.out +b5ca49a6f951391b5083c421501f645d packets00_0002.out +377af72746a6b1d93754130a3ff6f642 packets00_0003.out +5bc66d0e2f639e2cd2d2a8d9a6487c3b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -772e04600688399f64b456d57fc9d589 job1/estimators_0000.out -9c577d9f7d6ba26fe08a000bdef2112a job1/estimators_0001.out -728703475de78f7cd6b19ed25804d6fc job1/estimators_0002.out -cafcd8af12880610a081607341659f4f job1/estimators_0003.out +73aabc4ca257c9ebae6d7565df848e0d job1/estimators_0000.out +8b98deecd085abe3250f53b9b91161ad job1/estimators_0001.out +ae916593c7b194b9378cc51994b439c6 job1/estimators_0002.out +a7141c81f9f07c07b9520f9715ee9edc job1/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index f8f9a9050..942ff7aaa 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -6612e0e192ebaa7222ea80c135b07240 absorption.out +9b6e08da1a7ff4bb095586408e58c0bc absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -0c49c4cfa8d8ebdd3d75db268849dd01 deposition.out -6770426d4cf091b8defdc2a9f466d047 emission.out -e89d0ad5e1b346ec9f1de260e483fd99 emissiontrue.out -ef28712aa9caffa21463d40732bf88ce gamma_light_curve.out +91eab029c292915e999f17b361c01976 deposition.out +da000c6330f226464a3fc2ba16eb8beb emission.out +851560ece3b6630497d362ad8c69a127 emissiontrue.out +a65c34c5069444d22e04c7efb8bd0d69 gamma_light_curve.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -6cdf515af89c069795fa10fd26d54924 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +ba3d39bcb52c8f2f4bb30666cec29607 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -13ffbcfde4e3420b941240ddd74df716 packets00_0000.out -5bee476ad9f4eb613b15395b7588d9e9 packets00_0001.out -3114af660a585f68fdff7a0971e69d38 packets00_0002.out -8f79a881190938de1bb7c79601592727 packets00_0003.out -23fcbf4f2756078ea8b022fd9f6bd7fb spec.out +c028370406b2659f1e2cc8f7b476305f packets00_0000.out +d2b546c1df9ca44beec2a25fe5cd7a12 packets00_0001.out +37dd64d999dff9f764006b75b37c2627 packets00_0002.out +209c278c8753e7d57ef1120c4b1e8c59 packets00_0003.out +d90011df9b26a1b201891122b690b7e9 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -198363b716e60ba18c6a83338230f77d job0/estimators_0000.out -284a9e68c0a5a3a16ba2e1b97128e1de job0/estimators_0001.out -9466da87988a7a31786899edc936f688 job0/estimators_0002.out -d0faa900ea61cfac965045ebff22c5e7 job0/estimators_0003.out +2692110b12c41e4aff7c3407e0689961 job0/estimators_0000.out +4cc527f6893669a38fca316fbb2a41f0 job0/estimators_0001.out +49b4139ebb6c1401101ec15edef4ccec job0/estimators_0002.out +0be0aadf1444386b1842d90f47a2c4e8 job0/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index d81d6078f..ff38445c8 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -107e1739bd28d7d7a9c0c3bc018858f5 absorption.out +0b8379bbff5216cd6abcba82844b8487 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -62ec3028277a61411fb4878f33417790 deposition.out -6342d0dfe6524ee53bb3123c8ebd4a62 emission.out -8109358398a905d45c72709788195cfd emissiontrue.out -d0dde0dcbd5ec7e0593875e87328d94c gamma_light_curve.out -2bb73a7de8958d9dd3192469a379e021 gamma_spec.out +547a1de3163dec22eeeb454e95a47547 deposition.out +68213044ca74286c2aa953c5c5743a11 emission.out +a706d0f17dbbbeb6fd110b07fe6e4c6e emissiontrue.out +79d2e235c3f3c1e9d1b28bdbc5becf63 gamma_light_curve.out +f02c3fa27c869ecdfa683b3f322e4c97 gamma_spec.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -14bc0d07d9e35a645ea19c14d0957e71 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +2c58924b06fa661e845332174146b70b light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -8b7123e0603cd3ebb6b140af44648fe3 packets00_0000.out -9df44a85702594839856228fc6d8107e packets00_0001.out -52bb407bda6ca5c969decdd535541eb8 packets00_0002.out -2069061a9bb06052fe9b24c2beac0e47 packets00_0003.out -6dfd3b8134b8a1996664e3051910ddf1 spec.out +bbcda55b0e73fc6e59fe4af09174a9b3 packets00_0000.out +dc26f3f4662cbfa1952c414176e5ce13 packets00_0001.out +dfc316731561dde7037c8e8575bc15c2 packets00_0002.out +0a105cb9c97ab225676df616564e7328 packets00_0003.out +5d1b8350c2c7114b1481465644191e68 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -fc47ad3d373c59ae40140cf34956042f job1/estimators_0000.out -e1e45681fdaa388b8f737e2d6afaf262 job1/estimators_0001.out -878b571cdb92c02b2cbe3d4dc2c45a73 job1/estimators_0002.out -0241e8ab3bedce1570cfd44f982a5b0c job1/estimators_0003.out +e652bc4aedaa3ac656a223a4243a412b job1/estimators_0000.out +2f66598613edb2fccfa5e6e63852971d job1/estimators_0001.out +1bb8a67807243dfa484fae77e8a84c88 job1/estimators_0002.out +39a87321a11374d56d67575c20026ee4 job1/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index 704ba4360..abba9d368 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -51cffad535f5f1f7048b98a20328c387 absorption.out +888fe6d988b6fd0d9b59cf3b55b5a575 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -cd05d16e058461560492918152cc74c9 deposition.out -d8e908d32c96818b7b61cdc6d30aa0e4 emission.out -be12a56b07b334d266766b98d8122226 emissiontrue.out -21e3d0c1c663ba466729e1a49e8cb23b gamma_light_curve.out +ed7c357f88e63609dea1a4ae6401adc1 deposition.out +75bb459780e3ed4ee46ec1448027da7c emission.out +dd986a6d56658cd9bc80406bc4c56030 emissiontrue.out +7724afce818c73150db50ce7232d1a5e gamma_light_curve.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -972b71d48c29e32b421f543abc7e9bcd light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +00f1a6e50058ff026ce3ed0511ea7ce7 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -0cb977265ca330b6a6aa4c9e438b26de packets00_0000.out -3e1158741de20ad475a7c72524104348 packets00_0001.out -dee42e74dee1a2d5138c3f4f15861dae packets00_0002.out -87490a35fae65ca82ecd0ade87260f44 packets00_0003.out -04681ed38a39014bc297bd7c60d67cfb spec.out +ae937aa10f537a4be5879d2148711c7d packets00_0000.out +242f927ab741ee4fa4cdab11c057e675 packets00_0001.out +7fdac7c300f071bfa1015ee244ca7d7c packets00_0002.out +4e44ad72a46350ab16c5b4112f5cd44c packets00_0003.out +2d154c74193a57d21c3b2b31c33bee9e spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -35fefbf79caba333c8573956dbae4ada job0/estimators_0000.out -d2434a26bbecda34b2b051f7f9b4a171 job0/estimators_0001.out -d25a6da8da74e97ad24c05f9572763e4 job0/estimators_0002.out -080ad1056c855233c76cbaaee0699569 job0/estimators_0003.out +d7b0375369454baa750d6d7ab743abba job0/estimators_0000.out +f00f8c1829c964cecaee7efca667efe7 job0/estimators_0001.out +061900c0d8d04634d41befe29dbf74a2 job0/estimators_0002.out +cae5f71cfbd120dcd89270c8d4afc038 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index 2c05b6696..c17f3aeb4 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -40145cba9d7b26338c83d9b29b8fca8e absorption.out -a49f6298a24abfdefadff10de4976db2 absorption_res_00.out -7ba248b7fd4de1ded733d51962cafa87 absorption_res_01.out -64d551ea1402a6b49d97036bba0de622 absorption_res_02.out -e2a27a86b5c97e80b5f5248c4e7be7ef absorption_res_03.out -e4b34c85c690d3a5e5e854827f4a2ce2 absorption_res_04.out -93bbd35d8146a32bc1790a2c662cbdf2 absorption_res_05.out -7413dccb5748bdf338a09bf164b89c80 absorption_res_06.out -3e9d56098faa2bcf4a08b21807a65f85 absorption_res_07.out -bd757553bc9e139f2b19a7fce69ff965 absorption_res_08.out -b9c459deee045af874a92120496cc99b absorption_res_09.out -721280f6d3d2ec4b49529ffd45107585 absorption_res_10.out -f46d5be9cb1047eb0f70e472ddc29593 absorption_res_11.out -f11ac66c4937457c7d7add9677bc321f absorption_res_12.out -0c41ff566810314a6c9b2e3f5c5283e9 absorption_res_13.out -8397598be6eaa5bd366e3c46ea866583 absorption_res_14.out -96161473cc93196f93fe151ce759c772 absorption_res_15.out -ebf7d755d85572e83e9231a5ab8fbb57 absorption_res_16.out -16b0ce6033611e5b4e5404b89129642b absorption_res_17.out -d790820dfe5c332f3ebff5e3fa894d33 absorption_res_18.out -076a81f09eeb01ad930ecd10b0bbdbd0 absorption_res_19.out -c3f42930e4673c088c21a31ed66b9cf2 absorption_res_20.out -bc05397bec43166b1ef78c73e30fa210 absorption_res_21.out -0af6702e614090fdd7a5826516b32d45 absorption_res_22.out -bcf739c5099518ece2f578a92d0d2244 absorption_res_23.out -c17b6bf0abf77b165fb7fce59c7b914d absorption_res_24.out -dc406332035aa69613c01f6386f8f0aa absorption_res_25.out -cbcff2c0bb5436d50d2d20fed43167b4 absorption_res_26.out -d800f243d1a47195dfd8306112b587aa absorption_res_27.out -2588ba7e0414ff9940c503e3c73e23af absorption_res_28.out -00651b80a0d7707fa114b36c0248781e absorption_res_29.out -e9d3f2b71242353a8e54f9e7d52b54dd absorption_res_30.out -92954184ac6a24b856976108c5602279 absorption_res_31.out -eed4ec7cd32ebee3af246687f79ec370 absorption_res_32.out -d0ab47b53d16d830384db7c43a31a641 absorption_res_33.out -3660974f465785ff887ac91629ca35cc absorption_res_34.out -259dc3519aef8246d9b461a7a1cdbce8 absorption_res_35.out -8cbb8227115770ece2b136366f1d3fa2 absorption_res_36.out -6cf09f9d3431124e59499e735f243ab7 absorption_res_37.out -247c6c37b35a5c43c69fd4ac03a9b4d8 absorption_res_38.out -ace28f213217bb947eda2ed5371cbeec absorption_res_39.out -319f135699776f00ee4898a1f9886246 absorption_res_40.out -5dfd7cc34a2a0efecdbf39a2009615f1 absorption_res_41.out -3b44d8ef089edef98a68a5fcf90b3d42 absorption_res_42.out -0dd51a8baa980d8015e154a908e087c1 absorption_res_43.out -ca5c453e0bdac809b3ab0e41f719bb88 absorption_res_44.out -620198b21e4e06956432a64e668f7ead absorption_res_45.out -d9ac2c3d71bea664a50f79eb0a879a1f absorption_res_46.out -88a6a91f29468473bb86f5c6288c4646 absorption_res_47.out -cd8c7bcaba62824bc4e7b6fe5b666344 absorption_res_48.out -60be9adafc9232bad5b00da9284727b1 absorption_res_49.out -8f2b86ef0b3bbd9cc6b0b02ec05cf5b5 absorption_res_50.out -d362689e69f0741bc6b00af242f574db absorption_res_51.out -e5c2491143caf619127f867e00388616 absorption_res_52.out -cf9764335245f01cab7eb0ca67bc9cb0 absorption_res_53.out -be684d0067c88b9db2089456453de1f6 absorption_res_54.out -034a1d0da8a794bd8d7e4736aa5658d0 absorption_res_55.out -abff67fa68a16e1786a331b7be04dfb9 absorption_res_56.out -bf21a9a444c8cdd41a3b1f5143df8355 absorption_res_57.out -3358408a11db025e1a7783af175f3069 absorption_res_58.out -728fe3c86242f07e75f0f4ae8bbdc93f absorption_res_59.out -0f6e63e0c3ebfd6867556db87c3d7b10 absorption_res_60.out -3f7229684eb19ca95d8c822692918bc0 absorption_res_61.out -64c16f20a6594276072f5e408dd5c641 absorption_res_62.out -fa727a47501e2f6daef5a6a0bff05145 absorption_res_63.out -faa5773186151ffc3b6c43af3427446f absorption_res_64.out -e6d591b6de9cda3a71f9583ef4a3c287 absorption_res_65.out -9b6ce7ea24f7c48ae66b6b218b3f039e absorption_res_66.out -90c96a8c65554b3889956b0ac5e6cc71 absorption_res_67.out -64a2649465998e481a95d0d4a7040e31 absorption_res_68.out -c17b9cdba6881a92bb7f2ff1a63a5077 absorption_res_69.out -7648ffb87f99b99618f7e4671eacef0d absorption_res_70.out -0cc4c9a6ff4640cd7fdb1e86dac50618 absorption_res_71.out -f47a4fb9a2462b960ade7063fd4c3945 absorption_res_72.out -5087915b9b4c6c6df61aaa319fb6da45 absorption_res_73.out -4d0ecd248984c823d3f7e3cc04f0e83d absorption_res_74.out -6186b4165c1f0a0a984075607e1d2fa2 absorption_res_75.out -1dd29982ed34481eee3ae553f0121e53 absorption_res_76.out -624c4f8fcf2a8a072ea1b1d80c2b2adc absorption_res_77.out -2bae5033f40c84dc6adb7c8dbf4b49cc absorption_res_78.out -e432f6e214f51c039fb1547a97e8abfe absorption_res_79.out -96cc721062ec1fe21680f91c4202a882 absorption_res_80.out -17fffa783ef03c9b1f431fb8ff08ce40 absorption_res_81.out -110800d3f98735fde7a6cd1713e34497 absorption_res_82.out -a7ae492d7d731e653700d754bfd5f753 absorption_res_83.out -64f4ac589ce8a0dd26970fc989bf3fca absorption_res_84.out -1a9fd7a1b9aa7b54093db672f939175f absorption_res_85.out -91b40bf6fffa0af0b2c6d6d4accc1ab9 absorption_res_86.out -ca95159ac81ece7f2be399da26041acb absorption_res_87.out -e4cffbef0eb93bcdd14fb655ea536191 absorption_res_88.out -6a608d19b578462a77c52d7fc1159fbd absorption_res_89.out -6156ddf8ec8f8e26c9259e9d1ad0f329 absorption_res_90.out -4797edee6296eb6b07def2461370e19a absorption_res_91.out -2baf7dfff59bff883788d02605eadcb6 absorption_res_92.out -3bd46408c6a0d71e0e2bf48ec3f77ebb absorption_res_93.out -ce99824fe7b8386549e3579e1027291d absorption_res_94.out -e8dd71c63b9c03616ab77e95e47acc2b absorption_res_95.out -aa37858bc0ced42d09e00220905ff20a absorption_res_96.out -837eec544cdbe4532c5456156efa502c absorption_res_97.out -66662413629c6419bfd6f8c5ed107704 absorption_res_98.out -ddb3cbc3d487abd00df87be7c68d706e absorption_res_99.out +f9e8c462e7ef8bd0c0fade07bb715f3b absorption.out +274f502b0c431c87692eedaf5919ce4d absorption_res_00.out +1b23e9efcf255979d6e8dc1c9830e520 absorption_res_01.out +8f2d66054dd29553336e6b8a5491bbb6 absorption_res_02.out +e386c3bcbe983401a17bd95dc3d121d0 absorption_res_03.out +6a329922993d5f74dd860dbed3212635 absorption_res_04.out +4c73b13c528ea23c57bce1a988690cfb absorption_res_05.out +89efb4289fe1d9d399128d41a6642a05 absorption_res_06.out +18139fddb12924162c061157f9747207 absorption_res_07.out +c361a8425799dc3c16444f04fc197dcd absorption_res_08.out +24b714a39d7728e2e39c091a35e6241c absorption_res_09.out +acbca6ff80b948fa1c04ccab4037000f absorption_res_10.out +339b7c36dda10cf55418f2cacc59107f absorption_res_11.out +fabaefc81410ade72b31a9e6111af0e8 absorption_res_12.out +5ba48c6fced17fa5c84ba19ceb2c987e absorption_res_13.out +0899f426f6940ead33ef8c672f1fde00 absorption_res_14.out +f0ec41e87d648be6c2734d81e9b2a131 absorption_res_15.out +6e2cbfdb33a712025e11fec3ef58430a absorption_res_16.out +78cdb5e1399efa97c2cf87b5f30cb3d6 absorption_res_17.out +2bb07657b2a766dee543d3da2d154e41 absorption_res_18.out +39f1391db15fcd364f74689c05fae1d1 absorption_res_19.out +25f676d65df111740bee8deca71996b6 absorption_res_20.out +563a11129d764a915c89a9550b79408a absorption_res_21.out +d8d9d0df34288fef286dc46689a9ee03 absorption_res_22.out +516083a4ac583d51efca3e9b4bd6109a absorption_res_23.out +955163e7185855887b69ccacb553dddb absorption_res_24.out +8246b28aacb57b55aec1413793412344 absorption_res_25.out +2b481d6c113c632ddf7bbc15e4aecf8a absorption_res_26.out +99f5de348249be74f8cd4922927666a4 absorption_res_27.out +dd75e3b757da769ce06ea9ab3f854f90 absorption_res_28.out +af8da6bb3e95edd423441c817e1dc37d absorption_res_29.out +27c62988f57b5d905939782bfb3b0efe absorption_res_30.out +9371d71de8c01d9699811f29fb8a85c4 absorption_res_31.out +6e36bcef06a0605acfc3707604f36014 absorption_res_32.out +65c7ffbc0002be87c56bab4d797dfe19 absorption_res_33.out +67409a5ecea0880828b8a7234c8f3bf7 absorption_res_34.out +f10c90f165eec7bcba64ad9121989011 absorption_res_35.out +fbcd7f2ab65c0c535a657e72cc7edb3e absorption_res_36.out +635a99eaffd5d9f94b793e6f7ec73048 absorption_res_37.out +060b661d3a2e3ef001b2f9aeeffe10cb absorption_res_38.out +0863ed003882654f41655ad1665c20d5 absorption_res_39.out +1358786cd5a80c38f6b92b99e6b557f7 absorption_res_40.out +4caa8b9dbae91dc0c1882234b4ec0274 absorption_res_41.out +db49da7c14b3d32a62fabed98bb9c9c2 absorption_res_42.out +7d97f8989a5db571735d1a7b3f5b37bd absorption_res_43.out +ef4d0a36fec4da1705a10f98fa7a69c4 absorption_res_44.out +18cad46ac655c6cfafb9824fd2e5dfb2 absorption_res_45.out +2ffee6d7cb0c23e5ffb65db38d8a79af absorption_res_46.out +e8fec2be24fd7c1fe2c60941e74c990b absorption_res_47.out +89970ea8b3d5f85c069a7850f603e2ed absorption_res_48.out +a153dcd23cbd0e575579f5530bf0feb5 absorption_res_49.out +19dec21ea4ca6d122d4e6402e413e239 absorption_res_50.out +e2690942c3b57a50ced741027c94fb0a absorption_res_51.out +dc28aeb8509b183139472d242eb705f7 absorption_res_52.out +d4105a99be3e63e6351a077dd4e611f0 absorption_res_53.out +077e591ad2a1acb81412826e93a7b46b absorption_res_54.out +24035fc228f793f64cfcd1d96f0c6e23 absorption_res_55.out +471a08a1da666ae13f1f687ae868fa25 absorption_res_56.out +f6c6ef61dc942b2ad9735f67b528b4ac absorption_res_57.out +b857a70faa8d869c165d08763b85225c absorption_res_58.out +ae4d59c2630ca6b8ab8dd696dfc25fd4 absorption_res_59.out +bfd97c4e5495dffa84b2747896497e1f absorption_res_60.out +8db139458bb9280d9191540feb7f22aa absorption_res_61.out +23678df0058e7b136d548447c9247a5a absorption_res_62.out +1746f4b528f81b64f8c5ce789430d76a absorption_res_63.out +17b01b01353c695793e7956663dbaaf9 absorption_res_64.out +8700cba4ae77d530a3622c0ce5bbc8a8 absorption_res_65.out +67a9bdf952985811e14f60c8aadde0e5 absorption_res_66.out +528f8be97188ed25e32e3b3258ac5856 absorption_res_67.out +3eb4717018783c3aed3f298fb31583f7 absorption_res_68.out +6ad940791b99711306d5b3d5b947ee19 absorption_res_69.out +9d583ed1e8372c45f90a671df0e4dcb0 absorption_res_70.out +30fba9edf8484101009db72700fc3718 absorption_res_71.out +9c3332a1a4bc7d4ebbba1b6212e14d6c absorption_res_72.out +2e5b57f4f1adf29f21a0af09d7ee20d0 absorption_res_73.out +bd587ea7ccabea5c061acb24a62db797 absorption_res_74.out +14003f97741c6e428dba2ab2ee61aa9b absorption_res_75.out +f380a1f5f10e23a9eae4ddc860fec4b0 absorption_res_76.out +b9af5fe86e7e4601cb9ab0b5537e7303 absorption_res_77.out +e35b607f63d833a39e2936ca0528be1f absorption_res_78.out +b3d003d76facde4842f80b373cfe67aa absorption_res_79.out +54755075322b22a6f9014cc52c1145d5 absorption_res_80.out +ef297f2cca47bb00bf977a8053e15081 absorption_res_81.out +1b8fd6e037b3f508c08e814a4bb3f1ef absorption_res_82.out +357b5a10e02e415648c4f6bed251ba5d absorption_res_83.out +fc1cae8802aa49f3ee6111f8d8cfe287 absorption_res_84.out +5ca5d9d11fe1ef510f67c1e0eb073568 absorption_res_85.out +dedf1b98f85b928daad12bef4c373681 absorption_res_86.out +3aaa4d6ca5732a9536035e3559170e6c absorption_res_87.out +06fefa329cde29f5d86e77c0fa8d4c5c absorption_res_88.out +39d74ef9cc6c92c23200e6d400c28762 absorption_res_89.out +f7135992bb8a81787479ba759007d411 absorption_res_90.out +0bd9fdf583d626000f5d25aff31d071e absorption_res_91.out +a9c2a4462385ab0555d801ea431f5562 absorption_res_92.out +4bd91060043c8f96553bfd5a0ba6ec1a absorption_res_93.out +f52b5597e3d1f0f8e2a9b03e8d71e349 absorption_res_94.out +f8efb652b3b62df30d6490bbfdaf42fe absorption_res_95.out +4af3a8bbe04cd83ffca6201705ded960 absorption_res_96.out +6f63b6cbff3c903c64e7e6ecdea50c4c absorption_res_97.out +e62dba7cbb6826d15f6cb2fdde45c69b absorption_res_98.out +eb05e3560a97e99403464e9c79845341 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -91ff0e7c10ea98f68a04ad4e8434a837 deposition.out -83aad79cbe9d35eb3bd6f45d840b580d emission.out -022d4400c529a150df6383cbe6427ff5 emission_res_00.out -832b39613e1a2590bb606094c9fc0ea4 emission_res_01.out -7a7a23f3863dc5c6f7f8cf75cdfed414 emission_res_02.out -ef704303bb5dd818fa29488041333865 emission_res_03.out -f75f2265f24fde43505f21c7fbb06803 emission_res_04.out -aac0d418ea2de72ec208d8d594d4f69c emission_res_05.out -d9cb45191bd9bf21ca06a398f289a592 emission_res_06.out -7266c043925e5fa8b5ca0e575b540e3c emission_res_07.out -383c174d77092a0e89ef769320320d77 emission_res_08.out -e455d5f16b95e727c6b561d49d036947 emission_res_09.out -5b29ea98dd6f3d104aebefa7361f10e1 emission_res_10.out -a6c70df39db5ccdf94c97eadeb67d8b0 emission_res_11.out -7fc6ee3e018d822826719f38ed3afe11 emission_res_12.out -13ee370d97e2db4008ac4f3cc1cc5f1f emission_res_13.out -88615d99b4da7f2607967276fbe8c2ab emission_res_14.out -4fb122ed80b23be580b386e0d043a28e emission_res_15.out -447d8c3538d42aa0099b73ab841b69a1 emission_res_16.out -3da25d68602d2b1b755e9df14626072b emission_res_17.out -b1b4291edab3a0a9a5e8849d3d4edc56 emission_res_18.out -cb0cd1f6bd3b1f295f0e77ea61eb9d74 emission_res_19.out -31c3f5e65881f6aef5e6fcc472d579f9 emission_res_20.out -bf215d48e5bc31d0ba1c7a0d478a42d8 emission_res_21.out -061f6643f5feeee6b2d4660d38c3c7eb emission_res_22.out -1bc2b77716cda63def46de5cb8ea7423 emission_res_23.out -bb0b78de6c8669199fd120c3b5a6947c emission_res_24.out -d0ea08431b77b49e877a7139f2787ee8 emission_res_25.out -dd5c4acbecccc0659b844f2dcda20212 emission_res_26.out -db3cbf5ebdeac5e49878d0b3dfe63e49 emission_res_27.out -16a4e043678c5840473e2fa5c68eb2df emission_res_28.out -9ca11fac1926a9afc97b1fdd60c50234 emission_res_29.out -ab6b32c2e8824fd6dcf2d7e0515b3669 emission_res_30.out -eb372e9ad199299320a8273abcda97fc emission_res_31.out -a816d3df5c0e4380dbae74c9736e4eab emission_res_32.out -3ab3552a1977b14ad717ff911142d03b emission_res_33.out -ab3d6163d22f40e3d71911e2289d0ec6 emission_res_34.out -a9569d5affbc26e6952f9d48f38479cd emission_res_35.out -ca7881565f12e400bd195372ba95da73 emission_res_36.out -2185d57783feda69d3eee3213c8e374a emission_res_37.out -409f36ce5fd0b8edce170cc40952f8c6 emission_res_38.out -0f25bd1ff243319114b2ed22ac50cc6c emission_res_39.out -b21561c7deef8ef2766e20af184d07a2 emission_res_40.out -3ef75ea54cd49d62bdeea3f514fcdc73 emission_res_41.out -7214e38fce33d0136725c8db953ea10e emission_res_42.out -08da2c4a64a58b62597bec4c47928951 emission_res_43.out -7ab2bed5e2b9089fd7b56d58454d67c7 emission_res_44.out -7438416b8fc09af9f569f03d101e8491 emission_res_45.out -e2bcc0b7729c41034538e52e8af9dab3 emission_res_46.out -f8b365180a90bd8c585dc3cd66b7d3f2 emission_res_47.out -a31b91affd2693becb04bb15b3f3f25e emission_res_48.out -60c00dacab66fe478458621f86d6f57b emission_res_49.out -1bd04f4d5e2b26499902748628ca13d1 emission_res_50.out -221fd55b5da443913e17b0f9a589d7a0 emission_res_51.out -bfe99fa9c0affd11630df915b459a462 emission_res_52.out -9147cbeae7f856e31f4fca21f4b353be emission_res_53.out -d0a2c828830fc425276dd61a32e37a8f emission_res_54.out -b8f93469f6fbece8c9e90766ed037786 emission_res_55.out -758f85650982576f84b97b1ae06e59fd emission_res_56.out -c4755d9a12347bdc1216200c4d0a1c9a emission_res_57.out -3803c22c8502c4ce574f78b6d2e82115 emission_res_58.out -bd8271f61fed761f7ea11d210354b2aa emission_res_59.out -a8e77fd9345a083d1d0a0f69ab77f16c emission_res_60.out -c5b0a4418a59d9be90aa7795ab3c7da3 emission_res_61.out -e0df953cea43a51481469024896354eb emission_res_62.out -184d6f2b2c1570b98fda50391cdafa9c emission_res_63.out -e94c1ff76409a64a075bf0ce9f4af8e9 emission_res_64.out -7c9d76aadf41b4e46b2ec325fc66b761 emission_res_65.out -79cda130e75b781305e18ae2ebe5989a emission_res_66.out -6887500f16243a91547b1fefac5baab7 emission_res_67.out -085a0dcad45f682893d7d232faec8bff emission_res_68.out -361e78d58c31d2b0ad0cbbd0e1667248 emission_res_69.out -b7449283fff105d8f1bec48ed3f52cfa emission_res_70.out -b51b5bff9a04570bd4427bda37023612 emission_res_71.out -27de67a953d91e10542a7b40f8ad9039 emission_res_72.out -129ca0cbdf72029acd86eee9e1fc8a19 emission_res_73.out -d370f7131dfe86da2b274f67414fc677 emission_res_74.out -4f413a15da31f08eef4c876d4086901e emission_res_75.out -ab1599a934a858b049bfc2aa4843238d emission_res_76.out -56e0c5e6a7cfbfb5d8a2be0417b5b0f3 emission_res_77.out -1ae599fd83065394988453d62632e156 emission_res_78.out -55cb0cb52df03f68523b3eae452372e2 emission_res_79.out -ceec19a35d185684649d0486ad06161c emission_res_80.out -b7eff12aef0294165a224323d92120ce emission_res_81.out -cf9e624e48b2a848ceee7bed4c248028 emission_res_82.out -0f03edb825239f8e896c1978d8f3a506 emission_res_83.out -01c1c5ebf41323cc7b7776391b6502a6 emission_res_84.out -fee50d0e373d431eb4ecb33cbd0fed59 emission_res_85.out -4d740133c33311293cfad127af6727f8 emission_res_86.out -7289e2abe15aac32a58baedbbc5c8894 emission_res_87.out -f73e4d8dd1d549f50ff66883f866c377 emission_res_88.out -4c2fd689dfc152f32ee9a810c1adefa3 emission_res_89.out -5b42752a29c145c398f19da8b9837c05 emission_res_90.out -e23a57c5952eb4a8d613fcb6abe02904 emission_res_91.out -e83f1df14d6d29e95850ca5f5448ec83 emission_res_92.out -79088622f0edfab122bb71f639c3d7ab emission_res_93.out -9c2f725f8243343ab691e4ebfd7f7cc3 emission_res_94.out -3e1f2b86abf7e4e7b5a111b35388fae4 emission_res_95.out -8a34eeade7f6f02f81c8bc0c5e89e328 emission_res_96.out -66d65fec3b275839a3713f47c6974676 emission_res_97.out -065683b8690a13109e4f0f355ce917c6 emission_res_98.out -604d878a8ab1d7caa63f6db3687c2b4b emission_res_99.out -76bb60319bcb9c9347c7909904587658 emissiontrue.out -79c473e0fe20f5a9695ba986ed49987e emissiontrue_res_00.out -51c9f1a24ad2880d9e0ea3542d17841c emissiontrue_res_01.out -490d3b49bbda74557109bc9dd3a1c045 emissiontrue_res_02.out -d8dd137b5a3b487b1c2a81940d691e7d emissiontrue_res_03.out -62fd0c9874e6785657d9a960eff34b5a emissiontrue_res_04.out -f520d3d80c9398db57760d43c91ec764 emissiontrue_res_05.out -f05cf0b8b4863edfec30ce14d1e50006 emissiontrue_res_06.out -2ae42870e3ef937f89705a932709edb7 emissiontrue_res_07.out -95ee3bc984c1c0d1783d1a034dfb2d31 emissiontrue_res_08.out -b00450d5c158542029123592fa6701df emissiontrue_res_09.out -fdaaf60df073a024e24a6cbce6571894 emissiontrue_res_10.out -57378982873866fe1d58acb0938f905e emissiontrue_res_11.out -34340b5318f5b1f56393123c6ebfbbad emissiontrue_res_12.out -ac5d5d8da4d8dd6a21e90bf6827bbeed emissiontrue_res_13.out -cb5d5c2102ca7563e78e283223fd580c emissiontrue_res_14.out -32fbfcf410a8d425b55d11540f4c8e26 emissiontrue_res_15.out -ca43f9ae92e4791d9cf975d3139bbe1e emissiontrue_res_16.out -dbe70f2cbf548a66753a35f43f6d34fe emissiontrue_res_17.out -1acd2634c2258424440963a534d4479a emissiontrue_res_18.out -bdae9a83e5fba134547b87fa95f417b2 emissiontrue_res_19.out -1096d4a3cb479c3f326b5155798a0ef1 emissiontrue_res_20.out -d55fa523180ff6c3ea527f13fe3c154a emissiontrue_res_21.out -ba22113793d78398aaf25e33567847ee emissiontrue_res_22.out -7d7f7a641f3a2ec4b08b910b75e75e30 emissiontrue_res_23.out -f6af1a9f220c7061b0ca51090052f0c9 emissiontrue_res_24.out -5b9db8ac5a444a1ad646b5756dbbf70f emissiontrue_res_25.out -67e966261707e29975dc67462381370f emissiontrue_res_26.out -3ac4fe76df5410fe16317e5210f2ea82 emissiontrue_res_27.out -f3dab89e22c9dde14bd0836a42dc0eb9 emissiontrue_res_28.out -dfb294a17d799e51a465ed521d0537ee emissiontrue_res_29.out -49b1dc7cb2625658997206ca5d0c08c6 emissiontrue_res_30.out -8fab3d7e7cb4822b71262348bd173704 emissiontrue_res_31.out -3a45b04e7b4cd052108f9d1fa8561c18 emissiontrue_res_32.out -0ef3996fda0e1351a227402d3025e9c2 emissiontrue_res_33.out -85d9872528093e8867df2bd0ddf645f6 emissiontrue_res_34.out -ae02ef94549dfb04bc77463936884d13 emissiontrue_res_35.out -153df4691a6e3ef65f0e676a1482fb0a emissiontrue_res_36.out -f53199e96821d7a705e4013356c4a2c4 emissiontrue_res_37.out -6a67038ac41ea30fdde445fcaafbb789 emissiontrue_res_38.out -bf273fbe818f020f143653fc544c238d emissiontrue_res_39.out -4cc3a848ef3b3be2d9445120b0f54fb3 emissiontrue_res_40.out -2036794eba3af345423a2bf465136c6c emissiontrue_res_41.out -0656368375dc2f437d7d7ffe48488f0a emissiontrue_res_42.out -62f005b7e3df033306fa71a3c5e4ba68 emissiontrue_res_43.out -70fa398e124805b967bfbd1d9698df06 emissiontrue_res_44.out -8b5ecbf9d2a25eb479eff79e86c8632e emissiontrue_res_45.out -38c1105f8ef3c44ad81b122bbf233034 emissiontrue_res_46.out -016f8f114d67ea25f982937d9f351f1c emissiontrue_res_47.out -c698b98300b44f92f8f068ec9ddabf62 emissiontrue_res_48.out -dd98fe16e38f64c95fd3d279b00495f7 emissiontrue_res_49.out -4899314cd17d9e15c867390ed409aaf1 emissiontrue_res_50.out -8cde11b2fe0b1f778a1cb29e066c0632 emissiontrue_res_51.out -9d5bd8441a090ae1053fb7b270cf3a6b emissiontrue_res_52.out -313355007445da05067ac8233341233e emissiontrue_res_53.out -924db13ec3bc4739409b7368221eff07 emissiontrue_res_54.out -ae59f1c61e54151e845a83c8fee9bd3f emissiontrue_res_55.out -6f15692958a38d838d1c3830ab9bd437 emissiontrue_res_56.out -db89db9154f10015f79d6b3114886c6e emissiontrue_res_57.out -fd6f1a0f5b0caff9eb22f54e0bc87578 emissiontrue_res_58.out -faefabe9c4e661f3ae8cd3b2efb1f04c emissiontrue_res_59.out -8f265e513a223a5021fa9739110c787b emissiontrue_res_60.out -c5f9b6ec66f83d425f45a29b4e6ca223 emissiontrue_res_61.out -84f40ca90f541527cf8b4c8f070f16e1 emissiontrue_res_62.out -a2208c8cd43ec4a4468dad3a1f1519dd emissiontrue_res_63.out -d6aba0ab7e20d0f92cae8765933a7d5c emissiontrue_res_64.out -14874367d9ee81d06696290da92105e0 emissiontrue_res_65.out -c5e8f71e5499aa150727e9b19719235a emissiontrue_res_66.out -1e7382f8c26898ea33f22be6a23c827d emissiontrue_res_67.out -cb9ea6dedcc9250c7e3ceaf9e3a4b3e0 emissiontrue_res_68.out -f77725c3188c4010346ac32b401b8512 emissiontrue_res_69.out -93777fce7fa2b76fc89d07c45652f639 emissiontrue_res_70.out -3e14066bc26e36b25c1bc43e5da7755b emissiontrue_res_71.out -e00d4e60b1b1550d8d783ab2d9e8a6a0 emissiontrue_res_72.out -12397bedd882e6262512168fc14f6568 emissiontrue_res_73.out -31fd778269bb367df8af9a641bbe1327 emissiontrue_res_74.out -ada0d79c9ecadf95157187be1a52afa5 emissiontrue_res_75.out -21a7e6e4544be33399c595a3233d042d emissiontrue_res_76.out -d6d69814fe0ea9ce07fc67886c430539 emissiontrue_res_77.out -b8b623e485c11fada488b501f9d1a911 emissiontrue_res_78.out -8f03d05002460c21af01d6fb3fbc49b0 emissiontrue_res_79.out -0b9f6bca47495a9a585b96851000b5c9 emissiontrue_res_80.out -81b8a0ea498f4f99513615fc68bf45c9 emissiontrue_res_81.out -84a6ffcb7a598cf14f9c77d0447c8708 emissiontrue_res_82.out -09bac18180c98102303f1c33560ee517 emissiontrue_res_83.out -3d62fcbe3f3da2d3a4fb8e6903bd8dea emissiontrue_res_84.out -1c06aa36643338e7fde60db5bb03c282 emissiontrue_res_85.out -052c8801fc1ca32acfa41106af855ceb emissiontrue_res_86.out -cf1ed503f5333bdc7b6d2ea08e745082 emissiontrue_res_87.out -fd699bbe5eaa9c2f68e3f8b30d02a94d emissiontrue_res_88.out -bef21d88f2274a2ec32fdefaf522bad7 emissiontrue_res_89.out -229b6de864029903e8b3a0c51217edb1 emissiontrue_res_90.out -9c860032e5c7acdff5de4d43c2c401b7 emissiontrue_res_91.out -653b089ab8c48e4597f58b0f6b66568f emissiontrue_res_92.out -384d4510b2cfe4bd56d95b1ca5dd471a emissiontrue_res_93.out -ec2672c5064f57e76a066f3750f9bbcc emissiontrue_res_94.out -1244456435c0ab393a12fcce5d45cf96 emissiontrue_res_95.out -8dfab30828609653b700f22eb7cb2972 emissiontrue_res_96.out -0410b4bb37ae675a28ac51dff235c777 emissiontrue_res_97.out -dbb7f9bd53a06af974aabaaa9ff3890c emissiontrue_res_98.out -a741e8f176a490baf532e3d65ac6bd55 emissiontrue_res_99.out +f421b46da29529e44e57cb7caeac62db deposition.out +94e7893f4d16eaedf276ca3bb09408e2 emission.out +802067a4cd06e68099ae5d93d3e29773 emission_res_00.out +e885f6a4f62b14a6b45dd9423c20a98a emission_res_01.out +96dec81fc301a72fb5c7e08dc3637429 emission_res_02.out +3d95332d326b8ac4af0adf5af879543a emission_res_03.out +8a1f1252089b7f18d86b5738f3e37ab8 emission_res_04.out +3f7585082f3b3ebe844ceaa89863aedb emission_res_05.out +1d1555ab1c568793fcd362e9c5050d31 emission_res_06.out +57f31f3962ce4a18463d74841ff1b210 emission_res_07.out +0773ad2f6294f67ee91af110e7c64bd0 emission_res_08.out +f72ed64f15567c2317a4bbe238f31501 emission_res_09.out +064c28ace251811bdb07a9b7df383509 emission_res_10.out +06da84c944e866d0a85f292f799da601 emission_res_11.out +b98e07714fd362a755f3f12f35bb5084 emission_res_12.out +bc65982be583d84728ee39fdba1fda8b emission_res_13.out +95c634859bbc07187da5b7ae438fedd6 emission_res_14.out +1ee4dc26615d50737cc1c13c0811fcce emission_res_15.out +a21463ef64bfcccaf4f598cfbb6afae1 emission_res_16.out +0a6a79c5a0115fd3b331e45d8e242668 emission_res_17.out +3bdba3c4db9aeb5ada76d6198a911bdc emission_res_18.out +82ed3b9a44cbeab1e15c6c24967de7ff emission_res_19.out +e12b0df30e35686164792e078070f3ab emission_res_20.out +2d642d0d278d4b691187b7265b744610 emission_res_21.out +6c6389ec62f9aa14ef953772290b2d00 emission_res_22.out +84975687d246f6f7c78d6f2d04fd88ad emission_res_23.out +c6aa79e2280c41e13ff8461be02c0bb0 emission_res_24.out +2f92a55f470fb77669cf43f1e77dab89 emission_res_25.out +0d06fd2b501b740e876e72da835420e8 emission_res_26.out +ebed62e732f039a9b693f0271febc89e emission_res_27.out +f62e2aa4c4258a0379e95de144a8f694 emission_res_28.out +3e03b1bc7eedc9ac11fab9b362ac7ba4 emission_res_29.out +f95fce0026987aa1e2d45e9f42601799 emission_res_30.out +c44d05f443a167a9dbfbc12022fcf9f0 emission_res_31.out +4a106ace1b7bcc45ad4b0c985b704747 emission_res_32.out +6fddeaa911102604cb08a60922f518dc emission_res_33.out +de38fed5e2488f1cf5c8c67231135eab emission_res_34.out +b6450142bfeeeba4d8d9fb4546b8e00d emission_res_35.out +13f2b982cdf2c17e58b1128522637a27 emission_res_36.out +8a390b9d14dd186ea99117252ba69866 emission_res_37.out +bc9cab540155a5051fa9c72a9bde4904 emission_res_38.out +2cd6b2c4bd210424c75a0845a3bcb865 emission_res_39.out +6a462299b5a9556071a015616e735b22 emission_res_40.out +04bed39cfdda981d226aaf52a3f14446 emission_res_41.out +d8119b704c3c756907158cae1599b50b emission_res_42.out +180c543799c8222f5eb65eab46703390 emission_res_43.out +319e422dc7d67d5302c0af46031fa2ff emission_res_44.out +de9ff223f750723829be02852fcebe2c emission_res_45.out +ea6adaa69ef43bf3f77a5ddb02b9923b emission_res_46.out +e7251578e966a3d7411f45dd9ec7bcf0 emission_res_47.out +f7bfe17e81549093e7c1a55c6c41a8f6 emission_res_48.out +1d630e5b44474b813f4658b810dd1c51 emission_res_49.out +c96e48f5d4c22ed6795bf3c97634d478 emission_res_50.out +1a99b5727cba51bbb5579679c3c35e7a emission_res_51.out +08fb4109b9d80434bff19f74156dab93 emission_res_52.out +ad14b7efa870245ca7930cbbfd485f59 emission_res_53.out +16508a2eddfe4378122804eb08417ced emission_res_54.out +4e9ef3ddc1bad58af3ed46d353f10086 emission_res_55.out +6868217b5d9dd93da1193113416a8366 emission_res_56.out +2bee3ffecd99642130f792e6ad682253 emission_res_57.out +0446b4f5f267c6961811fb69f59fa250 emission_res_58.out +b1e4645cd0b8f29a6257a2adc07b8274 emission_res_59.out +435336fbabef2041315ca3005194cc4f emission_res_60.out +fb4cbb5640c27518f4f17a848d6a69c5 emission_res_61.out +f981fffabb8bc6d0f748a7316e3b0952 emission_res_62.out +2194689ac46a015e6909ff65892b011c emission_res_63.out +cc07bf8459f2e7d6875e2d179c7a0106 emission_res_64.out +1d5ae514e4fc6282201e78fe85484669 emission_res_65.out +d675c2588fc42731145a1d3c0b5c687b emission_res_66.out +2cf76193138ce584e31cadc9f5b3bd84 emission_res_67.out +8affb443ca4d8b0a77e7c88733debb94 emission_res_68.out +bc854df639f68c8b149124f1ea61c6bb emission_res_69.out +21517ada149c5cf22e13a74d2d0863a8 emission_res_70.out +2da4e995d536c0e54696515aff752e46 emission_res_71.out +cc0c3b1680328bc927c0f54482126c5b emission_res_72.out +8613f32cf8d3e29f5b8edd894c659f73 emission_res_73.out +c1994baf84849f372662843412c5de68 emission_res_74.out +52e5fa9e3717b0fb3dde8ba471b49bbb emission_res_75.out +1ea14b097540b319a03e199df3611e11 emission_res_76.out +a98f6a81be8953903c1086eb0a5be8c6 emission_res_77.out +9cebab17a7dd36b1c6d3ad384ad63225 emission_res_78.out +07890efda1402d7ca57e036986bb94e0 emission_res_79.out +402cabe1089be744674d03177da02bb5 emission_res_80.out +53e829019a110181ce49443a2a456c60 emission_res_81.out +3259348d2c75947f90d850a5f7edeebb emission_res_82.out +d2b3a5952c3070ba7022190ee1e01b3a emission_res_83.out +ace32f45b7f9acfe5bda96d10bd6a39c emission_res_84.out +fc3f2ffb314a2c36853f242d8afd2f18 emission_res_85.out +9c89eeab349e729d247aa103dc91e48a emission_res_86.out +7fc3cb5d79a61059025fb5ab94d5be0e emission_res_87.out +f3211188c037e359c947d69eb68fc855 emission_res_88.out +308f7883bc6b64f625dd0d177d5168f0 emission_res_89.out +fbfd42a65e22751bcbf42bfa2aca3b40 emission_res_90.out +1a1a8172c8907f9a615c2d6cbdbdcc25 emission_res_91.out +f0853330612ec6644947aa0cab728b1c emission_res_92.out +45f17ebf98700b22aaaf2534948f3739 emission_res_93.out +8e20cb52ecb1ada6dce9db0a1bdefca3 emission_res_94.out +5c99bbb14897b0d0228aded66a96c022 emission_res_95.out +d03f934f750cf063cfdcde6b7e1f274c emission_res_96.out +81168b09e51669a848901263b9b0d69f emission_res_97.out +f603c942ee34d4b4b12a910141e8f9cc emission_res_98.out +0e86758a606793c97614e61fa00e18bd emission_res_99.out +ddc4ce928abab65d46d480f89c2e574b emissiontrue.out +e86a156efcfe3b34f7436f4477868ccd emissiontrue_res_00.out +4f12e1ee9d7e764268d832470b6c3ae8 emissiontrue_res_01.out +03e5b5b9bb711cd002734e843e462ee9 emissiontrue_res_02.out +7ac89cf9180ffb2fca31007892a2138e emissiontrue_res_03.out +6d39ca494abf5e58f3c042d1eab6e8ac emissiontrue_res_04.out +57d913d72de624546786fd1adc6936d5 emissiontrue_res_05.out +b3a7774e7f90432cfd5041465f58c41a emissiontrue_res_06.out +46a2dd8ed093b86abbb33ab716b8fda3 emissiontrue_res_07.out +e8bf23ffd98fa0e4efc0fa44ec3ebc86 emissiontrue_res_08.out +2d495595ae8d7ce2798c69e61d70215f emissiontrue_res_09.out +fc9badf3dbf024782155aa3b15e88034 emissiontrue_res_10.out +647f4d3acea36b412dd3db484d0b7db1 emissiontrue_res_11.out +9d57d4aace7f6239b4998511bc31b2c4 emissiontrue_res_12.out +917648be6892d25b44b4f1024bd19901 emissiontrue_res_13.out +2d92697892551d8ff8831c2ea394164c emissiontrue_res_14.out +29a9d87a2ea0032ed40eff83e84bd91f emissiontrue_res_15.out +194129d693d005005aa5c022a2091693 emissiontrue_res_16.out +7adcd28f45232f7550a7e778e66ba17f emissiontrue_res_17.out +625a21043483d85de186ebd65173dfca emissiontrue_res_18.out +401ca73df0574e3460786f1bbdbb0886 emissiontrue_res_19.out +58e83e9a97c1cc581adf5d2b19c40ec3 emissiontrue_res_20.out +8501ad496eec2760c0ef67135767de2b emissiontrue_res_21.out +6083024a98dcd371bff283c80a6bfea5 emissiontrue_res_22.out +a3813332e1739c2613bc8469861550b2 emissiontrue_res_23.out +c7dd72feff75b0289389681471b35cfd emissiontrue_res_24.out +8372c7921bdf58199ac416677ac71573 emissiontrue_res_25.out +398f16256b356464e5511726e64114ef emissiontrue_res_26.out +7f7c72d10636e797c3dc6a019aaac7fc emissiontrue_res_27.out +bb8a2cc7f83d38a4aa5d04611df7c6bf emissiontrue_res_28.out +7a188814bf3c63160a0afcfcf046d250 emissiontrue_res_29.out +b2f7d4744092b5779876f8823e12e963 emissiontrue_res_30.out +e76d94d9cbb15be8af6e5007cfebf489 emissiontrue_res_31.out +98c07bcc9786a6f03bc15242cfc079f8 emissiontrue_res_32.out +351b911335c672f627b2e090c968bf16 emissiontrue_res_33.out +96bc46d50765b98ce3ee870ef9df4b52 emissiontrue_res_34.out +4460994748a4394f0f8ac79d59d177bd emissiontrue_res_35.out +cf31f73fcb64cdda5167507e0346e4f3 emissiontrue_res_36.out +4a502cd7f1881388589c122258265536 emissiontrue_res_37.out +e6336332dc88919f38ff742f37fb0a21 emissiontrue_res_38.out +804069802c8fde481bc95ce84fe82b4c emissiontrue_res_39.out +46bb77b2b0c2ae15dd0e91bdd9003fbd emissiontrue_res_40.out +a50a6600d9bdc78939539033a7d09106 emissiontrue_res_41.out +052f0eb5db6423d69887704483ba032e emissiontrue_res_42.out +4ba6bec99680742ade65c6690c4aaeaf emissiontrue_res_43.out +22b0143252ea8bcb364dcb93362ad735 emissiontrue_res_44.out +0c9847e9d43702a168f3dae685345e4d emissiontrue_res_45.out +be7ad75e02dd55a1c3ef0b5c0ef73aa7 emissiontrue_res_46.out +c9cad8ef312b13a8d4b44dba6f6c80f5 emissiontrue_res_47.out +a5496f4ed80af479e4bfeda1cf0edada emissiontrue_res_48.out +5ac17a32ed4d81f7ec3a21cd441761d6 emissiontrue_res_49.out +1e6243408c1397667bc52d08aab3fdc5 emissiontrue_res_50.out +573ba7e8afb89e8396b846cfdcfbe6f0 emissiontrue_res_51.out +e0dcc6d7cfa1e8917cbf5231b4f2470e emissiontrue_res_52.out +c71ef5e51679b446458b8c15d614ab80 emissiontrue_res_53.out +1c93d9ab3e6746f37bb284da3df685a0 emissiontrue_res_54.out +d5062a8c2c2ab51956ca2cb7e0cd847b emissiontrue_res_55.out +e550cb7d9b3c5144d82cc594b6ba8ae4 emissiontrue_res_56.out +54d230e990bfea095231c3010ee914fe emissiontrue_res_57.out +4694877ebf8197a4480552b953db45b9 emissiontrue_res_58.out +fa39c5bfe6c13eb5324fba201e9ab7e1 emissiontrue_res_59.out +d8bf15fbc7c518d763b2efa9d3d28ef2 emissiontrue_res_60.out +7a160fb9f07317b53c13ea6d63cb978e emissiontrue_res_61.out +048a5e3161bcd03dd782d8027e6925f4 emissiontrue_res_62.out +ff67b5dc757380bffc4f87d90a6898c6 emissiontrue_res_63.out +2881f44b20a65d31dff4a5414f6f2362 emissiontrue_res_64.out +3b31536580cb9cffd316a4e3caba08dd emissiontrue_res_65.out +273428d42380f08e9429d0109d06ae40 emissiontrue_res_66.out +e1792d1e140582983099dcd9f786492f emissiontrue_res_67.out +9fbf864fa61116e9f28b8b63411882f7 emissiontrue_res_68.out +671120c57fbee246a946adc22b8c2ba3 emissiontrue_res_69.out +f4270005c328a93fbe4dfa36d45a4b7d emissiontrue_res_70.out +61a345a7a515d7d18e1cc80dce1fd43c emissiontrue_res_71.out +a7be8c91f0cc5bea9a611debf14cbacf emissiontrue_res_72.out +be432fa37bacf3dcac8c062b5a32bf6d emissiontrue_res_73.out +c998e8db6da25720422497ec9004728e emissiontrue_res_74.out +dd0379f8cee49aed12a0cb16c375acdb emissiontrue_res_75.out +a730184bfb9f4f49fc0a85f6ff6c7b80 emissiontrue_res_76.out +041bf247a36a676297c6e572dd6076e8 emissiontrue_res_77.out +1f622bac25f4ede015e41c2cfab26f91 emissiontrue_res_78.out +03880bf9a5ccbb153e9b9cb7252507de emissiontrue_res_79.out +d6b91a8a879c41db91d6d8a1fd2e1cfa emissiontrue_res_80.out +afbb435db75bcac21f7097bb5b44c265 emissiontrue_res_81.out +8a3d1024a8546ed2d0bcad762baac39a emissiontrue_res_82.out +66cebcafcfa171672b95c695cd9f821b emissiontrue_res_83.out +ee722f27d5f6b82c4a8bc0772e6681f8 emissiontrue_res_84.out +e945a94c3c76e40fcc9a7f8b9bfa31e4 emissiontrue_res_85.out +b8929a4b94a29d50b986e6019caee4ea emissiontrue_res_86.out +bc4c78dfeb2b70b4e03e22ae4aad0306 emissiontrue_res_87.out +6b5252ea88bc79daf1df62c5a5f61fe7 emissiontrue_res_88.out +d340b8404b5f993c487de0f9e5be0464 emissiontrue_res_89.out +195d32c0039f58ac7203c549453f8ec1 emissiontrue_res_90.out +5c8d8902822e7925e83d64bf4d67bc90 emissiontrue_res_91.out +b18f8730f9de6d8f56f34b948489ec8d emissiontrue_res_92.out +aa9f9d8317db0f97019be1bf05c36a32 emissiontrue_res_93.out +df1484f3b24e5173a31a2e496c04166e emissiontrue_res_94.out +0cbdc62ffce5688bd58805c873be9f89 emissiontrue_res_95.out +cfbedb1f6be28a5205686538e0a0e102 emissiontrue_res_96.out +ee7b117bcc203fa9da9c1f530859725e emissiontrue_res_97.out +17ae8f115a621c762b01fbb522b590cc emissiontrue_res_98.out +f488ecba4cbe41a57e365c4b04b7c861 emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -4e0973fb2b9e60d0eda98360d506ec5a light_curve.out -c7ae0fe8b6cc0a72b6e5c1e86f7257b0 light_curve_res.out -9773becefdfe4afffb041b703210c67c linestat.out +b1e9d6e1b0460ddb425ebe296ef0eaee light_curve.out +c4376a7fa8ea4fc8a0345dc0c3231889 light_curve_res.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -4bac70073eb7a5ee7d9a93078a8997f0 packets00_0000.out -2dba597c8fb23e8d8e964689136ad67f packets00_0001.out -2475d8968b3ebd5b8aaa0382a69d0e30 packets00_0002.out -d9d9ffa16b340ee15706cdb78f27d8d6 packets00_0003.out -e51703a72a79f9a63ead5c524618f752 spec.out -f22c0e5e234d805a092185750e7d007b spec_res.out +d88772c9f2f982809105433aa1ef43ed packets00_0000.out +8b2b12f83be94c74e6b452ed629a01e6 packets00_0001.out +8eda58f172cdcb88a86e018a286ee9f2 packets00_0002.out +3492c21b7da16033c832dbbb53e23c04 packets00_0003.out +2013eb78c14b8ab574b3e7d045ee9f7f spec.out +f7aae73b1abecba91128abc65b17f4be spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -c3f19d02d901184f9819bd8e0693d9c7 job1/estimators_0000.out -46286c473a411515bff972ce1fb08fbf job1/estimators_0001.out -f5b424a0bcd3df7f53c0a865d89120c3 job1/estimators_0002.out -501e31d212be9b415d83701862b26615 job1/estimators_0003.out +00b8474e1bec3df40f2f643d6b34fc4e job1/estimators_0000.out +ad01423a9531a1c364a1901682609112 job1/estimators_0001.out +b630267042391a009fad2f00b0f0ce2f job1/estimators_0002.out +eb8561e04928876e09d70ba46585054a job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 4183970f7..2475bebe2 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -83e24d639e428701093b8eb8ed1a31ae deposition.out -623f4f36dad23b153a05e08166960125 gamma_light_curve.out +e9aae3a7ab36a1a44e40ea57355e1ba0 deposition.out +afe66f023087001ce7a9fff264f87b2b gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -38598b5933f38e0bdec026a622153d91 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +c167f0a32585932e22e6265b0c9ebbbb light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d38d8d182dc970853bf9187add77d08a packets00_0000.out -25d68708254be7a9c1c3c4fc42643f39 packets00_0001.out -bd64af97330ee5a650af344f6e411cb8 packets00_0002.out -437bbf940cd1d0e01fd525c0fc81f31b packets00_0003.out -ebc371bf6e228ab45b07b55831747255 spec.out +c5d9f0d8d6ea6137782e7f73cceb2a99 packets00_0000.out +2f157c26d84a5002e5f88f1ffe881654 packets00_0001.out +d395efd35c062824dd6ab0104e0867f8 packets00_0002.out +e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out +88a0e6320da73f235aec8739d4a123a3 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -d9ba577265c55a27d582dbe69a1decb4 job0/estimators_0000.out -9511d1207484ff6c2761b09f70944b89 job0/estimators_0001.out -919222f66b0e10ef65275e50daaec4c1 job0/estimators_0002.out -29967c802abc4c3245f93621f11d9b49 job0/estimators_0003.out +76e3af84b3a66c9a282e41a6627dc4e6 job0/estimators_0000.out +0feb35456d8d8e9bbfc6548ffa0ae332 job0/estimators_0001.out +edd1c258e08cac13e09fcae4bac10992 job0/estimators_0002.out +f7550c181706595984aaf71e651a381f job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt index 7275e99af..3190c5f58 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt @@ -100,108 +100,108 @@ b65007ef75f1eaf1a242c7b3119086c7 absorption_res_97.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_98.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -3078795ab726da1cd2ad7dde0dbda00d deposition.out -ea08268c1362628305e9bbc908ae4034 emission.out -905597a4348f4da3a5e3c3a3c876d533 emission_res_00.out -74fcd7190fe0cdc252bb775bf1e11f53 emission_res_01.out -3e87a9653970951aca91d7710f435c7b emission_res_02.out -bfdba577c91c80632ce68084fab35210 emission_res_03.out -ffb0f3193484f024d7277f3569b0fe7c emission_res_04.out -0c4fd207b77df74bc250d1b64fd74b1c emission_res_05.out -291a7ffffb345719f05f1609e79ec9c1 emission_res_06.out -87ecb54dcd2ede5cbf726318195db350 emission_res_07.out -c09a592073812449fc97fa7a48019afb emission_res_08.out -4701a0b8e7ba619dca3650bc9f3567bf emission_res_09.out -3ebad32f168007b2594c04a834d0b3a9 emission_res_10.out -e749e698ace0433a23eccbd178ce12f9 emission_res_11.out -ef07d84a48bd8a9b79137b3551730e1d emission_res_12.out -91df4ef503695bb7d52bc10de2ddbb5f emission_res_13.out -6e317e80bd6e01032406d57399236d44 emission_res_14.out -3e5e4a24a5dc689e279f06591a263724 emission_res_15.out -ceb92b65ed3101b5f08181a3303b2136 emission_res_16.out -4746da794b2ed8381fb21efe0f616058 emission_res_17.out -e875aee315347eb5b1a613300d2b1671 emission_res_18.out -b00184892f0167846854414db0c869e0 emission_res_19.out -2569fc69ac8f5a4fdb62674ef7148f67 emission_res_20.out -6ab027cd80aea2afba167ad0e7f8bb90 emission_res_21.out -88864cea0f01298d8af69b3357302d27 emission_res_22.out -692b5e61d1ad4a1ae78066903daa16e5 emission_res_23.out -cbc805af042b268c8065f567e50e090e emission_res_24.out -df2d4033324efbe8b9ec79039f0de3ba emission_res_25.out -6f67cc8b24d472a1808612654359421f emission_res_26.out -7f10b71c2716a1ffa32f2851bc903bf7 emission_res_27.out -91419838a8095fb82f1aaf1609e7858f emission_res_28.out -bc3f955aa5eaa02baff936002bd2106c emission_res_29.out -90713318b5fdfa75c6e107f3541d2031 emission_res_30.out -47ae71e20d67708e5d002f2eea4a603c emission_res_31.out -8155a93460bdae204ab5b7096603a687 emission_res_32.out -6e38614f7fc8092d9c6721eb8261e868 emission_res_33.out -04da1f16abb410b1a2fd443b301786b2 emission_res_34.out -87d39c6fac7561a025282dd07e7f7aad emission_res_35.out -47bdbfc8d68c39e450e00bfc289e342b emission_res_36.out -cdc6f57e68de4637ed28dc25bd4321ce emission_res_37.out -5394a9bcb4d43323a1ba463222e8e967 emission_res_38.out -44fdb759f689ffd9f42323e904025770 emission_res_39.out -5f7884a3cbe963cd101d47104902c5d7 emission_res_40.out -b3aa624fa434d321b3edea47c1d23c9a emission_res_41.out -785fe6d3e6bde47f18a2702e7e4b9811 emission_res_42.out -4bb0af3c5e928f760acf36b8d93bf7c5 emission_res_43.out -e2e9b3d2b4975545518ec6c93405438e emission_res_44.out -c150c53758a77c794c604355802bdcf5 emission_res_45.out -aa226f92be61b3d4b4dc54b444a6d01b emission_res_46.out -ad3ef975ea4ff4eaf5b09922ea463bf8 emission_res_47.out -4d359ddecdac58a0d2b79157fed709d0 emission_res_48.out -a3ab52b4891b9c9814cfd7e2b1c21870 emission_res_49.out -e8e20d37a36ae69028084de65e3fe183 emission_res_50.out -abb14d65a5cd7f1dc045066b4ef0dd35 emission_res_51.out -371bd97e8f1c040ad8dcb074bb1d5536 emission_res_52.out -926c8cf1195d8157898fa56306175aac emission_res_53.out -e7a2de45c36d548d49578054622a251a emission_res_54.out -9979b7aaac99200acfc4ba60acde8102 emission_res_55.out -98551baf09ab88c967ef9f5443087fe3 emission_res_56.out -7d4eed4b7bc8779c7cb4a69ceeefc99d emission_res_57.out -314bd58254d83b2dbdb555a6ad233d75 emission_res_58.out -63da2ac7fd42fe91103c92300b89c50c emission_res_59.out -0df7e29fe26ce2b63e392748e3587a94 emission_res_60.out -b3dbbdb468c1d4c4a2e5504f3e2117b1 emission_res_61.out -debb8f31ee899788292cbf2e5dc94ad6 emission_res_62.out -d3af154d9e236f93e688b08dad51b77b emission_res_63.out -101fa233822fae598a8730a3cf0c6e19 emission_res_64.out -b39cac497e8c4b11ae6cc47461cc18e6 emission_res_65.out -a41575e3e678dd757c0ec94454300df7 emission_res_66.out -739913b10c115d0a8f5a55386a2c820a emission_res_67.out -73d8cb84f4cccf8b3c4b614270cca7b5 emission_res_68.out -16f3b8cf4d53bf337a9c53ec7c7b222d emission_res_69.out -fca5667f65111a7f8b8cb6d2d0e9ed68 emission_res_70.out -80320923208a53874bf246f1175a1c84 emission_res_71.out -b47fd0820bd1367b9bd2682e4496585d emission_res_72.out -e1b61feff861af08466095c3f6b30afd emission_res_73.out -15b0a26b333f997e55757bcc5614f0fc emission_res_74.out -3a8c6a229ff3e9585cbc24c85ecd26d8 emission_res_75.out -1268423ad8146bd91650e7ff2f493713 emission_res_76.out -e247cb777d3721e2808ff7ef2d93fac3 emission_res_77.out -44397ccffd463c0b2de1beb70d94dd30 emission_res_78.out -c14b84bda8f05c77762c51c4113f0b0e emission_res_79.out -bbdda808eb721db9566a61d7b4d8f84c emission_res_80.out -6c4dff26f01a3bebcfba54bdf07af379 emission_res_81.out -b7653aab8ed46769a06bf4cd5b378b8c emission_res_82.out -b75cefb349a4a792f413ae8d96551d48 emission_res_83.out -547403061a8b34f2c44e7187848604b4 emission_res_84.out -cf5d866db9a57313fdad6de9f65758b8 emission_res_85.out -66c6927712880e790cdd936252ab787f emission_res_86.out -a72070f629252f26c7dea2e692c23d7a emission_res_87.out -ec5e830981de5b5e0463fd7068e8b1d8 emission_res_88.out -908b47f21b0aff0a5e04f18badd9a567 emission_res_89.out -2d2535c2bcbb596493d1abe42c0a0b57 emission_res_90.out -15ad3098729e6eb6a79aebf48e9220c0 emission_res_91.out -8311a29c47cc341acb00e528a4407014 emission_res_92.out -1398d9029aa5d04d579c6c10e1b958f7 emission_res_93.out -f18e3d5b66246c17040b02e5eba57243 emission_res_94.out -8360f3221bf86aeb22a3a248b6844501 emission_res_95.out -9bad4777ec16ef504f247287517f3a44 emission_res_96.out -b2fcb29f5a8e56cbf705d4bfe2c63083 emission_res_97.out -cc7158012e5cfda79c7fdb76b5d8133e emission_res_98.out -48d970c4a44078810d413d771698883d emission_res_99.out +eb9a40aba1639c6cbe0fc742e7b226ad deposition.out +ee60e743859c3ea2e0b13bb96718262e emission.out +5b5cbbc33f5a005f5fc164e755e4874c emission_res_00.out +f1b90bc2c43c1773ec470d3cd85dde59 emission_res_01.out +ce42a6571cadaceb68f47e32a7e0f3d2 emission_res_02.out +09c0577107e4ffdab46a012985c5e076 emission_res_03.out +79ad0829ab52f76f930bc498e4bc9e11 emission_res_04.out +f51ef4d304b7a8b9e28e122d56d84723 emission_res_05.out +4ca7e3e4a1c0dd9a2b598898394c2c03 emission_res_06.out +b463088c9a1a4a6a4df729b450d7dd67 emission_res_07.out +885b89009d73e4991d9e304b72670998 emission_res_08.out +1b595f4b1d19b05e667d255b2deba7b2 emission_res_09.out +fbbd709c745fb3528fd68b2a14df027f emission_res_10.out +6603ac2a3a5c1bc53fab11f992fc584e emission_res_11.out +ae81a8d1028a80481b962298770b5401 emission_res_12.out +f64b5d10f58bd56b124c07e890165ae2 emission_res_13.out +89cc30412e63e73ab84c6681d9fcd82e emission_res_14.out +f03d8a4101d1a1c2fd5da29a1eaab647 emission_res_15.out +e75f6ca6ef8922aaccba8237261df955 emission_res_16.out +1f8faf7732e0a0c32a77f0b04661c413 emission_res_17.out +d54eb08f80892a4118582b79189dfbb3 emission_res_18.out +0a56cebc1621df36c65b7ef6cdee7e05 emission_res_19.out +04d1a37fac98a832656e978094a43d6c emission_res_20.out +b19ad48cd03070148eb172bedf38fbb7 emission_res_21.out +0d655ac26da66fa25507695e4db1e817 emission_res_22.out +d1fea175ce452323dbf863357eeae15a emission_res_23.out +1841ce883463f39995332f8bbda2423b emission_res_24.out +c11fd5516e2307750d669df7039a7b20 emission_res_25.out +5b86b9df53b217f0afc4186cdc0a1293 emission_res_26.out +5e8acab45cbbb3dd8f697d8b285a2c9e emission_res_27.out +218ff185e70fb9017f1833282518e9e1 emission_res_28.out +a5ab48ed6db48645381ee1dca8de4cbf emission_res_29.out +9be7251c2722bd724a6987a75f1646a6 emission_res_30.out +a6fe7b9deddaf2eaaa65dd42e9bcbec1 emission_res_31.out +fa6b62976b9ba68e343a77c3d55ccb0e emission_res_32.out +3474f57d358c1a0f50db823ab8068290 emission_res_33.out +dfe037cdbfe02a84f5a0c9f1fb8b4fd6 emission_res_34.out +c96f9ce937680500a6cd04e8e15b2340 emission_res_35.out +bdac8dbcbcb7af99e91a22307ea6f814 emission_res_36.out +b9f335427b3e7fe0c2f6408f7afb238f emission_res_37.out +9a50103fce25e78d66692406a4c677d9 emission_res_38.out +48df2456573aba03d40145ab44edb42c emission_res_39.out +619470f037d33ee0756693b5ebc74b70 emission_res_40.out +aac3b42b0029a50fc65b196a58040ddf emission_res_41.out +0e2548c62162546a4459883fe2a59131 emission_res_42.out +f9b29ab230953449c4974d0080001afa emission_res_43.out +62fd3cdac988bfa7d237c1c3516fd428 emission_res_44.out +82216336acf3e904b9d1acfe7185594c emission_res_45.out +cc908279d19f0aaeb6aa323ccd72b2a3 emission_res_46.out +98a5b8c23cb0249c611e96ac6741ed58 emission_res_47.out +c68ed20f690597b6e969d476d7b7a69f emission_res_48.out +4ca22d7456bb4dd911c19ee66a9e1975 emission_res_49.out +2cc0b057bcf374b0959c868c02844bad emission_res_50.out +a4b992e1b8d48f4e948174e343663cf3 emission_res_51.out +d9e10632958f78e795c82277fb0a9425 emission_res_52.out +b4de3bad8762827a4757d23f501df846 emission_res_53.out +cb39071ecce707de6292d1fc3b402f67 emission_res_54.out +51d1dc630a99964d1cddb76b6c42e283 emission_res_55.out +d7ccf1583d57b1c8b52050687f1f4a42 emission_res_56.out +97af6c50c70c29d338c1674e8955ef65 emission_res_57.out +6436b855b32c5bb4864ae34ac479b8a6 emission_res_58.out +7dd8484239c18c3103ef61a65e293087 emission_res_59.out +27b80edcae0cb20c30bd40116e2c7370 emission_res_60.out +48781df2b675b45668a5e18fbb633bdf emission_res_61.out +61ab45b747c346298718c64fd5111b1f emission_res_62.out +8ad5e3a2e192bf7ad28fe018d6ed0a9a emission_res_63.out +d3d668c3f7d8e2231b8ab3da61960113 emission_res_64.out +e7b20a7c6a11c4b9a183728e57d71683 emission_res_65.out +f29028c1a600b52c9d2e8498cf953a14 emission_res_66.out +b6334c1158ff20a78b9ae2fd5af22a34 emission_res_67.out +fd02fb39331cc8ddc2ed50b77ec0324c emission_res_68.out +a2d03de2ef12752b0f15e297dc9c9340 emission_res_69.out +46c1009c127b71d4d6a8307ae82d8a00 emission_res_70.out +ade0d992a0febbc4ac7615722705a29f emission_res_71.out +c447df9343c5bbab867a643736635e55 emission_res_72.out +428b187e6a0bdda290527c311aa08113 emission_res_73.out +9ffb130cedb9a5823c7c79dd93b1cf5f emission_res_74.out +9c13ec9547badf606ad4f6d17c985007 emission_res_75.out +a6d66b10e0492e481db6612930fd074e emission_res_76.out +56ccdc3b383d96566e99c3e7eb8d7c2b emission_res_77.out +05d665e36617d1b37125874810c749aa emission_res_78.out +7f7fe112da08441d01497d3a724d0517 emission_res_79.out +5034f7fd2175d1b645741cd76fc84974 emission_res_80.out +d7df21e6450e763d9946231278bdf448 emission_res_81.out +31e3821a26c17525408cb6069d2b1633 emission_res_82.out +0d4d8f768a80b43be12607543159ab37 emission_res_83.out +5d454e2eee752935c8722ba9c79f87ec emission_res_84.out +06e5d9e2c8a55e524774d41f34ea3403 emission_res_85.out +acdeb126c274e61f69ab1ab9d9a89c7e emission_res_86.out +5098ac4a1f606c827b650563007e4cec emission_res_87.out +dcf89316163295f8cf705333cb7ca252 emission_res_88.out +a3ea2e2e94619a961a9d86d63a66e8d3 emission_res_89.out +c1a4662ff3ff24217bd23519be689d8d emission_res_90.out +43c31ba86a80fa91ef2dd6b0089e5a5d emission_res_91.out +e94f9ae65bca4f26f4c385a605251824 emission_res_92.out +beb656d366ea9e2f9fa7f5ced670384a emission_res_93.out +62b4ac7bb86680b8e0dd58b929b7d325 emission_res_94.out +874954196113d726af9db55259424708 emission_res_95.out +08a15ec6fbb99000f058b0ec8a143196 emission_res_96.out +13ce660057c530391b30848960d4c996 emission_res_97.out +be39e38cf053544e0e0a8e99292e4852 emission_res_98.out +02b06e2ed9a05ca2c075dcbd373f65b3 emission_res_99.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_00.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_01.out @@ -303,22 +303,22 @@ cc7158012e5cfda79c7fdb76b5d8133e emission_res_98.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_97.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_98.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_99.out -613057e0b479ed4e8344053a6dea55c6 gamma_light_curve.out -1a9ee77b546d00aa6069dbe9691b0454 gamma_spec.out +c42d80619ddea36d7f7fd7bc9ab257c2 gamma_light_curve.out +ee190b2ade0bbeb40a257d10ab7f1a34 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -381991b1150dcfc0862c42b91af8dd4b light_curve.out -b214de2593a6668d4807d61566e8020f light_curve_res.out -9773becefdfe4afffb041b703210c67c linestat.out +7e3aacd8ee3f3e1a3bd36ff94f4d85fe light_curve.out +789a5fa6f1c64c8b08062c61854f4b47 light_curve_res.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -594b4252eca354ff9819dd598d1eb3ce packets00_0000.out -ab125b9ee59730252b5818b2fd25d632 packets00_0001.out -33ca6208c9ca199366faca0c11a17c53 packets00_0002.out -2de9ba1fae243ff7d4d91076390e665d packets00_0003.out -7c20e85e0e15eeca78e93c9b4b90725b spec.out -5002b0d948af7208b4c11e9745c26ea6 spec_res.out +6da8a73c53bf054878e8d385dad5b24c packets00_0000.out +45df3063a9a76a9c0f926e10d29f772e packets00_0001.out +01bf4b44c6efd342d5dc62fbecd04990 packets00_0002.out +5c9f70d461efb06a3627dca6aab5b2d9 packets00_0003.out +174d35c403e43ae90380d786e591c078 spec.out +a35e02bc19e8aed065425582283e9d52 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -c60a144bdca982efb6ecc99fb4fcf6a9 job1/estimators_0000.out -5c6d9b1113f373a7aa306046e9c65e1c job1/estimators_0001.out -bce423f49527e8720bf338e1de872479 job1/estimators_0002.out -f25ba18020d577cc1b423465655fd28c job1/estimators_0003.out +d1b5b66e9f018c0a2bfb6ccc4768b23e job1/estimators_0000.out +00f380ea39781e2dbd41ff4c1afd01fc job1/estimators_0001.out +377757486870b7d66850e6dadba11efa job1/estimators_0002.out +e371aba7e0accf2e0f8d56b9a147b7ba job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index 2eb1629f3..af614a055 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ b92a62c73f9262be2a6f6db5294d762d absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -f0e5fbfef0724ae666ccfc113b6aa715 deposition.out -8730f6303955f5357e0ea93ee77783ac emission.out +fd6294b0c141377354770cb65fba1ed1 deposition.out +e1430aaaacf6c0c150cf57d0cbe764d8 emission.out f5902ae8e529c0e852df6b3614fd1597 emissiontrue.out -e859530aff21ef8e260a5b5e29f40b04 gamma_light_curve.out +f3658f06dcf3f3cb59f2af794051dd09 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -e8ca5a180498cd2c6b467abbdd963f65 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +79ada276fd59c2e1321109afd258fb59 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d387df4375ca73d6f294778d3677c429 packets00_0000.out -8b987921b1f6c093c83e5c505e96f0f3 packets00_0001.out -8a4fc5edcc2040355cfe344e7d640b48 packets00_0002.out -e30535b6ac363e22e4842b659173e798 packets00_0003.out -e04955ea3322610445a358f3e9b28fff spec.out +c2735ac629f244ca65ed93c9a68f804e packets00_0000.out +97ee84db14d194468fe7c8cc3748213c packets00_0001.out +e3a069b579947f54e3812795cf9deee0 packets00_0002.out +09eb173dc9f9ab59c8601d6dbdeb1af1 packets00_0003.out +ff5a909e77a5ae78b0ff39c51813013d spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -da7c966014744505a37187061214db2f job0/estimators_0000.out -50c01aa18855a5347923cd2147b50b79 job0/estimators_0001.out -e7e27f1e9a6bc19b9f15bfba533f3797 job0/estimators_0002.out -84b21e3c2c16bb577e9310f8cd5e877c job0/estimators_0003.out +4103663234968a59f86da66cbe7631d7 job0/estimators_0000.out +592a09fba94ba7569276e124bb766886 job0/estimators_0001.out +58d13995e193b8628bd36bdf41291ace job0/estimators_0002.out +b702a59839ee164667ad998047403529 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt index a76597a53..2731fa00a 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -59fc9c86755a14869fda7b5853eb2a1d absorption.out -5699e513a97f35794ba4e2d1f713e9f0 absorption_res_00.out -1e4a8d7889dd8df1833ad3871e89f872 absorption_res_01.out -47361aa95c10e36cf7628ac85269ed89 absorption_res_02.out -81d2c576ce4396a78d67d99bbc2884d2 absorption_res_03.out -58d6f18d732e60baa8221466ca1f6c42 absorption_res_04.out -3d8036084a7c243aee008a41b84c82f3 absorption_res_05.out -654232f48ac5d73fae562e9827a47980 absorption_res_06.out -a65d520eedaf4ace23fe1b8aa7269c27 absorption_res_07.out -0b43a0f6217b272d8ae54b4cb930ea1b absorption_res_08.out -0b0d9c6f559a7d577dab692900c0d884 absorption_res_09.out -2cb4ef6dd5447d6992409a48a3c324a5 absorption_res_10.out -7eab021356d76d656aa4aff3c373c306 absorption_res_11.out -e53882c51c6810319762bcd13956940b absorption_res_12.out -6ca3ba6c70446c79811b80ef27593320 absorption_res_13.out -b5a4ebcbb51e1e34f18431894cc7e93a absorption_res_14.out -d547cff268b0162006ec455f52901452 absorption_res_15.out -7cf1c2b9c75f0a1b583707a21f230eeb absorption_res_16.out -d1ce889a47fe62fe335dd59eff854ef8 absorption_res_17.out -a3d7e057de5dd712e069bb778d1300d1 absorption_res_18.out -c544d484855b013381f866821262c56d absorption_res_19.out -ae965203bbf105f69ecaad09c9a39f19 absorption_res_20.out -62c7f35e22f4ce365cae8b7f1403fc7d absorption_res_21.out -af95b5e1a8492a209489771307317b40 absorption_res_22.out -eb6b1479fb4cf46104be67596767a96a absorption_res_23.out -84cf3fa24b5962d4307e006f5d414b9d absorption_res_24.out -7edeb556771ba2d0d61ab09f8be9f959 absorption_res_25.out -1a5cef5cca5aaed0c88581b5d269d3d8 absorption_res_26.out -4efe3f2d842f1a254144608a22bce5bc absorption_res_27.out -657e4efae97aa961a768806af364e513 absorption_res_28.out -cbaa6189af1727a51dcde346851232b9 absorption_res_29.out -2029b094fa281359f5a50deea2fc0133 absorption_res_30.out -3965b4cc8791a9f9c951c2d979b0ccef absorption_res_31.out -995cc52f4f96b17592ffbd2f2e852f93 absorption_res_32.out -444889bc7fa608b3cb3ad04e57b56708 absorption_res_33.out -9b2ecefcdfdd219ff8d4cf1ba5498df2 absorption_res_34.out -40cdb14149d6dfab4bd357ac1c9aa95b absorption_res_35.out -425a6477f02ba50d41fecb6f67edc9f6 absorption_res_36.out -83229ae9e485ee173cbafc73bbe4878b absorption_res_37.out -548fcaccfbbf7cb09129810efeec76c0 absorption_res_38.out -720775c08a281d1b403f66d011d99ce4 absorption_res_39.out -754d3d90c979817cafd31d6ac2792c1e absorption_res_40.out -a82035f4be74da100da07179db11baa3 absorption_res_41.out -ad2486b8014bedfb5dbb4399c463e7b5 absorption_res_42.out -bb1e67da051f0711cd81b0826eec59e6 absorption_res_43.out -1dfe251c4ad9aa6e0606556552080e38 absorption_res_44.out -c0c13e76b1d0e3dada0d051f089f1b83 absorption_res_45.out -ab7785d535acaa6bf6257afa8f42ea53 absorption_res_46.out -f859f19fdc59905332b5a1107376b8d1 absorption_res_47.out -31a8902bec89a4ca1342e2a5b9ba9571 absorption_res_48.out -23625678a2c320831e020d6fd248c17a absorption_res_49.out -e2d48d836ac96f0fa7a8cc4f4704467e absorption_res_50.out -e4aa5e135aefcc69b73ea3822c581961 absorption_res_51.out -2b40a35a6d091a141991d82c40c3b3f1 absorption_res_52.out -d5dd001c02d9bc52c3f4656378094ed9 absorption_res_53.out -28760ced295dea2282ceb1c3c8478e8f absorption_res_54.out -80b1b844001be4cff21cb93d0d048d9a absorption_res_55.out -45b798d072019a147bb90c50c01438da absorption_res_56.out -609b66ead28e62fc97df2426bf98d4b1 absorption_res_57.out -8b20e1daacf59cf053e87d9752b2975a absorption_res_58.out -f85f42f7bdb876dfa96ef2e871a2a981 absorption_res_59.out -a6ea3b2b8ee67d2070f2111148f82dff absorption_res_60.out -b4810c4759f0d5b9785318285b666367 absorption_res_61.out -709156d689efd8d44d92c0208d3bc1ea absorption_res_62.out -fe18b702a2b8289412e4bf549ec905bd absorption_res_63.out -78bd6f6765332075ef2db579de49ca2b absorption_res_64.out -cc6fecdd09b48631ea05eb197677f112 absorption_res_65.out -4f5879e6abdda283320668d43f97bb85 absorption_res_66.out -4212abd7863916e8c33a4a97d5a67f10 absorption_res_67.out -2ec16e3bb4cf424b56bfcd155c5251ae absorption_res_68.out -f3e414e7877807a8a4e4745506eab78b absorption_res_69.out -85db39543bde77666e0b7f8a4af198f0 absorption_res_70.out -71612d6a5ced5ba7b805a0895f557e94 absorption_res_71.out -328fffca68e8c6d39334f3a197b70380 absorption_res_72.out -43ac73acf6d50b951565279e1397bab7 absorption_res_73.out -a1abe61126b1b688f8ae717039b47543 absorption_res_74.out -a3d7ac2813296f7a73d609fad17b26fa absorption_res_75.out -07c4222188ea6047b6b83026460e558f absorption_res_76.out -8721b59825456b357baa7fbe8e9bb56e absorption_res_77.out -4205e4db3de15c631c641147400fcff6 absorption_res_78.out -da4be9ddb59f36a62f5301beb639dbd4 absorption_res_79.out -2998108c4ccf134e57c951c9caa1d965 absorption_res_80.out -56e0396d5d80fdf6338328e54c4bbb0c absorption_res_81.out -b56c8f45a53827e307489641704e678c absorption_res_82.out -3038012354feef1bb95d668c209bdaea absorption_res_83.out -0c01bf3ed62def5d42ea54427dbf29fc absorption_res_84.out -aea034e23712e94a0528a0c6b2610397 absorption_res_85.out -c19cd526320bdcfcaa4083c50bf765ba absorption_res_86.out -a49c7664fdc62cef9247e2c9bac86239 absorption_res_87.out -92cbca3e62951205c7009b9cffe2f3b2 absorption_res_88.out -ced000627c653bdd3a0790a00a5120da absorption_res_89.out -9a8028e63dd350776a4681a3650766f5 absorption_res_90.out -576761b845125ff0eb392130097ac41d absorption_res_91.out -8819d5c6e05dcc2a92185d383e5842af absorption_res_92.out -40f4871a128882d889ebc8cd060f0536 absorption_res_93.out -478efbf8b444723d698668abcf8470fa absorption_res_94.out -e02fc87246408d5953b2be4de890b836 absorption_res_95.out -c3637a977b102295def7d0a520cf20ee absorption_res_96.out -9b56addf11702664760724a5d5103946 absorption_res_97.out -3a7585780b344f15d8f04ecc6786d49a absorption_res_98.out -7449cb79b49f745f19a993f36a12a98f absorption_res_99.out +6c32a87ac9d257a8b329a5f075efad3a absorption.out +70b683ad818216ec48d48696cbbbd075 absorption_res_00.out +0bbed7a5136fce5dc0489daa1f91bd1a absorption_res_01.out +7caee2243f96868528914ae280f946a0 absorption_res_02.out +50109d004978a600f4c7505cbc95728c absorption_res_03.out +a07108be239e1e2a7fb9d195ff9195f2 absorption_res_04.out +9c2dd19e20a5b65572c52ae70018087f absorption_res_05.out +f56fce649ac88ab5e590120959cba723 absorption_res_06.out +3f3edeefa2c49efc01ab9b858905c432 absorption_res_07.out +950caba1eb18e78c6b13e7559e5db2cf absorption_res_08.out +ae8bebae564422b200e2cf11d870b8ca absorption_res_09.out +a5e3cd330445d0cfa9ac0e4a463c55e1 absorption_res_10.out +6c8e26649544072f926d65a572ecec61 absorption_res_11.out +b99dbe8ccd589e4852e82ce9c074b08d absorption_res_12.out +f613cd0746f614759873f1fd6a525e1b absorption_res_13.out +41c6e8a8803cfa36866269dce65124bd absorption_res_14.out +f438d5343a18339268554c07d6fda55e absorption_res_15.out +ffc910e25fd0f72bf995e79237304851 absorption_res_16.out +9ae441d71d8854f37dbc94412ae76c97 absorption_res_17.out +e13654e23ef8e03fd735eaebebee9b28 absorption_res_18.out +874af4d9534de2321a1e28502489f1bb absorption_res_19.out +dda6dbd01f34ce94771d910a579ebc27 absorption_res_20.out +da4e61e4185fb54fac359d857e16fab0 absorption_res_21.out +bd868d631a29cf16758e20e9954cdd39 absorption_res_22.out +060b2deeb08274cb388bb710da0cb2ef absorption_res_23.out +0e11cae2199adf2358da2898f50770fb absorption_res_24.out +690a61bdc5807288ee186c12cae13850 absorption_res_25.out +689ae04979de85cee481ab64bb458e02 absorption_res_26.out +df02992609bce7b3bb1399065e3224a2 absorption_res_27.out +625e4dd1cf6becb28608e0b915db92a1 absorption_res_28.out +5464adb15639f49ba5599ef86e0b8578 absorption_res_29.out +473523c121ba4ffe9a4ee28c8a55977f absorption_res_30.out +1aca6c2e78404daa0848f699951bd77f absorption_res_31.out +365a42dc47224ff1641d890027d1cc3e absorption_res_32.out +fad44e570ed630367b2383e08c9e5b17 absorption_res_33.out +f627156ef5c56add4adc6041cb03903f absorption_res_34.out +79b50be9acff24b3ff7ec311eff953af absorption_res_35.out +b10e49910831962855e51f8efef8e0d1 absorption_res_36.out +33254fb8934eb66467fc89a27d128869 absorption_res_37.out +99bc60454b97ca3bee46b990d1e4d8c2 absorption_res_38.out +20329d703527026ec4a216d94f42f4be absorption_res_39.out +4b59cc44752138ce0b4be0b86ba37e2e absorption_res_40.out +ea6890f6076cfb17483f041b72776854 absorption_res_41.out +d25343c6d570a30df5070a40f3b56aab absorption_res_42.out +3a9d4209a067f2425b7e0c5e4780ae94 absorption_res_43.out +d31fdfb783127fc80eef3b751782a7f9 absorption_res_44.out +452b4f858430a96a3d84c49ea75bb9c2 absorption_res_45.out +a8f3ba15a7343663cb26d8a9132451f1 absorption_res_46.out +21be5c92e235e0755cf0fb36a0e68e16 absorption_res_47.out +77c6fd1b25694079d8b2fb91e4740709 absorption_res_48.out +a1986dd3cc131f88c289c832a0e729de absorption_res_49.out +766d614a8c44141a989f321c63596bd0 absorption_res_50.out +ca96a5c31bdf88a1a08ed84f13af2141 absorption_res_51.out +3216945730f187e9c83a964d04432241 absorption_res_52.out +008574e3a4a33362c6d709cc77a910d5 absorption_res_53.out +ea6221fe62552038e7dfd65a65aa69bc absorption_res_54.out +af56a6bcabdd0e7d31fd66a2c9c98c15 absorption_res_55.out +7845196ee00bdbe63ff85ff5bef65546 absorption_res_56.out +5e35255688ead8c4a81df1ac8110b61e absorption_res_57.out +e37de73840be356252a5c99f80b86a6b absorption_res_58.out +db827bd1935a7b48df4b727990ea90bd absorption_res_59.out +dc03931c924ef2ad3b7cc3128fdbc7da absorption_res_60.out +0d678bf1bd55213cd1d7d83de1b7f7c6 absorption_res_61.out +f758d34b14c36133801dd1f7fb6ac20e absorption_res_62.out +86ab5b5261a6519bb818a2716235631f absorption_res_63.out +3de1ed7603432fe860fbbd6898bbf74e absorption_res_64.out +2c74f885495a3a92ccafc748deaf01a0 absorption_res_65.out +38e4d59607605ea9afa5918d8297b87f absorption_res_66.out +08ac010423013a93d20ba13ef9f29360 absorption_res_67.out +e8e2ea73801314156514e3a855fa80fb absorption_res_68.out +2a99c37d1c0ceeb2383a96124fe48f01 absorption_res_69.out +06bbbe03922f984f8d726b6a8d80a354 absorption_res_70.out +2d0bc37970502b772811d289e6d03c5f absorption_res_71.out +05b3daac4f00bc84bfd4df025439e946 absorption_res_72.out +f70ad21e26267431b3a356107b14b0c9 absorption_res_73.out +49a57176915cc8ef99a9ddd7d554042c absorption_res_74.out +9e6fe2a725e05334641449df849fe57e absorption_res_75.out +83f11011a91434ddfc9ef42a57dc69b1 absorption_res_76.out +4be96d566e2a75932ac58d7cb8c2300a absorption_res_77.out +b6f2b1fb11b7d58c9943174c9d5de65b absorption_res_78.out +d9fb5ef6729689337d97613a6c7be9c5 absorption_res_79.out +129d7a3f336612a2cb72a117cb7fef69 absorption_res_80.out +314081e8a30fc87ea63e47b7188baff3 absorption_res_81.out +fd77abf1d1ae86df84f0efd29e18fd9f absorption_res_82.out +29b47e6926c73fa2e446d34fdfd36ceb absorption_res_83.out +7a450de8223cb82b3e6885d824cc7cc5 absorption_res_84.out +c7a8e65a818c852cc33b5986992f7491 absorption_res_85.out +d2069c00a3aa1250e24bfee5f3b04db2 absorption_res_86.out +498e5593f4ee5a9755c51b8004721435 absorption_res_87.out +9fb0bc71aac8756d463f1af7277b522c absorption_res_88.out +4bc3c1eb412c6977c728b03b315e06c8 absorption_res_89.out +64e5bc9131ee622e34434adbcec7f94e absorption_res_90.out +c3ab5f6299f06f94c23b91cd8cf60396 absorption_res_91.out +0f4c8858f821464b088ad2df750a8ea6 absorption_res_92.out +e8b48739bb8e87827646aef599bfbfa4 absorption_res_93.out +7c8ac6877eb808e1dbe1bebba2e32211 absorption_res_94.out +37da395cda8c34c9c7742d508f56e026 absorption_res_95.out +da57e71ad7436b36d30ff741e41a87fa absorption_res_96.out +d17be52ec55a01fd542f0d2275afcc3b absorption_res_97.out +6f6402a01ca879f11e76ba9574630dec absorption_res_98.out +1330bb475a0964fd04a664ba765e56d6 absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -3ec79426a090a009fa93f8f8c0432a09 deposition.out -04f83df4ff6d51f6b88502b2843586e8 emission.out -f6496d83192e1f669c74bb61b8af8992 emission_res_00.out -d5cc6a6e71f306104708395b5250d031 emission_res_01.out -bc11d1bf7f41c6ac34c1f9e2fd1e9c69 emission_res_02.out -4adc6ae27a77f446a0e581fa181eb74a emission_res_03.out -900e401886c64e0f390b681d51dd95e7 emission_res_04.out -ff9eec48a620d9dca2a3a2b83ca26969 emission_res_05.out -d0bab496d3b0641b6b81570281b5a84f emission_res_06.out -6ae8dd3ab9bb0ac36dc3d993e013c656 emission_res_07.out -2afff9e5739f8f561d6df3d177da92cd emission_res_08.out -8cee56671b45a3b417fd9f1e0fff4f79 emission_res_09.out -503f38ab48c2a1bfbcdf4a84966aef92 emission_res_10.out -16be1740b14dad6b4740f11b466b913a emission_res_11.out -3bdd46917f09afa6313466253704c5b5 emission_res_12.out -017b1929fca080258145b4adf8b526ea emission_res_13.out -cec02ddb139e3b1535cbf6c279c22657 emission_res_14.out -64b6a214c79dd0db81356f357dd76757 emission_res_15.out -09b2c1974c4e32399853d8730722bccc emission_res_16.out -db0fc44df6045dbc118ba5f3d68642c9 emission_res_17.out -514abc1cce484133f351bc2f4950b3d3 emission_res_18.out -6e28b782b39dc261cedec9bdb9d8a454 emission_res_19.out -e02fc9a2ff3c9601f2d7b9e72f2febaa emission_res_20.out -1acd847b6729af07d8ea14e7ffd3b178 emission_res_21.out -6dea1e7cdab40fe6840c7b19c1d6bb7d emission_res_22.out -410697fcf7f340d9d0559eb49a72e5b7 emission_res_23.out -8aaa7279c9b75227aeebf435f8bb43b9 emission_res_24.out -14f357c62905fa96eb467eb9ba2c64dc emission_res_25.out -6185aa548c3e49cf5191989ae1ec9244 emission_res_26.out -9bf6b197f58dc8c6d0cf7541d861eaba emission_res_27.out -7d9a78e0628c7705b23fc9813fe89fae emission_res_28.out -06edae0bc8ce24a57eb1543068e886d9 emission_res_29.out -e8ebc5d6c823995dafc662556b2c0cd6 emission_res_30.out -e1cf22808f4c231500dadd507d510c09 emission_res_31.out -e1084c89f679f0385caa787a31a88024 emission_res_32.out -9dd90d2975e9d117c6c594218d84d8d8 emission_res_33.out -f0e53c5e25b050b18f7b4e58e9d9a6a9 emission_res_34.out -c2a5dd4fa28b0ec032103f9d604653da emission_res_35.out -c585d248bedbfb29638bccdcd0190009 emission_res_36.out -e9a82832a680f36827bdcc062d691078 emission_res_37.out -d3fc1b3910e8f693b7173f62dcc7ea32 emission_res_38.out -1f2972e71701d51c21eb0e0966ec1558 emission_res_39.out -43c8f0406aa7b883d8bb9f309114fbfa emission_res_40.out -bfe29871723634b103e43880ee9c4d22 emission_res_41.out -5c52b4a46b0c162506c3056cf20c7ec9 emission_res_42.out -be534189bb7389e7bf49a273e4ffbcae emission_res_43.out -d624753276f51a0cb51715fb773b619f emission_res_44.out -64b1f8001b1189bc4d90d3e16af502e3 emission_res_45.out -8f9a667be3673ffd8d17e44497c0fb0b emission_res_46.out -c43d93b51f0e46cc08a828ccbdc5edea emission_res_47.out -09190f4afa871319b8073126786fd5f9 emission_res_48.out -0ff9e02b7b6dbc23455200c5a119baf2 emission_res_49.out -1a6dc0e45c73caf0591178ab84b7c659 emission_res_50.out -e6fca2208de2da21a9e1fc5ab3813e2f emission_res_51.out -c40a9d985dc71689210149a58b98bd0d emission_res_52.out -ce733a424e0fd0a28169546df73d1e45 emission_res_53.out -859de6be7b9feb6e3402297ce93c23ff emission_res_54.out -bde308448e01e2cb1baf1de8c259ea6e emission_res_55.out -37333bd85a618f62347e2187ef38d042 emission_res_56.out -ac01d46732b2aac14c44f67d3c8959dd emission_res_57.out -fd5cd638c6e28d39dbbfbf4558ba186d emission_res_58.out -8b7391cc559028ebcaf0cc87fd9fda34 emission_res_59.out -3a20f8ce520a3941e7cbfafaad408ac9 emission_res_60.out -ff20f079897f01799a935b83544fcd5e emission_res_61.out -0c0b41c6f53907dfe80470dc899d6ef2 emission_res_62.out -fac5bdc7215cd5b64f6569cce739177e emission_res_63.out -6889f2564c53a92898703dc6b8d133fa emission_res_64.out -3bd2fef8d4201088d3ea2f3c1688289f emission_res_65.out -dde184586876e0aa5e1b674fd2aca390 emission_res_66.out -70acb444a0cc73153804418057af934d emission_res_67.out -c92d46b6db718e36b45677ca2fbede66 emission_res_68.out -b6bdb44dcf2b8e64b5432d2ff2c81ddd emission_res_69.out -4cccffc25fae95dc02384add2a7640c7 emission_res_70.out -f8c1f2e96c1be3321f553396ca048671 emission_res_71.out -ed2be9c2ba57bf2411cf58266ee9c016 emission_res_72.out -5d185b7aac30f35a0539142106b43a54 emission_res_73.out -b31fd179b0b141b02dc281d9ee679e0e emission_res_74.out -16ecefcca7ce9506ad6bf609f753d125 emission_res_75.out -3914322428691f7299830c7d2cab9b4d emission_res_76.out -a27fca42e533fe8f599d7ae316671665 emission_res_77.out -76de50e037cce597ced68ceb39e86ec1 emission_res_78.out -fb918e209213dc68507472e9a7143141 emission_res_79.out -ef6ea48651ed2e6562e9a6441ffbca16 emission_res_80.out -e6216756e7ae9aed4bbbe04b7996f976 emission_res_81.out -dbe7592661cde081ddaf263d0d06cf0f emission_res_82.out -f02a682255ed0843e1991e8d0dbf725d emission_res_83.out -b9b6974ca11bd1f477176c5b202efa5e emission_res_84.out -a1718b1860708a64865e4d8c6b940a0d emission_res_85.out -0b000bc7af952a8168a2e061b980a916 emission_res_86.out -f17b92b4a121c989310a31b9a91281dd emission_res_87.out -16f9faf8a0b1b6e675538af5be21a2a8 emission_res_88.out -142f4b35133acbc77c84d090e96d3056 emission_res_89.out -7c4e9e3036dea08522832b0ac2d1d717 emission_res_90.out -77d4f33a94086da3b880e4cb20984cf2 emission_res_91.out -3634498273cd9fb742316716c64760df emission_res_92.out -58ed5d2bde98d07199ecd83f3b33e26b emission_res_93.out -1f18ea0c799b8c536db7b18a1fae9e1d emission_res_94.out -32099f6b5dd17c305b7f37ed60da5d8e emission_res_95.out -98558df6514777e8dafb9a2163099db4 emission_res_96.out -a9d4bf067b7da041df1df3f29db0cf4a emission_res_97.out -aab3f810382ec8b44651cda5773c63c1 emission_res_98.out -5c74788b815c7b27af919bcfd7282813 emission_res_99.out -8810bcbbd0846ac5e13129c2f406e19d emissiontrue.out -685864ad09fcf89341baa3eb8343fe28 emissiontrue_res_00.out -7e7d1d28c259800a1b3e8c3f351d3579 emissiontrue_res_01.out -bc5164eb6854e377110fc3e8617fc96e emissiontrue_res_02.out -8275bc03f8f4f88f6a251d59ad108836 emissiontrue_res_03.out -8d8c9a3f180ba334ffa0522d198f6d37 emissiontrue_res_04.out -965adf7973b719582cf0316357f15bb0 emissiontrue_res_05.out -dae10f17ee2dd7cedee310fa1ff9feb7 emissiontrue_res_06.out -12f6ee0d47db380ab227b46a939f9ee2 emissiontrue_res_07.out -962513fb8203e98cf1edc7cac8302416 emissiontrue_res_08.out -faff9b3b1b3c9c79dfdbc3e2070742bf emissiontrue_res_09.out -67878cad948566d43183bd4c37260dd0 emissiontrue_res_10.out -6de5c1d8807f1fb1d86ab4b5d5995255 emissiontrue_res_11.out -f6e246876a2d8c90514cc784a15fc87f emissiontrue_res_12.out -2cc3c89d66681c813991602fffdaef99 emissiontrue_res_13.out -eb352627a72de27d0937918b5c145b2d emissiontrue_res_14.out -597a46cb3e9d0b68ebc46b06ad6fd509 emissiontrue_res_15.out -8c6909c4685362eb95b83552eec4ed83 emissiontrue_res_16.out -5805b94162af981f8b91bcb4e236a02e emissiontrue_res_17.out -3d66631278e5f82c0e544045a60aa20b emissiontrue_res_18.out -2c0056a5de0974807a46e2a83fb5a6bd emissiontrue_res_19.out -32968d61be840f505c7812e6f704a8b0 emissiontrue_res_20.out -f9f315b8d0ab63b5bd5a1b961b52049f emissiontrue_res_21.out -903790dd73dae9aba55b729ee3bcf2bc emissiontrue_res_22.out -b36c479302623b7643210948a45cb88c emissiontrue_res_23.out -a2f08db31a34d783f2f8ad166288ec8d emissiontrue_res_24.out -c8e6377a522bbede11005bc4f542ebed emissiontrue_res_25.out -1d2f92451baa51b3f2e621a10e8f49da emissiontrue_res_26.out -336e81717f10899a3c6f23b5cca6e8ab emissiontrue_res_27.out -6cac5c9afa5f85d7016d842341f27082 emissiontrue_res_28.out -e92f3d5a52827f9343159297f4c4e963 emissiontrue_res_29.out -8a2ff43f4f8ee5b9e585890967048e4d emissiontrue_res_30.out -80d96b2fb0306ae5eb707b9a57d0174a emissiontrue_res_31.out -38d617140b50ab8040b06dc20bb875ca emissiontrue_res_32.out -5085f6d7e656bfafa8e9fcd2035fe709 emissiontrue_res_33.out -20ead7c8e928b6600e7b78ee6859d142 emissiontrue_res_34.out -0079456824a643d057425de3296e7d54 emissiontrue_res_35.out -901bd414e2be21bf8d2db70647b7eb35 emissiontrue_res_36.out -39803b5e2010496fa43b1e593c8374ce emissiontrue_res_37.out -6101dd8265f4f63e65f5397ac68dae0e emissiontrue_res_38.out -b91bde0f30a715ee6f27ed2d170c5e17 emissiontrue_res_39.out -cb58f4e58d76d76b431b1a908be5df73 emissiontrue_res_40.out -4e4370754bd5645651d959fd162bb379 emissiontrue_res_41.out -73be4be315b30d0b65e5fc0965bcb122 emissiontrue_res_42.out -1cf174da296b42e437c651574b9c4584 emissiontrue_res_43.out -9cff78bc00136792115aa6305222bbe1 emissiontrue_res_44.out -5814834c954ee28675c8b98e2e615dfb emissiontrue_res_45.out -0f2d7ea1ea30e13a809d34bc6016934e emissiontrue_res_46.out -f56bd55f5124e0f7235a58654ed1a716 emissiontrue_res_47.out -e6ae2088053bf938625142ea1fc737ad emissiontrue_res_48.out -368a2e0beb9e54dedfa780c0c0e57266 emissiontrue_res_49.out -5b3e2993c1bc785044b2ffd9282cf3f1 emissiontrue_res_50.out -b3321f466981fb7478ffa9b4b034ba0d emissiontrue_res_51.out -bc36ea9189185129e6cc52f2e690eb9c emissiontrue_res_52.out -121045d70b0829ad2203cd8f9ad1178f emissiontrue_res_53.out -21d890612ea48b994273d7369d03ef26 emissiontrue_res_54.out -25d7e4a138e3e25be85858b9a64aab7a emissiontrue_res_55.out -3efa5a28a0b272fd4aa4b737763e9c13 emissiontrue_res_56.out -b1436f2ac33761db2573aa2cfb4121df emissiontrue_res_57.out -755917be9c5218e2b519a05081d2c105 emissiontrue_res_58.out -1e0a3d00685a7b1b27697ec887e70569 emissiontrue_res_59.out -fd93f721361a662f7953983fbce16f79 emissiontrue_res_60.out -9fa71cac547c96e4f1d3dd184be51d7c emissiontrue_res_61.out -69d8761447c93c42177c0679ca968e33 emissiontrue_res_62.out -4f286ad799bfa72df4af4ac916bd040c emissiontrue_res_63.out -997fceb908dcc8a89ec7d12e66dc8f8b emissiontrue_res_64.out -5fc66fd687a675df747943ec1785ef65 emissiontrue_res_65.out -bb07f83212c4ebde16e9b4b6859ac40c emissiontrue_res_66.out -062e0cd4602e8a990cc9a7a0d116f800 emissiontrue_res_67.out -38ec1bb05225b2cdcddea12d9dc03e38 emissiontrue_res_68.out -d2ee8f14ed30997c7c47d578b7e84dea emissiontrue_res_69.out -f04e850a2e659317a3e3dc10f5ff9ee8 emissiontrue_res_70.out -11d94bf48955ddc8fdf29c57e9ed6d42 emissiontrue_res_71.out -2724610d4475cab7b0fa4be39cef6efb emissiontrue_res_72.out -ffd7fa89702a99d17df6685647ea5a5b emissiontrue_res_73.out -dd2b3636411a1bc779b65876f95aeed7 emissiontrue_res_74.out -5a156c8b4264f2a5909faba7a077ad38 emissiontrue_res_75.out -3888bb2cadbe8da3d353ce941d77015f emissiontrue_res_76.out -de75742beb47f1ccdec49251d5a6dd16 emissiontrue_res_77.out -61327b78f5293ca00bc89c3a0f3924f7 emissiontrue_res_78.out -232c25699d8d510165b8e30c444300ce emissiontrue_res_79.out -02348997fad4339ae85e41cf211a4e07 emissiontrue_res_80.out -e9858c158600b5e5c734102449a7e4e9 emissiontrue_res_81.out -e687789b46dd9fc65f803ac1fa7d60ef emissiontrue_res_82.out -654ffd46746fbb4a1abde0637425feb3 emissiontrue_res_83.out -29f6a5487094999bb092c67f9f6af287 emissiontrue_res_84.out -208d7958c959a03cf81db420c6eb32ea emissiontrue_res_85.out -fbcb8c930cd2ed6cf90b11c442754523 emissiontrue_res_86.out -acc55b3c58e4b3a1b39ae1b30889567a emissiontrue_res_87.out -94c12f56cb83e6026884dca7b961ffa3 emissiontrue_res_88.out -3058591c186a53f1a66af0f56e74bb16 emissiontrue_res_89.out -35dff03eacdd0e5a438202078af65e1e emissiontrue_res_90.out -2dea87c7a0f1f9a1da727439ea4f3112 emissiontrue_res_91.out -eba841a598fe4ab574f0c89279b80e3f emissiontrue_res_92.out -b6cc5c269f63edd684af76b676fc1b74 emissiontrue_res_93.out -4af6d59597c3ac41aee039cb36fb1184 emissiontrue_res_94.out -8190817f89d5997de3200afd63589829 emissiontrue_res_95.out -bfb033f78920b782fac4095143e31330 emissiontrue_res_96.out -ce2b6f5450dfad64200ad1f8444e1ea2 emissiontrue_res_97.out -e81385ea000699115f4275302c11bcd4 emissiontrue_res_98.out -f7ced96bfb7de5201b41ea401287484c emissiontrue_res_99.out -57e406ca80bfad913ad3d18fa32e4630 gamma_light_curve.out -8deab0eb42b7d0452d2dea74dd6f70b0 gamma_spec.out +077307c9e4a89453ffb3de622c6bcec9 deposition.out +a7334ce70ab45ad1bdc10afafe1c1ae4 emission.out +b9b02e1e727a758a78fd67b0f698de51 emission_res_00.out +7ca10b168860e2e62458a4177a7b5eb3 emission_res_01.out +958025f44e161528c21572783ceac794 emission_res_02.out +f0921f8ceddd36f249d87735c6ef4c2f emission_res_03.out +05156666fd7165d611021d33e260faf0 emission_res_04.out +e432511d73886977441b9b8df3d04d1a emission_res_05.out +2a827092eb3a7dc9dbba9dab9c7401bc emission_res_06.out +1e2ef4064a4442eace002e4a3d0d6be4 emission_res_07.out +4fef435891fe1738ab869e1321850460 emission_res_08.out +373fb583794afedfb1c8409f33f95a7f emission_res_09.out +e880d6db3604fd69f9abd94a730e1c81 emission_res_10.out +177ec9f87b5847f6bd49aa55fb4b2246 emission_res_11.out +f4cc2b3f7fe58aaf8aca17c120085649 emission_res_12.out +ccadd22de9453a677ae0b52ef0d22691 emission_res_13.out +a1f5d1e1ca790fcb459f37351ff03dcc emission_res_14.out +a1ba68e7307fe9aa0f18e016da6be34c emission_res_15.out +332aad97aa731d4baa663071f680dfd0 emission_res_16.out +0d515b16994281e03651c188b4f0eb08 emission_res_17.out +526596aaa44380bcea40a02db26debec emission_res_18.out +cbabe1d7d6c6377ce98b571e9072b993 emission_res_19.out +492b504a96cb744bd69c15187bb14591 emission_res_20.out +c09d00a717116fb3bacdf173acc8b45e emission_res_21.out +9faa6574412589e811e38dcd55e30aa2 emission_res_22.out +6fa3b29026b9a2da4731cd9a7c79c52e emission_res_23.out +2dcd588a98b971c44a146fe1285568f1 emission_res_24.out +27838ad43072b17ceea83a536e841109 emission_res_25.out +a359f64f9c7c858a25b78b6647660165 emission_res_26.out +cae2974849997afb1c8b3da1295c5933 emission_res_27.out +50a50d51249f89977a6859fd330ce63f emission_res_28.out +d10c49499a5b3ca538213cbba111b6c0 emission_res_29.out +5d24681b03786f070f5b5bf13b37103c emission_res_30.out +01d6e0ce7ca1c3850a30d1492d51c206 emission_res_31.out +df0ca8681525f259c45e5f612ff0fc61 emission_res_32.out +ff2dec034b91013add5495c0711384e3 emission_res_33.out +d5dd0c3239a8ad28ac204f17735f23f2 emission_res_34.out +6277465bc6681ddcfd25e8d820e808a2 emission_res_35.out +2f7fa54e96c6163acbb0c9fbbb0957c9 emission_res_36.out +4f6c595aab8288b66fb422543cb5fdef emission_res_37.out +0d3d0f4398ec4fa0841dc856d9cb4ad6 emission_res_38.out +0573da428731c5b2a8dfbbc9c8d65e2a emission_res_39.out +6c619321befa1cf21ffec40b3a75aff2 emission_res_40.out +5f7f79b3735f95484e3dd7a9283d26c5 emission_res_41.out +e5c2d49e4575a2dbdc8a09613482aa62 emission_res_42.out +55101df593e9d0bbd37c6a3ba27c24fc emission_res_43.out +9e298f07ab1ab38b61178755781b83a7 emission_res_44.out +cc682727ea89bfe8158166456f4180ed emission_res_45.out +988d205ad93ee21af868d1c566e53ce0 emission_res_46.out +533c041322b68cb3293bdf9e5637a28e emission_res_47.out +d33a8356fe7ac01b466987bbb9400bfb emission_res_48.out +305422fa22f65b0c3c95cb757c0948fe emission_res_49.out +b07467009410025e80f60f7f27599a58 emission_res_50.out +90b5dfe73aeea7c9ec0c5f63ecbd7cf1 emission_res_51.out +dabf2e2ad08c2c0f390bafde45f79060 emission_res_52.out +fa99dd84a4706b7bf0dee5838a2caa97 emission_res_53.out +1c104a1594f2a2a894645c27ec69030a emission_res_54.out +de2f3212b42b5b5b5a2962d71a02067e emission_res_55.out +b5e8c536f39ea33788d448e5bcaa72cf emission_res_56.out +53e37a611fd26c63764bddf2bd86edce emission_res_57.out +412d7069a8f7841a755f4bc68995d4b4 emission_res_58.out +788e05d7574fee2f581f344cfa9a89d3 emission_res_59.out +5848e952637bd425d06c5acc95cc41d9 emission_res_60.out +b903bd4c55e24f21a482357e4568b76a emission_res_61.out +735b7197fa398f8f31c52a42085baf6c emission_res_62.out +d60f52e1f718ac5e61e0a8385d51345c emission_res_63.out +31f8b577b2c6253c09edf51e556f2bfe emission_res_64.out +b38f5c9990f0de883a0dd93f9292ccc8 emission_res_65.out +bb15c3737a782c790c24074f1fa17f5d emission_res_66.out +0517e104a27fac11944dda2e381f2344 emission_res_67.out +6580631e160014a439c0b967efaed13e emission_res_68.out +9bc0f838a9c7153b5b3722ff0c655cea emission_res_69.out +9706c539e1e23c9315e898963e508e4d emission_res_70.out +6f0528171582b5765745d3860099a6c5 emission_res_71.out +14787890122c2b825bf85d638ac66c7c emission_res_72.out +34b46bd5f179f055b244e80d87b8ec47 emission_res_73.out +97432a8f498751c5c2df82c3cc1d5f1c emission_res_74.out +81ad122e4c40c517bbdff33d47523d00 emission_res_75.out +9ef1218de8eae4ae3ea54d8a00a06342 emission_res_76.out +c839c24c6e0c6d89c7dd6cae71ca6e85 emission_res_77.out +f7df1d3481c0f99ef315a9a75a728b9a emission_res_78.out +581f1a649dbb1ddc92f9023ffaf61457 emission_res_79.out +f8f1c4113ed1b3417351376787b4938c emission_res_80.out +e38cd23a2f215d6ce842a10b17d4f9f1 emission_res_81.out +3f4aa6ab21aed68f01f2a088e89c3fa8 emission_res_82.out +ed317345b0017feb761c9f30f232b781 emission_res_83.out +b999c8ad353d301508c6b814896f30de emission_res_84.out +16f5e166be4ee039365911bcea1c71d3 emission_res_85.out +60b7c8216710106c5e1773c364a58b2b emission_res_86.out +99ff241b7ff0875237c368b542be13d7 emission_res_87.out +da19a00b82858e67dd6da7a79e4ab667 emission_res_88.out +f2307cc270950eac3c0c6a51a6dd3c27 emission_res_89.out +248c40a52401451051facc8c1ad10d7b emission_res_90.out +91622fe8062a1c997e22ad599dee3c56 emission_res_91.out +d1d58dfec337d9512eb60925e1ea0cc4 emission_res_92.out +9342a1e16d17192307cbc99f50815a18 emission_res_93.out +4d0b5748af5a6517bc6d4c44d2d6e627 emission_res_94.out +136f2ca09e42a34722cb53750fb404f7 emission_res_95.out +f1775e028e2ce397b9e989b04419cd84 emission_res_96.out +aca84ede94af461133c95e4058117296 emission_res_97.out +b5165b7c3ae55222bd3b66cbdc0e2d66 emission_res_98.out +02793f101e8193b24e43e39a72586caf emission_res_99.out +2a5c21fd64fbf9a673d6dda04f1d5927 emissiontrue.out +55fdc2957d0fcc9060193ff05bef8c27 emissiontrue_res_00.out +0b6ac0b22afc10031d6882acb1002bda emissiontrue_res_01.out +a5af04b9eab7d6471e100a86de9f1141 emissiontrue_res_02.out +449374c739d7b4d654e01f3bab667cd7 emissiontrue_res_03.out +6b2769a0530b8d0a953159a817bc910d emissiontrue_res_04.out +ea8dd99a30e3f65b027b898a53ce4c96 emissiontrue_res_05.out +ccf73cda4fdd91cb2dfea38ff7f3917b emissiontrue_res_06.out +9f4d9179de3732b1660eda2542396ea8 emissiontrue_res_07.out +d5a0f2dadf91646e4f48a2876b9a488e emissiontrue_res_08.out +fcfbad2c7c877d29616e534592f0676a emissiontrue_res_09.out +9711c5b9a53a16e55ab8bcb4409d3ae6 emissiontrue_res_10.out +c3b09695a6ec66d62e038e0700a82154 emissiontrue_res_11.out +d3f9c3aece038556fda1568e867c30b5 emissiontrue_res_12.out +ccc0c551b3a294951fa0ad6c4968a1c1 emissiontrue_res_13.out +2a8c6fc70e760faf542a8076292de3c6 emissiontrue_res_14.out +10e7cdf789718dc102b1da488a6b13ea emissiontrue_res_15.out +c456ebb1ad6592fdbe0a59c397b1d616 emissiontrue_res_16.out +91dde63ef5b8297ca7f24a2c6625f257 emissiontrue_res_17.out +92fac447e6d1ff1627ba6d7c38cdd1c8 emissiontrue_res_18.out +97565384210340a388c2ea32756a3cc6 emissiontrue_res_19.out +ad12f8f4a541013f9a7efccbf694a263 emissiontrue_res_20.out +a2fc25b8bfa0598de3d6436dda7814e2 emissiontrue_res_21.out +8510b93cd6bd50637cf2c856011b54f8 emissiontrue_res_22.out +24e38d6dd36271227d8e54cc8c1fc9f9 emissiontrue_res_23.out +ec479601245af63cd65a6efdea7c28b0 emissiontrue_res_24.out +b59ac0b069a624c9ae09f7f402e6c1cc emissiontrue_res_25.out +335f286db0c5c6cfcae05578c6d39908 emissiontrue_res_26.out +e7bb5698d43a9eb6d75ba4ccf2848894 emissiontrue_res_27.out +c58acdacf25881b82bd8348e5fe20d78 emissiontrue_res_28.out +24ee98f3ed46b872a270cd207e836168 emissiontrue_res_29.out +fcaa3e6495a173ee1d702b525072bb60 emissiontrue_res_30.out +8f5cde52d67c3bcf040862336a1c379f emissiontrue_res_31.out +6e9bf7ebd7b7435c09d7e62d4699ed0e emissiontrue_res_32.out +fdb0a9117a4ba7af42460edf34fe862b emissiontrue_res_33.out +f02497f21b353430fabdeafe2d698d95 emissiontrue_res_34.out +4bfc17fba878708d345647366914c324 emissiontrue_res_35.out +974947a3c03065d37f8fc35a4d7c287d emissiontrue_res_36.out +3659f9a17d104adb9046a9bcdd900cce emissiontrue_res_37.out +729b5ad290d8815775f17c9fbf90298d emissiontrue_res_38.out +2a5dec3fceb8457b009efbf2dabba2bc emissiontrue_res_39.out +fc076f1bdbd19c6aa7ec38a2abcac2cb emissiontrue_res_40.out +581b9ace4930541f55257766b38cd6a0 emissiontrue_res_41.out +8adf7019579d73b94e95cd017ff36a7a emissiontrue_res_42.out +63e5f37d7b0ed90584b5e2110339d4c6 emissiontrue_res_43.out +54d8e565e2b323e604756caff3f5d924 emissiontrue_res_44.out +1c5a83055f70d350497d73d7d64baf93 emissiontrue_res_45.out +cb1daa5da4f593ab648d0f6359bbe18e emissiontrue_res_46.out +7f263da3579ad7f3cdc17a6115f343e0 emissiontrue_res_47.out +30787f966f78be5d48f08739acd9ac26 emissiontrue_res_48.out +36296b1061a47ba95835aca94fd068df emissiontrue_res_49.out +455a0eb4d77993ac7582ec907b4fa63f emissiontrue_res_50.out +337aa247804a2c9bf157a57e56bcda22 emissiontrue_res_51.out +af69b920454520d7d547c9325d84a929 emissiontrue_res_52.out +22a958110f2b05d9d8ce646f62d5e189 emissiontrue_res_53.out +62cb84ac4162beba12bc6e7b36e1542d emissiontrue_res_54.out +4c9ee1054f487df0f52f486eae767b13 emissiontrue_res_55.out +4d7bb6e51f337351a35f3724dcd224c3 emissiontrue_res_56.out +4fb48f823148552ff7b2523018a36c4a emissiontrue_res_57.out +45e16aac53c604c27ce376581b8ca77a emissiontrue_res_58.out +666f211e9203d4e4d79f367ac6197f12 emissiontrue_res_59.out +6612e5f8758a985940d3a533937d526f emissiontrue_res_60.out +e8c444c9de9101b22f3d2f630bb967bc emissiontrue_res_61.out +7e4f857047d54abce9e6354aa612cc36 emissiontrue_res_62.out +e00c5ccf8bbf375b1cdd14f95722ab8a emissiontrue_res_63.out +837e2480b5d343c6741279b39b2e7eee emissiontrue_res_64.out +f6c6b2fd6cfe5903a84e5bef318d2d1a emissiontrue_res_65.out +1a001e0369629a1566e3f5389d674565 emissiontrue_res_66.out +16dd8f0efe0871c7ba2323018f47fd0f emissiontrue_res_67.out +e7a52b1e0a8dd0950f616e1c0160de38 emissiontrue_res_68.out +ef7d9f37d999f06f5f9fec1b1eaf175f emissiontrue_res_69.out +50a464d8ebe40956b0ddd2573d28dd0e emissiontrue_res_70.out +3972cd9256c1d59b1eb853331c8f59d2 emissiontrue_res_71.out +fc3eccab798ea4df14f18dbda1a9b466 emissiontrue_res_72.out +21865746b4d76628f9260e250b4a4056 emissiontrue_res_73.out +58690a95e505189b77c3cef366458475 emissiontrue_res_74.out +b564cdb95ad2b2b57897891e94b54d51 emissiontrue_res_75.out +0599468a2f168e4439f13bfe85820b55 emissiontrue_res_76.out +922ff67fe134432e6be19ca391d95a7f emissiontrue_res_77.out +b899dbf7321093d50870ab6e2d29661c emissiontrue_res_78.out +23cd8280a24394f7523f0da2bb2299aa emissiontrue_res_79.out +574f833e9888172dcd2d13d9b27c22d9 emissiontrue_res_80.out +b776945cd632ca451b10271bcfb25f4e emissiontrue_res_81.out +4959130b18d6dbd591cbe9ecf297865f emissiontrue_res_82.out +fddd2d5aa52c816f6d4c86bfe91c6980 emissiontrue_res_83.out +1987eb5161fae664d9f9c4623aec6d52 emissiontrue_res_84.out +acc84a710dcfdfecb65768af6719e59f emissiontrue_res_85.out +80fc2385fa329233f2ce88aadb823529 emissiontrue_res_86.out +29954468cf512e7e4726d6997f8e0edb emissiontrue_res_87.out +22bd9008c989dec1b3fbbaeb5585df2d emissiontrue_res_88.out +9ac2ce7848b261465e67ad67ad9db108 emissiontrue_res_89.out +9ec011415cbbf0f912a91379903bd683 emissiontrue_res_90.out +af668a24d5b573a8ddea1224f5f042e4 emissiontrue_res_91.out +a68798b17fcfb7ddbcfe838b0adf8944 emissiontrue_res_92.out +5ab69bf64dbfe323be4cace58642182c emissiontrue_res_93.out +d0f439c6a296804d0a3dc1fecca7f0dc emissiontrue_res_94.out +687493730698aefa27b36721c2c13cac emissiontrue_res_95.out +add3f2b9e1897092dfa6a9cc2ae60e13 emissiontrue_res_96.out +6ad55ad7c6b8c10aa171bbdcfbe557c0 emissiontrue_res_97.out +c5469fb7ebe9a487003478f39d9e4f7d emissiontrue_res_98.out +da76c4a991cdef77d7a8fe291cae633b emissiontrue_res_99.out +19ff935ead37f47f4637d09c4bbdf94a gamma_light_curve.out +0ec8518b09891bdd5ae92701250e926f gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -8a9aa4ea5e6eab77831a63993eb94898 light_curve.out -c61846d6ab4f3a533830451b08211652 light_curve_res.out -9773becefdfe4afffb041b703210c67c linestat.out +c418bd488a88758b8998799fb0e85f56 light_curve.out +dc87afe89962c6cc982654d6b51fe6d4 light_curve_res.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -952e5e3daf8e38eea0bfecfc09ff7943 packets00_0000.out -7047fa1e52f3ae3bd48c81b83c93a776 packets00_0001.out -0325a37eb3a8e294b6c9c1e476ac7a1e packets00_0002.out -3f1ddf501b59a3bc567bd44b85ab8a71 packets00_0003.out -eb3020ac9f92ad77cafe08debabebef3 spec.out -976e15317990950e776b033ee7c2f024 spec_res.out +d657a1b558b3d8f5ef12ffc2fe97af0c packets00_0000.out +5607b49884bd2a64e7546e79e9beb5b5 packets00_0001.out +6d750b33c47adb3ab9e147cc7f226ef5 packets00_0002.out +b80d451b7a65caf3e7e358bb2e31e215 packets00_0003.out +75a19500dc039b998f89bdaa549d4840 spec.out +fc09caca8a29c0090c5747885cb037aa spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -81feaa4b7b09112a50d60fa05fe60301 job1/estimators_0000.out -f5262e7ac7c1b099a8adb12131a20767 job1/estimators_0001.out -ddf4bd94c15fd89dbc5a6966a2065589 job1/estimators_0002.out -a1ca68ee3c877216dfee647a5a678f7e job1/estimators_0003.out +27a2cc4fd0945df10105078bc2a80f26 job1/estimators_0000.out +9a6b237afdb0c6dd8201e36fb431b1a6 job1/estimators_0001.out +4591e80eeaf5212c242e212a93c32fd5 job1/estimators_0002.out +2aeea9f1649606d3069a8043b4f50c2b job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index 5e1e440e0..620c6bf38 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -baff4b7ad509ea85def4c9d4f07a1f95 deposition.out -ba021df2fd3e0702cc22b961d914078c gamma_light_curve.out +ab3d72c064c34a388f7b61274f4cfe7a deposition.out +dcde6c7de036fea5e230d1d09e8bf708 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -97ad2f8d42d6f06b7dbff2cb8f69d0ca light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +f0c53ee7bd627cdffa79a78172ae55b0 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -a78c3e8320953da52f91e67d0764f64e packets00_0000.out -2c639f325202bde2acaac93346dc2a20 packets00_0001.out -c34aa67738d56f205ebc0b5d39de2e6b packets00_0002.out -e8a435024d6648a528819c5b82773e90 packets00_0003.out -1c544cd7f0655c7c0c7b94da02adfeaa spec.out +69f7ff7b95a98965ba7470e7a56aa00e packets00_0000.out +6f81cdc308ab997a2aae42e9aad3b5ce packets00_0001.out +a6c0fee501b6128a3fdb60ab924aba93 packets00_0002.out +84f08d240ba21f289e94737ca195f160 packets00_0003.out +b653a3329cd63cfa1f429ff83c33693b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -7c6f21a50b6ffbac7ac7f321c1aa22a6 job0/estimators_0000.out -2c481b50d1b482f875264f5b0f4eb97f job0/estimators_0001.out -96654d3446da68f668f1b9da11d5e2e2 job0/estimators_0002.out -4534eeae3da8b1c1ccf8237b263f5b25 job0/estimators_0003.out +a3a985a3091152eb9b5a8865e94f6c8e job0/estimators_0000.out +42db38927e1d95963b9db81422c760ed job0/estimators_0001.out +253fac738196aa1c188200929cdcde62 job0/estimators_0002.out +3c09f9da7bc2046ce27b4a371077b42f job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index 583de178d..6cd761e8c 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -f839c7f6a8f4d229faad887904a8a98a absorption.out -09376d1b89b5370a3e73e1824bed17ec absorption_res_00.out -b1d951cb71922d06883109171f0ce25f absorption_res_01.out -5e96f879d0587773be948d68c281903b absorption_res_02.out -027ff191c8b22ced35e82af26a694d87 absorption_res_03.out -d4887a355af979067706f6cc0bf7c6b5 absorption_res_04.out -c57918bd32f328745cf80dfd8cde5332 absorption_res_05.out -6d7e070265b1959412f494f8c8e772a0 absorption_res_06.out -2b00f4183b26acfa717a1400be344120 absorption_res_07.out -3790ea9b33ed0a9eda25638da1466e83 absorption_res_08.out -fc6aad1fc05ceb72747d78ad8a369601 absorption_res_09.out -d3adca931a6ef57d2f7f3d4d2221354a absorption_res_10.out -3a4810e2dedd9592e829c70edb95a074 absorption_res_11.out -3cbbb8dfcfe632c20ae79a8677c5a2c8 absorption_res_12.out -0a6a94041c70df5ee47fef0bb5e08433 absorption_res_13.out -8cf306e9cfb2d8a9811336d2b56b545f absorption_res_14.out -bdc0537a7e04416e89a8173948254e8c absorption_res_15.out -640e0b6025aee44ba971f97970c8a955 absorption_res_16.out -73f1a6ae84c4cb3fa4a1f2492c8a6229 absorption_res_17.out -51a661fc5b33fbe7566e0c4e12cf66a3 absorption_res_18.out -f9dfa624d0e940434c518c4e21bbc19a absorption_res_19.out -e415c6d0f8b5677ca25a13fd8b1d6005 absorption_res_20.out -58df21d4ab31b8b3b58fecd8e24f86cc absorption_res_21.out -0752575d51fcd75f1e7674763f78b08d absorption_res_22.out -bb29811ab55b0d7eca501d8bc8410d0a absorption_res_23.out -f1801d9565269012d5a90e3a8a104ee8 absorption_res_24.out -edc7d3e3f0da4efcbd5c8a9a135404b7 absorption_res_25.out -b79a42f8e3847bedbe3c34f9352fa020 absorption_res_26.out -b903fcee284126df79563bcc93b29fa6 absorption_res_27.out -8a3041c25bf267aaa3ac4b49f3bc5b6c absorption_res_28.out -03169c9a16d39bb5104cf7a59f0b0bf8 absorption_res_29.out -6dc0d2cac88980fd46304e4e81389e13 absorption_res_30.out -7daa3c1af60ded35cb82b5c5e2464b06 absorption_res_31.out -33ff23b1cf2c721ecda1fbd1dfe73eba absorption_res_32.out -5bee3043bfa77b0dca50281f7caf677b absorption_res_33.out -a2055a93efab6d5d79ab820ca55d318a absorption_res_34.out -45478f4ed25a524e0313ff2f0318a6df absorption_res_35.out -da3dc8e2d2877676570808fb304e2ec6 absorption_res_36.out -f22d36c2b2aa1d472529c5202fec99d8 absorption_res_37.out -1fcb13187ddce02895c36f33a17d6d0b absorption_res_38.out -efa612329d7481e3e3e977d9699ae5b2 absorption_res_39.out -74755fdc21a6ec305f67ffa56803fbc9 absorption_res_40.out -fec337d91aff3da8b0d56c9d1104ad80 absorption_res_41.out -acf6b4a95d3b6d3a4ea99ee510f90c03 absorption_res_42.out -7a919bfa22c3211d27203a90972ce821 absorption_res_43.out -83b86cbd6b7b5b2880dcb8111a516c13 absorption_res_44.out -52de2172ec1a1b7d9e6821e018d4534e absorption_res_45.out -2eeb44f061354ad16d2cfbaa77a0d9e1 absorption_res_46.out -c2d1faef89d7871078e6a64c702a6732 absorption_res_47.out -37dc6edee76f5aa49e85a8f945da09b9 absorption_res_48.out -2dbe414eee757bbe3249bddd5a9c2a1a absorption_res_49.out -c0e0183481160310cf7f2e4378a6e7e5 absorption_res_50.out -a84ae8b4db7576c3ed2fb7787a99300a absorption_res_51.out -692de580ea1572356ada3ec95257cea3 absorption_res_52.out -3bdac6b7568f1578419fcf1c48b1706e absorption_res_53.out -9c2b6472b7e138ac7e0af1fb71377776 absorption_res_54.out -f7a6f4c593d6199993167f097bfb2ba0 absorption_res_55.out -a0f3a107bbce5af0dc5fd9ec9d539001 absorption_res_56.out -919ebcc30bd8ea19ed93c798cc3f2336 absorption_res_57.out -50fab27c50543160b65553cef1eecf26 absorption_res_58.out -a56928c9993940e6f943d6c968b67c6f absorption_res_59.out -282c18a64c062f568f378a362209513c absorption_res_60.out -2455e5fad9388b985c8f1b581cdc79e7 absorption_res_61.out -372300b2f5b853886c6e9e1eedc916b1 absorption_res_62.out -3020202ad589fd97057abcb9e165f038 absorption_res_63.out -65b029deacee0f15eb611481e61bdc93 absorption_res_64.out -a1796c9f23e814e99be7aef9105346dd absorption_res_65.out -9aba44f0c2e575aa86d59f04d44b2746 absorption_res_66.out -0b82c59a328307d75ed0ed907e2bc6b2 absorption_res_67.out -9340bc1396d704e06b6f6e6da3af0078 absorption_res_68.out -3197b0b0c63cf6d5ee7a98349f2fa100 absorption_res_69.out -19eb37aa8edbde73cebdd4632cd04e2b absorption_res_70.out -4b3123055b89024f17fd59ab8c9606fd absorption_res_71.out -e9b56e249edf86afe1f5a507876c74de absorption_res_72.out -d3041d471a5ec3ea4cf4c2ba434563ad absorption_res_73.out -b5cc02daac2124cafbaa382d5064a3f6 absorption_res_74.out -648c751cb36c3373a0ac91531c6223e5 absorption_res_75.out -7c34ba9915cbed39b0053533e73dc1af absorption_res_76.out -5c6dac30081c39400c00855025334406 absorption_res_77.out -771a9f022fc7aa83035aea57cc7b05e5 absorption_res_78.out -298016b5a9e58ad9abbf01093744b7e7 absorption_res_79.out -68156fbb7ace590c9d9651ac249bcb23 absorption_res_80.out -d7ec8c695aa3627a105bbb3349ad4867 absorption_res_81.out -9cf62803f9341eaf0dc7fd91afb03789 absorption_res_82.out -4eb965c4a75850ed8706e14db4b4e5a4 absorption_res_83.out -6cd600eb3ec01c661d8f699a8eb33c5c absorption_res_84.out -cd39056652b881298753e13d70cebaaf absorption_res_85.out -a46498285b21f5f5d2a15aeaf94cc1d9 absorption_res_86.out -ae5f6aba6cae9804ee43af8a4f34cc69 absorption_res_87.out -158f88012a890bfdea3e973194b01f76 absorption_res_88.out -8e10b2d5012f8fd0be80bffbfe9add47 absorption_res_89.out -4690695d7ae813e5bd3abdf337458170 absorption_res_90.out -073acabf72539815623ac1f3ebfe4552 absorption_res_91.out -39e79c431f75ca51ae634e7859b5af80 absorption_res_92.out -a71ac53333b0d5c756dade66238429e7 absorption_res_93.out -d65d626017a1b3d19ea12a33dd768146 absorption_res_94.out -198833e7dc3005756099157c8bfc8fbf absorption_res_95.out -8c842dba99945556dc5c4a67598b6141 absorption_res_96.out -ae2a852c6df1afd99f0ecad5388ab3f6 absorption_res_97.out -a079f7669915997c8ae72495aca90719 absorption_res_98.out -10661c6ecee39c36510afafe70768b45 absorption_res_99.out +73a673c95bc1593acf754f8c02d5f804 absorption.out +57ebd62f64cc92da4d9365e72a4cef02 absorption_res_00.out +f1ee522d66760fdbd7750d2a5a965e19 absorption_res_01.out +3a2c509fe14035475f328b2cb4f5fb22 absorption_res_02.out +a54bd0b5675a814bd967f49092e16977 absorption_res_03.out +9ecac20f93d03365cd1f4cc52a7c1c92 absorption_res_04.out +9cbff5c61d786150f9f7ef8b8d6c22e5 absorption_res_05.out +8b54a9338e668439b48b73b52bb65fa5 absorption_res_06.out +e4d4a8ecc64c5d4be7368d423133e30b absorption_res_07.out +c2ea4361964c3bb571f4f29ef09cc99d absorption_res_08.out +f9b2376726cea600c5a8fbad943e538c absorption_res_09.out +1a4106001d5bcf2bec6a9d85d57d67b8 absorption_res_10.out +dd74853a68c5fa001b4615de62ef8a21 absorption_res_11.out +4a7cdd84ee7e0af239e5135e556da5f3 absorption_res_12.out +eb6186e5894f216875c2040d841264cf absorption_res_13.out +a69081647d5a3c2ce325c4d0d18ca37e absorption_res_14.out +0a26f7d72b90c9a1e57b5133bc973c77 absorption_res_15.out +27d8a7eec6a0c89963d4b51f7deb7ac1 absorption_res_16.out +09b2edb0585b874f9cfdb179b29663a1 absorption_res_17.out +04aba6c7d08a79cbb4e302804b161510 absorption_res_18.out +33bc33d96239de005d7c3cfa08b96c63 absorption_res_19.out +de1dabfab78e0f8fc864d1c4e09763fe absorption_res_20.out +59f4ddbb66da30788727163d327689be absorption_res_21.out +f2f1d5ae8e7794322ae81c893e4c2fcb absorption_res_22.out +3989afdd8d8ba08570bb91293d5fc5c4 absorption_res_23.out +b5ac821ba8ce67d5063d39e6e29ddec9 absorption_res_24.out +593f4b4dc3d97dbe242cb09a4a252247 absorption_res_25.out +e280959170dfe29c2a23a073d41cd6b3 absorption_res_26.out +00461795b3290287ea08b8b9d94652c3 absorption_res_27.out +dab473f749a02a43da4f154ead02208f absorption_res_28.out +68d85e1c70bf91fb6644c65319581e59 absorption_res_29.out +8a0218da2d5f1122d9f3da6e106e6843 absorption_res_30.out +1ef38a581462854e16af7070a7f95ff4 absorption_res_31.out +17e7e1f36203baf2651df1495e716150 absorption_res_32.out +65a8bb2d01fb3ebef14b6bf94365a255 absorption_res_33.out +21e897eecf1917fc6ceb874df0d3a91d absorption_res_34.out +d372647e5dc5f4a5dc1bfc62efad89c8 absorption_res_35.out +d1e2c0418a30e80e23e42de37cb6434c absorption_res_36.out +80309c3af967cc07549da2c1f96e75b9 absorption_res_37.out +60664f1bdb7d28ecbc628163415a285c absorption_res_38.out +c23ee8bff6a8978a12105de73bec938d absorption_res_39.out +12092e986abc49007b04289344450b49 absorption_res_40.out +2e0de564ae95bd949bc134811f8b20f7 absorption_res_41.out +3a5339fa61291f37df739f2729828789 absorption_res_42.out +7c7b1be72341a97ea9d6452b237e85b7 absorption_res_43.out +9a2bcc3fa42243d268e997937ec18510 absorption_res_44.out +1bca72c8d90c67166e05944099934044 absorption_res_45.out +5e0a05afb3cca622ec47fa691cf83c6d absorption_res_46.out +0c6de37d2bcacb094f872b8723b93576 absorption_res_47.out +fe5274e09314a5da209db679e737a770 absorption_res_48.out +df6a4f41b7be822b3e35997dce6cf47c absorption_res_49.out +361f8b68d2e17599efc69d6894083dba absorption_res_50.out +229784d71bd4be4b9d2d67d5f5b4c376 absorption_res_51.out +8ddf2b1a21c324f975af093bd82e0343 absorption_res_52.out +6b203ed1ce84a5b06337bbfa5112bffc absorption_res_53.out +6954c457db66a5a772304b07228a44e3 absorption_res_54.out +35e84f36e34a50db3227ea4d559155bf absorption_res_55.out +e77555fa98a6d42d6107d5a99767f159 absorption_res_56.out +a264f44109fc87fd9ec615c0b8b90fd0 absorption_res_57.out +fa44b80d9405d03c80e7db71bec14176 absorption_res_58.out +253cb3daaf06e15a1dca09ff2f83a50a absorption_res_59.out +213531480ef9d40a06642f52563ac292 absorption_res_60.out +8de6412aad4785fe752086ce4b19a7aa absorption_res_61.out +a06c903aef091949c46c41d344956da1 absorption_res_62.out +5527f6bd82ea723fe06a18f76e7b0ac1 absorption_res_63.out +4880765d17fd504800f2ba00f8273f85 absorption_res_64.out +5c261b53c267fb9f73a366fb3916081c absorption_res_65.out +453ae7c71d3836ef8108680aeb55e803 absorption_res_66.out +f732fd1ea044593db37d3a821e016d1f absorption_res_67.out +875337d140097d998c4feebe0471319f absorption_res_68.out +70c20ea58ec9eb737728d3b1f37416d4 absorption_res_69.out +4ec9e532652eff5f1dfd05d30ec5ed72 absorption_res_70.out +1e99d7c2bfd984f21470a25f6091f894 absorption_res_71.out +ecd129c3affb789b4cd61952750f2781 absorption_res_72.out +1e00770b3bdf563c43cd8dceaf1b12b5 absorption_res_73.out +9ec60deda551bc05289d3bf0ee21c6b4 absorption_res_74.out +883f4743717f70167163e7abeb68e1fc absorption_res_75.out +8f0a92889b24bae7079ab65986002332 absorption_res_76.out +c5c599348784446068da2fbef3d977a3 absorption_res_77.out +3e04db75fab41b3c68b7697cd521ce9d absorption_res_78.out +24cb6b352c72c70597c1b931307a9db9 absorption_res_79.out +66f9049c225b6cc53356e4669717e705 absorption_res_80.out +e786ed288df32e02061b067585469f32 absorption_res_81.out +baf8ac891bbf60fbc6083512b2340782 absorption_res_82.out +863ab3fea004f0f95655f42fe6e5d9d0 absorption_res_83.out +716d303ae352fbeba7ce0106168ac8cf absorption_res_84.out +7824b85365510a8fe2e287228d67cb3f absorption_res_85.out +dfd47ca581c86f3535499f20c12bc97d absorption_res_86.out +84ff2e9aed4055e27fc47f15856457d6 absorption_res_87.out +b6df8f98364a6c37a9694d84965a30fd absorption_res_88.out +11c991824633f02a47191a47fc4dd1a6 absorption_res_89.out +a57e222288ca56cd5f45716c26780ed2 absorption_res_90.out +170a20d3fff79527e8eb0e18fc9073ea absorption_res_91.out +5cbf4ebc576bede07378709f508cebd2 absorption_res_92.out +5a18d5ac96dfeae71259e187cb16b3fd absorption_res_93.out +9be8f0efb3c7fb8ebb054aeacceb1430 absorption_res_94.out +7406bd1b4e70cab14c368d4b6e91c6f0 absorption_res_95.out +d0687a0a05583b02f6ea54755049cfbe absorption_res_96.out +b0e4aa5c8cf52271ce96a49b3fbeeeab absorption_res_97.out +fe3db3c1e4aa70b0e4b34331d91d2051 absorption_res_98.out +cf414873dbea6dd809c3c215120f6110 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -01bd19928247966645cdab9708de5c8d deposition.out -9780aea2fd971ea4e1ee9a0d66ae2707 emission.out -caf05b95bd6772642e7e467c899cf8f3 emission_res_00.out -df9ac20536b70058b8fa4679fbf08606 emission_res_01.out -09c6a89a3b33223e2a69d0df4b99b093 emission_res_02.out -12fe67dc3032204699f51fbdb1806d53 emission_res_03.out -35732aeaf56b27c56d8f5b30c9633a46 emission_res_04.out -226a4bda44e62c9cca766a73cb9c501f emission_res_05.out -fa3188ff36f65874e56a322ac330311a emission_res_06.out -21464872febb9195bcdb66613b84e166 emission_res_07.out -668d85e2d919e2a1cae4aacf6501a4b2 emission_res_08.out -e91d258d006db1d2f51e8ae2e30b970f emission_res_09.out -023512b7f2e40bde11740a06689588d7 emission_res_10.out -64e4b2fb6bb47e5f5b235441b1a4b789 emission_res_11.out -dc8c39f78c63d579b776ec7a579df0f1 emission_res_12.out -29040606466f26b839c4b2f5acd338dc emission_res_13.out -3ab6699f20dbb04d1f89eeaae7dc1fe5 emission_res_14.out -fe3468ef859bb54d4273f97196b9b2bb emission_res_15.out -d0bbe2e7e55e2b54557c67bda941bd0a emission_res_16.out -3b95ffc2dfb1aa4ddcdbdeb0bf3f0f91 emission_res_17.out -7f1eb035efc1830a0fc3ebd3f514f49b emission_res_18.out -09267f83d1196dbb15c1365c6ff8aa39 emission_res_19.out -d0dad331fe85cdf946af5bbff98d369c emission_res_20.out -8f645ae2a40ceeee3d838b0af0d8e5b3 emission_res_21.out -f79a3500f7296f86b800825cc09ff3ad emission_res_22.out -3b3dba0b9c45504fd803f63cb6b71931 emission_res_23.out -e03dc38ef37974d03372c404ee504257 emission_res_24.out -382da61dfa307a55fe5dde92df5ab35a emission_res_25.out -f2f12586e3d87f3f29a3e954fdc1c234 emission_res_26.out -38cb2fd2b7054e4c1572cb9f681d53e1 emission_res_27.out -a2671b19f0e6c9de23179cd8c5736a1b emission_res_28.out -42532fb05de7be59501e21cc4ec7ea2e emission_res_29.out -b87a595605ed848035ebb79a1847dd01 emission_res_30.out -52848ddd22a05abe9a20e66e98ffd3e1 emission_res_31.out -8a320bd7fb77adbbbd9412a925ba89c3 emission_res_32.out -88d1bc6fa346515d9056f480fd23c377 emission_res_33.out -abef896caba9755b18bed9a2ce4a6a90 emission_res_34.out -2a7dc57e1a9ca00f188370eaac1b7abc emission_res_35.out -f7c0439c3991c91490f2402133e24466 emission_res_36.out -09f3168600c7d0ef2d43afd7a5988244 emission_res_37.out -e5615f2e3172437e750cae0b17b27fa2 emission_res_38.out -3cd195770363e95a385e85f451573ee1 emission_res_39.out -bfefcc2268797447f38110fc938a6eb9 emission_res_40.out -8001e649d72a9afbc29a18eb15e4a510 emission_res_41.out -aed0b8ce47ab904aef6092bd8f63b907 emission_res_42.out -8a2be3a718deb8a009990c898526c1d3 emission_res_43.out -9e5712b2a668c36c43a2b5756a5985ef emission_res_44.out -4c022af08d2e195e8ae59420c55a792e emission_res_45.out -d914e3985bee435f44bdc577b9b5f820 emission_res_46.out -bfa417c908125bf3d48b5aa3256ed19e emission_res_47.out -a006b5e107ed874c486643de6b4da1cf emission_res_48.out -851a75b7cb7c25f4988b3bcf704d303c emission_res_49.out -99960ec8f5846709f89703d9773632ab emission_res_50.out -69a5277175c1b48890155af9b16fa66d emission_res_51.out -46bf934085bbbeb78a469af225f2a657 emission_res_52.out -12e5a3139c9bf5105d31a1a6ecd9539f emission_res_53.out -037ded84ddb3965503d86555c6389185 emission_res_54.out -897e3eb47377be8d48f9f60ef4d89b64 emission_res_55.out -fd3beb5a3585d862b12278a130a36fd6 emission_res_56.out -406ca966ece1fca3b5cba75e879f19ed emission_res_57.out -a8e1386d4874adbb8b306fec261338bd emission_res_58.out -b4231858d71ca3f70bea0aec1cbd1f35 emission_res_59.out -99bb49085d60c46c0142e6fc26100624 emission_res_60.out -30769281ccd77429859a5b180b0a1d20 emission_res_61.out -a8255c957bfe52c8d049cedb5c1e9708 emission_res_62.out -1c74510371f838215664f3058cd69f22 emission_res_63.out -954fcca5b630d787c52fc006905651fe emission_res_64.out -fef8a6d3a9f8d6344a70fc6fed257666 emission_res_65.out -346f62c2b9616eded9bbf9fcd42206bb emission_res_66.out -d3ffff9d12f552f2f8dbac9bf74aec0e emission_res_67.out -29eafca02d1c2fc38277b86bbc45af51 emission_res_68.out -a94d137d9ad3fe2403ec4f6944a10c50 emission_res_69.out -99b0895319275c54f6046fd52d4904e5 emission_res_70.out -ace0291b16189c2671d16e08c7dc8c09 emission_res_71.out -179bc71be2a2550bb1e7e661e2bdc30f emission_res_72.out -cd40d1e44d32ab457758d2ae267581bf emission_res_73.out -7b3c9edc78f9971773104004ae443997 emission_res_74.out -e600bbcc5cb1c7eeff0107122dd27d9b emission_res_75.out -296a1a0c334ca2e9ce36aa449c9f1fde emission_res_76.out -ac6ca177fada079572e6aa06e89b4e2c emission_res_77.out -bf4ef5ab2a7f4a52f34f9c59c75e837d emission_res_78.out -2b8941764b8dfb31ee98e3e304e2c627 emission_res_79.out -50cf71cd1e1896226fdf2c4a4561c520 emission_res_80.out -27392bc340d653f3cf3ad8f42b4f0eea emission_res_81.out -a38ab6c962811f99e4406c9411a35b93 emission_res_82.out -2f1a279a68e84a05685ddb59a1cc9bf3 emission_res_83.out -6be244db2cc63c3ed8745c9f42331d7c emission_res_84.out -92f2197edc4500c802484ebcb51e27cb emission_res_85.out -2d9a2ab411bd6f0a28115b4848e1617e emission_res_86.out -fc6911e4b88d605b5082159a2e55a173 emission_res_87.out -198b8a674507f08c9ba638e80c90b3a1 emission_res_88.out -749711b5c98386ec60b55e3403af30eb emission_res_89.out -6dc5cc6f7c3500536f50940a648fee8b emission_res_90.out -6076c03ef770f62ec3ca73dc56902d03 emission_res_91.out -04850e1fdfda57c48be326f69f2093ec emission_res_92.out -4768a4b167c66009bf85b543df94387a emission_res_93.out -a2e5886381adb431175f2fe9ae873fe3 emission_res_94.out -c2f881c0c45e73df91933632c0cec3fd emission_res_95.out -1ebe123edeead15306da112f9924ed1d emission_res_96.out -8cd46d453a7d5211ee1ad39a9fb180cb emission_res_97.out -2c8eaa9a444d20d3140a6ab0155456b1 emission_res_98.out -9eb79b52b3f252f533c34e5057d45b14 emission_res_99.out -f1081c1dacf56fbe259d583797f1fb74 emissiontrue.out -a220ff31f03562422d8bd8fe6198998e emissiontrue_res_00.out -7a892dbb8e39691fb28b1178a8534a3b emissiontrue_res_01.out -9bdb0c28c52ed897a92bccb56c22cbf2 emissiontrue_res_02.out -b40151007ce13ded7ec67854b5c7dce6 emissiontrue_res_03.out -88f14d25f8bdfe9c7eb8aee769ab29a1 emissiontrue_res_04.out -b124ada26fc942a3374cf90e7f0f883f emissiontrue_res_05.out -8a5d314da8b51898d7f89ce701ca2250 emissiontrue_res_06.out -306c12713ea6dc2f291b5d494d8c9783 emissiontrue_res_07.out -a79ee29b7903846770ac7d1c033b8a16 emissiontrue_res_08.out -4e93e0bfa32d07de8fdae23b371f878c emissiontrue_res_09.out -a89e26bae369355d3c06921d5c6c0f5e emissiontrue_res_10.out -c0a40164acc0fdc1d33c6e923d3b6f17 emissiontrue_res_11.out -247f8f585cc731aa430ecb9af514838a emissiontrue_res_12.out -fe224815a1167bbeccadfda352ddaf15 emissiontrue_res_13.out -37af747f86385008b295bf08b515c000 emissiontrue_res_14.out -b43e6f8dd961bf119b1e29d7896b38d5 emissiontrue_res_15.out -8c196ed7ce87d24eb65c8aa36fca8ca4 emissiontrue_res_16.out -dac6b3d6337df4b6c55eb17c83c2cc5a emissiontrue_res_17.out -90cc2e9f476d2fcc2af52536ab21180f emissiontrue_res_18.out -1c7ca165129928f3ca9104e869149df2 emissiontrue_res_19.out -72239cc2d50d710863179bea2ec6af9c emissiontrue_res_20.out -412c88215f1a77cf89c9300e499ea1c0 emissiontrue_res_21.out -d5ac6efdaa0867006a5ea768413a92aa emissiontrue_res_22.out -d4d60f6100faa6748962627708f87d70 emissiontrue_res_23.out -468d61f3e933cec3c6cf9f1b981dbdcf emissiontrue_res_24.out -3b52e163bcfcbbcb82632bb8900d86bb emissiontrue_res_25.out -9181ce345dd6bca193bdf56148e3deea emissiontrue_res_26.out -8ba8546bec26ce912cc0ecc3b3082a81 emissiontrue_res_27.out -d2e7cbe10d325f86c0faa1ed45eed3f2 emissiontrue_res_28.out -88c100589d6d85f4971febf74b429583 emissiontrue_res_29.out -cde9d037ca75561ae57966f08e80332b emissiontrue_res_30.out -8c0c6132b6b3d64e246fcd2ea874d859 emissiontrue_res_31.out -3372b23a68f1e66682b64818eeb52e5e emissiontrue_res_32.out -cbeeeddd8ad7d2ce98929cf3296ed4d1 emissiontrue_res_33.out -51e8eca686139582e931290c686a6062 emissiontrue_res_34.out -83d3f6192234716ddd650437f1a0227c emissiontrue_res_35.out -c73b549bb7a5689de664125f9afb3a24 emissiontrue_res_36.out -b843af918636bccc7e0958b320e2cfea emissiontrue_res_37.out -a3cc993fe42d19232340214e85f3002d emissiontrue_res_38.out -d9bff692d4cf533ac2b0bef4f4be17a3 emissiontrue_res_39.out -5f3074f32b249caa9bcdd9b57bd4c152 emissiontrue_res_40.out -ead10b1884be4bb186579f5726c315e9 emissiontrue_res_41.out -2b685f9013b121b7ca535ed53a226e0b emissiontrue_res_42.out -ea3e31491cd9e628b2a16ab80332ab77 emissiontrue_res_43.out -f551e930de448385055e88d14bca1f1b emissiontrue_res_44.out -76d449bfbacd7a9387d0c240a89dfe44 emissiontrue_res_45.out -8c8d2b7a459d26566d14d52351a8c14d emissiontrue_res_46.out -42efa0fc4debb8a4c3d8872d6c152e5c emissiontrue_res_47.out -50ddf21c6a87576281b0b030a29ddcf1 emissiontrue_res_48.out -1733b5d5dacfe98bb8320bad76d448ce emissiontrue_res_49.out -748c65c25d2cc15aa32f71704a294830 emissiontrue_res_50.out -65450f789bab13329403164d5322e536 emissiontrue_res_51.out -6971857f8edb52367624d9ed7b1262f1 emissiontrue_res_52.out -8a5d3dbae5d961b8671cecb24f2fcf50 emissiontrue_res_53.out -7fa3fbcd25d6b6bbcccc996cca3b6510 emissiontrue_res_54.out -f33bd08740f855319bea4030047d6aee emissiontrue_res_55.out -d694d01d11ad9f992ed3e28189d1eb2d emissiontrue_res_56.out -c4e55ae36422dbb9e0d0ac0ccf207d3a emissiontrue_res_57.out -484746a46b614ef988d84590051cc491 emissiontrue_res_58.out -bdf07cc3fc8cb83082c23ca8a4691d65 emissiontrue_res_59.out -172465e20885114bc8ef348757a3d4af emissiontrue_res_60.out -444eba20ec3e69a08fe1b44ce869ff9c emissiontrue_res_61.out -1394de62bf847c57dbe78da5cab2c137 emissiontrue_res_62.out -52329de45516ba61dc99664452eccb9c emissiontrue_res_63.out -a59c91a64ed2613b50c59c628368aea1 emissiontrue_res_64.out -316e1eda8c4c78daad243afa59958c8d emissiontrue_res_65.out -755067a572ed040306e286d5f492410f emissiontrue_res_66.out -3507fe93fb039568856f06797ad00949 emissiontrue_res_67.out -96de22c711a53f7df36eff583c48762a emissiontrue_res_68.out -b5c35c853304818a174c5bd973b8812b emissiontrue_res_69.out -3aa2d7b8a8fe200fa155455bbb692ef1 emissiontrue_res_70.out -be8fba4f7969a10a732215f51de24bbd emissiontrue_res_71.out -532a79669862c3e872d851b6dfaee3b5 emissiontrue_res_72.out -d17e81426b9f1f7ead89f5493d27c0b9 emissiontrue_res_73.out -3f2cd49daf224c39d9f9e62e2f74c8c7 emissiontrue_res_74.out -d9aabe6ccb4e013df16c16f1183974ff emissiontrue_res_75.out -15bed6a6e5d7af4e9e930d4b376258e1 emissiontrue_res_76.out -50bdc817847170ec1f7be955e1b67fb1 emissiontrue_res_77.out -67fe3d8773e46b7552e30ea13039e39d emissiontrue_res_78.out -f460ebcd922ea65ba2bf3e0c99aa2494 emissiontrue_res_79.out -b30576ee4f61211171e63fe2b1f6c1dc emissiontrue_res_80.out -ff64e78c22a507e20a8cc6fca7afb4fb emissiontrue_res_81.out -1085db149d67e98b23d34bdaaea96256 emissiontrue_res_82.out -09bf43815d57556321fe2f13bfee8e10 emissiontrue_res_83.out -4add58f2a89af41c61214eea4142cf24 emissiontrue_res_84.out -128e57a3abafc1614696696a987b645c emissiontrue_res_85.out -ec5d8ebfb92b5bda8c96304528866bd2 emissiontrue_res_86.out -cdb8a04f39facbd2adad97cd08dacdbb emissiontrue_res_87.out -3c3517723c9f03d6a9057091226f0990 emissiontrue_res_88.out -78def8022fb15eedc9ded8a086d77928 emissiontrue_res_89.out -ff9a45b3d57042b5abad4ac147cc65d0 emissiontrue_res_90.out -e895c856243e85345c08d8dd1893ca4e emissiontrue_res_91.out -937312fe80d64a99f1e6752511e3921a emissiontrue_res_92.out -d18d0013fc6f520634c0b2b3278020a9 emissiontrue_res_93.out -02a317c51dcc4b40dacdb26af9df65af emissiontrue_res_94.out -695fcc7113f6591b340021408e593206 emissiontrue_res_95.out -442b4d85308cbf341f6ddb27f2280fef emissiontrue_res_96.out -371b99bc08acaf9e539c05ce20eaf4b3 emissiontrue_res_97.out -3b1236be8ee9fe49928379cac36cee3f emissiontrue_res_98.out -9e2b0a72d0e48ea0f15addeb717feea6 emissiontrue_res_99.out -8a370f8ac30f1b1a3fe36d8ff06bceb0 gamma_light_curve.out -2e6de551ab8d8d085497cbe9dd193b03 gamma_spec.out +75971c72789adfc8396f1d1db429ffb4 deposition.out +a2f872a2ab6c8764ba84a0a038da7834 emission.out +4c52b7730d02998f5bac7201edb0e3f3 emission_res_00.out +c3d2072cef2b736bb34c7804015cc192 emission_res_01.out +26ecd91e4bd9829bfa192604e9e7b475 emission_res_02.out +d6b59da6b2c1b1f774d813f180ead45e emission_res_03.out +39e0325c3003ee4f26c73bfce84c3872 emission_res_04.out +4009ade69d3d7cb5f34f5fc410122ede emission_res_05.out +3c7195c1ef608fd6ea486bdc8c1f2f20 emission_res_06.out +6c838516989f679e7b15ece9173cadaf emission_res_07.out +cd8fcaec794f0eab824ab41847ba98de emission_res_08.out +e794790e8b42a617bebb59bcb907c786 emission_res_09.out +1dc61f1598cb33ac2f49307c4840ed16 emission_res_10.out +2df63eea44205a91c42fdbdbb49fde73 emission_res_11.out +0b0ae528d23fed51aa5da674e21e6425 emission_res_12.out +f8789dce46ed788ae26488fc0104831d emission_res_13.out +cff871e30c2471ed6201df4ce840cc24 emission_res_14.out +16e2c3285b8b88ab046dff2a74f87adc emission_res_15.out +5afde660e7298586300c9a2aaf354587 emission_res_16.out +c82850a7257ad8c870ccf480e6272602 emission_res_17.out +9cb473e85289d6b7e6023abe7208cb80 emission_res_18.out +3cdf5517932a55f5760d66a6571c3269 emission_res_19.out +c4f61776e492442927d359dc8afbbc25 emission_res_20.out +592822e50be18d73f364198d7604c426 emission_res_21.out +ae19676de49dfd32c6cd5eda63c1b66d emission_res_22.out +31e66b26946b75243ed42e947e203283 emission_res_23.out +a0e48f6890a45f252e2a5abee9a0d89a emission_res_24.out +c5938618e283ec382742374946af33ba emission_res_25.out +f164901106f1584205d60d439b03043b emission_res_26.out +3ab2b5c2869842856b336b990d4ce54f emission_res_27.out +ae2bbe221312807bc8702a7f7008596e emission_res_28.out +94010cffb6e64dd14ad381304e853a2a emission_res_29.out +985394f4b2602681da7f7776aa7545e2 emission_res_30.out +79b25d59f6c710a97c29c62aacb528e7 emission_res_31.out +a5f68ebaf83b8be76117a6d861f861f6 emission_res_32.out +c1fa6bd2e0343b5529b5e6f47297733f emission_res_33.out +f833bb44f065a7723aea931608fddbf8 emission_res_34.out +98c880cedda2b50e89df6caeef21c456 emission_res_35.out +f10deeb5c4705a69491096390821314f emission_res_36.out +9cd447c8a77b15b294a7f0ddf12b1d90 emission_res_37.out +246a3d197c6c6a2a536e0e2f44b1446e emission_res_38.out +9c8adbfeede3cb0e8dc0930f80f0104a emission_res_39.out +e162aefd6e47b8ed7e936e329bb12838 emission_res_40.out +aaeaa726a6765b9ea8a1b4ab9f53f73d emission_res_41.out +5f4514b28b093c8639a852c14c5fc052 emission_res_42.out +d6b5f4b613b6c6ed1e182e3d32a10a87 emission_res_43.out +05be39fa9a02a50f6d8b77ebd6157877 emission_res_44.out +88dc63cf460f14cd49546268fc78a6db emission_res_45.out +4e7975c80cbdbaa7f8ff2bdc2392bde1 emission_res_46.out +08be29f80297107edda7923b26960ff7 emission_res_47.out +974ecd68fbf504533e2618d7d8d8348d emission_res_48.out +cfbea031c116ebe368f7e87bc3b17753 emission_res_49.out +906649981efb65d5e35da8dc3bcd70b2 emission_res_50.out +d62a53cb0ea3a05f442ea9a4f4eeb442 emission_res_51.out +613514cfd30d77490d025ae8ad536b0e emission_res_52.out +b5fcba42c6f529bef9b1fc61fbb6dae3 emission_res_53.out +51ed25e723f4e12dba10e3e3bd646e12 emission_res_54.out +b201787cc5bb2dffafd7d014df2b79ef emission_res_55.out +792935dfc6b41c476bf7335f192c98f6 emission_res_56.out +4910c8d30a240d9a51545f310cda2b7b emission_res_57.out +310393cd63eddfceddad00dd76e129fc emission_res_58.out +2d81b2f3bb2c5352062485288e72d563 emission_res_59.out +8387632456a7c3f7a7991c20b442e7a6 emission_res_60.out +4342d626b6baf9267d39a87608577315 emission_res_61.out +5a4d31adb0a4ff6d830edc8a4b0bd8e1 emission_res_62.out +383018cb3f7fd574c8ebda11483522a5 emission_res_63.out +7d914e4b015a9de22e18ffbcd10b499f emission_res_64.out +bc192e7385916b5bc8e5e86a16068e80 emission_res_65.out +9fa08ce00c34b68ee0563f4328c17ee2 emission_res_66.out +5a435e687ed6d6192400805ff0786c38 emission_res_67.out +a95847373ce9ae9c629253527f269a57 emission_res_68.out +e83f0035a4c3138e2c30761bbe505dbf emission_res_69.out +aa2446a7c7a28dbb3c47c76e41e5e366 emission_res_70.out +125742b7f4d639a218ca76a99203c68f emission_res_71.out +ec120cd58afab1366d3d0825a1da6ca0 emission_res_72.out +48fd4cfbb060e8fdba36c6027ab3ac25 emission_res_73.out +f7c5365a29458920bd39f34c335e7199 emission_res_74.out +7df5bb82d9d439e85caf80b23a104653 emission_res_75.out +8252464da3b82f51eb6377a91c53312a emission_res_76.out +2708fe27a5b71d03218fd224c096d2f0 emission_res_77.out +cd210a55d6692b5a4be8462b63717a2a emission_res_78.out +2897a9249ae46ca94dc4e7a080aaef96 emission_res_79.out +6c6ee07d1c8b022d7a28f9af2e77261e emission_res_80.out +40c60cad3d7b74a10cd3e766f5bf86e5 emission_res_81.out +f71eb64693418b37e842679d0ad57979 emission_res_82.out +62d4391961370e49495b729f974c8482 emission_res_83.out +e90a8b49e4c951f698bc0471ea503db9 emission_res_84.out +da7c88dbafd963e465da24e023765a98 emission_res_85.out +e8a89d6e8d15e7284b0fef9451880ef2 emission_res_86.out +b8bf59745200d06d95b969e70fafa0ed emission_res_87.out +bdc9306faf248619735e084da23bccad emission_res_88.out +bc5ec160a5a82958882115b482fc407d emission_res_89.out +6089d149a2d6d0c6751991ba03275dd4 emission_res_90.out +8598f429197f57b390684ee490e4d97b emission_res_91.out +5e7a33b687423ef5120cfa554eb7264a emission_res_92.out +702c210afce6f19960984cad701198e2 emission_res_93.out +787ce6f2037b4d84b3ed42194d317cc0 emission_res_94.out +6b92b55a3cd37b5128cdb2db7dc87e77 emission_res_95.out +7785f9e5a6c04bebe2c495a8736e7e1a emission_res_96.out +408ca8ecf5979f78ac855012eea72d38 emission_res_97.out +ee5863d361e8ccd89b2d4b1e0b87cf3c emission_res_98.out +b1ed4cb38d5ab14051f5f211b11af0df emission_res_99.out +bb61d3e6bc64f419e2689f722a0fa758 emissiontrue.out +3f0144f6e9cfdf376233240d4fb98abd emissiontrue_res_00.out +47b58ef2fe0799741b2a9bf5db7af3d4 emissiontrue_res_01.out +c9934c7491842ddfcecc92cca61e7819 emissiontrue_res_02.out +39bbdee3d7e537966a03edb090d275f0 emissiontrue_res_03.out +d7c3e9ce57f70d64b35ff9bc26ab155f emissiontrue_res_04.out +dd549e393641628c94bf28a35bf39a7f emissiontrue_res_05.out +9558e5f4e0af1051dcd0ed583e2f9bf2 emissiontrue_res_06.out +a40cf16c08249c6bb0d50a9cf093f0e8 emissiontrue_res_07.out +7ca8a53b6ffd7c8f12e19da3a84ab9c8 emissiontrue_res_08.out +153bfc688deba154e894570176662b86 emissiontrue_res_09.out +3f9bf7335d1c7a5d22fc8c88e31dcb21 emissiontrue_res_10.out +a7f29be96bd28f7ec250cb75506663e4 emissiontrue_res_11.out +2c535f393c20cc74c87cceac13d7dd5e emissiontrue_res_12.out +2168dfcfcad6f3318d85a053fbdaa885 emissiontrue_res_13.out +f56e2adb4c285d1b372fad8fc05715e9 emissiontrue_res_14.out +464c9bc4604a8ab1bf6291410b4a8a12 emissiontrue_res_15.out +de4dec7d7db7c160881f4fdbe09df472 emissiontrue_res_16.out +8e784a79fd9a72f71cd181cfd3202b05 emissiontrue_res_17.out +6b100d63b825652997c94636923ff869 emissiontrue_res_18.out +310b16f1c60aeb6186681bb68abf33d3 emissiontrue_res_19.out +ec580d356a0b6300b352bd2e0545c937 emissiontrue_res_20.out +835027931e6b70269168276fba737f6f emissiontrue_res_21.out +3a52dc8eed7ec2076a78dd309997bf3c emissiontrue_res_22.out +dc343bd91e93a3e2409dabe630742000 emissiontrue_res_23.out +a9e1715d965770b5f9a427998d689f0a emissiontrue_res_24.out +c02410d98b5d61fc28b77cfe4a9e4cad emissiontrue_res_25.out +a2d4b36b77b2642b1782b26fdcaccd1d emissiontrue_res_26.out +654b575a4026d5cb39b8b4c36a8e4468 emissiontrue_res_27.out +31f15226dadcae0c71c688cd6ef5a12f emissiontrue_res_28.out +9373325dba7dfb218b723b4c73fe28eb emissiontrue_res_29.out +a3c4f88d5de93185af7b4bfb66a45a17 emissiontrue_res_30.out +0d000c7ded03608e47216ca68ee6e1cd emissiontrue_res_31.out +10e58f9a080663532e52dc0239aa926e emissiontrue_res_32.out +96757e7eafd9eb6f95e70177bfb40cef emissiontrue_res_33.out +76503205f89ed62cef4ab94d21c6c396 emissiontrue_res_34.out +ed24b0a48704db2f565f485784341373 emissiontrue_res_35.out +a98b0d15ec3481741ae2155fb878b7f2 emissiontrue_res_36.out +50f08762cb5a4ef3e06f6de5702c56df emissiontrue_res_37.out +178779f1990ffca44fad02b0409dc7f9 emissiontrue_res_38.out +d5a5bd9059cda656bddb3f567e4e94bd emissiontrue_res_39.out +a6a125b4d52887a72f93ced0d6a6a6da emissiontrue_res_40.out +087cadaef27bce9cbab09104fe60598c emissiontrue_res_41.out +8169d7ba81f17cbb9fdfd45cedfbd3d2 emissiontrue_res_42.out +76796c0945a0522e1bd6f8c7fe1584b4 emissiontrue_res_43.out +f10c7ef60a723d38117dbb808164151a emissiontrue_res_44.out +ef0e2c00f453cc87c9f69f2ea987fcce emissiontrue_res_45.out +f36d04814660179e0895364642559ed5 emissiontrue_res_46.out +54a683202e51a46801c0f8e96dc64fdd emissiontrue_res_47.out +4aff3e79635e44e061a07b5eb54fa939 emissiontrue_res_48.out +0388487769e1fa0c61bf7d44fd15935a emissiontrue_res_49.out +2756c3cef1ea3a63f43273dee78641f0 emissiontrue_res_50.out +886ae27cf3c549acf67dd5ff4d2d3770 emissiontrue_res_51.out +3b0f141af0a486213953448ba4b3ecde emissiontrue_res_52.out +75edd7f33ec5cc2266362928277a5a80 emissiontrue_res_53.out +828727fece567684cd9e48c5d867f865 emissiontrue_res_54.out +3bca274e882428e737eb0adde08dc27c emissiontrue_res_55.out +584c1a4b92befa47496618c1de0728a6 emissiontrue_res_56.out +29e767d139416cd843dbd3e51dc41483 emissiontrue_res_57.out +d8290e65f7cfe35de6fe3bcf456a1dfd emissiontrue_res_58.out +525107cf94ddd00abe2401b2e50beffc emissiontrue_res_59.out +679ac07b6dfc70b754742a8150f95a0f emissiontrue_res_60.out +a693433bb4eacd652b9cd392f44ca4d3 emissiontrue_res_61.out +869256b97ecf91aadcff25481301573e emissiontrue_res_62.out +803d0ae2f13ae7158c1be1ae18fff6b3 emissiontrue_res_63.out +9fea8078617d214c1811853387f4f8bb emissiontrue_res_64.out +35007efc7ceacef428d970fa193815fe emissiontrue_res_65.out +a657581d41e51dc58347b50518d3b1e2 emissiontrue_res_66.out +b74a89f66563e1e84cacc22eec1ce031 emissiontrue_res_67.out +1db390e1ac6f0c9a9aefb9a234c79806 emissiontrue_res_68.out +d56419153cfb0e95887d8b57a1e41ebc emissiontrue_res_69.out +0cae0c49ff00fb323b1806e8bab9c8f9 emissiontrue_res_70.out +dd35ed9c209daf16edfc6502bb0cacf8 emissiontrue_res_71.out +7724ad91c6be3071594b20228aef652f emissiontrue_res_72.out +0833ffbb50f75ed710d13994ebed1ac5 emissiontrue_res_73.out +488664d33f245893ab1df3ea9e618633 emissiontrue_res_74.out +02bff5fa69059b681606dbd7b75ddff2 emissiontrue_res_75.out +de16229631944c5592891efedaeec71c emissiontrue_res_76.out +81c663c7656db3d3060d8f01ba549761 emissiontrue_res_77.out +36ac119600cdd7a4bfecabcea1530a08 emissiontrue_res_78.out +25ceea3c278cd72a4d62d0b185d8c6e6 emissiontrue_res_79.out +a05ace1a3c3172b34852ccec4c44a3f8 emissiontrue_res_80.out +dc7e59db13b05a7d5bcfb5decd1758aa emissiontrue_res_81.out +bdfea8c02934fac10416e0d2d40afa58 emissiontrue_res_82.out +5db89a73f4407c7f0118fa2b345f275a emissiontrue_res_83.out +ac13f555c6a1cf7a7ee8032146680703 emissiontrue_res_84.out +67b9e8eeab14a3acf5839a40724a8f90 emissiontrue_res_85.out +a9d8a5af407e1d094af1980d8f41dd73 emissiontrue_res_86.out +4c53588a8c123e1dcd4cf3f3f9005fe3 emissiontrue_res_87.out +c7bd6663569708e68836fb4a03ac3342 emissiontrue_res_88.out +15693f57b437cf857fec2ac3d1692b04 emissiontrue_res_89.out +307d42be9100824c7cff00944b842d39 emissiontrue_res_90.out +a0be179e1ea1099a9f32790c5efc0c6d emissiontrue_res_91.out +66ef1d5ba15ce66e28ef84299899ea16 emissiontrue_res_92.out +d127a6983a9aa786b13531133eb8209c emissiontrue_res_93.out +c0cd6b35736ac661f85c27874ec16683 emissiontrue_res_94.out +aaf153e621a38b95e1f51a25b6bdb359 emissiontrue_res_95.out +3d8161f87191464ce2b7ea2e1dac02cd emissiontrue_res_96.out +25d96adb9355fba3629c9b6ba13dc2b0 emissiontrue_res_97.out +5928c4e91c9457d83d2480adbadf636f emissiontrue_res_98.out +280e5d8f7da54d1d203afb1ec19fbeed emissiontrue_res_99.out +73089da35f724273c17e1f107a66d870 gamma_light_curve.out +e69908c43dad66f2e0ddf2c94e5ecbef gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -ddcd979f77ce63df38a604634ed975ba light_curve.out -d2f6c90ac32be89bab395bbdb4932f0d light_curve_res.out -9773becefdfe4afffb041b703210c67c linestat.out +7bc4f0781f4758bae2d13ff4d0aa321e light_curve.out +f6b59f6864b93d62611502f6c1e955bb light_curve_res.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d6c0219cab5fc8c9bc9766a5cca43c44 packets00_0000.out -4207225f21ecb78897122db8726e49c2 packets00_0001.out -948d43f454ddc88d63343dcdbd36bd6d packets00_0002.out -62513b5559e069fd1f24e746c6a80ff0 packets00_0003.out -4715f765a68a2f9ea81e56b8dac697df spec.out -e78908c4548a0c652c0f05b14e64cb49 spec_res.out +3787a94e0d776d975879a491d231cd24 packets00_0000.out +53c2e9a1c5052a57dea47fbae245ffce packets00_0001.out +df05d69d21d24a536cd43258f04b0ad5 packets00_0002.out +4f90fa221b0b625480cfc1b8c5968b51 packets00_0003.out +57f35904b8ce66d0280d76b19350cccd spec.out +096b48197101531a2e77246f4313861e spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -b8e49f14003ea7359cc904cbbafc418b job1/estimators_0000.out -d893b483868defec46dcd6967d50b766 job1/estimators_0001.out -b5dca1726fc96a9987671c9f19cfbfc3 job1/estimators_0002.out -408d4ea2b9dfb505802572172ad2442a job1/estimators_0003.out +b6346e495f1bccf8b0c3ba0d31d7c122 job1/estimators_0000.out +bec5a267110c6f1432fbd817030f3928 job1/estimators_0001.out +720896de818b9b0bf52b7c6a07898292 job1/estimators_0002.out +c1dd5690ebe3a24e6753f48d3eba5c63 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index 053993b34..196f3491b 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -091b4d802b3550712d94b40106be60e5 absorption.out +9ce61b3c4fff199ff39faf4377180234 absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -4d929a95df334834be2c93d1b6cd3a19 deposition.out -25e05e72e89cdb6d1dd4c5f354edd774 emission.out -aa091714028c7ed425cfb313450f7518 emissiontrue.out -029b183f609bf0765d793b01bdc6a1f1 gamma_light_curve.out +5abf030d9a1e628153f416f935ba8169 deposition.out +6b548ead4025ba2a3cd16011d1bc56bf emission.out +4dc6b9a8bcf3c051700393b7f7ae0423 emissiontrue.out +f4c1297950f7a4de53b3c6ea46341f16 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -785c2cdfd015a553276ca150db437315 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +f0560aac1cc23c1ef20d936f4d03b2f8 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -f0b4c6fb5758defd5f6f1502dc90f039 packets00_0000.out -20210c7010add7c3a51ed103c4ebe02b packets00_0001.out -3e2467b7c46b7617db77dae9d922ca0f packets00_0002.out -f1c0736e2563eb55f4c3e9deccd0dbd6 packets00_0003.out -824b8e35b981fd2b481959e6dfde821b spec.out +06f78283ab6c70372b5623c03c324e60 packets00_0000.out +7bc7b7f13abcfc0d9c9b607201fadadf packets00_0001.out +8a11dad99e2bcc445c7c1b17a7ecdb1d packets00_0002.out +c6ff00913b6991c00ac3914845303e55 packets00_0003.out +1a56005ffb39f1e11225d16ad7e6b5fd spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -de58722214caa437a3e7a3542621a8c6 job0/estimators_0000.out -806703e3c07c78b99a8990314c692a88 job0/estimators_0001.out -ce3aa8b98938ad212e511b4aae959fee job0/estimators_0002.out -a76f706fa21bb93bec0d2d2c290f6bbf job0/estimators_0003.out +62acea9eb4b1f63068932890202f52d0 job0/estimators_0000.out +ac22c6d53430692779dd3ab027cd82e1 job0/estimators_0001.out +2637ca75ee400f2c0913cc6c047ed233 job0/estimators_0002.out +b7f556b98a9b4ea15a850576ffbff76b job0/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt index 441297cb7..fc3ef3505 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -f9d9f33b0111f41d2df66ee38ce7858c absorption.out -1415c33cabda1b5b8c452cde5a3774a6 absorption_res_00.out -bfff2119309df259a4dec4437e740b5e absorption_res_01.out -1cd342aa4c5a07f20aa00d186dcd61f8 absorption_res_02.out -d4578fc93a81b6dbd1a3787b9ee72883 absorption_res_03.out -cf4df86bf09622c3f3687d6b38f06750 absorption_res_04.out -8114d6980fa76210de9895dcbfd5d7f9 absorption_res_05.out -b7ab214af73b16c99b599a301fb8824a absorption_res_06.out -2faa6db408aad5e73ee82ea69a2e03b4 absorption_res_07.out -bcb7ec08a176961fc8440c49ea6c5631 absorption_res_08.out -18771d6446e2084a91697877629b7464 absorption_res_09.out -0c5efbea3c6ea1e6e59f4c2febfff5b0 absorption_res_10.out -a9a4affcb9d1d6563a33e06fbd933c85 absorption_res_11.out -80d1fa5067b13cf53c7a8af7daecc0e5 absorption_res_12.out -b9d9e53ca11d51488e81917b17680f4e absorption_res_13.out -539989921c1f6b7fe32ad3e0da0067b6 absorption_res_14.out -e9f796f17dd040dda87e9e656c07f426 absorption_res_15.out -f874ceebd65c40d7fdc3a51016976576 absorption_res_16.out -1168013b4a37e3e35bc37d04d65c68bf absorption_res_17.out -1bdec8ee5f161110a7dbe88ff1f6d19c absorption_res_18.out -dfb14cc33008ad397dfa2e071ceb3d23 absorption_res_19.out -8ded9d4b501cccec0e019d8cc5a0e4f1 absorption_res_20.out -180e6b3ec60bd5a415c51cbf6a97d4ea absorption_res_21.out -aff008087a6cf24ea09b999ee058ce7b absorption_res_22.out -bf64a434fc8b99f96b3dcd8d1565115a absorption_res_23.out -e38e016b75c00d2de1ef556d78b9a8b9 absorption_res_24.out -55aa2eb071f9b81f18480819035b056e absorption_res_25.out -206e0fce2e46daa7a7fe0413f946a4c3 absorption_res_26.out -28bc5dc0c5f2c821c64561ce7f5a5726 absorption_res_27.out -c62b405b4a8d095eb6139de1cebc3634 absorption_res_28.out -7fc002687e2c3590e2c805bd8860deab absorption_res_29.out -71c7396e0acb04e45c0b5e8a170afa70 absorption_res_30.out -1b7a198aa9e9062ca70758429804c1c8 absorption_res_31.out -ba2c6e2211d2f3bf7fb0f9b4a19e6583 absorption_res_32.out -d4d7003abfe44ca3798adbe2b771c1eb absorption_res_33.out -8c3b099c95112c0f6d115311e8c3e9df absorption_res_34.out -e1c9f7c79bdb2b9582f4326cbe3c3313 absorption_res_35.out -7475419afb8f1c2f293b0654461d34be absorption_res_36.out -a87542ffc6abb4f5ae64e289b920fb75 absorption_res_37.out -3ab66c18494bc3540838c850f14b33e1 absorption_res_38.out -94d447efe8b0b443c3c0156d23e34ed7 absorption_res_39.out -63b294d22a70eee35e5312e4b7816350 absorption_res_40.out -d87ff57594b6dd6f2ddf4a505a0efecd absorption_res_41.out -07e025a7ac3c350c419b073fc7405e0d absorption_res_42.out -21a40a55505668ce4c3e779c7d675a9d absorption_res_43.out -b0207c3b981e5ea035ec37780fbbcb25 absorption_res_44.out -1520fa316f7f49726e0aff57a434846c absorption_res_45.out -2b5fe32aec00e7a503e651d9706f688a absorption_res_46.out -6d63f260b98feea4a7e92a91fca764fd absorption_res_47.out -6ee763c60cce9bcc038d257a987405ca absorption_res_48.out -15c42a3d72a880aa3f6400d145debec2 absorption_res_49.out -05d19de1f7a78e710ffe402796084258 absorption_res_50.out -861c66e86503dcd0a276d21da7c9ff15 absorption_res_51.out -839c70f6bef9f22aa31b095c22223867 absorption_res_52.out -feeb4fb3bd8ce672ac64bf826ad2ac30 absorption_res_53.out -bd65b6e2f80c47b55a27efa9142ba743 absorption_res_54.out -9495dd3fb5ef7994701f0a6045e155de absorption_res_55.out -cf2f2a208734e2590a63e9e7e42dc0b1 absorption_res_56.out -a904885a5aa27edb3b27876c7386945c absorption_res_57.out -e65359e96adf60b5a54be6283d239936 absorption_res_58.out -fdef337ce618b60166e6f5d251b14e79 absorption_res_59.out -9132207b8bf026ff6d9e21dbee769b6b absorption_res_60.out -aa5182794b9420eb708597378f366095 absorption_res_61.out -6366f0f5fbff04d491443fb320a07903 absorption_res_62.out -ef4f5b8431d6cad9ae329f0818252088 absorption_res_63.out -a9a983fd855bed1da22a1021353aabe2 absorption_res_64.out -d97df9893fe674a5e80b631d1e123610 absorption_res_65.out -e2a2c6c50c8f736f07244a125467f244 absorption_res_66.out -237aad18bc6ebda568a3846a4e0bb597 absorption_res_67.out -dae76fedba9a0039bf348fab86f89943 absorption_res_68.out -b0ff298f73c97a468b8b77b64e683ad5 absorption_res_69.out -2a08148ccd2f856f8c88230d360ca0fb absorption_res_70.out -f430478f7e9ae4f7a87e7260bf08cb0d absorption_res_71.out -f2051749c1f93003787d62818678d830 absorption_res_72.out -8db7b8df503243b208e37ea3b1d64062 absorption_res_73.out -550272cedd7b294ff5854c5f8bf211a3 absorption_res_74.out -cb78306f08d6b63fd369d9fd892ac2af absorption_res_75.out -732ad4238250b16c1645d81be341da6e absorption_res_76.out -59cd48baf927633be38c312670896f15 absorption_res_77.out -879e6e78767b151adc7767e3721fb224 absorption_res_78.out -5b459a7bba891e3d36084ed67d7df414 absorption_res_79.out -90e1c75c5fd16b256ddc7f7b696ba84a absorption_res_80.out -9a0a00771a603a1677acca48e218f0b1 absorption_res_81.out -50184f3d12777ef6a11bdb4f3e8099da absorption_res_82.out -2f6bcedd2fe6691631c522bdb4d830bb absorption_res_83.out -f7cf9bf4ec035dc16ce1deedbb459cb2 absorption_res_84.out -8adf717c95e9c47444f3deca9ca12838 absorption_res_85.out -142cae30b42233fde978cd2c5b06c288 absorption_res_86.out -176468d481f921f967c45417b24d062e absorption_res_87.out -7153704cf352c6d526580b351c5ab627 absorption_res_88.out -f032833487fbbedc92cd44e7a48af121 absorption_res_89.out -23c137796e6e46bbc9ca7a2b89af5d7f absorption_res_90.out -4e98bcd53e0cf200d62ca0d7c8688231 absorption_res_91.out -09b0fd22a8c02d88f4f929ada716957f absorption_res_92.out -66c851bb3c5b0ffb7e2fa7721f02df5d absorption_res_93.out -143f23a098284b711cef7f720f490112 absorption_res_94.out -42f73e52978ea74443f162f939ef3d7c absorption_res_95.out -5c22a9c74919e641e8956fc02122bd23 absorption_res_96.out -cb0a086debde9795efd7a28b71bbd341 absorption_res_97.out -16aaecd9522e2e722e87038d23bf8c8b absorption_res_98.out -5254654046c05de846138e519ff50131 absorption_res_99.out +931c97ffb5d4d9c9fd10cf1284387208 absorption.out +45fc92e39e41c375ae20d69e160572c9 absorption_res_00.out +158afae1f979b7b51a5711971c84c821 absorption_res_01.out +ca26598a8e991b08f2cc5ba1f37bd5ff absorption_res_02.out +3ece848c3c0e8c245276069672e4c479 absorption_res_03.out +5bca6c45b209ef1657dc89486aa23eab absorption_res_04.out +baf8d2827c63a2f84a635778e86b9b93 absorption_res_05.out +1b76fb486d17b76f148aad380eff6eed absorption_res_06.out +efe596a3c21db4b55607969cedc6e5ec absorption_res_07.out +bdd26207e0bf7f7fcb7593e980bda525 absorption_res_08.out +543ab9837681a6d2c0c4d6dd71a06d99 absorption_res_09.out +756ddfe504e396577a298050f4ec8e82 absorption_res_10.out +51976c1d4238b80b7d5f965afddd744d absorption_res_11.out +4fa3601d333b1171edbd9be2c28f19e8 absorption_res_12.out +7a0e77895411ebefda43c30734998a3c absorption_res_13.out +b936f574fdc2afb713d6d11c373d2d22 absorption_res_14.out +0b3183706d3507a85bb7545eca8042bf absorption_res_15.out +0835933cb9b8266e273eb9177ddc9466 absorption_res_16.out +972ecccfbe135137c1faf24fe02dc722 absorption_res_17.out +354c324a72d2148e03e90397b506c98a absorption_res_18.out +4e9ec25f7c87d5ecd66399ec4de70370 absorption_res_19.out +c4a3022dccf3f75162719f4dc055d4bc absorption_res_20.out +79bc69757d8a70ab5f8df7b5c7af9877 absorption_res_21.out +f73d9622514bd8a06eeafe39e2086d23 absorption_res_22.out +3410ef187f67fd3e7367057da7fbff05 absorption_res_23.out +3d6ec91bf43cbab49db4cb8f160ac414 absorption_res_24.out +e76b39f8eda9843ca94cc38313b9a05c absorption_res_25.out +d39a1024a883ddf281cf76f216ef3213 absorption_res_26.out +cf83afb6df1d75fa24215c17f7b5304e absorption_res_27.out +85cf48df266846bf8a40f9cd862647ba absorption_res_28.out +562beb760d8cb4f3c8f3d695f6392c86 absorption_res_29.out +f642de7b7c6733faafee267b4d9d3767 absorption_res_30.out +66b949dc8333823fcdd22f880db8ba99 absorption_res_31.out +fc98760a9f5cf3e86a26763b4a7ef6c1 absorption_res_32.out +cdb693ddb09a3fae645f17c83879f05a absorption_res_33.out +f7c0229ba7247a9e43e9ac2d35fa09c6 absorption_res_34.out +25599ba375ecec58b6ad25ec098acee9 absorption_res_35.out +4233503db76611ce865f25655f41c975 absorption_res_36.out +6bd67f7c4e4935e63ac585e6f15a2d9c absorption_res_37.out +da66d1158f211d1e9969b8db32999422 absorption_res_38.out +53bfecaf6887d2d3dcc3b0c9e218a15c absorption_res_39.out +fd5b9de30acfc77d6ecd4c2d35705fd9 absorption_res_40.out +95c28cbe1f4615c9b697d002d6058c68 absorption_res_41.out +1f68e28cda1eaad1420aada83a4974a7 absorption_res_42.out +25f4dedc15b0adb3b5c087a252197d27 absorption_res_43.out +350d405aabce54a59058300953ce74a4 absorption_res_44.out +4980f419b481860d4482191e8860b97e absorption_res_45.out +875662a4ece981353504708350c7fc2f absorption_res_46.out +0525bee34bb539407f3da46165ccf83c absorption_res_47.out +8c7bb374867c9b6602a4bc6512dbd968 absorption_res_48.out +e17b1b0d4ee8cff8fdae911d888e787f absorption_res_49.out +8af9e1db924c294821ee5242bc604609 absorption_res_50.out +5c8ac1e6b3db541009b78bb9a49ee090 absorption_res_51.out +8b21d319f4d5917cdff0ea54eb0d05f9 absorption_res_52.out +85e294aceffeb502d12a08585cc5c7fa absorption_res_53.out +9ce79225ae7678af0a3e8cdf583f86f2 absorption_res_54.out +91f3aaa50a065a05da424f14a9feb863 absorption_res_55.out +06705d8b1496eb85fe124e2c499fa39b absorption_res_56.out +8cd8977f01f190ac40bb7a69cf297355 absorption_res_57.out +e50250c7db5bab88f07c33ea40afd303 absorption_res_58.out +745153d716bbf36ee2c06993ee7ab609 absorption_res_59.out +becc501f78574398cf6a6153913af27e absorption_res_60.out +859340e7dc554e9ca62b6d3fc63c9528 absorption_res_61.out +862d77d746d5c1cdd3f1b327ad44cca7 absorption_res_62.out +d3f8c8696f2246cdef0c7d40c731d854 absorption_res_63.out +623e3e0a3a1e5210c1def3a007ef7bba absorption_res_64.out +bbbb9c213b0be6b3778a0f08039dcd68 absorption_res_65.out +aaeaa16e2d5448bdea04d54dccd5fd03 absorption_res_66.out +efec4fdd6c829b84f5f69c6a0b88392e absorption_res_67.out +8a04358a043d2542d9dacbcbcceae569 absorption_res_68.out +7fae37dc0355c76241856b387014c868 absorption_res_69.out +322c294a1a3655a2b5ddc10f38e813e1 absorption_res_70.out +4b3846f784e73144cb66c12513fa2484 absorption_res_71.out +8aac92bd56053c9c25c95888114f2d2f absorption_res_72.out +d3dc47009a90fbb60b742933ae198d90 absorption_res_73.out +816193467de45a82006ed18c6a9b1d31 absorption_res_74.out +84830e58bff187fc381a35d0128b7a99 absorption_res_75.out +d3dccea5e7478d18bdb32e71de66ab42 absorption_res_76.out +1fa0829e43b21e2890999ed9f0c52410 absorption_res_77.out +8fc9374480ac761c4e64ce2c013a7fe2 absorption_res_78.out +2af9d7c906aab8a53dd14386a81db8c8 absorption_res_79.out +5fb1a4fcee24abd1c2ad95fe99a01141 absorption_res_80.out +dc3d6fa13b48338d1d87e643e918ccf1 absorption_res_81.out +eb0428709342297aa5785dd6b3e53f4d absorption_res_82.out +20546f0d95299c712e8839c64e8ea3b7 absorption_res_83.out +d1030d11adc82a7b615187366af963f2 absorption_res_84.out +206951cd7e22e54f1d217313bad2d50a absorption_res_85.out +dff02f6d8a232e588449d5f4590bc03f absorption_res_86.out +309a8fe28c71aa426e35eaa3cfed1100 absorption_res_87.out +762b3d2ae1a0e8d4581e78655b3c2537 absorption_res_88.out +cae86777a7f7783a2265bf049db25998 absorption_res_89.out +f380f94e9e14263b10431187520faa4f absorption_res_90.out +d63d436d019d0111f372e41cc37f1a82 absorption_res_91.out +4db08a469f1e3035d70bb8c1c14c4b9f absorption_res_92.out +1f0898a6bbd27f5d1e6d2fc522128c86 absorption_res_93.out +e9a6edb0f9f9c0f0ca5e9b269172ea4c absorption_res_94.out +feb823b4debbc9c584a38fca3dfecab4 absorption_res_95.out +e5ceee3b7262cb62fb78cdca0ea59fa9 absorption_res_96.out +4c3c0b3b673d92b79f01e9a9f5d5f7d6 absorption_res_97.out +177d2331a3ff15e7d4e34f6d4574e0f7 absorption_res_98.out +f7b68c0636c7ca9bf007c942ad1d812f absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -275491f5acc91a7230bc351c0b7346a4 deposition.out -9fbb2f1301742d73d55224506e1ebf93 emission.out -f9fb255f00a9f33c6135b4e35e42e368 emission_res_00.out -5dad6776368f276e1a8b2b825ce76fd1 emission_res_01.out -b4699b8982efb1f3984af1203831a346 emission_res_02.out -4e918f52d3d2736cc2a6befd0383635d emission_res_03.out -afc925f1c45f6eba0026243243d330c9 emission_res_04.out -a40346ab0af94f8e4f39410d7b1a240a emission_res_05.out -73005292d39a2e72dc4fb21d365545e5 emission_res_06.out -884a82edd72678b4dca5400fb5ced095 emission_res_07.out -4ff444cfd84769ea64f93c7adc77938a emission_res_08.out -565b925b3e7b917bbc05f8a62205d7b1 emission_res_09.out -bbd9590e9ca230332f61f04027ce9ced emission_res_10.out -d07dcd09ce9b29518d431b140598d724 emission_res_11.out -e9024f2252d25d42cac565a06bfd6e49 emission_res_12.out -32a0222a3e506001b3eb415bea3a8bff emission_res_13.out -241c0c82d37c55f096bfe7c699689308 emission_res_14.out -40e5e11a0bb01a0cac4f9b785d54b7f0 emission_res_15.out -8f6e4830ee0d6310ef395d4e6567faa4 emission_res_16.out -2b85e34732816961eea195274ec4bee6 emission_res_17.out -babea64f2327ed03ae73e7f8808e985c emission_res_18.out -9351b6d784d8316986cd7f67e4ec4e01 emission_res_19.out -310c45e1f0863cef3a9a090bfe9e3353 emission_res_20.out -8b66394bd3f347b2119cf5de76dce461 emission_res_21.out -28bb31ae28d77558c90011ac933d2373 emission_res_22.out -41d147df49319895dbfc873a9d540b77 emission_res_23.out -fe3db1c8aba1b4586307c02a1eedaa6a emission_res_24.out -9f05b69af260444a9c9ce56442aee88e emission_res_25.out -1cd7738255ba925c38cd18268764657e emission_res_26.out -7d4029bfd6fdfaa0738e65578fd5c52c emission_res_27.out -d2cc0db19d961ebb01b07e75266c598f emission_res_28.out -375ebf17886774ede8bc1b0f5962e992 emission_res_29.out -7141c45fcf41da01605260ded3973329 emission_res_30.out -a940cde30e636005d77ff8cc85757300 emission_res_31.out -f249c6a82333a8ed543a0710ee7a4534 emission_res_32.out -541b4d27a07ae1959b3797648e65dee5 emission_res_33.out -9fc88390d03371bf49c19eef906074f6 emission_res_34.out -645f0005f040b81fc46aff228a5eb1b7 emission_res_35.out -40db661a76b8f70dbe4cd11da9a504c6 emission_res_36.out -70cdf7faac4685d56e37f92daf0500c4 emission_res_37.out -3a8460b9cd38770014e63445877d8187 emission_res_38.out -596b43dbad1645f6f0498d4c13c5e0ba emission_res_39.out -6b6401875f5114ccaf76f425ed809eb7 emission_res_40.out -fe7bb5b3b809ff59423672ae1b3bc9d1 emission_res_41.out -186848dca7cd4d055b6e8cfc60205c1d emission_res_42.out -5957a27327253edcd36be19726c27232 emission_res_43.out -00e44c14be3cb5daddf7d2c7e05b19b3 emission_res_44.out -d02b8c6aab3190a8237994b834d7939e emission_res_45.out -779c8640cd813158aa845d132df0e0b0 emission_res_46.out -e37fe2eeabd1b9ab633d83c94260a4b5 emission_res_47.out -e970d499a8b257b0d8071a7cad9dbe12 emission_res_48.out -01a7b8579dc028e3a505157950d952b5 emission_res_49.out -3a5fd46ffcccb52992d7d35bbcbd168b emission_res_50.out -fda73e796850203c57d56115ee6aa763 emission_res_51.out -08546e5ebcb4c5b733f21970cf26d774 emission_res_52.out -e0c8153037f827af20cfe1a4b26a9b74 emission_res_53.out -f3930d8d6e998b163b7ca09db6c89bc6 emission_res_54.out -41692236735e2f07d3d133c365ec4005 emission_res_55.out -e096f73b63b060ccc5f79db7bf317c8b emission_res_56.out -4596fe7c35e24bafdf943aab4dcd5c8a emission_res_57.out -dd3b87ca11eeab44155412647ca11f3d emission_res_58.out -643ab97cbafeb72947878109c49aadce emission_res_59.out -576e3479369e52a07b23d3d2c96ecab8 emission_res_60.out -17c94789f052b387e62b11bd8db7930f emission_res_61.out -065d7bc2bdbcd21298a0d32c260e0c56 emission_res_62.out -9d39c7ee52ead788d40cb5e20cdddf8b emission_res_63.out -eab7a5ae905a30e4c8b76f4460a92029 emission_res_64.out -8bff96106ffd20b8566b08f1f008442f emission_res_65.out -e03171cbe55f191f3892de44007fd687 emission_res_66.out -e4420b0549a5e00955eda566dcdd3a89 emission_res_67.out -f9b94eeb4a19b05fd9655976e9af78a2 emission_res_68.out -2ef173fe9b15f3d861f12bd232c1fd25 emission_res_69.out -b7f674d4dec8275fe451ff5a34f25a8a emission_res_70.out -d52257100dfe8ff26cf2d9613128fed1 emission_res_71.out -1bcc077e56b8fdd159383db841aeab98 emission_res_72.out -f25f3e0df6d3eb85e5add70782a47088 emission_res_73.out -f0c2dad7ef3b7f3d67009d339f51bb5e emission_res_74.out -91f7a2a68c2bc6e2046f0cab3f8adf9c emission_res_75.out -44c80f80d3555b32f68460992171652c emission_res_76.out -1eeb996c0edfb625249e9384b61735b3 emission_res_77.out -89aec949f80dd011705d9fafbcff0e24 emission_res_78.out -0e2dfa316fe807ab46a6aa02a060adcc emission_res_79.out -52f413ce63ce50130554158d51f11de7 emission_res_80.out -c39c9b0d51309b456165c7e4a898ce21 emission_res_81.out -b07eb0fdc78eaf59eb78aef5b8e1526d emission_res_82.out -1eac0b2c5e1ba81125657c35415c702e emission_res_83.out -b9af853e40af788cc57500ea43e152db emission_res_84.out -e8c1eeb8bab87747a6e1d73c00c731a5 emission_res_85.out -bfbac09ce2d1b49aa38cef1d6287f633 emission_res_86.out -7f0048285b2011f0461e3a0997c89883 emission_res_87.out -6c4324121be752867cdeb779c9f03b5f emission_res_88.out -8c4e3ddb3966889ba20f446f8b977fb1 emission_res_89.out -7d1d8af860f6ca9a43d3a959d1a00103 emission_res_90.out -ab7a9ab66325b6235e8dbc2ae049be59 emission_res_91.out -51abdcec5100bcb9c593c92034fcce22 emission_res_92.out -83be3d0c293e3fe28966c47bb758da42 emission_res_93.out -4436133befe9ca7bc91526cc8141c963 emission_res_94.out -f1eba0c1eb2d89548b7c052f471bf40f emission_res_95.out -526bf216786d815ee5d48c78cb586e90 emission_res_96.out -26f777a345f1a5bb4ee86f282e8e8645 emission_res_97.out -3159046472d2828db40a48dc9b0bbeee emission_res_98.out -ee19633730963f0f6854225e6128aa87 emission_res_99.out -950ecb16197766824e08e0171663792b emissiontrue.out -fd1b8b88329ec0da176d99da6f64f779 emissiontrue_res_00.out -af080f439470c59d8355eca48a5d10f7 emissiontrue_res_01.out -9afc365f26beb919e82422be34ac0284 emissiontrue_res_02.out -8f45b11e292a03a719a809bb8027fb90 emissiontrue_res_03.out -c3deaf1c269e0cd23ace4bc7949d85b8 emissiontrue_res_04.out -617ff7fd1960f48effa90ce5ad4cc8e9 emissiontrue_res_05.out -090c7687d0c4fa2b38dc09a3a5d9e792 emissiontrue_res_06.out -aeaf78b1bf9c31824439711d0468769b emissiontrue_res_07.out -1d2c40c54e1f51823d16c501c9e9717b emissiontrue_res_08.out -7eba70f6edb1ed7fa58359e594ecefe7 emissiontrue_res_09.out -1814bc26d5e1da60c7d5c3ac241b295e emissiontrue_res_10.out -566e48f30d2cbf0076d6aa944406031e emissiontrue_res_11.out -b22843844e3f893cb4ffe395a32396a6 emissiontrue_res_12.out -00f84bf13580ebd6872dd3a880d68ada emissiontrue_res_13.out -1995d20b96438577a369aba43ecd608f emissiontrue_res_14.out -f7454aac1bfaa01206db0a97686c1d9e emissiontrue_res_15.out -857f647db7f7e67243f66a8136291d89 emissiontrue_res_16.out -0fae346cb7d1fe86a8402e6b4d60da82 emissiontrue_res_17.out -33f780c697c3da8d1b1fbab5cae34534 emissiontrue_res_18.out -c305c7992e58df1234b8d8fa506a4fbc emissiontrue_res_19.out -d5db8c35af14da9757eee3fc75a9c413 emissiontrue_res_20.out -42c03310318d58fa67f835542336c689 emissiontrue_res_21.out -c1cbe5cdf760c09d66e6f6dd935ace00 emissiontrue_res_22.out -8fd9054a56a63381a650d5ce4c17c6d9 emissiontrue_res_23.out -7555e96991d7af1d2a4ce5949353f2b7 emissiontrue_res_24.out -56d76818729acf576e2a99b65ffd54b8 emissiontrue_res_25.out -4ef3ae3ebdf718b4cb807676e01d1388 emissiontrue_res_26.out -1fdade8885225390a16d7eeb90939d48 emissiontrue_res_27.out -822eefde3b9d364d284a6b9f6a0df6a1 emissiontrue_res_28.out -721f7ebc658bf429bd28e15c612d54e8 emissiontrue_res_29.out -fb12df7ba1c71089eb4432b3a2b5709a emissiontrue_res_30.out -6dc7da1560f0aa42e0d61a0c5e19027e emissiontrue_res_31.out -ff47d27f4e3348de0269b69f735a16b2 emissiontrue_res_32.out -d5b6b1db6fb6ec75f78674e3c91ef804 emissiontrue_res_33.out -e1082f7cd8c45a33e9b48a84f81c2b66 emissiontrue_res_34.out -43ebba3e6f29e644176be8745d8be8ec emissiontrue_res_35.out -7ce02121c64c9df750078936d975129f emissiontrue_res_36.out -1535663870570a236e07966dc801a9b6 emissiontrue_res_37.out -f7bb83165617c85f7e3086c295f4ce65 emissiontrue_res_38.out -46a432e439448c6912bac0150aa35e11 emissiontrue_res_39.out -00f9523217e20634847b274b996379c2 emissiontrue_res_40.out -256bb8f30bd6ba1d3b468ed9ccf3d0b6 emissiontrue_res_41.out -231fbf8868c5b3c95e690f783787df05 emissiontrue_res_42.out -331c80353bb564dfc01720b4a10e223c emissiontrue_res_43.out -2df7d66282856923deff11a432351b82 emissiontrue_res_44.out -053e85388e063b2b2ebe3dcf20da2642 emissiontrue_res_45.out -3f8651e1f5f3789ef917bc2248b3cc09 emissiontrue_res_46.out -4b098a0e892130edbb3a7c7e7c45aae7 emissiontrue_res_47.out -94c2321b7c26b332f5d40f6120426611 emissiontrue_res_48.out -bca82dfcd79bde3a864468209d6dfff0 emissiontrue_res_49.out -7f3e0e7e0e5b6d92731be38d0130ffbb emissiontrue_res_50.out -e7f00adc3c311cc4126f690cb3e1613f emissiontrue_res_51.out -6e6aefeaa6c853c4639a9fe3d18ccc2d emissiontrue_res_52.out -22f0ceaae71d85ace9fd43acc1a275ce emissiontrue_res_53.out -dfa8e5101ff46eb4120593076280d9a4 emissiontrue_res_54.out -2b280187d1ecccb131277e40d6c696af emissiontrue_res_55.out -33fede083ea6ec9030be16c8d7b53395 emissiontrue_res_56.out -fbf1d93b16bc65dc4683a2803ca14b39 emissiontrue_res_57.out -7865c8f5853c958e24e652ae524bd70e emissiontrue_res_58.out -e5543b1f88e874a493a0b3563e2c7ad9 emissiontrue_res_59.out -4dd879a94ae043b9484b935ad4ec67d5 emissiontrue_res_60.out -3c408cea760807a979107b458c82b2f9 emissiontrue_res_61.out -6ad0ddf23738056b0a6f29306dfa5e2f emissiontrue_res_62.out -9c374cef90a3e8c48066f9e434c77ffb emissiontrue_res_63.out -e81ff278ad9a2981876d142b35338fb0 emissiontrue_res_64.out -9bd21f0db424e62d56dfb51d919da308 emissiontrue_res_65.out -91d6573508bcbf80635b541568518416 emissiontrue_res_66.out -16c82a685c50580a65174a83266a7ef1 emissiontrue_res_67.out -d8640a73819284efc7a88fbf54c87445 emissiontrue_res_68.out -1ce9dda44b95d8d306770b6ff4ebaa09 emissiontrue_res_69.out -e8bb9cf03c00897a98c4eedf2422b3f3 emissiontrue_res_70.out -71b6f8a2bd9ef5d4f4e300eddfbb7c61 emissiontrue_res_71.out -b92e1eb931228356a0743945100b38f6 emissiontrue_res_72.out -9583512d18b5b34ba660e9c0059d6600 emissiontrue_res_73.out -23118adeb2aa9386db8282e997490b08 emissiontrue_res_74.out -843def2e9023f811f10b1ac318feda1f emissiontrue_res_75.out -885062925e51ac47f7e95dbb6c53cbe6 emissiontrue_res_76.out -d7c7278adf3efe34a221161d5ad2baf4 emissiontrue_res_77.out -4b2e3829b3ca32f5ae69ecc858996042 emissiontrue_res_78.out -3401fe62ac2f1e7976f1c0b987e82823 emissiontrue_res_79.out -2a0dd602c544cddb8284cd4420190ebe emissiontrue_res_80.out -ad93a94b6ceea35e10ff896d2ecd3cb4 emissiontrue_res_81.out -6191add32a2cf9262f0638688634bd9c emissiontrue_res_82.out -9940d2eacda861af505d8b897e1ed45d emissiontrue_res_83.out -bf76c3e077c1152f3a38de0d248826e8 emissiontrue_res_84.out -0ef48e27f2bf7645021dd443c75e32c0 emissiontrue_res_85.out -4abcb009235e642fc6444eca0a92829d emissiontrue_res_86.out -e8d625c5614e625aa823c5587f95c3cd emissiontrue_res_87.out -9c0dc917bc797e33242214964b482b20 emissiontrue_res_88.out -658436ef191cfd877f39822581d485df emissiontrue_res_89.out -704264ebdd36aa0fd2cc01c6f5cf1d55 emissiontrue_res_90.out -90b24a1bded838366a6dde23a01d6ac7 emissiontrue_res_91.out -59fc86b0bfac9b321fccf5b153f4905a emissiontrue_res_92.out -47f8158dc26f36ca12a6ef6ffdc79435 emissiontrue_res_93.out -cf42065ab5d7be29f11fa12b5479149d emissiontrue_res_94.out -600d6fca285cc4aa612c200f277b91c6 emissiontrue_res_95.out -20e782f89ca8dac83e1a793f24425eac emissiontrue_res_96.out -5dae3ffe4109ce799596b95e36a736f3 emissiontrue_res_97.out -765e33b6e7d0935e6f2bdde08be05129 emissiontrue_res_98.out -d6d0bde7d1bddae7e3438651c6946b18 emissiontrue_res_99.out -cdc683de61a29dba0af18694ab055f99 gamma_light_curve.out -afce5b78cd100311d653137dd182ee29 gamma_spec.out +a89a171795aff4207996405e987df0c8 deposition.out +3ca46c8cb5ca3f148548262e536aa502 emission.out +efb2a97f998b06b7a3ff16a5475405c5 emission_res_00.out +a42dabde264a364f813a89253d2b6799 emission_res_01.out +84167f306d8675235373c338a37e5024 emission_res_02.out +fa857d721e3a34d3e1a334a2a929cc8f emission_res_03.out +51782eaa0705606547e064c2526f9445 emission_res_04.out +2e14b027dbeb690482ea09750a9c67e0 emission_res_05.out +09f0210bec04a76457f377ac3462d8bf emission_res_06.out +fd61a7aba1d9eb9b6899651d241ba298 emission_res_07.out +04026ce955041f5d75d9cd391886df19 emission_res_08.out +eabcca1f3d5d584d5f8c35fe82d2caf9 emission_res_09.out +0d059a759689989fdd824bb791391da9 emission_res_10.out +25481b8e52aee29f5c85812602c79354 emission_res_11.out +c48574184e78d9ccb9ffae553e30f384 emission_res_12.out +51f24905da355a12e3ff05f6d7f5f512 emission_res_13.out +c3e3ec0c38e30504ec9ccc4e3e18ae4d emission_res_14.out +cb1f0d5fa32d63f65414337384e77393 emission_res_15.out +8d75c51213dbf4c99eea3b1e1258909f emission_res_16.out +d235e6113d6b52296ad453961bd20bd1 emission_res_17.out +5ca3083f45154a896a9a63c4b210a0bf emission_res_18.out +b5304475b5305a83705d95aac217b624 emission_res_19.out +07dffa4005e7eaca2abfacfeff9c38ac emission_res_20.out +640b0741add1dfb4ffea23e78175b7fa emission_res_21.out +ab8fcb310d470aec8bfa1c2cb692cf3a emission_res_22.out +3f63a6ccaee7203266e3e884837571b4 emission_res_23.out +631db0929de7dcda980ceaa28b205702 emission_res_24.out +43c98724f8bbe3c0abd0c181690873d8 emission_res_25.out +812a5ce219ea03ee1e4a87b157deb124 emission_res_26.out +8dbdec471531273000dcace8a14aa758 emission_res_27.out +9631d29fc0e9c81ee1d6bdc0a54b06c5 emission_res_28.out +1ccde2142e85ee944af651d62997b206 emission_res_29.out +e51cb80d790e9753fd45576be521b620 emission_res_30.out +0ac3b4058a71cf83e087995ab7638594 emission_res_31.out +98252c8b2479a8cd9dfb29243f74436c emission_res_32.out +3c37d6bb2ff7cee3c25b9062eb74a9f1 emission_res_33.out +4ee0abc14bce47ef04de014ce11638f4 emission_res_34.out +835811e35b298f41549bc92071400da4 emission_res_35.out +5c9fe9cc1d7fe59d75288ea24bd79b36 emission_res_36.out +53221fd3c2a2dffe03d3b69d553871c2 emission_res_37.out +190ef003c342968c064536e8342fea79 emission_res_38.out +6baa1cc1098fe5761da9148b02d07fca emission_res_39.out +5a74c088c4447ef8084e4baf4a55c143 emission_res_40.out +6f94628732892df9176f993c6bc2c6f3 emission_res_41.out +861582bcf4aa45f5ed71419b23939f4d emission_res_42.out +64a4f1a0e386e0458b5b644b6d3569de emission_res_43.out +28087c1e4014faaf9f637ea130ba73e3 emission_res_44.out +3874d4b6fe32b7a023cecff720130cb2 emission_res_45.out +8ad86da8eacf53e38355de574c2c227c emission_res_46.out +f31a39b4fa8e391134811cbf6b90dda6 emission_res_47.out +6c7ad623e88658314eb69fa685aab5d6 emission_res_48.out +32ab3cd0b2fb155ca57424df13803ba3 emission_res_49.out +714e6f74808bf4fc4167bd464a325456 emission_res_50.out +799b820709008d77b263b1ecc2633260 emission_res_51.out +008a75660dbb8ee8926e708f18680d00 emission_res_52.out +6fd7ba30e4e4bb38991ffba8f506c3d1 emission_res_53.out +8fe0c12b36bebf572e5beba70a8d9b40 emission_res_54.out +cb556ed989910b0681c03f8ce658c134 emission_res_55.out +75d8e66cc6bfc9976fd5e8371f5bc8de emission_res_56.out +d6fcff00cd33bf0a770266a61a701bda emission_res_57.out +1f7352a9e05b4c76412dc497bab215da emission_res_58.out +6364c1460bf27f6f552aee3ff0604a4a emission_res_59.out +443971b047db3b8a6a47672d70a78263 emission_res_60.out +254e2941d94d1611dc9c77a7bb1ef836 emission_res_61.out +7424c8ce30b08fcff6299695af7dde79 emission_res_62.out +78a3ee2a6710f9c5ebd93ab7a8657be8 emission_res_63.out +2a0642ce1914923a9d306e61be8dad4f emission_res_64.out +fe92a431f55a94c0cbfed14e14621833 emission_res_65.out +264e90b5ddf1b707c3cfa9b70024be9f emission_res_66.out +bc6bb0e72fb993f69950059a69941f06 emission_res_67.out +2f4fc837d59a59dda1715d96093a1ea6 emission_res_68.out +536a6bb78fa845eb5e65a5cb8de1db9e emission_res_69.out +945686d9ed8abfd7031f695cd8a5dd83 emission_res_70.out +798506de309f1878f94502b879497d4a emission_res_71.out +1265fb80e89ee15389da8dfce7b24a1c emission_res_72.out +03efa70ee26b750ec3470e1e280bf90f emission_res_73.out +4df2361ba3097710c6323947e15c0b24 emission_res_74.out +cbeb12b5858ace20b5f40d008b2ec9aa emission_res_75.out +eb7d4ad950d1cf86b645cc683c10bd6b emission_res_76.out +5c0ba65e3c2e74a9ef768f8d1b7ada50 emission_res_77.out +65665c6c9e4e011724bace6c0bbc4b9c emission_res_78.out +a5890a8a62f48d3d55bf09743b603d52 emission_res_79.out +20217cb15b379a51dd590fd03a3f0d28 emission_res_80.out +f44a34e336c7cc1b95e3ea2c3e12adb4 emission_res_81.out +5cf5dfa93d2deee8ff6bc9c6db2541b2 emission_res_82.out +9908642f26515576b9db5485134b6963 emission_res_83.out +b9b1239557508f025de7178882f8be22 emission_res_84.out +42d791ea9c7207b7e2e6668e64aff955 emission_res_85.out +60bde2e2dc48b57aabd70030e6e23c5a emission_res_86.out +965da381c5a3a2fec11ed72a6bae7346 emission_res_87.out +2cf6a1b6faa99e00dd805912659e0e1b emission_res_88.out +5c3b8e26184cac764d7129f529f2f5ef emission_res_89.out +e2551e1ddb39ab1cab6805837dbcefb3 emission_res_90.out +745de626b661c48712a2a25c5fc0c2a1 emission_res_91.out +087f89cbf65a727741bceac4eea78a2f emission_res_92.out +1f1b09dace020e65f7f1745505e8f672 emission_res_93.out +6798465db15a07927b58f0bac6bf4009 emission_res_94.out +5c28a2a329e5d5a125e27ea899d344cb emission_res_95.out +31b4846a82e8f1e96a05a006d9f6fbcb emission_res_96.out +9dce3bdab79270ebdc7e2dadbdb00d09 emission_res_97.out +cf5dd72a7476a489593cf09466f0fddc emission_res_98.out +c6333d10cab0ea07fcd2fd07c70034c3 emission_res_99.out +3f3294daf992f147d8ba87d0659eb026 emissiontrue.out +c98a0e115ff2bedc71ad5d06bc46cbdd emissiontrue_res_00.out +919980d48d9531e0e20489305fe0d589 emissiontrue_res_01.out +e3bd87a53c44b78dac244fc06774f74b emissiontrue_res_02.out +caafec683f8c23e9ef15298a21cae04b emissiontrue_res_03.out +b7b13cb06b213339f278033501a5c191 emissiontrue_res_04.out +9a29d54c35d6b7313f902c0b1bb7599d emissiontrue_res_05.out +af7960ee378bb3124c1ab6b99112e542 emissiontrue_res_06.out +9c6e5ae4c1d6d066e1484582c8619d74 emissiontrue_res_07.out +9b1032295003fc634de687165e6e9523 emissiontrue_res_08.out +234d4929bf4c1a4995afe41d76bb2684 emissiontrue_res_09.out +b53d480e51148fb0ed9d88219da3c5a7 emissiontrue_res_10.out +ec3739f05813a62d3c465c3641e321b8 emissiontrue_res_11.out +3b511944d1a92e2ddb296a17ae19bcbe emissiontrue_res_12.out +63988843a3d5374d313dd4ce5851777f emissiontrue_res_13.out +624b604d787e115400af1f5e91b44966 emissiontrue_res_14.out +88243dc5380ba936f0d167ec747924d4 emissiontrue_res_15.out +61fd8766ea2d51ffd3ce619f889fc341 emissiontrue_res_16.out +bf33621e63f720bd51bdcb39b9a41c57 emissiontrue_res_17.out +31070c2dc3784d4b4a13835b2ac179be emissiontrue_res_18.out +94a8e37157294185ed3d3717a63db709 emissiontrue_res_19.out +f46a303297c7f3e532518d3f710aebf7 emissiontrue_res_20.out +17515c627adec802ac58b8e5dcc6da5f emissiontrue_res_21.out +03871e2c3fd09ab9775212406c91e853 emissiontrue_res_22.out +fc0540cf5147f126fa258ad2136e716c emissiontrue_res_23.out +befdec2593fae1d4a72bb292b752f3d9 emissiontrue_res_24.out +e4c30cbc725e0f8c84fff1443c07c5ea emissiontrue_res_25.out +3eddded35fcaa06fdb0060da2cfc4697 emissiontrue_res_26.out +c58a4c9e446f49b73ee8e00d9740c32f emissiontrue_res_27.out +2e5ee93842799f852007f59efe6fa468 emissiontrue_res_28.out +5404de96ebf2632514809d2a627d0286 emissiontrue_res_29.out +c89ce7a0a2337b3c95d3067cbc7b313b emissiontrue_res_30.out +06175bb372384aa50d414479bc83da45 emissiontrue_res_31.out +f6a11f75bf997c7114086e73a1ed1275 emissiontrue_res_32.out +c3794d45a6d4515ccd180e3fc0bf3cf2 emissiontrue_res_33.out +b664347f4abf082718072a523df33ecd emissiontrue_res_34.out +72b434706d74faf90ddc6d1914c88c96 emissiontrue_res_35.out +6c69bf37e8362d2b499465db8804a5f7 emissiontrue_res_36.out +fb98e59aa0d7e98f6dcd9591781d7f9c emissiontrue_res_37.out +acc9b971f7c2b9b44933a46dd68ebcd0 emissiontrue_res_38.out +84866cb4b84925339c4ad052ddde01fb emissiontrue_res_39.out +5835326f44b75d54b472d968b381a4d5 emissiontrue_res_40.out +3804242eebe6e368996132c19a7c3e57 emissiontrue_res_41.out +47ed580bb2513aac5d82a0196d993299 emissiontrue_res_42.out +7d424c9b1ae15fb84f86df9dbc9ce73e emissiontrue_res_43.out +50864642b8e70949234375cfb9e48586 emissiontrue_res_44.out +2687f46746ea59871599adba8224767a emissiontrue_res_45.out +4e4feb446d944669f6a26997bd8876bd emissiontrue_res_46.out +6cf1970b4b46133a06bd0300ad55b320 emissiontrue_res_47.out +47d138a8e735fd40979c8d78936126b8 emissiontrue_res_48.out +595e0d0829f3b376162dcde00f8b0eff emissiontrue_res_49.out +c3c644b0bc99c6888b621da34db89868 emissiontrue_res_50.out +cc2f48d2af9ab2a631534e9fdd2f5877 emissiontrue_res_51.out +c1a82d76c64074f6ab510411def9238f emissiontrue_res_52.out +51c06170b630f3fded7db77131a89f1a emissiontrue_res_53.out +dc200d7bb90a3a5f03c8b021fa8a6480 emissiontrue_res_54.out +0ef6577077bf41bfbed269f2d4f2d525 emissiontrue_res_55.out +9bd253e45e94b52d1e5c9cede313a75d emissiontrue_res_56.out +5b131b9c46f11100e53a4ff46be6bfe9 emissiontrue_res_57.out +0934346f117b1291081b7a0a754df2c8 emissiontrue_res_58.out +c836a2c3155c1977e8832692d5d00ca6 emissiontrue_res_59.out +17be98f743fc2d96968fb41848de5680 emissiontrue_res_60.out +5740cace63535a3406ddf90941c3de10 emissiontrue_res_61.out +5a74bf3c318d4c15c4e201ea300ca358 emissiontrue_res_62.out +6cda2c7eb62e6d289632adf761c4dbab emissiontrue_res_63.out +a405c78d833b7bd37cc1b545304654fb emissiontrue_res_64.out +b7e6c1cfa8b61a5c9b6300df5635b522 emissiontrue_res_65.out +ba297d0e2780439288cc26837b6f55a9 emissiontrue_res_66.out +3d6e46cadc2fb50de64f2e8ba36c96e4 emissiontrue_res_67.out +f7bd48e9ad58f44fbe5519fefcc60174 emissiontrue_res_68.out +4d8e9c610776fc15b9ee0cfca9886e40 emissiontrue_res_69.out +22c7168316cfd353733f430e40ee33bc emissiontrue_res_70.out +7664328d845c0964bb4f62f25e2eb53f emissiontrue_res_71.out +15c5df41bc2bea7c55d12a8afa745be5 emissiontrue_res_72.out +2ca910467b8274e3b72f744daf5067f1 emissiontrue_res_73.out +7cbb4d5d43a9ece02b3d4c05b9f608cb emissiontrue_res_74.out +88c4afc2a954c48532d930bb5a5a1a5a emissiontrue_res_75.out +65fe497b52f19c9fd068dbcb4d8690e2 emissiontrue_res_76.out +3bc18b08834bcdaad251361d750d6341 emissiontrue_res_77.out +47d8f081b33c3e90aab80cda9ace5cc7 emissiontrue_res_78.out +e3789e5b54c3724f332ee38ca6657aa2 emissiontrue_res_79.out +e3504ef9a6abcc2ef00d68b435a862cf emissiontrue_res_80.out +d6b95930b9f4e2183ad797a168170114 emissiontrue_res_81.out +ca395553dfcc2a9f8461f46ae8505a52 emissiontrue_res_82.out +c8648b1db2f63eee19098a7d8b6bb78d emissiontrue_res_83.out +7e06d4e41af77f410bc8092389fa1bb3 emissiontrue_res_84.out +9b196a474cdaa9e1cc38d1cb635de7cb emissiontrue_res_85.out +5b55c6ae5fabd22aac576c590a0577f4 emissiontrue_res_86.out +ade09e7cfb4ffd8273057ff215b0a1a7 emissiontrue_res_87.out +191e742e7ee8c8135d43bc7916e3fc62 emissiontrue_res_88.out +925886a6ecbba522e0dcd8a5f7cf5e82 emissiontrue_res_89.out +20372b9bd4089b4134866cdc18af7408 emissiontrue_res_90.out +5775a7cac3e6fc0aba609811e1e81aeb emissiontrue_res_91.out +a19b09db4371baf6bb740dda2beae51a emissiontrue_res_92.out +c271b4ad987e592da9b037b41cb42781 emissiontrue_res_93.out +d8c570fc7b74510a75ea9f53de0da1ef emissiontrue_res_94.out +2e2384e2faa540b678c1970ecda87bd3 emissiontrue_res_95.out +a2aca5f8ea42526d6fb26f225059f724 emissiontrue_res_96.out +cf9f298b68301c0658d4c99feaa7ad13 emissiontrue_res_97.out +ec84019316219d6da3b5e775df634823 emissiontrue_res_98.out +32c54228f21daef517842c0312ebad67 emissiontrue_res_99.out +d5ce5bdb06e91519b27416a22f7100ff gamma_light_curve.out +980745142eda1cf04f5c89f10c3fc96b gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -de7b04ab1824e74feb7cfee6ba03cac1 light_curve.out -8dd30f7e21f771d9b66c9ec187c5a1cb light_curve_res.out -9773becefdfe4afffb041b703210c67c linestat.out +96ea3e3328e70b4491ffe0d55e853b29 light_curve.out +7e4a49bf389bf336c0745b602e21468f light_curve_res.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -7b20881009d844044b8a88b800dc5d47 packets00_0000.out -219e009891c5bfb4afecf25d17f7aa42 packets00_0001.out -e59b4d823e7d2ccb684fac9b84c09145 packets00_0002.out -762e8c94de5c230d4898f9832cf74394 packets00_0003.out -0dc93f648321d9740506c95a890f0694 spec.out -a73f647e0654520b1319aef34e7a1887 spec_res.out +ca0cad54b337590f4d881ca2ec7542d2 packets00_0000.out +e58ede787afe0fb5fc82d49b071586c3 packets00_0001.out +ec98e6641906656d97ca0d82335436fb packets00_0002.out +e802497c7ed89464a51eb0884be7b959 packets00_0003.out +a1d482542b13466b0b7976654de18bee spec.out +9f902c07f4dd9d8ca3664cab3dea060a spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -baefa6f0e15123920c0938ab294779f4 job1/estimators_0000.out -d0320f73d2807e18891f9efd57bf1f8e job1/estimators_0001.out -00f3d1db98086d2f4dd34a2c30be0ef4 job1/estimators_0002.out -8dc6701d17295ae74d5b0e123371ce4d job1/estimators_0003.out +077d45790401e79340f2d4493d296a02 job1/estimators_0000.out +7ee333019530ae1ead47c4f23d8568bf job1/estimators_0001.out +b9a8e2f604b7755b02253d9764235b14 job1/estimators_0002.out +3add597d82a32b0855ef078f4b5d169c job1/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index a1bafac54..714adc155 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -5fc79fe6b3326ac0f90d76a5b385f903 deposition.out -2c29aed8c4f22148a1609d0d33f24bf6 gamma_light_curve.out +5a6a785cacfeed6eba6cd0d871301974 deposition.out +c657b77e4d00bad2650f40ed0f2ca494 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -9c265a4eb5104b0e6cb469121120dbb9 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +2c912821e702307536768d4a714fd680 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -f5e7edc0a8b489551300f2f55d354ef4 packets00_0000.out -7de15c2f5e80f511e78b7f74d9b9f131 packets00_0001.out -cd298d033a103ad160b66ebd2d02fc73 packets00_0002.out -4690dcd41fa19a1da9deae38e979d057 packets00_0003.out -8915e92a7c3bee5388ca4805ab75a45e spec.out +c5fcded63551749abec1a322748e9f6d packets00_0000.out +a154f9a8511bed32dca64634d174f6f0 packets00_0001.out +7554b0d216037e2fd5bfd993681a329d packets00_0002.out +fb1b9057f1e7fc470fce0cf6011d352b packets00_0003.out +efeeac5b0345ab0e40d5eab91e7c8b13 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -e66c556773f7788e7c4c8e3e6319955e job0/estimators_0000.out -8d39154197b0b3eb47f0176aeaf878bf job0/estimators_0001.out -c78a879cce8a59dc7024d4455d6ed1dc job0/estimators_0002.out -91d37441617933156a1ae3d8e3f9467b job0/estimators_0003.out +052d10ff59ce151cd0ddbaf15b2c4ac9 job0/estimators_0000.out +7424d8f6de56afa74fd555d1e46eabcc job0/estimators_0001.out +fbbd2b3c64ee24ab76e967004aa1a0af job0/estimators_0002.out +a7b97f1a19f1cb2a9fb98cc161a08683 job0/estimators_0003.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 2304f34d8..beb846c3a 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -a0a9957fe56f07b30fd667bbc8862c43 absorption.out +2f49e5377a3d06fd34268f5c302f3140 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -50f22638abddae941d86e18d15e851a9 deposition.out -82e9cc26719f53714737065dda43da79 emission.out -2fca8b6df84bfec802c623725b584294 emissiontrue.out -bbc12a10475fb7a801a04f06e56861ed gamma_light_curve.out -1db22751dc8a80ba3f23831630b52097 gamma_spec.out +5829cb3d83a3181ce87d10aab2ef571a deposition.out +a4ba89eafd095c3b1d1aa61e969fd08f emission.out +9af0101468fd7d7c3efb0d07cb4a14cd emissiontrue.out +e5bd8b74708d70302232e7454839955c gamma_light_curve.out +b46d2fe763c220aed7a2392f0f4f1a2b gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -ab459cc8e8540d5f4352bfbda140a469 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +32d9e350690d4ecf12d2b6ad715c41ad light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -916d4e06cb3ce8dec7ffc2cd26c23813 packets00_0000.out -c1d45735e4ea8f456f432eaed16a576b packets00_0001.out -cec5745c1c74df35eba3aae44e245c65 packets00_0002.out -06eb1b90a2f5b4758cb2268920f954b5 packets00_0003.out -b9f314f9a296a32b1732c4ac163088e7 spec.out +1f24db4701861dad5978e575fdadee78 packets00_0000.out +2418d26a487c6576632b1ba568c49d17 packets00_0001.out +3bb68d5b38b5f4ceca390d13089c3f92 packets00_0002.out +2284490ade972c38c015cd653c24174f packets00_0003.out +69e8b3178e6be6f7e78ae73f3bbd873a spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -f6dbb21ee3f2d1b270bca6207de07ad2 job1/estimators_0000.out -3315ea1ed7d294aa93c75de8b2d42bf2 job1/estimators_0001.out -e313b30095557e70332faa0dc3ea84ed job1/estimators_0002.out -3939046c8f072fbcafb2825969713398 job1/nlte_0000.out -0ba1f4ba0599789a13b31a213be8da1a job1/nlte_0001.out -57379e4bf2c927b19432577266515439 job1/nlte_0002.out +fb95afe60e57121b5bb3c1cd062ce60d job1/estimators_0000.out +9dffdd580798be16aa7cd445ca41b553 job1/estimators_0001.out +2d3a4e11fd7f0aa346562fe599cc588e job1/estimators_0002.out +543f1eeed777a9fe2c81c492d9460bfd job1/nlte_0000.out +b4041ef65fd2705ecf820e14e2013fff job1/nlte_0001.out +8c53f992c35cfac925d48bc30ff2caa2 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -8d1912ef1d02d786c6f2cf0802422adf job1/radfield_0000.out -a80801660c77cec7a6fd9d144361c71e job1/radfield_0001.out -982f164f7c07f26afbefe86c1820b709 job1/radfield_0002.out +76cff3ddbf99d2cff8838e16c3046e6f job1/radfield_0000.out +e1537e18e673cc57741a4c2bb7d5eda9 job1/radfield_0001.out +64d02d654732b412aaf336604294868d job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index 7293b961f..c5ca526a8 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -0214118b0d1f2bcf1ea70600d1e2c236 absorption.out +131cbf501b5a645fb0f6b7d5935a332e absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -83baaf0e40350f5228742c0b62f99e19 deposition.out -806f2bac5f9839b7d5dde80872d2335b emission.out -f47c36a3905e6baac50624adbf781d15 emissiontrue.out -326082c70b15571eac4ee4804cf49f7e gamma_light_curve.out +dcbf9412ab83a18e2035666b616e89d4 deposition.out +54a9b747ca68dd130eb1efbc9f7e13bf emission.out +859c4997aa7d3c9f62878dcd9f535e33 emissiontrue.out +d521daee1fa89b99c7e548b36c8603b2 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -439ccc3d173c5aa186dd5e94cec510eb light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +b27913a2d317f53f0e99d38b6ab3f0e4 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -30d9c4633451e6f3bfb434cfcb266401 packets00_0000.out -0900e8ebaa69550ff2cb3d07bb52f028 packets00_0001.out -a3e11f4e07025d0b63646f147bbe6da5 packets00_0002.out -f261efe2b09c6e55d382b49718560eeb packets00_0003.out -c98d7b9bc20e210c34c1d9d18cdcd30b spec.out +4d889f720bcd204a789317918cd19ce3 packets00_0000.out +c443dd6213110f138f769e8c8797b5d2 packets00_0001.out +0035bf7388ea6cc4e605456c10c0f84c packets00_0002.out +dbe137676dbe07dbeda3521b329b45f0 packets00_0003.out +cb0993f79ecd0cf650337525143bde5b spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -fd429c9db02f7d0917608ffd949a50cc job0/estimators_0000.out -84f1a8955e08a43dfeeea183e90bbb45 job0/estimators_0001.out -d1360d523b32630082fdf65dd3307c42 job0/estimators_0002.out -074b0b9cdc06c0f8d35c6c92d546652d job0/nlte_0000.out -0c4abb5cc11ed764d1a5eb59cf928437 job0/nlte_0001.out -83a67ce6f367b1155c3545cbfd80f28b job0/nlte_0002.out +42b5ee39f991a3499a39d18b0676cac7 job0/estimators_0000.out +68295a40ce0ff8dade91ed0a2068dbef job0/estimators_0001.out +b6d7da56b3b3f9e61d17044898302d2b job0/estimators_0002.out +edac9d99f6066ccf019da96a84f92c80 job0/nlte_0000.out +77ea65d6004d9c04888846a0ce2121fc job0/nlte_0001.out +f05f0d7c9d5b814f18ca9cf43e73ccbd job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -d597d4a3d94b6de5ef6256100e7e6679 job0/radfield_0000.out -4024d5821c91fbdf67949c4eee93c7a1 job0/radfield_0001.out -e141770e4494a03955f192d0628ac211 job0/radfield_0002.out +a229397eef43b789830071c02bae4eec job0/radfield_0000.out +b5bb2a5f69d1ce47fb6446a085d8d3d8 job0/radfield_0001.out +6f70f10c8a9c99aa95678433b13b92c4 job0/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 5f45634f8..fb4b3db91 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -5db21c9087270dfe4f04ffd619b3e2c0 absorption.out +208c12670db21e2b1292ccd272daa9d1 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -5a701de02f8d29c3440703b239f76da7 deposition.out -ddc58b8fb083aa5ce0eb363b5a8c7557 emission.out -69a76d0f782b4387f72872d1e49fa75c emissiontrue.out -c06d57c1b70d100869e924c42a852d2e gamma_light_curve.out -327ed1bb0201a62ca2daed74523419ea gamma_spec.out +e25747048f8502665f23520c5bfb4328 deposition.out +93c8fbf8185a3b45a96883d15d57a051 emission.out +5871be78febfb9cce9659e3d686c3771 emissiontrue.out +0c8a3fbb1473b818d0cab8aff5294092 gamma_light_curve.out +774211c072a2c67dd17707a0e355b0ad gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -647bab9757d1a50f0a7ee2803af2ece8 light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +906adfb01fdaa2f5946c64a504511420 light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -53f0eb86a14d1878972506c6820e22ac packets00_0000.out -8d9eef504f09763b2527be4ada18c938 packets00_0001.out -e26a2efbc2e720a8af45978e8a2f26a0 packets00_0002.out -a2142aed3cb852bd2154f29c38607a8e packets00_0003.out -42c12cc4e318ea5450e71e27261798c3 spec.out +9bb900b56efd416799deb7c725a3b17c packets00_0000.out +6320adc4ce70eeb64d233f310a844f0c packets00_0001.out +646fbdb744361e548bb3ad760d586f59 packets00_0002.out +465222336cefe78f1dcfc49c75402375 packets00_0003.out +d7cab8edbffe1afc767d7b98e84ce387 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -b34c9abd72bf77ef15e70b3cae5c5a01 job1/estimators_0000.out -54ca53c073550a0d07addd5aa0dc2caf job1/estimators_0001.out -a1462f00ec8c84af6643abf349ba549d job1/estimators_0002.out -6038cb41537b773a9fd659af21e04a41 job1/nlte_0000.out -5f3d791a08c7ee9142e883275db74b33 job1/nlte_0001.out -b8527165c6a02c223fe1b2e8e2f554a7 job1/nlte_0002.out +076c670c54d8fb04182a41a0906e0c02 job1/estimators_0000.out +0e59f5c370cfb0f99de36082f48b8e9c job1/estimators_0001.out +7c8ddc14ec60ab347d59f3728e200c63 job1/estimators_0002.out +d1fb48b49884d8177e6af38b40593d68 job1/nlte_0000.out +44a0595547c92454f9e24f85c0ae8326 job1/nlte_0001.out +71cd27d0a8918f127f28cfc5fd72e6f0 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -c45755ed24897d2871689f992ed2c0e9 job1/radfield_0000.out -92930c7409684e306e10e19d3229d1fb job1/radfield_0001.out -135611c424d52921baa48877098cd545 job1/radfield_0002.out +2eb4624dd5c1369fcbd28c9d5a1bbed0 job1/radfield_0000.out +f26f80533a25880b53870ffd2a1ccae3 job1/radfield_0001.out +98e5090a68555676241a2f5924b247f1 job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index 7ad82eb65..113ef9c5e 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -2bab28e6c44dc5f73ce68bd1e9792e2b absorption.out +86974870567c9f3afec4d0c91f06c0f2 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -9f443fef6a1bd8ea9ce3fb796f713c06 deposition.out -d7852586693f119d71c452553abac594 emission.out -66e15feb69cdcdba0f477301a3c15db1 emissiontrue.out -6883b2c110209525613b23caf2a38631 gamma_light_curve.out +7dc09f050d647fa589e5a776d2b079e2 deposition.out +24a88918d6417447b45e72f6714067b4 emission.out +799e3f35257a3338d73bed4f7167d189 emissiontrue.out +83723fbf0ca46aa72d07f1d8af2b11d4 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -7c328b45adf004d1e23d9e97befdb2af light_curve.out -9773becefdfe4afffb041b703210c67c linestat.out +f19b0cecf67575b042a3de2318eb2cda light_curve.out +3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -21d24f8cf6bbe362a4458e3c61981365 packets00_0000.out -4fcea2d6a448c5d1102de8b6eab523ad packets00_0001.out -0ba50b79e12743d56f8397d7e9ebbdc6 packets00_0002.out -8255f260fdab8e7079473293c0df424e packets00_0003.out -6359d469d801b3eda814b0cc4a5eb196 spec.out +66e71b732fa464b5f4c1be95c1d597a8 packets00_0000.out +01fec475ece90544cb04edb4c1418981 packets00_0001.out +ee423894bf4cc220ccf167f537205cff packets00_0002.out +d5cdf7fe11f27ea0fe0951e63f948555 packets00_0003.out +7846d067675fb864fde871e2f9547449 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -037eca48b4120f8f100285d4d03492fe job0/estimators_0000.out -f034f2846fb5b5e84e554de0c1cff479 job0/estimators_0001.out -d64821f262bc506a4e2cbfdf9428bc69 job0/estimators_0002.out -70745363977227f69b62785cf6773acd job0/nlte_0000.out -c49c7ccf68d648435a82116406c8d6eb job0/nlte_0001.out -800cb6ec93bb650868774f6f03b72dbd job0/nlte_0002.out +a100df93a414fe49230617583f0eb1d5 job0/estimators_0000.out +5d5971e62e23c5d9e96093840c15447e job0/estimators_0001.out +b96da6e56966046c66102d86dfeccdb4 job0/estimators_0002.out +0e877b1417b452a7ebda2d53ac267d1a job0/nlte_0000.out +a8fb6228e23298597b71c60c12319a11 job0/nlte_0001.out +4b516ae17c600afc38dd8a63cbfa03e0 job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -e49dde6600b47037b6557cf80fd88fd8 job0/radfield_0000.out -ea41d42c7769892ed09670146727f025 job0/radfield_0001.out -f961b54108e02d7dd06facf00adf8776 job0/radfield_0002.out +6fbabfb080eead960ab969fdd050d8cf job0/radfield_0000.out +4b01065c6e54ed8c28d55b80d005484a job0/radfield_0001.out +2040872a4f19535421c278d93afa3959 job0/radfield_0002.out diff --git a/update_packets.cc b/update_packets.cc index cc0619de3..39aee9501 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -363,7 +363,7 @@ void update_packets(const int my_rank, const int nts, std::span packets) // printout("sorting packets..."); - std::ranges::sort(packets, std_compare_packets_bymodelgriddensity); + std::ranges::stable_sort(packets, std_compare_packets_bymodelgriddensity); // printout("took %lds\n", std::time(nullptr) - sys_time_start_pass); From ed32dcc2b6993f9d4b8b5b1eff337ecfe4b8b114 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 12 Aug 2024 16:21:27 +0100 Subject: [PATCH 015/117] Fix some clang-tidy 19 warnings, use more std::ranges, const correctness, and anonymous namespaces (#103) --- .clang-tidy | 8 +- Makefile | 8 +- decay.cc | 975 ++++++----- gammapkt.cc | 218 +-- grid.cc | 3598 ++++++++++++++++++++-------------------- input.cc | 109 +- kpkt.cc | 181 +- ltepop.cc | 414 ++--- macroatom.cc | 21 +- md5.cc | 8 +- md5.h | 2 +- nltepop.cc | 94 +- nonthermal.cc | 32 +- packet.cc | 11 +- radfield.cc | 471 +++--- ratecoeff.cc | 913 +++++----- rpkt.cc | 375 +++-- sn3d.h | 10 +- spectrum_lightcurve.cc | 15 +- thermalbalance.cc | 165 +- update_grid.cc | 2 +- update_packets.cc | 1 - vpkt.cc | 2 +- 23 files changed, 3813 insertions(+), 3820 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 7c7a87aa8..2c570b4a3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -36,13 +36,15 @@ Checks: > -hicpp-no-array-decay, -hicpp-no-malloc, -hicpp-signed-bitwise, - -misc-use-anonymous-namespace, -misc-no-recursion, -misc-non-private-member-variables-in-classes, + -modernize-use-ranges, -readability-identifier-length, -readability-function-cognitive-complexity, -readability-magic-numbers, -WarningsAsErrors: '' +WarningsAsErrors: > + *, + -performance-enum-size, FormatStyle: file ExtraArgs: [-std=c++20] CheckOptions: @@ -68,3 +70,5 @@ CheckOptions: value: lower_case - key: bugprone-reserved-identifier.AllowedIdentifiers value: '__host__;__device__' + - key: misc-include-cleaner.IgnoreHeaders + value: '.*(ranges).*' diff --git a/Makefile b/Makefile index 0f1715b19..f945b1811 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ ifeq ($(OPENMP),ON) ifeq ($(COMPILER_NAME),NVHPC) ifeq ($(GPU),ON) - CXXFLAGS += -mp=gpu -gpu=unified + CXXFLAGS += -mp=gpu -gpu=mem:unified else CXXFLAGS += -mp endif @@ -105,14 +105,14 @@ ifeq ($(STDPAR),ON) ifeq ($(COMPILER_NAME),NVHPC) ifeq ($(GPU),ON) - CXXFLAGS += -stdpar=gpu -gpu=unified + CXXFLAGS += -stdpar=gpu -gpu=mem:unified # CXXFLAGS += -gpu=cc80 else CXXFLAGS += -stdpar=multicore endif else ifeq ($(COMPILER_NAME),CLANG) - # CXXFLAGS += -fexperimental-library - LDFLAGS += -ltbb + CXXFLAGS += -fexperimental-library + # LDFLAGS += -ltbb # LDFLAGS += -Xlinker -debug_snapshot else ifeq ($(COMPILER_NAME),GCC) LDFLAGS += -ltbb diff --git a/decay.cc b/decay.cc index a35ceec8a..550551644 100644 --- a/decay.cc +++ b/decay.cc @@ -60,12 +60,7 @@ struct Nuclide { std::array branchprobs = {0.}; // branch probability of each decay type }; -std::vector nuclides; - -} // anonymous namespace - -[[nodiscard]] constexpr static auto decay_daughter_z(const int z_parent, const int /*a_parent*/, - const int decaytype) -> int +[[nodiscard]] constexpr auto decay_daughter_z(const int z_parent, const int /*a_parent*/, const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { assert_always(decaytype >= 0); @@ -92,8 +87,7 @@ std::vector nuclides; return -1; // no daughter } -[[nodiscard]] constexpr static auto decay_daughter_a(const int /*z_parent*/, const int a_parent, - const int decaytype) -> int +[[nodiscard]] constexpr auto decay_daughter_a(const int /*z_parent*/, const int a_parent, const int decaytype) -> int // check if (z_parent, a_parent) is a parent of (z, a) { switch (static_cast(decaytype)) { @@ -131,42 +125,46 @@ struct DecayPath { [[nodiscard]] auto final_daughter_z() const -> int { return decay_daughter_z(z.back(), a.back(), decaytypes.back()); } }; -static std::vector decaypaths; +std::vector nuclides; +std::vector decaypaths; // decaypath_energy_per_mass points to an array of length npts_model * num_decaypaths // the index [mgi * num_decaypaths + i] will hold the decay energy per mass [erg/g] released by chain i in cell mgi // during the simulation time range -static double *decaypath_energy_per_mass{}; +double *decaypath_energy_per_mass{}; #ifdef MPI_ON MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; #endif -[[nodiscard]] auto get_num_nuclides() -> int { return static_cast(nuclides.size()); } - -[[nodiscard]] auto get_elname(const int z) -> std::string { - assert_testmodeonly(z <= Z_MAX); - return std::string(elsymbols[z]); -} - -[[nodiscard]] auto get_nuc_z(int nucindex) -> int { +[[nodiscard]] auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> double { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); - return nuclides[nucindex].z; + assert_testmodeonly(decaytype >= 0); + assert_testmodeonly(decaytype < decaytypes::DECAYTYPE_COUNT); + return nuclides[nucindex].branchprobs[decaytype]; } -[[nodiscard]] auto get_nuc_a(int nucindex) -> int { - assert_testmodeonly(nucindex >= 0); - assert_testmodeonly(nucindex < get_num_nuclides()); - return nuclides[nucindex].a; +[[nodiscard]] auto get_nuc_decaybranchprob(const int z_parent, const int a_parent, const int decaytype) -> double { + return get_nuc_decaybranchprob(get_nucindex(z_parent, a_parent), decaytype); +} + +[[nodiscard]] auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool +// check if (z_parent, a_parent) is a parent of (z, a) +{ + assert_testmodeonly(nuc_exists(z_parent, a_parent)); + // each radioactive nuclide is limited to one daughter nuclide + return std::ranges::any_of(all_decaytypes, [=](const auto decaytype) { + return decay_daughter_z(z_parent, a_parent, decaytype) == z && decay_daughter_a(z_parent, a_parent, decaytype) == a; + }); } -[[nodiscard]] static auto get_nuc_z_a(int nucindex) -> std::pair { +[[nodiscard]] auto get_nuc_z_a(const int nucindex) -> std::pair { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return {nuclides[nucindex].z, nuclides[nucindex].a}; } -[[nodiscard]] static auto get_nucindex_or_neg_one(int z, int a) -> int +[[nodiscard]] auto get_nucindex_or_neg_one(const int z, const int a) -> int // get the nuclide array index from the atomic number and mass number { assert_testmodeonly(get_num_nuclides() > 0); @@ -180,38 +178,15 @@ MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; return -1; // nuclide not found } -[[nodiscard]] auto get_nucindex(int z, int a) -> int -// get the nuclide array index from the atomic number and mass number -{ - const int nucindex = get_nucindex_or_neg_one(z, a); - if (nucindex >= 0) { - return nucindex; - } - printout("Could not find nuclide Z=%d A=%d\n", z, a); - assert_always(false); // nuclide not found - return -1; -} - -[[nodiscard]] auto nuc_exists(int z, int a) -> bool -// check if nuclide exists in the simulation -{ - for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) { - if (nuclides[nucindex].z == z && nuclides[nucindex].a == a) { - return true; - } - } - return false; -} - -[[nodiscard]] static auto get_meanlife(int nucindex) -> double { +[[nodiscard]] auto get_meanlife(const int nucindex) -> double { assert_testmodeonly(nucindex >= 0); assert_testmodeonly(nucindex < get_num_nuclides()); return nuclides[nucindex].meanlife; } -static void printout_nuclidename(const int z, const int a) { printout("(Z=%d)%s%d", z, get_elname(z).c_str(), a); } +void printout_nuclidename(const int z, const int a) { printout("(Z=%d)%s%d", z, get_elname(z).c_str(), a); } -static void printout_nuclidemeanlife(const int z, const int a) { +void printout_nuclidemeanlife(const int z, const int a) { const int nucindex = get_nucindex_or_neg_one(z, a); const bool exists = (nucindex >= 0); if (exists && get_meanlife(nucindex) > 0.) { @@ -223,46 +198,7 @@ static void printout_nuclidemeanlife(const int z, const int a) { } } -[[nodiscard]] static auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> double { - assert_testmodeonly(nucindex >= 0); - assert_testmodeonly(nucindex < get_num_nuclides()); - assert_testmodeonly(decaytype >= 0); - assert_testmodeonly(decaytype < decaytypes::DECAYTYPE_COUNT); - return nuclides[nucindex].branchprobs[decaytype]; -} - -[[nodiscard]] static auto get_nuc_decaybranchprob(const int z_parent, const int a_parent, - const int decaytype) -> double { - return get_nuc_decaybranchprob(get_nucindex(z_parent, a_parent), decaytype); -} - -[[nodiscard]] static auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool -// check if (z_parent, a_parent) is a parent of (z, a) -{ - assert_testmodeonly(nuc_exists(z_parent, a_parent)); - // each radioactive nuclide is limited to one daughter nuclide - return std::ranges::any_of(all_decaytypes, [=](const auto decaytype) { - return decay_daughter_z(z_parent, a_parent, decaytype) == z && decay_daughter_a(z_parent, a_parent, decaytype) == a; - }); -} - -[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(int nucindex) -> double -// average energy per decay in the form of gamma rays [erg] -{ - return nuclides[nucindex].endecay_gamma; -} - -[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(int z, int a) -> double { - return nucdecayenergygamma(get_nucindex(z, a)); -} - -void set_nucdecayenergygamma(int nucindex, double value) -// set average energy per decay in the form of gamma rays [erg] -{ - nuclides[nucindex].endecay_gamma = value; -} - -[[nodiscard]] static auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double +[[nodiscard]] auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double // decay energy in the form of kinetic energy of electrons, positrons, or alpha particles, // depending on the relevant decay type (but not including neutrinos) { @@ -288,7 +224,7 @@ void set_nucdecayenergygamma(int nucindex, double value) } } -[[nodiscard]] static auto nucdecayenergytotal(const int z, const int a) -> double +[[nodiscard]] auto nucdecayenergytotal(const int z, const int a) -> double // average energy (erg) per decay in the form of gammas and particles [erg] { const int nucindex = get_nucindex(z, a); @@ -300,7 +236,7 @@ void set_nucdecayenergygamma(int nucindex, double value) return nuclides[nucindex].endecay_gamma + endecay_particles; } -[[nodiscard]] static auto nucdecayenergy(int nucindex, int decaytype) -> double +[[nodiscard]] auto nucdecayenergy(const int nucindex, const int decaytype) -> double // contributed energy release per decay [erg] for decaytype (e.g. decaytypes::DECAYTYPE_BETAPLUS) // (excludes neutrinos!) { @@ -309,20 +245,18 @@ void set_nucdecayenergygamma(int nucindex, double value) return endecay; } -[[nodiscard]] static auto nucdecayenergyqval(int nucindex, int decaytype) -> double { +[[nodiscard]] auto nucdecayenergyqval(const int nucindex, const int decaytype) -> double { return nuclides[nucindex].endecay_q[decaytype]; } -[[nodiscard]] static auto get_num_decaypaths() -> int { return static_cast(decaypaths.size()); } +[[nodiscard]] auto get_num_decaypaths() -> int { return static_cast(decaypaths.size()); } -[[nodiscard]] static auto get_decaypathlength(const DecayPath &dpath) -> int { - return static_cast(dpath.z.size()); -} -[[nodiscard]] static auto get_decaypathlength(int decaypathindex) -> int { +[[nodiscard]] auto get_decaypathlength(const DecayPath &dpath) -> int { return static_cast(dpath.z.size()); } +[[nodiscard]] auto get_decaypathlength(const int decaypathindex) -> int { return get_decaypathlength(decaypaths[decaypathindex]); } -[[nodiscard]] static auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> double { +[[nodiscard]] auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> double { // return the product of all branching factors in the decay path double branchprod = 1.; @@ -333,7 +267,7 @@ void set_nucdecayenergygamma(int nucindex, double value) return branchprod; } -[[nodiscard]] static auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { +[[nodiscard]] auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { // a decaypath's energy is the decay energy of the last nuclide and decaytype in the chain const int nucindex_end = dpath.nucindex.back(); @@ -341,11 +275,11 @@ void set_nucdecayenergygamma(int nucindex, double value) return nucdecayenergy(nucindex_end, decaytype_end); } -[[nodiscard]] static auto get_decaypath_lastnucdecayenergy(const int decaypathindex) -> double { +[[nodiscard]] auto get_decaypath_lastnucdecayenergy(const int decaypathindex) -> double { return get_decaypath_lastnucdecayenergy(decaypaths[decaypathindex]); } -static void printout_decaytype(const int decaytype) { +void printout_decaytype(const int decaytype) { switch (decaytype) { case decaytypes::DECAYTYPE_ALPHA: { printout("alpha"); @@ -372,7 +306,7 @@ static void printout_decaytype(const int decaytype) { } } -static void printout_decaypath(const int decaypathindex) { +void printout_decaypath(const int decaypathindex) { assert_always(!decaypaths.empty()); const auto &decaypath = decaypaths[decaypathindex]; printout(" decaypath %d: ", decaypathindex); @@ -397,7 +331,7 @@ static void printout_decaypath(const int decaypathindex) { printout("\n"); } -static void extend_lastdecaypath() +void extend_lastdecaypath() // follow decays at the ends of the current list of decaypaths, // to get decaypaths from all descendants { @@ -432,33 +366,8 @@ static void extend_lastdecaypath() } } -static auto operator<(const DecayPath &d1, const DecayPath &d2) -> bool -// true if d1 < d2 -// chains are sorted by mass number, then atomic number, then length -{ - const int d1_length = get_decaypathlength(d1); - const int d2_length = get_decaypathlength(d2); - const int smallestpathlength = std::min(d1_length, d2_length); - for (int i = 0; i < smallestpathlength; i++) { - if (d1.a[i] < d2.a[i]) { - return true; - } - if (d1.a[i] > d2.a[i]) { - return false; - } - if (d1.z[i] < d2.z[i]) { - return true; - } - if (d1.z[i] > d2.z[i]) { - return false; - } - } - // one is an extension of the other - return d1_length < d2_length; -} - -static void find_decaypaths(const std::vector &custom_zlist, const std::vector &custom_alist, - std::vector &standard_nuclides) { +void find_decaypaths(const std::vector &custom_zlist, const std::vector &custom_alist, + const std::vector &standard_nuclides) { decaypaths.clear(); for (int startnucindex = 0; startnucindex < get_num_nuclides(); startnucindex++) { const int z = get_nuc_z(startnucindex); @@ -491,7 +400,29 @@ static void find_decaypaths(const std::vector &custom_zlist, const std::vec } } - std::stable_sort(decaypaths.begin(), decaypaths.end()); + std::ranges::stable_sort(decaypaths, [](const DecayPath &d1, const DecayPath &d2) { + // true if d1 < d2 + // chains are sorted by mass number, then atomic number, then length + const int d1_length = get_decaypathlength(d1); + const int d2_length = get_decaypathlength(d2); + const int smallestpathlength = std::min(d1_length, d2_length); + for (int i = 0; i < smallestpathlength; i++) { + if (d1.a[i] < d2.a[i]) { + return true; + } + if (d1.a[i] > d2.a[i]) { + return false; + } + if (d1.z[i] < d2.z[i]) { + return true; + } + if (d1.z[i] > d2.z[i]) { + return false; + } + } + // one is an extension of the other, so place the shorter one first + return d1_length < d2_length; + }); for (auto &decaypath : decaypaths) { // all nuclei in the path (except for the last one, which is allowed to be stable) must have a mean life >0 @@ -515,358 +446,158 @@ static void find_decaypaths(const std::vector &custom_zlist, const std::vec decaypaths.shrink_to_fit(); } -static void filter_unused_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist, - std::vector &standard_nuclides) { +void filter_unused_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist, + const std::vector &standard_nuclides) { // remove nuclides that are not a standard or custom input-specified nuclide, or connected to these by decays - nuclides.erase( - std::remove_if(nuclides.begin(), nuclides.end(), - [&](const auto &nuc) { - // keep nucleus if it is in the standard list - if (std::ranges::any_of(standard_nuclides, [&](const auto &stdnuc) { - return (stdnuc.z == nuc.z) && (stdnuc.a == nuc.a); - })) { - return false; - } - // keep nucleus if it is in the custom list - for (size_t i = 0; i < custom_zlist.size(); i++) { - if ((nuc.z == custom_zlist[i]) && (nuc.a == custom_alist[i])) { - return false; - } - } - - const bool in_any_decaypath = std::ranges::any_of(decaypaths, [&nuc](const auto &decaypath) { - for (size_t i = 0; i < decaypath.z.size(); i++) { - if (decaypath.z[i] == nuc.z && decaypath.a[i] == nuc.a) { - // nuc is in the decay path - return true; - } - } - - // return true if nuc is the final daughter of a decay path - return (decaypath.final_daughter_z() == nuc.z && decaypath.final_daughter_a() == nuc.a); - }); - - if (in_any_decaypath) { - return false; - } - - printout("removing unused nuclide (Z=%d)%s%d\n", nuc.z, get_elname(nuc.z).c_str(), nuc.a); - return true; - }), - nuclides.end()); + std::erase_if(nuclides, [&](const auto &nuc) { + // keep nucleus if it is in the standard list + if (std::ranges::any_of(standard_nuclides, + [&](const auto &stdnuc) { return (stdnuc.z == nuc.z) && (stdnuc.a == nuc.a); })) { + return false; + } + // keep nucleus if it is in the custom list + for (size_t i = 0; i < custom_zlist.size(); i++) { + if ((nuc.z == custom_zlist[i]) && (nuc.a == custom_alist[i])) { + return false; + } + } + + const bool in_any_decaypath = std::ranges::any_of(decaypaths, [&nuc](const auto &decaypath) { + for (size_t i = 0; i < decaypath.z.size(); i++) { + if (decaypath.z[i] == nuc.z && decaypath.a[i] == nuc.a) { + // nuc is in the decay path + return true; + } + } + + // return true if nuc is the final daughter of a decay path + return (decaypath.final_daughter_z() == nuc.z && decaypath.final_daughter_a() == nuc.a); + }); + + if (in_any_decaypath) { + return false; + } + + printout("removing unused nuclide (Z=%d)%s%d\n", nuc.z, get_elname(nuc.z).c_str(), nuc.a); + return true; + }); nuclides.shrink_to_fit(); // update the nuclide indicies in the decay paths after we possibly removed some nuclides for (auto &decaypath : decaypaths) { - std::transform(decaypath.z.cbegin(), decaypath.z.cend(), decaypath.a.cbegin(), decaypath.nucindex.begin(), - [](const auto z, const auto a) { return get_nucindex(z, a); }); + std::ranges::transform(decaypath.z, decaypath.a, decaypath.nucindex.begin(), + [](const auto z, const auto a) { return get_nucindex(z, a); }); } } -auto get_nucstring_z(const std::string &strnuc) -> int -// convert something like Ni56 to integer 28 -{ - std::string elcode = strnuc; - elcode.erase(std::remove_if(elcode.begin(), elcode.end(), &isdigit), elcode.end()); +auto sample_decaytime(const int decaypathindex, const double tdecaymin, const double tdecaymax) -> double { + double tdecay = -1; + const double t_model = grid::get_t_model(); + // rejection method. draw random times until they are within the correct range. + while (tdecay <= tdecaymin || tdecay >= tdecaymax) { + tdecay = t_model; // can't decay before initial model snapshot time - for (int z = 0; z <= Z_MAX; z++) { - if (elcode == get_elname(z)) { - return z; + const auto decaypathlength = get_decaypathlength(decaypathindex); + for (int i = 0; i < decaypathlength; i++) { + const int nucindex = decaypaths[decaypathindex].nucindex[i]; + const double zrand = rng_uniform_pos(); + tdecay += -get_meanlife(nucindex) * log(zrand); } } - printout("Could not get atomic number of '%s' '%s'\n", strnuc.c_str(), elcode.c_str()); - assert_always(false); // could not match to an element - return -1; + return tdecay; } -auto get_nucstring_a(const std::string &strnuc) -> int -// convert something like Ni56 to integer 56 -{ - // find first digit character - size_t i = 0; - for (; i < strnuc.length(); i++) { - if (isdigit(strnuc[i]) != 0) { - break; +constexpr auto calculate_decaychain(const double firstinitabund, const std::vector &lambdas, + const int num_nuclides, const double timediff, + const bool useexpansionfactor) -> double { + // calculate final number abundance from multiple decays, e.g., Ni56 -> Co56 -> Fe56 (nuc[0] -> nuc[1] -> nuc[2]) + // the top nuclide initial abundance is set and the chain-end abundance is returned (all intermediates nuclides + // are assumed to start with zero abundance) + // note: first and last can be nuclide can be the same if num_nuclides==1, reducing to simple decay formula + // + // timediff: time elapsed since firstinitabund was true [seconds] + // numnuclides: number of items in lambdas to use + // lambdas: array of 1/(mean lifetime) for nuc[0]..nuc[num_nuclides-1] [seconds^-1] + // useexpansionfactor: if true, return a modified 'abundance' at the end of the chain, with a weighting factor + // accounting for photon energy loss from expansion since the decays occured + // (This is needed to get the initial temperature) + + assert_always(num_nuclides >= 1); + + double lambdaproduct = 1.; + for (int j = 0; j < num_nuclides - 1; j++) { + lambdaproduct *= lambdas[j]; + } + + double sum = 0; + for (int j = 0; j < num_nuclides; j++) { + double denominator = 1.; + for (int p = 0; p < num_nuclides; p++) { + if (p != j) { + denominator *= (lambdas[p] - lambdas[j]); + } + } + + if (!useexpansionfactor) // abundance output + { + sum += exp(-lambdas[j] * timediff) / denominator; + } else { + if (lambdas[j] > 0.) { + const double sumtermtop = + ((1 + 1 / lambdas[j] / timediff) * exp(-timediff * lambdas[j])) - (1. / lambdas[j] / timediff); + sum += sumtermtop / denominator; + } } } - // remove the non-digit charts - const std::string strmassnum = strnuc.substr(i); + const double lastabund = firstinitabund * lambdaproduct * sum; - const int a = std::atoi(strmassnum.c_str()); - assert_always(a > 0); - return a; + return lastabund; } -void init_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist) { - // add all nuclides and decays, and later trim any irrelevant ones (not connected to input-specified nuclei) later - - assert_always(custom_zlist.size() == custom_alist.size()); +auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const double time) -> double +// Get the mass fraction of a nuclide accounting for all decays including those of its parent and grandparent. +// e.g., Co56 abundance may first increase with time due to Ni56 decays, then decease due to Co56 decay +// Can be called for stable nuclides that are one daughters of the radioactive nuclide list e.g., Fe56 +// For stable nuclides, abundance returned only comes from other decays (some could be included in init model elem frac) +{ + assert_always(time >= 0.); - // Ni57 - nuclides.push_back({.z = 28, .a = 57, .meanlife = 51.36 * 60}); - nuclides.back().endecay_positron = 0.354 * MEV; - nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 0.436; - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1. - 0.436; + const double t_afterinit = time - grid::get_t_model(); + const int nucindex = get_nucindex_or_neg_one(z, a); + const bool nuc_exists_z_a = (nucindex >= 0); - // Ni56 - nuclides.push_back({.z = 28, .a = 56, .meanlife = 8.80 * DAY}); - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + // decay chains include all paths from radionuclides to other radionuclides (including trivial size-one chains) - // Co56 - nuclides.push_back({.z = 27, .a = 56, .meanlife = 113.7 * DAY}); - nuclides.back().endecay_positron = 0.63 * MEV; - nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 0.19; - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1 - 0.19; + double nuctotal = 0.; // abundance or decay rate, depending on mode parameter + for (const auto &decaypath : decaypaths) { + const int z_end = decaypath.z.back(); + const int a_end = decaypath.a.back(); - // Cr48 - nuclides.push_back({.z = 24, .a = 48, .meanlife = 1.29602 * DAY}); - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + // match 4He abundance to alpha decay of any nucleus (no continue), otherwise check daughter nuclide matches + if (z != 2 || a != 4 || decaypath.decaytypes.back() != decaytypes::DECAYTYPE_ALPHA) { + if (nuc_exists_z_a && (z_end != z || a_end != a)) // requested nuclide is in network, so match last nuc in chain + { + continue; + } - // V48 - nuclides.push_back({.z = 23, .a = 48, .meanlife = 23.0442 * DAY}); - nuclides.back().endecay_positron = 0.290 * MEV * 0.499; - nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 1.; + // if requested nuclide is not in network then match daughter of last nucleus in chain + if (!nuc_exists_z_a && !nuc_is_parent(z_end, a_end, z, a)) { + continue; + } + } - // Co57 - nuclides.push_back({.z = 27, .a = 57, .meanlife = 392.03 * DAY}); - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + const int z_top = decaypath.z[0]; + const int a_top = decaypath.a[0]; + const int nucindex_top = decaypath.nucindex[0]; - // Fe52 - nuclides.push_back({.z = 26, .a = 52, .meanlife = 0.497429 * DAY}); - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); + assert_always(top_initabund >= 0.); + if (top_initabund <= 0.) { + continue; + } - // Mn52 - nuclides.push_back({.z = 25, .a = 52, .meanlife = 0.0211395 * DAY}); - nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; - - auto standard_nuclides = nuclides; - - // any nuclides in the custom list that are not in the standard list need beta and alpha decay data - - bool use_custom_nuclides = false; - for (size_t i = 0; i < custom_zlist.size(); i++) { - if (custom_zlist[i] < 0 || custom_alist[i] < 0) { - continue; - } - const bool in_std_list = std::ranges::any_of(standard_nuclides, [=](const auto &stdnuc) { - return (custom_zlist[i] == stdnuc.z) && (custom_alist[i] == stdnuc.a); - }); - if (!in_std_list) { - use_custom_nuclides = true; - break; - } - } - - if (use_custom_nuclides) { - auto fbetaminus = fstream_required("betaminusdecays.txt", std::ios::in); - assert_always(fbetaminus.is_open()); - std::string line; - while (get_noncommentline(fbetaminus, line)) { - // energies are average per beta decay - // columns: # A, Z, Q[MeV], E_gamma[MeV], E_elec[MeV], E_neutrino[MeV], meanlife[s] - int a = -1; - int z = -1; - double q_mev = 0.; - double e_gamma_mev = 0.; - double e_elec_mev = 0.; - double e_neutrino = 0.; - double tau_sec = 0.; - std::stringstream(line) >> a >> z >> q_mev >> e_gamma_mev >> e_elec_mev >> e_neutrino >> tau_sec; - - assert_always(!nuc_exists(z, a)); - nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec}); - nuclides.back().branchprobs[DECAYTYPE_BETAMINUS] = 1.; - nuclides.back().endecay_q[DECAYTYPE_BETAMINUS] = q_mev * MEV; - nuclides.back().endecay_electron = e_elec_mev * MEV; - nuclides.back().endecay_gamma = e_gamma_mev * MEV; - assert_always(e_elec_mev >= 0.); - } - - auto falpha = fstream_required("alphadecays.txt", std::ios::in); - assert_always(falpha.is_open()); - while (get_noncommentline(falpha, line)) { - // columns: # A, Z, branch_alpha, branch_beta, halflife[s], Q_total_alphadec[MeV], Q_total_betadec[MeV], - // E_alpha[MeV], E_gamma[MeV], E_beta[MeV] - int a = -1; - int z = -1; - double branch_alpha = 0.; - double branch_beta = 0.; - double halflife = 0.; - double Q_total_alphadec = 0.; - double Q_total_betadec = 0.; - double e_alpha_mev = 0.; - double e_gamma_mev = 0.; - double e_beta_mev = 0.; - std::stringstream(line) >> a >> z >> branch_alpha >> branch_beta >> halflife >> Q_total_alphadec >> - Q_total_betadec >> e_alpha_mev >> e_gamma_mev >> e_beta_mev; - - const bool keeprow = ((branch_alpha > 0. || branch_beta > 0.) && halflife > 0.); - if (keeprow) { - const double tau_sec = halflife / std::numbers::ln2; - int alphanucindex = -1; - if (nuc_exists(z, a)) { - alphanucindex = get_nucindex(z, a); - } else { - nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec, .endecay_gamma = e_gamma_mev * MEV}); - alphanucindex = static_cast(nuclides.size() - 1); - } - nuclides[alphanucindex].endecay_alpha = e_alpha_mev * MEV; - nuclides[alphanucindex].branchprobs[DECAYTYPE_BETAMINUS] = branch_beta; - nuclides[alphanucindex].endecay_q[DECAYTYPE_BETAMINUS] = Q_total_betadec * MEV; - nuclides[alphanucindex].branchprobs[DECAYTYPE_ALPHA] = branch_alpha; - nuclides[alphanucindex].endecay_q[DECAYTYPE_ALPHA] = Q_total_alphadec * MEV; - - // printout("alphadecay file: Adding (Z=%d)%s%d endecay_alpha %g endecay_gamma %g tau_s %g\n", - // z, get_elname(z), a, e_alpha_mev, e_gamma_mev, tau_sec); - } - } - } - - // add any extra nuclides that were specified but not in the decay data files - for (int i = 0; i < static_cast(custom_alist.size()); i++) { - const int z = custom_zlist[i]; - const int a = custom_alist[i]; - if (!nuc_exists(z, a)) { - // printout("Adding Z %d A %d with no decay data (assuming stable)\n", z, a); - nuclides.push_back({.z = z, .a = a, .meanlife = -1}); - } - } - - printout("Number of nuclides before filtering: %d\n", get_num_nuclides()); - find_decaypaths(custom_zlist, custom_alist, standard_nuclides); - filter_unused_nuclides(custom_zlist, custom_alist, standard_nuclides); - - printout("Number of nuclides: %d\n", get_num_nuclides()); - - const int maxdecaypathlength = std::accumulate( - decaypaths.cbegin(), decaypaths.cend(), 0, - [](const int maxlen, const auto &decaypath) { return std::max(maxlen, get_decaypathlength(decaypath)); }); - - printout("Number of decay paths: %d (max length %d)\n", get_num_decaypaths(), maxdecaypathlength); - - /// Read in data for gamma ray lines and make a list of them in energy order. - gammapkt::init_gamma_data(); - - // TODO: generalise this to all included nuclides - printout("decayenergy(NI56), decayenergy(CO56), decayenergy_gamma(CO56): %g, %g, %g\n", - nucdecayenergytotal(28, 56) / MEV, nucdecayenergytotal(27, 56) / MEV, nucdecayenergygamma(27, 56) / MEV); - printout("decayenergy(NI57), decayenergy_gamma(NI57), nucdecayenergy(CO57): %g, %g, %g\n", - nucdecayenergytotal(28, 57) / MEV, nucdecayenergygamma(28, 57) / MEV, nucdecayenergytotal(27, 57) / MEV); - printout("decayenergy(CR48), decayenergy(V48): %g %g\n", nucdecayenergytotal(24, 48) / MEV, - nucdecayenergytotal(23, 48) / MEV); - printout("decayenergy(FE52), decayenergy(MN52): %g %g\n", nucdecayenergytotal(26, 52) / MEV, - nucdecayenergytotal(25, 52) / MEV); -} - -static auto sample_decaytime(const int decaypathindex, const double tdecaymin, const double tdecaymax) -> double { - double tdecay = -1; - const double t_model = grid::get_t_model(); - // rejection method. draw random times until they are within the correct range. - while (tdecay <= tdecaymin || tdecay >= tdecaymax) { - tdecay = t_model; // can't decay before initial model snapshot time - - const auto decaypathlength = get_decaypathlength(decaypathindex); - for (int i = 0; i < decaypathlength; i++) { - const int nucindex = decaypaths[decaypathindex].nucindex[i]; - const double zrand = rng_uniform_pos(); - tdecay += -get_meanlife(nucindex) * log(zrand); - } - } - return tdecay; -} - -static constexpr auto calculate_decaychain(const double firstinitabund, const std::vector &lambdas, - const int num_nuclides, const double timediff, - const bool useexpansionfactor) -> double { - // calculate final number abundance from multiple decays, e.g., Ni56 -> Co56 -> Fe56 (nuc[0] -> nuc[1] -> nuc[2]) - // the top nuclide initial abundance is set and the chain-end abundance is returned (all intermediates nuclides - // are assumed to start with zero abundance) - // note: first and last can be nuclide can be the same if num_nuclides==1, reducing to simple decay formula - // - // timediff: time elapsed since firstinitabund was true [seconds] - // numnuclides: number of items in lambdas to use - // lambdas: array of 1/(mean lifetime) for nuc[0]..nuc[num_nuclides-1] [seconds^-1] - // useexpansionfactor: if true, return a modified 'abundance' at the end of the chain, with a weighting factor - // accounting for photon energy loss from expansion since the decays occured - // (This is needed to get the initial temperature) - - assert_always(num_nuclides >= 1); - - double lambdaproduct = 1.; - for (int j = 0; j < num_nuclides - 1; j++) { - lambdaproduct *= lambdas[j]; - } - - double sum = 0; - for (int j = 0; j < num_nuclides; j++) { - double denominator = 1.; - for (int p = 0; p < num_nuclides; p++) { - if (p != j) { - denominator *= (lambdas[p] - lambdas[j]); - } - } - - if (!useexpansionfactor) // abundance output - { - sum += exp(-lambdas[j] * timediff) / denominator; - } else { - if (lambdas[j] > 0.) { - const double sumtermtop = - ((1 + 1 / lambdas[j] / timediff) * exp(-timediff * lambdas[j])) - (1. / lambdas[j] / timediff); - sum += sumtermtop / denominator; - } - } - } - - const double lastabund = firstinitabund * lambdaproduct * sum; - - return lastabund; -} - -static auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const double time) -> double -// Get the mass fraction of a nuclide accounting for all decays including those of its parent and grandparent. -// e.g., Co56 abundance may first increase with time due to Ni56 decays, then decease due to Co56 decay -// Can be called for stable nuclides that are one daughters of the radioactive nuclide list e.g., Fe56 -// For stable nuclides, abundance returned only comes from other decays (some could be included in init model elem frac) -{ - assert_always(time >= 0.); - - const double t_afterinit = time - grid::get_t_model(); - const int nucindex = get_nucindex_or_neg_one(z, a); - const bool nuc_exists_z_a = (nucindex >= 0); - - // decay chains include all paths from radionuclides to other radionuclides (including trivial size-one chains) - - double nuctotal = 0.; // abundance or decay rate, depending on mode parameter - for (const auto &decaypath : decaypaths) { - const int z_end = decaypath.z.back(); - const int a_end = decaypath.a.back(); - - // match 4He abundance to alpha decay of any nucleus (no continue), otherwise check daughter nuclide matches - if (z != 2 || a != 4 || decaypath.decaytypes.back() != decaytypes::DECAYTYPE_ALPHA) { - if (nuc_exists_z_a && (z_end != z || a_end != a)) // requested nuclide is in network, so match last nuc in chain - { - continue; - } - - // if requested nuclide is not in network then match daughter of last nucleus in chain - if (!nuc_exists_z_a && !nuc_is_parent(z_end, a_end, z, a)) { - continue; - } - } - - const int z_top = decaypath.z[0]; - const int a_top = decaypath.a[0]; - const int nucindex_top = decaypath.nucindex[0]; - - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); - assert_always(top_initabund >= 0.); - if (top_initabund <= 0.) { - continue; - } - - const int decaypathlength = get_decaypathlength(decaypath); + const int decaypathlength = get_decaypathlength(decaypath); int fulldecaypathlength = decaypathlength; // if the nuclide is out of network, it's one past the end of the chain @@ -891,8 +622,8 @@ static auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, return nuctotal; } -static auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const int decaypathindex, - const double time) -> double +auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const int decaypathindex, + const double time) -> double // returns decay energy [erg/g] that would be released from time tstart [s] to time infinity by a given decaypath { // e.g. Ni56 -> Co56, represents the decay of Co56 nuclei @@ -928,9 +659,9 @@ static auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, return endecay; } -static auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, - const int decaypathindex, - const double tstart) -> double +auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, + const int decaypathindex, + const double tstart) -> double // just here as as check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() // this version does an Euler integration { @@ -971,33 +702,8 @@ static auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical( return chain_endecay; } -auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridindex, const double tstart) -> double -// calculate the decay energy per unit mass [erg/g] released from time t_model to tstart, accounting for -// the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) -{ - double tot_endecay = 0.; - for (const auto &decaypath : decaypaths) { - const int decaypathlength = get_decaypathlength(decaypath); - - const int z_top = decaypath.z[0]; - const int a_top = decaypath.a[0]; - const int nucindex_top = decaypath.nucindex[0]; - - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); - - const double chain_endecay = (decaypath.branchproduct * - calculate_decaychain(top_initabund, decaypath.lambdas, decaypathlength + 1, - tstart - grid::get_t_model(), true) * - get_decaypath_lastnucdecayenergy(decaypath)); - - tot_endecay += chain_endecay; - } - - return tot_endecay; -} - -static auto get_endecay_per_ejectamass_between_times(const int mgi, const int decaypathindex, double tlow, - double thigh) -> double +auto get_endecay_per_ejectamass_between_times(const int mgi, const int decaypathindex, const double tlow, + const double thigh) -> double // get decay energy per mass [erg/g] released by a decaypath between times tlow [s] and thigh [s] { assert_always(tlow <= thigh); @@ -1009,7 +715,7 @@ static auto get_endecay_per_ejectamass_between_times(const int mgi, const int de return endiff; } -static auto calculate_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double +auto calculate_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double // calculate the decay energy released during the simulation time per unit mass [erg/g] { assert_testmodeonly(mgi < grid::get_npts_model()); @@ -1023,7 +729,7 @@ static auto calculate_simtime_endecay_per_ejectamass(const int mgi, const int de } } -static auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double +auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double // get the decay energy released during the simulation time per unit mass [erg/g] { const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); @@ -1033,8 +739,7 @@ static auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypat return chainendecay; } -static auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int modelgridindex, - const double time) -> double +auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int modelgridindex, const double time) -> double // total decay power per mass [erg/s/g] for a given decaypath { // only decays at the end of the chain contributed from the initial abundance of the top of the chain are counted @@ -1071,6 +776,286 @@ static auto get_decaypath_power_per_ejectamass(const int decaypathindex, const i return decaypower; } +} // anonymous namespace + +[[nodiscard]] auto get_num_nuclides() -> int { return static_cast(nuclides.size()); } + +[[nodiscard]] auto get_elname(const int z) -> std::string { + assert_testmodeonly(z <= Z_MAX); + return std::string(elsymbols[z]); +} + +[[nodiscard]] auto get_nuc_z(const int nucindex) -> int { + assert_testmodeonly(nucindex >= 0); + assert_testmodeonly(nucindex < get_num_nuclides()); + return nuclides[nucindex].z; +} + +[[nodiscard]] auto get_nuc_a(const int nucindex) -> int { + assert_testmodeonly(nucindex >= 0); + assert_testmodeonly(nucindex < get_num_nuclides()); + return nuclides[nucindex].a; +} + +[[nodiscard]] auto get_nucindex(const int z, const int a) -> int +// get the nuclide array index from the atomic number and mass number +{ + const int nucindex = get_nucindex_or_neg_one(z, a); + if (nucindex >= 0) { + return nucindex; + } + printout("Could not find nuclide Z=%d A=%d\n", z, a); + assert_always(false); // nuclide not found + return -1; +} + +[[nodiscard]] auto nuc_exists(const int z, const int a) -> bool +// check if nuclide exists in the simulation +{ + for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) { + if (nuclides[nucindex].z == z && nuclides[nucindex].a == a) { + return true; + } + } + return false; +} + +[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(const int nucindex) -> double +// average energy per decay in the form of gamma rays [erg] +{ + return nuclides[nucindex].endecay_gamma; +} + +[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(const int z, const int a) -> double { + return nucdecayenergygamma(get_nucindex(z, a)); +} + +void set_nucdecayenergygamma(const int nucindex, const double value) +// set average energy per decay in the form of gamma rays [erg] +{ + nuclides[nucindex].endecay_gamma = value; +} + +auto get_nucstring_z(const std::string &strnuc) -> int +// convert something like Ni56 to integer 28 +{ + std::string elcode = strnuc; + std::erase_if(elcode, &isdigit); + + for (int z = 0; z <= Z_MAX; z++) { + if (elcode == get_elname(z)) { + return z; + } + } + printout("Could not get atomic number of '%s' '%s'\n", strnuc.c_str(), elcode.c_str()); + assert_always(false); // could not match to an element + return -1; +} + +auto get_nucstring_a(const std::string &strnuc) -> int +// convert something like Ni56 to integer 56 +{ + // find first digit character + size_t i = 0; + for (; i < strnuc.length(); i++) { + if (isdigit(strnuc[i]) != 0) { + break; + } + } + + // remove the non-digit charts + const std::string strmassnum = strnuc.substr(i); + + const int a = std::atoi(strmassnum.c_str()); + assert_always(a > 0); + return a; +} + +void init_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist) { + // add all nuclides and decays, and later trim any irrelevant ones (not connected to input-specified nuclei) later + + assert_always(custom_zlist.size() == custom_alist.size()); + + // Ni57 + nuclides.push_back({.z = 28, .a = 57, .meanlife = 51.36 * 60}); + nuclides.back().endecay_positron = 0.354 * MEV; + nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 0.436; + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1. - 0.436; + + // Ni56 + nuclides.push_back({.z = 28, .a = 56, .meanlife = 8.80 * DAY}); + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + + // Co56 + nuclides.push_back({.z = 27, .a = 56, .meanlife = 113.7 * DAY}); + nuclides.back().endecay_positron = 0.63 * MEV; + nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 0.19; + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1 - 0.19; + + // Cr48 + nuclides.push_back({.z = 24, .a = 48, .meanlife = 1.29602 * DAY}); + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + + // V48 + nuclides.push_back({.z = 23, .a = 48, .meanlife = 23.0442 * DAY}); + nuclides.back().endecay_positron = 0.290 * MEV * 0.499; + nuclides.back().branchprobs[DECAYTYPE_BETAPLUS] = 1.; + + // Co57 + nuclides.push_back({.z = 27, .a = 57, .meanlife = 392.03 * DAY}); + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + + // Fe52 + nuclides.push_back({.z = 26, .a = 52, .meanlife = 0.497429 * DAY}); + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + + // Mn52 + nuclides.push_back({.z = 25, .a = 52, .meanlife = 0.0211395 * DAY}); + nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; + + auto standard_nuclides = nuclides; + + // any nuclides in the custom list that are not in the standard list need beta and alpha decay data + + bool use_custom_nuclides = false; + for (size_t i = 0; i < custom_zlist.size(); i++) { + if (custom_zlist[i] < 0 || custom_alist[i] < 0) { + continue; + } + const bool in_std_list = std::ranges::any_of(standard_nuclides, [=](const auto &stdnuc) { + return (custom_zlist[i] == stdnuc.z) && (custom_alist[i] == stdnuc.a); + }); + if (!in_std_list) { + use_custom_nuclides = true; + break; + } + } + + if (use_custom_nuclides) { + auto fbetaminus = fstream_required("betaminusdecays.txt", std::ios::in); + assert_always(fbetaminus.is_open()); + std::string line; + while (get_noncommentline(fbetaminus, line)) { + // energies are average per beta decay + // columns: # A, Z, Q[MeV], E_gamma[MeV], E_elec[MeV], E_neutrino[MeV], meanlife[s] + int a = -1; + int z = -1; + double q_mev = 0.; + double e_gamma_mev = 0.; + double e_elec_mev = 0.; + double e_neutrino = 0.; + double tau_sec = 0.; + std::stringstream(line) >> a >> z >> q_mev >> e_gamma_mev >> e_elec_mev >> e_neutrino >> tau_sec; + + assert_always(!nuc_exists(z, a)); + nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec}); + nuclides.back().branchprobs[DECAYTYPE_BETAMINUS] = 1.; + nuclides.back().endecay_q[DECAYTYPE_BETAMINUS] = q_mev * MEV; + nuclides.back().endecay_electron = e_elec_mev * MEV; + nuclides.back().endecay_gamma = e_gamma_mev * MEV; + assert_always(e_elec_mev >= 0.); + } + + auto falpha = fstream_required("alphadecays.txt", std::ios::in); + assert_always(falpha.is_open()); + while (get_noncommentline(falpha, line)) { + // columns: # A, Z, branch_alpha, branch_beta, halflife[s], Q_total_alphadec[MeV], Q_total_betadec[MeV], + // E_alpha[MeV], E_gamma[MeV], E_beta[MeV] + int a = -1; + int z = -1; + double branch_alpha = 0.; + double branch_beta = 0.; + double halflife = 0.; + double Q_total_alphadec = 0.; + double Q_total_betadec = 0.; + double e_alpha_mev = 0.; + double e_gamma_mev = 0.; + double e_beta_mev = 0.; + std::stringstream(line) >> a >> z >> branch_alpha >> branch_beta >> halflife >> Q_total_alphadec >> + Q_total_betadec >> e_alpha_mev >> e_gamma_mev >> e_beta_mev; + + const bool keeprow = ((branch_alpha > 0. || branch_beta > 0.) && halflife > 0.); + if (keeprow) { + const double tau_sec = halflife / std::numbers::ln2; + int alphanucindex = -1; + if (nuc_exists(z, a)) { + alphanucindex = get_nucindex(z, a); + } else { + nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec, .endecay_gamma = e_gamma_mev * MEV}); + alphanucindex = static_cast(nuclides.size() - 1); + } + nuclides[alphanucindex].endecay_alpha = e_alpha_mev * MEV; + nuclides[alphanucindex].branchprobs[DECAYTYPE_BETAMINUS] = branch_beta; + nuclides[alphanucindex].endecay_q[DECAYTYPE_BETAMINUS] = Q_total_betadec * MEV; + nuclides[alphanucindex].branchprobs[DECAYTYPE_ALPHA] = branch_alpha; + nuclides[alphanucindex].endecay_q[DECAYTYPE_ALPHA] = Q_total_alphadec * MEV; + + // printout("alphadecay file: Adding (Z=%d)%s%d endecay_alpha %g endecay_gamma %g tau_s %g\n", + // z, get_elname(z), a, e_alpha_mev, e_gamma_mev, tau_sec); + } + } + } + + // add any extra nuclides that were specified but not in the decay data files + for (int i = 0; i < static_cast(custom_alist.size()); i++) { + const int z = custom_zlist[i]; + const int a = custom_alist[i]; + if (!nuc_exists(z, a)) { + // printout("Adding Z %d A %d with no decay data (assuming stable)\n", z, a); + nuclides.push_back({.z = z, .a = a, .meanlife = -1}); + } + } + + printout("Number of nuclides before filtering: %d\n", get_num_nuclides()); + find_decaypaths(custom_zlist, custom_alist, standard_nuclides); + filter_unused_nuclides(custom_zlist, custom_alist, standard_nuclides); + + printout("Number of nuclides: %d\n", get_num_nuclides()); + + const int maxdecaypathlength = std::accumulate( + decaypaths.cbegin(), decaypaths.cend(), 0, + [](const int maxlen, const auto &decaypath) { return std::max(maxlen, get_decaypathlength(decaypath)); }); + + printout("Number of decay paths: %d (max length %d)\n", get_num_decaypaths(), maxdecaypathlength); + + /// Read in data for gamma ray lines and make a list of them in energy order. + gammapkt::init_gamma_data(); + + // TODO: generalise this to all included nuclides + printout("decayenergy(NI56), decayenergy(CO56), decayenergy_gamma(CO56): %g, %g, %g\n", + nucdecayenergytotal(28, 56) / MEV, nucdecayenergytotal(27, 56) / MEV, nucdecayenergygamma(27, 56) / MEV); + printout("decayenergy(NI57), decayenergy_gamma(NI57), nucdecayenergy(CO57): %g, %g, %g\n", + nucdecayenergytotal(28, 57) / MEV, nucdecayenergygamma(28, 57) / MEV, nucdecayenergytotal(27, 57) / MEV); + printout("decayenergy(CR48), decayenergy(V48): %g %g\n", nucdecayenergytotal(24, 48) / MEV, + nucdecayenergytotal(23, 48) / MEV); + printout("decayenergy(FE52), decayenergy(MN52): %g %g\n", nucdecayenergytotal(26, 52) / MEV, + nucdecayenergytotal(25, 52) / MEV); +} + +auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridindex, const double tstart) -> double +// calculate the decay energy per unit mass [erg/g] released from time t_model to tstart, accounting for +// the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) +{ + double tot_endecay = 0.; + for (const auto &decaypath : decaypaths) { + const int decaypathlength = get_decaypathlength(decaypath); + + const int z_top = decaypath.z[0]; + const int a_top = decaypath.a[0]; + const int nucindex_top = decaypath.nucindex[0]; + + const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); + + const double chain_endecay = (decaypath.branchproduct * + calculate_decaychain(top_initabund, decaypath.lambdas, decaypathlength + 1, + tstart - grid::get_t_model(), true) * + get_decaypath_lastnucdecayenergy(decaypath)); + + tot_endecay += chain_endecay; + } + + return tot_endecay; +} auto get_modelcell_simtime_endecay_per_mass(const int mgi) -> double // get the density at time tmin of decay energy that will @@ -1418,7 +1403,7 @@ void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { // first decaychannelindex such that cumulative_en_sum[decaychannelindex] > zrand_en const int decaychannelindex = - std::upper_bound(cumulative_en_sum.cbegin(), cumulative_en_sum.cend(), zrand_en) - cumulative_en_sum.cbegin(); + static_cast(std::ranges::upper_bound(cumulative_en_sum, zrand_en) - cumulative_en_sum.cbegin()); assert_always(decaychannelindex >= 0); assert_always(decaychannelindex < num_decaychannels); diff --git a/gammapkt.cc b/gammapkt.cc index 4966cc9cd..e2b6f9a3f 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -29,45 +29,32 @@ namespace gammapkt { // Code for handing gamma rays - creation and propagation +namespace { struct GammaLine { double energy{}; // in erg double probability{}; }; -static std::vector> gamma_spectra; +std::vector> gamma_spectra; struct el_photoion_data { double energy; // energy in MeV double sigma_xcom; // cross section in barns/atom }; -static constexpr int numb_xcom_elements = USE_XCOM_GAMMAPHOTOION ? 100 : 0; +constexpr int numb_xcom_elements = USE_XCOM_GAMMAPHOTOION ? 100 : 0; -static std::array, numb_xcom_elements> photoion_data; +std::array, numb_xcom_elements> photoion_data; struct NucGammaLine { int nucindex; // is it a Ni56, Co56, a fake line, etc int nucgammaindex; // which of the lines of that nuclide is it double energy; // in erg - - auto operator<(const NucGammaLine &g2) const -> bool { - // true if d1 < d2 - if (energy < g2.energy) { - return true; - } - if (energy == g2.energy && nucindex < g2.nucindex) { - return true; - } - if (energy == g2.energy && nucindex == g2.nucindex && nucgammaindex < g2.nucgammaindex) { - return true; - } - return false; - } }; -static std::vector allnuc_gamma_line_list; +std::vector allnuc_gamma_line_list; -static void read_gamma_spectrum(const int nucindex, const char filename[50]) +void read_gamma_spectrum(const int nucindex, const char filename[50]) // reads in gamma_spectra and returns the average energy in gamma rays per nuclear decay { printout("reading gamma spectrum for Z=%d A=%d from %s...", decay::get_nuc_z(nucindex), decay::get_nuc_a(nucindex), @@ -95,7 +82,7 @@ static void read_gamma_spectrum(const int nucindex, const char filename[50]) printout("nlines %d avg_en_gamma %g MeV\n", nlines, E_gamma_avg / MEV); } -static void set_trivial_gamma_spectrum(const int nucindex) { +void set_trivial_gamma_spectrum(const int nucindex) { // printout("Setting trivial gamma spectrum for z %d a %d engamma %g\n", z, a, decay::nucdecayenergygamma(z, a)); const int nlines = 1; gamma_spectra[nucindex].resize(nlines); @@ -103,7 +90,7 @@ static void set_trivial_gamma_spectrum(const int nucindex) { gamma_spectra[nucindex][0].probability = 1.; } -static void read_decaydata() { +void read_decaydata() { // migrate from old filename if (!std::filesystem::exists("ni56_lines.txt") && std::filesystem::exists("ni_lines.txt")) { printout("Moving ni_lines.txt to ni56_lines.txt\n"); @@ -166,7 +153,7 @@ static void read_decaydata() { } // construct an energy ordered gamma ray line list. -static void init_gamma_linelist() { +void init_gamma_linelist() { read_decaydata(); // Now do the sorting. @@ -188,7 +175,19 @@ static void init_gamma_linelist() { } allnuc_gamma_line_list.shrink_to_fit(); assert_always(static_cast(allnuc_gamma_line_list.size()) == total_lines); - std::stable_sort(allnuc_gamma_line_list.begin(), allnuc_gamma_line_list.end()); + std::ranges::stable_sort(allnuc_gamma_line_list, [](const NucGammaLine &g1, const NucGammaLine &g2) { + // true if d1 < d2 + if (g1.energy < g2.energy) { + return true; + } + if (g1.energy == g2.energy && g1.nucindex < g2.nucindex) { + return true; + } + if (g1.energy == g2.energy && g1.nucindex == g2.nucindex && g1.nucgammaindex < g2.nucgammaindex) { + return true; + } + return false; + }); FILE *const line_list = fopen_required("gammalinelist.out", "w"); @@ -204,7 +203,7 @@ static void init_gamma_linelist() { fclose(line_list); } -static void init_xcom_photoion_data() { +void init_xcom_photoion_data() { // read the file printout("reading XCOM photoionization data...\n"); // reserve memory @@ -234,14 +233,7 @@ static void init_xcom_photoion_data() { } } -void init_gamma_data() { - init_gamma_linelist(); - if constexpr (USE_XCOM_GAMMAPHOTOION) { - init_xcom_photoion_data(); - } -} - -__host__ __device__ static auto choose_gamma_ray(const int nucindex) -> double { +__host__ __device__ auto choose_gamma_ray(const int nucindex) -> double { // Routine to choose which gamma ray line it'll be. const double E_gamma = decay::nucdecayenergygamma(nucindex); // Average energy per gamma line of a decay @@ -259,67 +251,7 @@ __host__ __device__ static auto choose_gamma_ray(const int nucindex) -> double { assert_always(false); } -__host__ __device__ void pellet_gamma_decay(Packet &pkt) { - // Subroutine to convert a pellet to a gamma ray (or kpkt if no gamma spec loaded) - - // pkt is a pointer to the packet that is decaying. - - // Start by getting the position of the pellet at the point of decay. Pellet - // is moving with the matter. - - // if no gamma spectra is known, then covert straight to kpkts (e.g., Fe52, Mn52) - if (gamma_spectra[pkt.pellet_nucindex].empty()) { - pkt.type = TYPE_KPKT; - pkt.absorptiontype = -6; - return; - } - - // Now let's give the gamma ray a direction. - // Assuming isotropic emission in cmf - - const auto dir_cmf = get_rand_isotropic_unitvec(); - - // This direction is in the cmf - we want to convert it to the rest - // frame - use aberation of angles. We want to convert from cmf to - // rest so need -ve velocity. - - const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.tdecay); - // negative time since we want the backwards transformation here - - pkt.dir = angle_ab(dir_cmf, vel_vec); - - // Now need to assign the frequency of the packet in the co-moving frame. - - pkt.nu_cmf = choose_gamma_ray(pkt.pellet_nucindex); - - // Finally we want to put in the rest frame energy and frequency. And record - // that it's now a gamma ray. - - pkt.prop_time = pkt.tdecay; - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); - pkt.nu_rf = pkt.nu_cmf / dopplerfactor; - pkt.e_rf = pkt.e_cmf / dopplerfactor; - - pkt.type = TYPE_GAMMA; - pkt.last_cross = BOUNDARY_NONE; - - // initialise polarisation information - pkt.stokes[0] = 1.; - pkt.stokes[1] = 0.; - pkt.stokes[2] = 0.; - - pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); - if ((dot(pkt.pol_dir, pkt.pol_dir)) < 1.e-8) { - pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 1., 0.}); - } - - pkt.pol_dir = vec_norm(pkt.pol_dir); - // printout("initialise pol state of packet %g, %g, %g, %g, - // %g\n",pkt.stokes_qu[0],pkt.stokes_qu[1],pkt.pol_dir[0],pkt.pol_dir[1],pkt.pol_dir[2]); - // printout("pkt direction %g, %g, %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); -} - -constexpr static auto sigma_compton_partial(const double x, const double f_max) -> double +constexpr auto sigma_compton_partial(const double x, const double f_max) -> double // Routine to compute the partial cross section for Compton scattering. // xx is the photon energy (in units of electron mass) and f // is the energy loss factor up to which we wish to integrate. @@ -331,7 +263,7 @@ constexpr static auto sigma_compton_partial(const double x, const double f_max) return (3 * SIGMA_T * (term1 + term2 + term3) / (8 * x)); } -static auto get_chi_compton_rf(const Packet &pkt) -> double { +auto get_chi_compton_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for Compton scattering in the observer reference frame // Start by working out the compton x-section in the co-moving frame. @@ -352,7 +284,7 @@ static auto get_chi_compton_rf(const Packet &pkt) -> double { return chi_rf; } -static auto choose_f(const double xx, const double zrand) -> double +auto choose_f(const double xx, const double zrand) -> double // To choose the value of f to integrate to - idea is we want // sigma_compton_partial(xx,f) = zrand. { @@ -388,7 +320,7 @@ static auto choose_f(const double xx, const double zrand) -> double return ftry; } -static auto thomson_angle() -> double { +auto thomson_angle() -> double { // For Thomson scattering we can get the new angle from a random number very easily. const double B_coeff = (8. * rng_uniform()) - 4.; @@ -408,8 +340,7 @@ static auto thomson_angle() -> double { return mu; } -[[nodiscard]] static auto scatter_dir(const std::array dir_in, - const double cos_theta) -> std::array +[[nodiscard]] auto scatter_dir(const std::array dir_in, const double cos_theta) -> std::array // Routine for scattering a direction through angle theta. { // begin with setting the direction in coordinates where original direction @@ -448,7 +379,7 @@ static auto thomson_angle() -> double { return dir_out; } -static void compton_scatter(Packet &pkt) +void compton_scatter(Packet &pkt) // Routine to deal with physical Compton scattering event. { // printout("Compton scattering.\n"); @@ -545,7 +476,7 @@ static void compton_scatter(Packet &pkt) } } -static auto get_chi_photo_electric_rf(const Packet &pkt) -> double { +auto get_chi_photo_electric_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for photo electric effect scattering in the observer reference frame double chi_cmf{NAN}; @@ -643,7 +574,7 @@ static auto get_chi_photo_electric_rf(const Packet &pkt) -> double { return chi_rf; } -static auto sigma_pair_prod_rf(const Packet &pkt) -> double { +auto sigma_pair_prod_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame const int mgi = grid::get_cell_modelgridindex(pkt.where); @@ -706,7 +637,7 @@ static auto sigma_pair_prod_rf(const Packet &pkt) -> double { return chi_rf; } -constexpr static auto meanf_sigma(const double x) -> double +constexpr auto meanf_sigma(const double x) -> double // Routine to compute the mean energy converted to non-thermal electrons times // the Klein-Nishina cross section. { @@ -723,7 +654,7 @@ constexpr static auto meanf_sigma(const double x) -> double return tot; } -static void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const int nonemptymgi) { +void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const int nonemptymgi) { // Subroutine to record the heating rate in a cell due to gamma rays. // By heating rate I mean, for now, really the rate at which the code is making // k-packets in that cell which will then convert into r-packets. This is (going @@ -757,7 +688,7 @@ static void update_gamma_dep(const Packet &pkt, const double dist, const int mgi atomicadd(globals::dep_estimator_gamma[nonemptymgi], heating_cont); } -static void pair_prod(Packet &pkt) { +void pair_prod(Packet &pkt) { // Routine to deal with pair production. // In pair production, the original gamma makes an electron positron pair - kinetic energy equal to @@ -805,7 +736,7 @@ static void pair_prod(Packet &pkt) { } } -static void transport_gamma(Packet &pkt, double t2) +void transport_gamma(Packet &pkt, const double t2) // Now routine for moving a gamma packet. Idea is that we have as input // a gamma packet with known properties at time t1 and we want to follow it // until time t2. @@ -951,7 +882,7 @@ static void transport_gamma(Packet &pkt, double t2) } } -static void barnes_thermalisation(Packet &pkt) +void barnes_thermalisation(Packet &pkt) // Barnes treatment: packet is either getting absorbed immediately and locally // creating a k-packet or it escapes. The absorption probability matches the // Barnes thermalization efficiency, for expressions see the original paper: @@ -986,7 +917,7 @@ static void barnes_thermalisation(Packet &pkt) } } -static void wollaeger_thermalisation(Packet &pkt) { +void wollaeger_thermalisation(Packet &pkt) { // corresponds to a local version of the Barnes scheme, i.e. it takes into account the local mass // density rather than a value averaged over the ejecta constexpr double mean_gamma_opac = 0.1; @@ -1029,7 +960,7 @@ static void wollaeger_thermalisation(Packet &pkt) { } } -static void guttman_thermalisation(Packet &pkt) { +void guttman_thermalisation(Packet &pkt) { // Guttman+2024, arXiv:2403.08769v1 // extension of the Wollaeger scheme. Rather than calculating a single optical depth in radial outward // direction, it calculates a spherical average in all possible gamma-ray emission directions. @@ -1105,7 +1036,76 @@ static void guttman_thermalisation(Packet &pkt) { } } -__host__ __device__ void do_gamma(Packet &pkt, const int nts, double t2) { +} // anonymous namespace + +void init_gamma_data() { + init_gamma_linelist(); + if constexpr (USE_XCOM_GAMMAPHOTOION) { + init_xcom_photoion_data(); + } +} + +__host__ __device__ void pellet_gamma_decay(Packet &pkt) { + // Subroutine to convert a pellet to a gamma ray (or kpkt if no gamma spec loaded) + + // pkt is a pointer to the packet that is decaying. + + // Start by getting the position of the pellet at the point of decay. Pellet + // is moving with the matter. + + // if no gamma spectra is known, then covert straight to kpkts (e.g., Fe52, Mn52) + if (gamma_spectra[pkt.pellet_nucindex].empty()) { + pkt.type = TYPE_KPKT; + pkt.absorptiontype = -6; + return; + } + + // Now let's give the gamma ray a direction. + // Assuming isotropic emission in cmf + + const auto dir_cmf = get_rand_isotropic_unitvec(); + + // This direction is in the cmf - we want to convert it to the rest + // frame - use aberation of angles. We want to convert from cmf to + // rest so need -ve velocity. + + const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.tdecay); + // negative time since we want the backwards transformation here + + pkt.dir = angle_ab(dir_cmf, vel_vec); + + // Now need to assign the frequency of the packet in the co-moving frame. + + pkt.nu_cmf = choose_gamma_ray(pkt.pellet_nucindex); + + // Finally we want to put in the rest frame energy and frequency. And record + // that it's now a gamma ray. + + pkt.prop_time = pkt.tdecay; + const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + pkt.nu_rf = pkt.nu_cmf / dopplerfactor; + pkt.e_rf = pkt.e_cmf / dopplerfactor; + + pkt.type = TYPE_GAMMA; + pkt.last_cross = BOUNDARY_NONE; + + // initialise polarisation information + pkt.stokes[0] = 1.; + pkt.stokes[1] = 0.; + pkt.stokes[2] = 0.; + + pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); + if ((dot(pkt.pol_dir, pkt.pol_dir)) < 1.e-8) { + pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 1., 0.}); + } + + pkt.pol_dir = vec_norm(pkt.pol_dir); + // printout("initialise pol state of packet %g, %g, %g, %g, + // %g\n",pkt.stokes_qu[0],pkt.stokes_qu[1],pkt.pol_dir[0],pkt.pol_dir[1],pkt.pol_dir[2]); + // printout("pkt direction %g, %g, %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); +} + +__host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::DETAILED) { transport_gamma(pkt, t2); } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::BARNES) { diff --git a/grid.cc b/grid.cc index 688eb75af..cc2d14126 100644 --- a/grid.cc +++ b/grid.cc @@ -116,94 +116,63 @@ void read_possible_yefile() { fclose(filein); } -} // anonymous namespace - -auto wid_init(const int cellindex, const int axis) -> double -// for a uniform grid this is the extent along the x,y,z coordinate (x_2 - x_1, etc.) -// for spherical grid this is the radial extent (r_outer - r_inner) -// these values are at time globals::tmin -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - return 2 * globals::rmax / ncoordgrid[axis]; - } - - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { - return (axis == 0) ? globals::rmax / ncoordgrid[axis] : 2 * globals::rmax / ncoordgrid[axis]; - } - - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - const int modelgridindex = get_cell_modelgridindex(cellindex); - const double v_inner = modelgridindex > 0 ? vout_model[modelgridindex - 1] : 0.; - return (vout_model[modelgridindex] - v_inner) * globals::tmin; - } +void set_npts_model(const int new_npts_model) { + npts_model = new_npts_model; - assert_always(false); + assert_always(modelgrid == nullptr); + modelgrid = static_cast(calloc(npts_model + 1, sizeof(ModelGridCell))); + assert_always(modelgrid != nullptr); + mg_associated_cells.resize(npts_model + 1, 0); + nonemptymgi_of_mgi.resize(npts_model + 1, -1); } -auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double -// return the model cell volume (when mapped to the propagation cells) at globals::tmin -// for a uniform cubic grid this is constant -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - return (wid_init(modelgridindex, 0) * wid_init(modelgridindex, 1) * wid_init(modelgridindex, 2)) * - get_numassociatedcells(modelgridindex); - } +void allocate_initradiobund() { + assert_always(npts_model > 0); - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { - return wid_init(modelgridindex, 1) * PI * - (pow(get_cellcoordmax(modelgridindex, 0), 2) - pow(get_cellcoordmin(modelgridindex, 0), 2)); - } + const size_t num_nuclides = decay::get_num_nuclides(); - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - return 4. / 3. * PI * (pow(get_cellcoordmax(modelgridindex, 0), 3) - pow(get_cellcoordmin(modelgridindex, 0), 3)); + const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); +#ifdef MPI_ON + auto my_rank_cells = (npts_model + 1) / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_cells += (npts_model + 1) - (my_rank_cells * globals::node_nprocs); } - assert_always(false); -} - -auto get_gridcell_volume_tmin(const int cellindex) -> double -// return the propagation cell volume at globals::tmin -// for a spherical grid, the cell index is required (and should be equivalent to a modelgridindex) -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - return (wid_init(cellindex, 0) * wid_init(cellindex, 0) * wid_init(cellindex, 0)); - } + MPI_Aint size = my_rank_cells * num_nuclides * sizeof(float); - // 2D and 1D with direct mapping to propagation cells - const int mgi = get_cell_modelgridindex(cellindex); - return get_modelcell_assocvolume_tmin(mgi); -} + int disp_unit = sizeof(float); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &initradioabund_allcells, &win_initradioabund_allcells) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_initradioabund_allcells, 0, &size, &disp_unit, &initradioabund_allcells) == + MPI_SUCCESS); +#else + initradioabund_allcells = static_cast(malloc(totalradioabundsize)); +#endif + printout( + "[info] mem_usage: radioabundance data for %zu nuclides for %zu cells occupies %.3f MB (node shared memory)\n", + num_nuclides, npts_model, static_cast(totalradioabundsize) / 1024. / 1024.); -auto get_cellcoordmax(const int cellindex, const int axis) -> double -// get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell -// e.g., the minimum x position in xyz coords, or the minimum radius -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(0, axis); - } +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { - assert_testmodeonly(axis <= 1); - return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); - } + assert_always(initradioabund_allcells != nullptr); - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - assert_testmodeonly(axis == 0); - return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); + for (size_t mgi = 0; mgi < (npts_model + 1); mgi++) { + modelgrid[mgi].initradioabund = &initradioabund_allcells[mgi * num_nuclides]; + if (mgi % static_cast(globals::node_nprocs) == static_cast(globals::rank_in_node)) { + for (int i = 0; i < decay::get_num_nuclides(); i++) { + modelgrid[mgi].initradioabund[i] = 0.; + } + } } - - assert_always(false); -} - -auto get_cellcoordmin(const int cellindex, const int axis) -> double -// get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell -// e.g., the minimum x position in xyz coords, or the minimum radius -{ - return cell[cellindex].pos_min[axis]; - // return - coordmax[axis] + (2 * get_cellcoordpointnum(cellindex, axis) * coordmax[axis] / ncoordgrid[axis]); +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif } -static auto get_cell_r_inner(const int cellindex) -> double { +auto get_cell_r_inner(const int cellindex) -> double { if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { return get_cellcoordmin(cellindex, 0); } @@ -222,1956 +191,2182 @@ static auto get_cell_r_inner(const int cellindex) -> double { } } -auto get_coordcellindexincrement(const int axis) -> int -// how much do we change the cellindex to move along a coordinately axis (e.g., the x, y, z directions, or r -// direction) -{ - // assert_testmodeonly(axis < get_ngriddimensions()); - - switch (axis) { - case 0: - return 1; - - case 1: - return ncoordgrid[0]; - - case 2: - return ncoordgrid[0] * ncoordgrid[1]; - - default: - if constexpr (TESTMODE) { - printout("invalid coordinate index %d", axis); - assert_testmodeonly(false); - } else { - __builtin_unreachable(); - } +void set_ffegrp(const int modelgridindex, float x) { + if (!(x >= 0.)) { + printout("WARNING: Fe-group mass fraction %g is negative in cell %d\n", x, modelgridindex); + assert_always(x > -1e-6); + x = 0.; } -} - -auto get_cellcoordpointnum(const int cellindex, const int axis) -> int -// convert a cell index number into an integer (x,y,z or r) coordinate index from 0 to ncoordgrid[axis] -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D || GRID_TYPE == GRID_CYLINDRICAL2D) { - switch (axis) { - // 3D Cartesian: increment x first, then y, then z - // 2D Cylindrical: increment r first, then z - case 0: - return cellindex % ncoordgrid[0]; - case 1: - return (cellindex / ncoordgrid[0]) % ncoordgrid[1]; + assert_always(x >= 0); + assert_always(x <= 1.001); + modelgrid[modelgridindex].ffegrp = x; +} - case 2: - return (cellindex / (ncoordgrid[0] * ncoordgrid[1])) % ncoordgrid[2]; +void set_cell_modelgridindex(const int cellindex, const int new_modelgridindex) { + assert_testmodeonly(cellindex < ngrid); + assert_testmodeonly(new_modelgridindex <= get_npts_model()); + cell[cellindex].modelgridindex = new_modelgridindex; +} - default: - if constexpr (TESTMODE) { - printout("invalid coordinate index %d", axis); - assert_testmodeonly(false); - } else { - __builtin_unreachable(); - } - } +void set_modelinitradioabund(const int modelgridindex, const int nucindex, float abund) { + // set the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index + // initradioabund array is in node shared memory + assert_always(nucindex >= 0); + if (!(abund >= 0.)) { + printout("WARNING: nuclear mass fraction for nucindex %d = %g is negative in cell %d\n", nucindex, abund, + modelgridindex); + assert_always(abund > -1e-6); + abund = 0.; } - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - return cellindex; - } + assert_always(abund >= 0.); + assert_always(abund <= 1.); - assert_always(false); + assert_always(modelgrid[modelgridindex].initradioabund != nullptr); + modelgrid[modelgridindex].initradioabund[nucindex] = abund; } -auto get_rho_tmin(const int modelgridindex) -> float { return modelgrid[modelgridindex].rhoinit; } +void set_initenergyq(const int modelgridindex, const double initenergyq) { + modelgrid[modelgridindex].initenergyq = initenergyq; +} -__host__ __device__ auto get_rho(const int modelgridindex) -> float { return modelgrid[modelgridindex].rho; } +void set_elem_stable_abund_from_total(const int mgi, const int element, const float elemabundance) { + // set the stable mass fraction of an element from the total element mass fraction + // by subtracting the abundances of radioactive isotopes. + // if the element Z=anumber has no specific stable abundance variable then the function does nothing -__host__ __device__ auto get_nne(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); + const int atomic_number = get_atomicnumber(element); - const double nne = modelgrid[modelgridindex].nne; - assert_testmodeonly(std::isfinite(nne)); - return nne; -} + double isofracsum = 0.; // mass fraction sum of radioactive isotopes + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + if (decay::get_nuc_z(nucindex) == atomic_number) { + // radioactive isotope of this element + isofracsum += get_modelinitradioabund(mgi, nucindex); + } + } -__host__ __device__ auto get_nnetot(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); + double massfracstable = elemabundance - isofracsum; - const double nnetot = modelgrid[modelgridindex].nnetot; - assert_always(std::isfinite(nnetot)); - return nnetot; -} + if (massfracstable < 0.) { + //  allow some roundoff error before we complain + if ((isofracsum - elemabundance - 1.) > 1e-4 && std::abs(isofracsum - elemabundance) > 1e-6) { + printout("WARNING: cell %d Z=%d element abundance is less than the sum of its radioisotope abundances \n", mgi, + atomic_number); + printout(" massfrac(Z) %g massfrac_radioisotopes(Z) %g\n", elemabundance, isofracsum); + printout(" increasing elemental abundance to %g and setting stable isotopic abundance to zero\n", isofracsum); + } + assert_always(massfracstable >= -1e-2); // result is allowed to be slightly negative due to roundoff error + massfracstable = 0.; // bring up to zero if negative + } -__host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } + // if (globals::rank_in_node == 0) + { modelgrid[mgi].initmassfracstable[element] = massfracstable; } -void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) -// mass fraction of an element (all isotopes combined) -{ - modelgrid[modelgridindex].composition[element].abundance = newabundance; + // (isofracsum + massfracstable) might not exactly match elemabundance if we had to boost it to reach isofracsum + modelgrid[mgi].composition[element].abundance = isofracsum + massfracstable; } -__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double -// mass fraction of an element (all isotopes combined) +void allocate_nonemptycells_composition_cooling() +/// Initialise composition dependent cell data for the given cell { - const double elem_meanweight = grid::get_element_meanweight(modelgridindex, element); - return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); -} + const size_t npts_nonempty = get_nonempty_npts_model(); -__host__ __device__ auto get_kappagrey(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].kappagrey; -} +#ifdef MPI_ON + int my_rank_nonemptycells = nonempty_npts_model / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_nonemptycells += nonempty_npts_model - (my_rank_nonemptycells * globals::node_nprocs); + } +#endif -__host__ __device__ auto get_Te(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].Te; -} - -__host__ __device__ auto get_TR(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].TR; -} +#ifdef MPI_ON + size_t my_rank_cells_nonempty = nonempty_npts_model / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_cells_nonempty += nonempty_npts_model - (my_rank_cells_nonempty * globals::node_nprocs); + } +#endif -__host__ __device__ auto get_TJ(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].TJ; -} +#ifdef MPI_ON + { + MPI_Aint size = my_rank_cells_nonempty * get_nelements() * sizeof(float); + int disp_unit = sizeof(float); + MPI_Win mpiwin = MPI_WIN_NULL; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &initmassfracstable_allcells, &mpiwin) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &initmassfracstable_allcells) == MPI_SUCCESS); + } -__host__ __device__ auto get_W(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].W; -} + { + auto size = static_cast(my_rank_cells_nonempty * get_nelements() * sizeof(float)); + int disp_unit = sizeof(float); + MPI_Win mpiwin = MPI_WIN_NULL; -void set_rho(const int modelgridindex, float rho) { - assert_always(rho >= 0.); - assert_always(std::isfinite(rho)); - modelgrid[modelgridindex].rho = rho; -} + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &elem_meanweight_allcells, &mpiwin) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_meanweight_allcells) == MPI_SUCCESS); + MPI_Barrier(globals::mpi_comm_node); + } +#else + initmassfracstable_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); + elem_meanweight_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); +#endif -void set_nne(const int modelgridindex, float nne) { - assert_always(nne >= 0.); - assert_always(std::isfinite(nne)); - modelgrid[modelgridindex].nne = nne; -} + double *nltepops_allcells{}; + if (globals::total_nlte_levels > 0) { +#ifdef MPI_ON + auto size = static_cast(my_rank_nonemptycells * globals::total_nlte_levels * sizeof(double)); + int disp_unit = sizeof(double); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nltepops_allcells, + &win_nltepops_allcells) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_nltepops_allcells, 0, &size, &disp_unit, &nltepops_allcells) == MPI_SUCCESS); -void set_nnetot(const int modelgridindex, float nnetot) { - assert_always(nnetot >= 0.); - assert_always(std::isfinite(nnetot)); - modelgrid[modelgridindex].nnetot = nnetot; -} + MPI_Barrier(globals::mpi_comm_node); +#else + nltepops_allcells = static_cast(malloc(npts_nonempty * globals::total_nlte_levels * sizeof(double))); +#endif -static void set_ffegrp(const int modelgridindex, float x) { - if (!(x >= 0.)) { - printout("WARNING: Fe-group mass fraction %g is negative in cell %d\n", x, modelgridindex); - assert_always(x > -1e-6); - x = 0.; + assert_always(nltepops_allcells != nullptr); } - assert_always(x >= 0); - assert_always(x <= 1.001); - modelgrid[modelgridindex].ffegrp = x; -} - -void set_kappagrey(const int modelgridindex, float kappagrey) { modelgrid[modelgridindex].kappagrey = kappagrey; } + for (size_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); -void set_Te(const int modelgridindex, float Te) { modelgrid[modelgridindex].Te = Te; } + modelgrid[modelgridindex].elements_uppermost_ion = static_cast(malloc(get_nelements() * sizeof(int))); -void set_TR(const int modelgridindex, float TR) { modelgrid[modelgridindex].TR = TR; } + assert_always(modelgrid[modelgridindex].elements_uppermost_ion != nullptr); -void set_TJ(const int modelgridindex, float TJ) { modelgrid[modelgridindex].TJ = TJ; } + modelgrid[modelgridindex].composition = + static_cast(malloc(get_nelements() * sizeof(ModelCellElement))); -void set_W(const int modelgridindex, float W) { modelgrid[modelgridindex].W = W; } + if (modelgrid[modelgridindex].composition == nullptr) { + printout("[fatal] input: not enough memory to initialize compositionlist for cell %d... abort\n", modelgridindex); + std::abort(); + } -auto get_model_type() -> enum gridtypes { return model_type; } + modelgrid[modelgridindex].initmassfracstable = &initmassfracstable_allcells[nonemptymgi * get_nelements()]; -void set_model_type(enum gridtypes model_type_value) { model_type = model_type_value; } + assert_always(modelgrid[modelgridindex].initmassfracstable != nullptr); -__host__ __device__ auto get_npts_model() -> int -// number of model grid cells -{ - assert_testmodeonly(npts_model > 0); - return npts_model; -} + modelgrid[modelgridindex].elem_meanweight = &elem_meanweight_allcells[nonemptymgi * get_nelements()]; -auto get_nonempty_npts_model() -> int -// number of model grid cells -{ - assert_testmodeonly(nonempty_npts_model > 0); - return nonempty_npts_model; -} + assert_always(modelgrid[modelgridindex].elem_meanweight != nullptr); -static void set_npts_model(int new_npts_model) { - npts_model = new_npts_model; + if (globals::total_nlte_levels > 0) { + modelgrid[modelgridindex].nlte_pops = &nltepops_allcells[nonemptymgi * globals::total_nlte_levels]; + assert_always(modelgrid[modelgridindex].nlte_pops != nullptr); - assert_always(modelgrid == nullptr); - modelgrid = static_cast(calloc(npts_model + 1, sizeof(ModelGridCell))); - assert_always(modelgrid != nullptr); - mg_associated_cells.resize(npts_model + 1, 0); - nonemptymgi_of_mgi.resize(npts_model + 1, -1); -} + for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { + modelgrid[modelgridindex].nlte_pops[nlteindex] = -1.; /// flag to indicate that there is + /// currently no information on the nlte populations + } + } else { + modelgrid[modelgridindex].nlte_pops = nullptr; + } -static void allocate_initradiobund() { - assert_always(npts_model > 0); + for (int element = 0; element < get_nelements(); element++) { + /// Set initial abundances to zero + modelgrid[modelgridindex].composition[element].abundance = 0.; - const size_t num_nuclides = decay::get_num_nuclides(); + /// and allocate memory to store the ground level populations for each ionisation stage + modelgrid[modelgridindex].composition[element].groundlevelpop = + static_cast(calloc(get_nions(element), sizeof(float))); + if (modelgrid[modelgridindex].composition[element].groundlevelpop == nullptr) { + printout( + "[fatal] input: not enough memory to initialize groundlevelpoplist for element %d in cell %d... abort\n", + element, modelgridindex); + std::abort(); + } - const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); -#ifdef MPI_ON - auto my_rank_cells = (npts_model + 1) / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += (npts_model + 1) - (my_rank_cells * globals::node_nprocs); - } + modelgrid[modelgridindex].composition[element].partfunct = + static_cast(calloc(get_nions(element), sizeof(float))); - MPI_Aint size = my_rank_cells * num_nuclides * sizeof(float); + if (modelgrid[modelgridindex].composition[element].partfunct == nullptr) { + printout("[fatal] input: not enough memory to initialize partfunctlist for element %d in cell %d... abort\n", + element, modelgridindex); + std::abort(); + } + } - int disp_unit = sizeof(float); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initradioabund_allcells, &win_initradioabund_allcells) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_initradioabund_allcells, 0, &size, &disp_unit, &initradioabund_allcells) == - MPI_SUCCESS); -#else - initradioabund_allcells = static_cast(malloc(totalradioabundsize)); -#endif - printout( - "[info] mem_usage: radioabundance data for %zu nuclides for %zu cells occupies %.3f MB (node shared memory)\n", - num_nuclides, npts_model, static_cast(totalradioabundsize) / 1024. / 1024.); + modelgrid[modelgridindex].cooling_contrib_ion = static_cast(malloc(get_nelements() * sizeof(double *))); -#ifdef MPI_ON - MPI_Barrier(globals::mpi_comm_node); -#endif + if (modelgrid[modelgridindex].cooling_contrib_ion == nullptr) { + printout("[fatal] input: not enough memory to initialize coolinglist for cell %d... abort\n", modelgridindex); + std::abort(); + } - assert_always(initradioabund_allcells != nullptr); + modelgrid[modelgridindex].cooling_contrib_ion[0] = + static_cast(malloc(get_includedions() * sizeof(double))); - for (size_t mgi = 0; mgi < (npts_model + 1); mgi++) { - modelgrid[mgi].initradioabund = &initradioabund_allcells[mgi * num_nuclides]; - if (mgi % static_cast(globals::node_nprocs) == static_cast(globals::rank_in_node)) { - for (int i = 0; i < decay::get_num_nuclides(); i++) { - modelgrid[mgi].initradioabund[i] = 0.; - } + for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { + modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex] = -1.; // flag as invalid } - } -#ifdef MPI_ON - MPI_Barrier(globals::mpi_comm_node); -#endif -} -auto get_t_model() -> double -// get time at which model input densities are defined -{ - assert_testmodeonly(t_model > 0.); - return t_model; -} + int allionindex = 0; + for (int element = 0; element < get_nelements(); element++) { + /// and allocate memory to store the ground level populations for each ionisation stage -__host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { - assert_testmodeonly(cellindex >= 0); - assert_testmodeonly(cellindex < ngrid); - const int mgi = cell[cellindex].modelgridindex; - assert_testmodeonly(mgi >= 0); - assert_testmodeonly(mgi < (get_npts_model() + 1)); - return mgi; -} + modelgrid[modelgridindex].cooling_contrib_ion[element] = + &modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex]; -static void set_cell_modelgridindex(const int cellindex, const int new_modelgridindex) { - assert_testmodeonly(cellindex < ngrid); - assert_testmodeonly(new_modelgridindex <= get_npts_model()); - cell[cellindex].modelgridindex = new_modelgridindex; -} + assert_always(modelgrid[modelgridindex].cooling_contrib_ion[element] != nullptr); -__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int -// number of propagation cells associated with each modelgrid cell -{ - assert_testmodeonly(modelgridindex <= get_npts_model()); - return mg_associated_cells[modelgridindex]; + allionindex += get_nions(element); + } + } } -__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int -// get the index in the list of non-empty cells for a given model grid cell -{ - assert_testmodeonly(get_nonempty_npts_model() > 0); - assert_testmodeonly(mgi < get_npts_model()); +void allocate_nonemptymodelcells() { + // Determine the number of simulation cells associated with the model cells + for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { + mg_associated_cells[mgi] = 0; + modelgrid[mgi].initial_radial_pos_sum = 0.; + } - const int nonemptymgi = nonemptymgi_of_mgi[mgi]; - // assert_testmodeonly(nonemptymgi >= 0 || get_numassociatedcells(mgi) == 0); - assert_testmodeonly(nonemptymgi >= 0); - assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + for (int cellindex = 0; cellindex < ngrid; cellindex++) { + const auto radial_pos_mid = get_cellradialposmid(cellindex); - return nonemptymgi; -} + if (FORCE_SPHERICAL_ESCAPE_SURFACE && radial_pos_mid > globals::vmax * globals::tmin) { + // for 1D models, the final shell outer v should already be at vmax + assert_always(model_type != GRID_SPHERICAL1D || cell[cellindex].modelgridindex == get_npts_model()); + cell[cellindex].modelgridindex = get_npts_model(); + } -__host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int -// get the index in the list of non-empty cells for a given model grid cell -{ - assert_testmodeonly(get_nonempty_npts_model() > 0); - assert_testmodeonly(nonemptymgi >= 0); - assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + const int mgi = get_cell_modelgridindex(cellindex); + assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); - const int mgi = mgi_of_nonemptymgi[nonemptymgi]; + mg_associated_cells[mgi] += 1; + modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; - assert_always(mgi >= 0); - return mgi; -} + assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || + (mgi == get_npts_model())); + } -// the abundances below are initial abundances at t_model + // find number of non-empty cells and allocate nonempty list + nonempty_npts_model = 0; + for (int mgi = 0; mgi < get_npts_model(); mgi++) { + if (get_numassociatedcells(mgi) > 0) { + nonempty_npts_model++; + } + } + assert_always(nonempty_npts_model > 0); -auto get_modelinitradioabund(const int modelgridindex, const int nucindex) -> float { - // get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index + mgi_of_nonemptymgi.resize(nonempty_npts_model); - assert_testmodeonly(modelgrid[modelgridindex].initradioabund != nullptr); - return modelgrid[modelgridindex].initradioabund[nucindex]; -} + int nonemptymgi = 0; // index within list of non-empty modelgrid cells -static void set_modelinitradioabund(const int modelgridindex, const int nucindex, float abund) { - // set the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index - // initradioabund array is in node shared memory - assert_always(nucindex >= 0); - if (!(abund >= 0.)) { - printout("WARNING: nuclear mass fraction for nucindex %d = %g is negative in cell %d\n", nucindex, abund, - modelgridindex); - assert_always(abund > -1e-6); - abund = 0.; + for (int mgi = 0; mgi < get_npts_model(); mgi++) { + if (get_numassociatedcells(mgi) > 0) { + if (get_rho_tmin(mgi) <= 0) { + printout("Error: negative or zero density. Abort.\n"); + std::abort(); + } + nonemptymgi_of_mgi[mgi] = nonemptymgi; + mgi_of_nonemptymgi[nonemptymgi] = mgi; + nonemptymgi++; + } else { + nonemptymgi_of_mgi[mgi] = -1; + set_rho_tmin(mgi, 0.); + set_rho(mgi, 0.); + if (modelgrid[mgi].initradioabund != nullptr) { + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + set_modelinitradioabund(mgi, nucindex, 0.); + } + } + } } - assert_always(abund >= 0.); - assert_always(abund <= 1.); + allocate_nonemptycells_composition_cooling(); - assert_always(modelgrid[modelgridindex].initradioabund != nullptr); - modelgrid[modelgridindex].initradioabund[nucindex] = abund; -} + if constexpr (EXPANSIONOPACITIES_ON || RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY > 0.) { + allocate_expansionopacities(); + } -auto get_stable_initabund(const int mgi, const int element) -> float { - assert_testmodeonly(modelgrid[mgi].initmassfracstable != nullptr); - return modelgrid[mgi].initmassfracstable[element]; -} + globals::dep_estimator_gamma.resize(nonempty_npts_model, 0.); + globals::dep_estimator_positron.resize(nonempty_npts_model, 0.); + globals::dep_estimator_electron.resize(nonempty_npts_model, 0.); + globals::dep_estimator_alpha.resize(nonempty_npts_model, 0.); -auto get_element_meanweight(const int mgi, const int element) -> float -// weight is in grams -{ - if (USE_CALCULATED_MEANATOMICWEIGHT) { - const double mu = modelgrid[mgi].elem_meanweight[element]; - if (mu > 0) { - return mu; + auto ionestimsize = nonempty_npts_model * globals::nbfcontinua_ground * sizeof(double); + + if (USE_LUT_PHOTOION && ionestimsize > 0) { +#ifdef MPI_ON + auto my_rank_cells = nonempty_npts_model / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); } - } - return globals::elements[element].initstablemeannucmass; -} -void set_element_meanweight(const int mgi, const int element, const float meanweight) -// weight is in grams -{ - assert_always(meanweight > 0.); - modelgrid[mgi].elem_meanweight[element] = meanweight; -} + auto size = static_cast(my_rank_cells * globals::nbfcontinua_ground * sizeof(double)); + int disp_unit = sizeof(double); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &globals::corrphotoionrenorm, + &globals::win_corrphotoionrenorm) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(globals::win_corrphotoionrenorm, 0, &size, &disp_unit, + &globals::corrphotoionrenorm) == MPI_SUCCESS); +#else + globals::corrphotoionrenorm = static_cast(malloc(ionestimsize)); +#endif -auto get_electronfrac(const int modelgridindex) -> double { - double nucleondens = 0.; - for (int element = 0; element < get_nelements(); element++) { - nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(modelgridindex, element) / MH; + globals::gammaestimator = static_cast(malloc(ionestimsize)); +#ifdef DO_TITER + globals::gammaestimator_save = static_cast(malloc(ionestimsize)); +#endif + } else { + globals::corrphotoionrenorm = nullptr; + globals::gammaestimator = nullptr; +#ifdef DO_TITER + globals::gammaestimator_save = nullptr; +#endif } - return get_nnetot(modelgridindex) / nucleondens; -} -auto get_initelectronfrac(const int modelgridindex) -> double { return modelgrid[modelgridindex].initelectronfrac; } + if (USE_LUT_BFHEATING && ionestimsize > 0) { + globals::bfheatingestimator = static_cast(malloc(ionestimsize)); +#ifdef DO_TITER + globals::bfheatingestimator_save = static_cast(malloc(ionestimsize)); +#endif + } else { + globals::bfheatingestimator = nullptr; +#ifdef DO_TITER + globals::bfheatingestimator_save = nullptr; +#endif + } -auto get_initenergyq(const int modelgridindex) -> double { - // q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] + globals::ffheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::colheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); +#ifdef DO_TITER + globals::ffheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::colheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); +#endif - return modelgrid[modelgridindex].initenergyq; -} +#ifdef MPI_ON + // barrier to make sure node master has set abundance values to node shared memory + MPI_Barrier(MPI_COMM_WORLD); +#endif -static void set_initenergyq(const int modelgridindex, const double initenergyq) { - modelgrid[modelgridindex].initenergyq = initenergyq; -} + printout("[info] mem_usage: the modelgrid array occupies %.3f MB\n", + (get_npts_model() + 1) * sizeof(modelgrid[0]) / 1024. / 1024.); -static void set_elem_stable_abund_from_total(const int mgi, const int element, const float elemabundance) { - // set the stable mass fraction of an element from the total element mass fraction - // by subtracting the abundances of radioactive isotopes. - // if the element Z=anumber has no specific stable abundance variable then the function does nothing + printout("There are %zu modelgrid cells with associated propagation cells\n", nonempty_npts_model); - const int atomic_number = get_atomicnumber(element); + printout( + "[info] mem_usage: NLTE populations for all allocated cells occupy a total of %.3f MB (node shared memory)\n", + get_nonempty_npts_model() * globals::total_nlte_levels * sizeof(double) / 1024. / 1024.); +} - double isofracsum = 0.; // mass fraction sum of radioactive isotopes - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - if (decay::get_nuc_z(nucindex) == atomic_number) { - // radioactive isotope of this element - isofracsum += get_modelinitradioabund(mgi, nucindex); +void map_1dmodelto3dgrid() +// Map 1D spherical model grid onto propagation grid +{ + for (int cellindex = 0; cellindex < ngrid; cellindex++) { + const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; + const int mgi = static_cast(std::find_if_not(vout_model, vout_model + get_npts_model(), + [cellvmid](double v_outer) { return v_outer < cellvmid; }) - + vout_model); + + if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { + set_cell_modelgridindex(cellindex, mgi); + } else { + set_cell_modelgridindex(cellindex, get_npts_model()); } } +} - double massfracstable = elemabundance - isofracsum; +void map_2dmodelto3dgrid() +// Map 2D cylindrical model onto propagation grid +{ + for (int cellindex = 0; cellindex < ngrid; cellindex++) { + int mgi = get_npts_model(); // default to empty unless set - if (massfracstable < 0.) { - //  allow some roundoff error before we complain - if ((isofracsum - elemabundance - 1.) > 1e-4 && std::abs(isofracsum - elemabundance) > 1e-6) { - printout("WARNING: cell %d Z=%d element abundance is less than the sum of its radioisotope abundances \n", mgi, - atomic_number); - printout(" massfrac(Z) %g massfrac_radioisotopes(Z) %g\n", elemabundance, isofracsum); - printout(" increasing elemental abundance to %g and setting stable isotopic abundance to zero\n", isofracsum); + // map to 3D Cartesian grid + std::array pos_mid{}; + for (int d = 0; d < 3; d++) { + pos_mid[d] = (get_cellcoordmin(cellindex, d) + (0.5 * wid_init(cellindex, d))); } - assert_always(massfracstable >= -1e-2); // result is allowed to be slightly negative due to roundoff error - massfracstable = 0.; // bring up to zero if negative - } - - // if (globals::rank_in_node == 0) - { modelgrid[mgi].initmassfracstable[element] = massfracstable; } - // (isofracsum + massfracstable) might not exactly match elemabundance if we had to boost it to reach isofracsum - modelgrid[mgi].composition[element].abundance = isofracsum + massfracstable; -} + // 2D grid is uniform so rcyl and z positions can easily be calculated + const double rcylindrical = std::sqrt(std::pow(pos_mid[0], 2) + std::pow(pos_mid[1], 2)); -auto get_cellradialposmid(const int cellindex) -> double -// get the radial distance from the origin to the centre of the cell at time tmin -{ - if (GRID_TYPE == GRID_SPHERICAL1D) { - // mid point radius - // return get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); - // volume averaged mean radius is slightly complex for radial shells - const double r_inner = grid::get_cellcoordmin(cellindex, 0); - const double r_outer = r_inner + grid::wid_init(cellindex, 0); - return 3. / 4 * (pow(r_outer, 4.) - pow(r_inner, 4.)) / (pow(r_outer, 3) - pow(r_inner, 3.)); - } + const int n_rcyl = static_cast(rcylindrical / globals::tmin / globals::vmax * ncoord_model[0]); + const int n_z = + static_cast((pos_mid[2] / globals::tmin + globals::vmax) / (2 * globals::vmax) * ncoord_model[1]); - if (GRID_TYPE == GRID_CYLINDRICAL2D) { - const double rcyl_mid = get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); - const double z_mid = get_cellcoordmin(cellindex, 1) + (0.5 * wid_init(cellindex, 1)); - return std::sqrt(std::pow(rcyl_mid, 2) + std::pow(z_mid, 2)); - } + if (n_rcyl >= 0 && n_rcyl < ncoord_model[0] && n_z >= 0 && n_z < ncoord_model[1]) { + mgi = (n_z * ncoord_model[0]) + n_rcyl; + } - // cubic grid requires taking the length of the 3D position vector - std::array dcen{}; - for (int axis = 0; axis < 3; axis++) { - dcen[axis] = get_cellcoordmin(cellindex, axis) + (0.5 * wid_init(cellindex, axis)); + if (modelgrid[mgi].rhoinit > 0) { + set_cell_modelgridindex(cellindex, mgi); + } else { + set_cell_modelgridindex(cellindex, get_npts_model()); + } } - - return vec_len(dcen); } -auto get_elements_uppermost_ion(const int modelgridindex, const int element) -> int { - return modelgrid[modelgridindex].elements_uppermost_ion[element]; -} +void map_modeltogrid_direct() +// mgi and cellindex are interchangeable in this mode +{ + for (int cellindex = 0; cellindex < ngrid; cellindex++) { + const int mgi = cellindex; // direct mapping -void set_elements_uppermost_ion(const int modelgridindex, const int element, const int newvalue) { - modelgrid[modelgridindex].elements_uppermost_ion[element] = newvalue; + if (modelgrid[mgi].rhoinit > 0) { + set_cell_modelgridindex(cellindex, mgi); + } else { + set_cell_modelgridindex(cellindex, get_npts_model()); + } + } } -void calculate_kappagrey() { - double rho_sum = 0.; - double fe_sum = 0.; - double opcase3_sum = 0.; - const int empty_cells = 0; +void abundances_read() { +#ifdef MPI_ON + // barrier to make sure node master has set values in node shared memory + MPI_Barrier(MPI_COMM_WORLD); +#endif + printout("reading abundances.txt..."); + const bool threedimensional = (get_model_type() == GRID_CARTESIAN3D); - for (int n = 0; n < ngrid; n++) { - const int mgi = get_cell_modelgridindex(n); - rho_sum += get_rho_tmin(mgi); - fe_sum += get_ffegrp(mgi); + /// Open the abundances file + auto abundance_file = fstream_required("abundances.txt", std::ios::in); - if (globals::opacity_case == 3) { - if (get_rho_tmin(mgi) > 0.) { - double kappagrey = ((0.9 * get_ffegrp(mgi)) + 0.1); + /// and process through the grid to read in the abundances per cell + /// The abundance file should only contain information for non-empty + /// cells. Its format must be cellnumber (integer), abundance for + /// element Z=1 (float) up to abundance for element Z=30 (float) + /// i.e. in total one integer and 30 floats. - if (get_rho_tmin(mgi) > globals::rho_crit) { - kappagrey *= globals::rho_crit / get_rho_tmin(mgi); - } + // loop over propagation cells for 3D models, or modelgrid cells + for (int mgi = 0; mgi < get_npts_model(); mgi++) { + std::string line; + assert_always(get_noncommentline(abundance_file, line)); + std::istringstream ssline(line); - set_kappagrey(mgi, kappagrey); - } else if (get_rho_tmin(mgi) == 0.) { - set_kappagrey(mgi, 0.); - } else if (get_rho_tmin(mgi) < 0.) { - printout("Error: negative density. Abort.\n"); - std::abort(); + int cellnumberinput = -1; + assert_always(ssline >> cellnumberinput); + assert_always(cellnumberinput == mgi + first_cellindex); + + // the abundances.txt file specifies the elemental mass fractions for each model cell + // (or proportial to mass frac, e.g. element densities because they will be normalised anyway) + // The abundances begin with hydrogen, helium, etc, going as far up the atomic numbers as required + double normfactor = 0.; + float abundances_in[150] = {0.}; + double abund_in = 0.; + for (int anumber = 1; anumber <= 150; anumber++) { + abundances_in[anumber - 1] = 0.; + if (!(ssline >> abund_in)) { + // at least one element (hydrogen) should have been specified for nonempty cells + assert_always(anumber > 1 || get_numassociatedcells(mgi) == 0); + break; } - opcase3_sum += get_kappagrey(mgi) * get_rho_tmin(mgi); + + if (abund_in < 0. || abund_in < std::numeric_limits::min()) { + assert_always(abund_in > -1e-6); + abund_in = 0.; + } + abundances_in[anumber - 1] = static_cast(abund_in); + normfactor += abundances_in[anumber - 1]; } - } - /// Second pass through allows calculation of normalized chi_grey - double check1 = 0.; - double check2 = 0.; - for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { - const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); - if (get_rho_tmin(mgi) > 0) { - double kappa = 0.; - if (globals::opacity_case == 0) { - kappa = globals::GREY_OP; - } else if (globals::opacity_case == 1 || globals::opacity_case == 4) { - /// kappagrey used for initial grey approximation in case 4 - kappa = ((0.9 * get_ffegrp(mgi)) + 0.1) * globals::GREY_OP / ((0.9 * mfeg / mtot_input) + 0.1); - } else if (globals::opacity_case == 2) { - const double opcase2_normal = globals::GREY_OP * rho_sum / ((0.9 * fe_sum) + (0.1 * (ngrid - empty_cells))); - kappa = opcase2_normal / get_rho_tmin(mgi) * ((0.9 * get_ffegrp(mgi)) + 0.1); - } else if (globals::opacity_case == 3) { - globals::opcase3_normal = globals::GREY_OP * rho_sum / opcase3_sum; - kappa = get_kappagrey(mgi) * globals::opcase3_normal; - } else if (globals::opacity_case == 5) { - // electron-fraction-dependent opacities - // values from table 1 of Tanaka et al. (2020). - // const double Ye = get_electronfrac(mgi); - const double Ye = get_initelectronfrac(mgi); - if (Ye <= 0.1) { - kappa = 19.5; - } else if (Ye <= 0.15) { - kappa = 32.2; - } else if (Ye <= 0.20) { - kappa = 22.3; - } else if (Ye <= 0.25) { - kappa = 5.6; - } else if (Ye <= 0.30) { - kappa = 5.36; - } else if (Ye <= 0.35) { - kappa = 3.3; - } else { - kappa = 0.96; - } - } else if (globals::opacity_case == 6) { - // grey opacity used in Just+2022, https://ui.adsabs.harvard.edu/abs/2022MNRAS.510.2820J/abstract - // kappa is a simple analytic function of temperature and lanthanide mass fraction - // adapted to best fit lightcurves from Kasen+2017 in ALCAR simulations - const double T_rad = get_TR(mgi); - double X_lan = 0.; - for (int element = 0; element < get_nelements(); element++) { - const int z = get_atomicnumber(element); - if (z >= 57 && z <= 71) { - X_lan += get_elem_abundance(mgi, element); - } - } - // first step: temperature-independent factor - if (X_lan < 1e-7) { - kappa = 0.2; - } else if (X_lan < 1e-3) { - kappa = 3 * pow(X_lan / 1e-3, 0.3); - } else if (X_lan < 1e-1) { - kappa = 3 * pow(X_lan / 1e-3, 0.5); - } else { - kappa = 30 * pow(X_lan / 1e-1, 0.1); - } - // second step: multiply temperature-dependent factor - if (T_rad < 2000.) { - kappa *= pow(T_rad / 2000., 5.); - } - } else { - printout("Unknown opacity case. Abort.\n"); - std::abort(); + if (get_numassociatedcells(mgi) > 0) { + if (threedimensional || normfactor <= 0.) { + normfactor = 1.; } - set_kappagrey(mgi, kappa); - } else if (get_rho_tmin(mgi) == 0.) { - set_kappagrey(mgi, 0.); - } else if (get_rho_tmin(mgi) < 0.) { - printout("Error: negative density. Abort.\n"); - std::abort(); - } + for (int element = 0; element < get_nelements(); element++) { + /// now set the abundances (by mass) of included elements, i.e. + /// read out the abundances specified in the atomic data file + const int anumber = get_atomicnumber(element); + const float elemabundance = abundances_in[anumber - 1] / normfactor; + assert_always(elemabundance >= 0.); - check1 = check1 + (get_kappagrey(mgi) * get_rho_tmin(mgi)); - check2 = check2 + get_rho_tmin(mgi); + // radioactive nuclide abundances should have already been set by read_??_model + set_elem_stable_abund_from_total(mgi, element, elemabundance); + } + } } - printout("Grey normalisation check: %g\n", check1 / check2); +#ifdef MPI_ON + // barrier to make sure node master has set values in node shared memory + MPI_Barrier(MPI_COMM_WORLD); +#endif + printout("done.\n"); } -static void allocate_nonemptycells_composition_cooling() -/// Initialise composition dependent cell data for the given cell -{ - const size_t npts_nonempty = get_nonempty_npts_model(); +void parse_model_headerline(const std::string &line, std::vector &zlist, std::vector &alist, + std::vector &colnames) { + // custom header line + std::istringstream iss(line); + std::string token; -#ifdef MPI_ON - int my_rank_nonemptycells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_nonemptycells += nonempty_npts_model - (my_rank_nonemptycells * globals::node_nprocs); + int columnindex = -1; + + while (std::getline(iss, token, ' ')) { + if (std::ranges::all_of(token, isspace)) { // skip whitespace tokens + continue; + } + + columnindex++; + + if (token == "#inputcellid") { + assert_always(columnindex == 0); + } else if (token == "velocity_outer") { + assert_always(columnindex == 1); + } else if (token == "vel_r_max_kmps") { + assert_always(columnindex == 1); + } else if (token.starts_with("pos_")) { + continue; + } else if (token == "logrho") { + // 1D models have log10(rho [g/cm3]) + assert_always(columnindex == 2); + assert_always(get_model_type() == GRID_SPHERICAL1D); + } else if (token == "rho") { + // 2D and 3D models have rho [g/cm3] + assert_always(get_model_type() != GRID_SPHERICAL1D); + assert_always((columnindex == 4 && get_model_type() == GRID_CARTESIAN3D) || + (columnindex == 3 && get_model_type() == GRID_CYLINDRICAL2D)); + continue; + } else if (token.starts_with("X_") && token != "X_Fegroup") { + colnames.push_back(token); + const int z = decay::get_nucstring_z(token.substr(2)); // + 2 skips the 'X_' + const int a = decay::get_nucstring_a(token.substr(2)); + assert_always(z >= 0); + assert_always(a >= 0); + // printout("Custom column: '%s' Z %d A %d\n", token.c_str(), z, a); + zlist.push_back(z); + alist.push_back(a); + } else { + // printout("Custom column: '%s' Z %d A %d\n", token.c_str(), -1, -1); + colnames.push_back(token); + zlist.push_back(-1); + alist.push_back(-1); + } } -#endif +} -#ifdef MPI_ON - size_t my_rank_cells_nonempty = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells_nonempty += nonempty_npts_model - (my_rank_cells_nonempty * globals::node_nprocs); +auto get_token_count(std::string &line) -> int { + std::string token; + int abundcolcount = 0; + auto ssline = std::istringstream(line); + while (std::getline(ssline, token, ' ')) { + if (!std::ranges::all_of(token, isspace)) { // skip whitespace tokens + abundcolcount++; + } } -#endif + return abundcolcount; +} -#ifdef MPI_ON - { - MPI_Aint size = my_rank_cells_nonempty * get_nelements() * sizeof(float); - int disp_unit = sizeof(float); - MPI_Win mpiwin = MPI_WIN_NULL; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initmassfracstable_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &initmassfracstable_allcells) == MPI_SUCCESS); +void read_model_radioabundances(std::fstream &fmodel, std::istringstream &ssline_in, const int mgi, const bool keepcell, + const std::vector &colnames, const std::vector &nucindexlist, + const bool one_line_per_cell) { + std::string line; + if (!one_line_per_cell) { + assert_always(std::getline(fmodel, line)); } - { - auto size = static_cast(my_rank_cells_nonempty * get_nelements() * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win mpiwin = MPI_WIN_NULL; + auto ssline = one_line_per_cell ? std::move(ssline_in) : std::istringstream(line); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &elem_meanweight_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_meanweight_allcells) == MPI_SUCCESS); - MPI_Barrier(globals::mpi_comm_node); + if (!keepcell) { + return; } -#else - initmassfracstable_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); - elem_meanweight_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); -#endif - double *nltepops_allcells{}; - if (globals::total_nlte_levels > 0) { -#ifdef MPI_ON - auto size = static_cast(my_rank_nonemptycells * globals::total_nlte_levels * sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nltepops_allcells, - &win_nltepops_allcells) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_nltepops_allcells, 0, &size, &disp_unit, &nltepops_allcells) == MPI_SUCCESS); - - MPI_Barrier(globals::mpi_comm_node); -#else - nltepops_allcells = static_cast(malloc(npts_nonempty * globals::total_nlte_levels * sizeof(double))); -#endif + for (size_t i = 0; i < colnames.size(); i++) { + double valuein = 0.; + assert_always(ssline >> valuein); // usually a mass fraction, but now can be anything - assert_always(nltepops_allcells != nullptr); + if (nucindexlist[i] >= 0) { + assert_testmodeonly(valuein <= 1.); + set_modelinitradioabund(mgi, nucindexlist[i], valuein); + } else if (colnames[i] == "X_Fegroup") { + set_ffegrp(mgi, valuein); + } else if (colnames[i] == "cellYe") { + set_initelectronfrac(mgi, valuein); + } else if (colnames[i] == "q") { + // use value for t_model and adjust to tmin with expansion factor + set_initenergyq(mgi, valuein * t_model / globals::tmin); + } else if (colnames[i] == "tracercount") { + ; + } else { + if (mgi == 0) { + printout("WARNING: ignoring column '%s' nucindex %d valuein[mgi=0] %lg\n", colnames[i].c_str(), nucindexlist[i], + valuein); + } + } } + double valuein = 0.; + assert_always(!(ssline >> valuein)); // should be no tokens left! +} - for (size_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); +auto read_model_columns(std::fstream &fmodel) -> std::tuple, std::vector, bool> { + auto pos_data_start = fmodel.tellg(); // get position in case we need to undo getline - modelgrid[modelgridindex].elements_uppermost_ion = static_cast(malloc(get_nelements() * sizeof(int))); + std::vector zlist; + std::vector alist; + std::vector colnames; - assert_always(modelgrid[modelgridindex].elements_uppermost_ion != nullptr); + std::string line; + std::getline(fmodel, line); - modelgrid[modelgridindex].composition = - static_cast(malloc(get_nelements() * sizeof(ModelCellElement))); + std::string headerline; - if (modelgrid[modelgridindex].composition == nullptr) { - printout("[fatal] input: not enough memory to initialize compositionlist for cell %d... abort\n", modelgridindex); - std::abort(); + const bool header_specified = lineiscommentonly(line); + + if (header_specified) { + // line is the header + headerline = line; + pos_data_start = fmodel.tellg(); + std::getline(fmodel, line); + } else { + // line is not a comment, so it must be the first line of data + // add a default header for unlabelled columns + switch (model_type) { + case GRID_SPHERICAL1D: + headerline = std::string("#inputcellid vel_r_max_kmps logrho"); + break; + case GRID_CYLINDRICAL2D: + headerline = std::string("#inputcellid pos_rcyl_mid pos_z_mid rho"); + break; + case GRID_CARTESIAN3D: + headerline = std::string("#inputcellid pos_x_min pos_y_min pos_z_min rho"); + break; } + headerline += std::string(" X_Fegroup X_Ni56 X_Co56 X_Fe52 X_Cr48"); + } - modelgrid[modelgridindex].initmassfracstable = &initmassfracstable_allcells[nonemptymgi * get_nelements()]; + int colcount = get_token_count(line); + const bool one_line_per_cell = (colcount >= get_token_count(headerline)); - assert_always(modelgrid[modelgridindex].initmassfracstable != nullptr); + printout("model.txt has %s line per cell format\n", one_line_per_cell ? "one" : "two"); - modelgrid[modelgridindex].elem_meanweight = &elem_meanweight_allcells[nonemptymgi * get_nelements()]; + if (!one_line_per_cell) { // add columns from the second line + std::getline(fmodel, line); + colcount += get_token_count(line); + } - assert_always(modelgrid[modelgridindex].elem_meanweight != nullptr); + if (!header_specified && colcount > get_token_count(headerline)) { + headerline += " X_Ni57 X_Co57"; + } - if (globals::total_nlte_levels > 0) { - modelgrid[modelgridindex].nlte_pops = &nltepops_allcells[nonemptymgi * globals::total_nlte_levels]; - assert_always(modelgrid[modelgridindex].nlte_pops != nullptr); + assert_always(colcount == get_token_count(headerline)); - for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { - modelgrid[modelgridindex].nlte_pops[nlteindex] = -1.; /// flag to indicate that there is - /// currently no information on the nlte populations - } - } else { - modelgrid[modelgridindex].nlte_pops = nullptr; - } + fmodel.seekg(pos_data_start); // get back to start of data - for (int element = 0; element < get_nelements(); element++) { - /// Set initial abundances to zero - modelgrid[modelgridindex].composition[element].abundance = 0.; + if (header_specified) { + printout("model.txt has header line: %s\n", headerline.c_str()); + } else { + printout("model.txt has no header line. Using default: %s\n", headerline.c_str()); + } - /// and allocate memory to store the ground level populations for each ionisation stage - modelgrid[modelgridindex].composition[element].groundlevelpop = - static_cast(calloc(get_nions(element), sizeof(float))); - if (modelgrid[modelgridindex].composition[element].groundlevelpop == nullptr) { - printout( - "[fatal] input: not enough memory to initialize groundlevelpoplist for element %d in cell %d... abort\n", - element, modelgridindex); - std::abort(); - } + parse_model_headerline(headerline, zlist, alist, colnames); - modelgrid[modelgridindex].composition[element].partfunct = - static_cast(calloc(get_nions(element), sizeof(float))); + decay::init_nuclides(zlist, alist); - if (modelgrid[modelgridindex].composition[element].partfunct == nullptr) { - printout("[fatal] input: not enough memory to initialize partfunctlist for element %d in cell %d... abort\n", - element, modelgridindex); - std::abort(); - } - } + std::vector nucindexlist(zlist.size()); + for (std::size_t i = 0; i < zlist.size(); i++) { + nucindexlist[i] = (zlist[i] > 0) ? decay::get_nucindex(zlist[i], alist[i]) : -1; + } - modelgrid[modelgridindex].cooling_contrib_ion = static_cast(malloc(get_nelements() * sizeof(double *))); + allocate_initradiobund(); - if (modelgrid[modelgridindex].cooling_contrib_ion == nullptr) { - printout("[fatal] input: not enough memory to initialize coolinglist for cell %d... abort\n", modelgridindex); - std::abort(); - } + return {colnames, nucindexlist, one_line_per_cell}; +} + +void read_1d_model() +// Read in a 1D spherical model +{ + auto fmodel = fstream_required("model.txt", std::ios::in); + + std::string line; + + // 1st read the number of data points in the table of input model. + int npts_model_in = 0; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> npts_model_in; + + set_npts_model(npts_model_in); + ncoord_model[0] = npts_model_in; + + vout_model = static_cast(malloc((get_npts_model() + 1) * sizeof(double))); + + // Now read the time (in days) at which the model is specified. + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; + + // Now read in the lines of the model. Each line has 5 entries: the + // cell number (integer) the velocity at outer boundary of cell (float), + // the mass density in the cell (float), the abundance of Ni56 by mass + // in the cell (float) and the total abundance of all Fe-grp elements + // in the cell (float). For now, the last number is recorded but never + // used. - modelgrid[modelgridindex].cooling_contrib_ion[0] = - static_cast(malloc(get_includedions() * sizeof(double))); + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { - modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex] = -1.; // flag as invalid - } + int mgi = 0; + while (std::getline(fmodel, line)) { + double vout_kmps{NAN}; + double log_rho{NAN}; + int cellnumberin = 0; + std::istringstream ssline(line); - int allionindex = 0; - for (int element = 0; element < get_nelements(); element++) { - /// and allocate memory to store the ground level populations for each ionisation stage + if (ssline >> cellnumberin >> vout_kmps >> log_rho) { + if (mgi == 0) { + first_cellindex = cellnumberin; + printout("first_cellindex %d\n", first_cellindex); + } + assert_always(cellnumberin == mgi + first_cellindex); - modelgrid[modelgridindex].cooling_contrib_ion[element] = - &modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex]; + vout_model[mgi] = vout_kmps * 1.e5; - assert_always(modelgrid[modelgridindex].cooling_contrib_ion[element] != nullptr); + const double rho_tmin = pow(10., log_rho) * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + set_rho(mgi, rho_tmin); + } else { + printout("Unexpected number of values in model.txt\n"); + printout("line: %s\n", line.c_str()); + assert_always(false); + } + read_model_radioabundances(fmodel, ssline, mgi, true, colnames, nucindexlist, one_line_per_cell); - allionindex += get_nions(element); + mgi += 1; + if (mgi == get_npts_model()) { + break; } } -} -static void allocate_nonemptymodelcells() { - // Determine the number of simulation cells associated with the model cells - for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { - mg_associated_cells[mgi] = 0; - modelgrid[mgi].initial_radial_pos_sum = 0.; + if (mgi != get_npts_model()) { + printout("ERROR in model.txt. Found only %d cells instead of %d expected.\n", mgi - 1, get_npts_model()); + std::abort(); } - for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const auto radial_pos_mid = get_cellradialposmid(cellindex); + globals::vmax = vout_model[get_npts_model() - 1]; +} - if (FORCE_SPHERICAL_ESCAPE_SURFACE && radial_pos_mid > globals::vmax * globals::tmin) { - // for 1D models, the final shell outer v should already be at vmax - assert_always(model_type != GRID_SPHERICAL1D || cell[cellindex].modelgridindex == get_npts_model()); - cell[cellindex].modelgridindex = get_npts_model(); - } +void read_2d_model() +// Read in a 2D axisymmetric spherical coordinate model +{ + auto fmodel = fstream_required("model.txt", std::ios::in); - const int mgi = get_cell_modelgridindex(cellindex); - assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); + std::string line; - mg_associated_cells[mgi] += 1; - modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; + // 1st read the number of data points in the table of input model. + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> ncoord_model[0] >> ncoord_model[1]; // r and z (cylindrical polar) + ncoord_model[2] = 0.; - assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || - (mgi == get_npts_model())); - } + set_npts_model(ncoord_model[0] * ncoord_model[1]); - // find number of non-empty cells and allocate nonempty list - nonempty_npts_model = 0; - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_numassociatedcells(mgi) > 0) { - nonempty_npts_model++; - } - } - assert_always(nonempty_npts_model > 0); + // Now read the time (in days) at which the model is specified. + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; - mgi_of_nonemptymgi.resize(nonempty_npts_model); + /// Now read in vmax for the model (in cm s^-1). + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> globals::vmax; - int nonemptymgi = 0; // index within list of non-empty modelgrid cells + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_numassociatedcells(mgi) > 0) { - if (get_rho_tmin(mgi) <= 0) { - printout("Error: negative or zero density. Abort.\n"); - std::abort(); - } - nonemptymgi_of_mgi[mgi] = nonemptymgi; - mgi_of_nonemptymgi[nonemptymgi] = mgi; - nonemptymgi++; - } else { - nonemptymgi_of_mgi[mgi] = -1; - set_rho_tmin(mgi, 0.); - set_rho(mgi, 0.); - if (modelgrid[mgi].initradioabund != nullptr) { - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - set_modelinitradioabund(mgi, nucindex, 0.); - } - } + // Now read in the model. Each point in the model has two lines of input. + // First is an index for the cell then its r-mid point then its z-mid point + // then its total mass density. + // Second is the total FeG mass, initial 56Ni mass, initial 56Co mass + + int mgi = 0; + int nonemptymgi = 0; + while (std::getline(fmodel, line)) { + int cellnumberin = 0; + float cell_r_in{NAN}; + float cell_z_in{NAN}; + double rho_tmodel{NAN}; + std::istringstream ssline(line); + assert_always(ssline >> cellnumberin >> cell_r_in >> cell_z_in >> rho_tmodel); + + if (mgi == 0) { + first_cellindex = cellnumberin; } - } + assert_always(cellnumberin == mgi + first_cellindex); - allocate_nonemptycells_composition_cooling(); + const int n_rcyl = (mgi % ncoord_model[0]); + const double pos_r_cyl_mid = (n_rcyl + 0.5) * globals::vmax * t_model / ncoord_model[0]; + assert_always(fabs((cell_r_in / pos_r_cyl_mid) - 1) < 1e-3); + const int n_z = (mgi / ncoord_model[0]); + const double pos_z_mid = globals::vmax * t_model * (-1 + 2 * (n_z + 0.5) / ncoord_model[1]); + assert_always(fabs((cell_z_in / pos_z_mid) - 1) < 1e-3); - if constexpr (EXPANSIONOPACITIES_ON || RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY > 0.) { - allocate_expansionopacities(); - } + if (rho_tmodel < 0) { + printout("negative input density %g %d\n", rho_tmodel, mgi); + std::abort(); + } - globals::dep_estimator_gamma.resize(nonempty_npts_model, 0.); - globals::dep_estimator_positron.resize(nonempty_npts_model, 0.); - globals::dep_estimator_electron.resize(nonempty_npts_model, 0.); - globals::dep_estimator_alpha.resize(nonempty_npts_model, 0.); + const bool keepcell = (rho_tmodel > 0); + const double rho_tmin = rho_tmodel * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + set_rho(mgi, rho_tmin); - auto ionestimsize = nonempty_npts_model * globals::nbfcontinua_ground * sizeof(double); + read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - if (USE_LUT_PHOTOION && ionestimsize > 0) { -#ifdef MPI_ON - auto my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); + if (keepcell) { + nonemptymgi++; } - auto size = static_cast(my_rank_cells * globals::nbfcontinua_ground * sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &globals::corrphotoionrenorm, - &globals::win_corrphotoionrenorm) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(globals::win_corrphotoionrenorm, 0, &size, &disp_unit, - &globals::corrphotoionrenorm) == MPI_SUCCESS); -#else - globals::corrphotoionrenorm = static_cast(malloc(ionestimsize)); -#endif - - globals::gammaestimator = static_cast(malloc(ionestimsize)); -#ifdef DO_TITER - globals::gammaestimator_save = static_cast(malloc(ionestimsize)); -#endif - } else { - globals::corrphotoionrenorm = nullptr; - globals::gammaestimator = nullptr; -#ifdef DO_TITER - globals::gammaestimator_save = nullptr; -#endif + mgi++; } - if (USE_LUT_BFHEATING && ionestimsize > 0) { - globals::bfheatingestimator = static_cast(malloc(ionestimsize)); -#ifdef DO_TITER - globals::bfheatingestimator_save = static_cast(malloc(ionestimsize)); -#endif - } else { - globals::bfheatingestimator = nullptr; -#ifdef DO_TITER - globals::bfheatingestimator_save = nullptr; -#endif + if (mgi != get_npts_model()) { + printout("ERROR in model.txt. Found %d only cells instead of %d expected.\n", mgi - 1, get_npts_model()); + std::abort(); } - globals::ffheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); - globals::colheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); -#ifdef DO_TITER - globals::ffheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); - globals::colheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); -#endif - -#ifdef MPI_ON - // barrier to make sure node master has set abundance values to node shared memory - MPI_Barrier(MPI_COMM_WORLD); -#endif - - printout("[info] mem_usage: the modelgrid array occupies %.3f MB\n", - (get_npts_model() + 1) * sizeof(modelgrid[0]) / 1024. / 1024.); - - printout("There are %zu modelgrid cells with associated propagation cells\n", nonempty_npts_model); - - printout( - "[info] mem_usage: NLTE populations for all allocated cells occupy a total of %.3f MB (node shared memory)\n", - get_nonempty_npts_model() * globals::total_nlte_levels * sizeof(double) / 1024. / 1024.); -} - -static void map_1dmodelto3dgrid() -// Map 1D spherical model grid onto propagation grid -{ - for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; - const int mgi = static_cast(std::find_if_not(vout_model, vout_model + get_npts_model(), - [cellvmid](double v_outer) { return v_outer < cellvmid; }) - - vout_model); - - if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); - } else { - set_cell_modelgridindex(cellindex, get_npts_model()); - } - } + printout("effectively used model grid cells: %d\n", nonemptymgi); } -static void map_2dmodelto3dgrid() -// Map 2D cylindrical model onto propagation grid +void read_3d_model() +/// Subroutine to read in a 3-D model. { - for (int cellindex = 0; cellindex < ngrid; cellindex++) { - int mgi = get_npts_model(); // default to empty unless set - - // map to 3D Cartesian grid - std::array pos_mid{}; - for (int d = 0; d < 3; d++) { - pos_mid[d] = (get_cellcoordmin(cellindex, d) + (0.5 * wid_init(cellindex, d))); - } + auto fmodel = fstream_required("model.txt", std::ios::in); - // 2D grid is uniform so rcyl and z positions can easily be calculated - const double rcylindrical = std::sqrt(std::pow(pos_mid[0], 2) + std::pow(pos_mid[1], 2)); + std::string line; - const int n_rcyl = static_cast(rcylindrical / globals::tmin / globals::vmax * ncoord_model[0]); - const int n_z = - static_cast((pos_mid[2] / globals::tmin + globals::vmax) / (2 * globals::vmax) * ncoord_model[1]); + /// 1st read the number of data points in the table of input model. + /// This MUST be the same number as the maximum number of points used in the grid - if not, abort. + int npts_model_in = 0; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> npts_model_in; + set_npts_model(npts_model_in); - if (n_rcyl >= 0 && n_rcyl < ncoord_model[0] && n_z >= 0 && n_z < ncoord_model[1]) { - mgi = (n_z * ncoord_model[0]) + n_rcyl; - } + ncoord_model[0] = ncoord_model[1] = ncoord_model[2] = static_cast(round(pow(npts_model_in, 1 / 3.))); + assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_model_in); - if (modelgrid[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); - } else { - set_cell_modelgridindex(cellindex, get_npts_model()); - } - } -} + // for a 3D input model, the progation cells will match the input cells exactly + ncoordgrid[0] = ncoord_model[0]; + ncoordgrid[1] = ncoord_model[1]; + ncoordgrid[2] = ncoord_model[2]; + ngrid = npts_model_in; -static void map_modeltogrid_direct() -// mgi and cellindex are interchangeable in this mode -{ - for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const int mgi = cellindex; // direct mapping + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; - if (modelgrid[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); - } else { - set_cell_modelgridindex(cellindex, get_npts_model()); - } - } -} + /// Now read in vmax for the model (in cm s^-1). + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> globals::vmax; -static void abundances_read() { -#ifdef MPI_ON - // barrier to make sure node master has set values in node shared memory - MPI_Barrier(MPI_COMM_WORLD); -#endif - printout("reading abundances.txt..."); - const bool threedimensional = (get_model_type() == GRID_CARTESIAN3D); + const double xmax_tmodel = globals::vmax * t_model; - /// Open the abundances file - auto abundance_file = fstream_required("abundances.txt", std::ios::in); + /// Now read in the lines of the model. + min_den = -1.; - /// and process through the grid to read in the abundances per cell - /// The abundance file should only contain information for non-empty - /// cells. Its format must be cellnumber (integer), abundance for - /// element Z=1 (float) up to abundance for element Z=30 (float) - /// i.e. in total one integer and 30 floats. + // check if expected positions match in either xyz or zyx column order + // set false if a problem is detected + bool posmatch_xyz = true; + bool posmatch_zyx = true; - // loop over propagation cells for 3D models, or modelgrid cells - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - std::string line; - assert_always(get_noncommentline(abundance_file, line)); - std::istringstream ssline(line); + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - int cellnumberinput = -1; - assert_always(ssline >> cellnumberinput); - assert_always(cellnumberinput == mgi + first_cellindex); + // mgi is the index to the model grid - empty cells are sent to special value get_npts_model(), + // otherwise each input cell is one modelgrid cell + int mgi = 0; // corresponds to model.txt index column, but zero indexed! (model.txt might be 1-indexed) + int nonemptymgi = 0; + while (std::getline(fmodel, line)) { + int cellnumberin = 0; + std::array cellpos_in{}; + float rho_model{NAN}; + std::istringstream ssline(line); - // the abundances.txt file specifies the elemental mass fractions for each model cell - // (or proportial to mass frac, e.g. element densities because they will be normalised anyway) - // The abundances begin with hydrogen, helium, etc, going as far up the atomic numbers as required - double normfactor = 0.; - float abundances_in[150] = {0.}; - double abund_in = 0.; - for (int anumber = 1; anumber <= 150; anumber++) { - abundances_in[anumber - 1] = 0.; - if (!(ssline >> abund_in)) { - // at least one element (hydrogen) should have been specified for nonempty cells - assert_always(anumber > 1 || get_numassociatedcells(mgi) == 0); - break; - } + assert_always(ssline >> cellnumberin >> cellpos_in[0] >> cellpos_in[1] >> cellpos_in[2] >> rho_model); + // printout("cell %d, posz %g, posy %g, posx %g, rho %g, rho_init %g\n",dum1,dum3,dum4,dum5,rho_model,rho_model* + // pow( (t_model/globals::tmin), 3.)); - if (abund_in < 0. || abund_in < std::numeric_limits::min()) { - assert_always(abund_in > -1e-6); - abund_in = 0.; - } - abundances_in[anumber - 1] = static_cast(abund_in); - normfactor += abundances_in[anumber - 1]; + if (mgi == 0) { + first_cellindex = cellnumberin; } + assert_always(cellnumberin == mgi + first_cellindex); - if (get_numassociatedcells(mgi) > 0) { - if (threedimensional || normfactor <= 0.) { - normfactor = 1.; - } + if (mgi % (ncoord_model[1] * ncoord_model[2]) == 0) { + printout("read up to cell mgi %d\n", mgi); + } - for (int element = 0; element < get_nelements(); element++) { - /// now set the abundances (by mass) of included elements, i.e. - /// read out the abundances specified in the atomic data file - const int anumber = get_atomicnumber(element); - const float elemabundance = abundances_in[anumber - 1] / normfactor; - assert_always(elemabundance >= 0.); + // cell coordinates in the 3D model.txt file are sometimes reordered by the scaling script + // however, the cellindex always should increment X first, then Y, then Z - // radioactive nuclide abundances should have already been set by read_??_model - set_elem_stable_abund_from_total(mgi, element, elemabundance); + for (int axis = 0; axis < 3; axis++) { + const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; + const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); + // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid + // %d\n", + // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, + // get_cellcoordpointnum(mgi, axis), ncoordgrid[axis]); + if (fabs(cellpos_expected - cellpos_in[axis]) > 0.5 * cellwidth) { + posmatch_xyz = false; + } + if (fabs(cellpos_expected - cellpos_in[2 - axis]) > 0.5 * cellwidth) { + posmatch_zyx = false; } } - } - -#ifdef MPI_ON - // barrier to make sure node master has set values in node shared memory - MPI_Barrier(MPI_COMM_WORLD); -#endif - printout("done.\n"); -} -static void parse_model_headerline(const std::string &line, std::vector &zlist, std::vector &alist, - std::vector &colnames) { - // custom header line - std::istringstream iss(line); - std::string token; + if (rho_model < 0) { + printout("negative input density %g %d\n", rho_model, mgi); + std::abort(); + } - int columnindex = -1; + // in 3D cartesian, cellindex and modelgridindex are interchangeable + const bool keepcell = (rho_model > 0); + const double rho_tmin = rho_model * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + set_rho(mgi, rho_tmin); - while (std::getline(iss, token, ' ')) { - if (std::ranges::all_of(token, isspace)) { // skip whitespace tokens - continue; + if (min_den < 0. || min_den > rho_model) { + min_den = rho_model; } - columnindex++; + read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - if (token == "#inputcellid") { - assert_always(columnindex == 0); - } else if (token == "velocity_outer") { - assert_always(columnindex == 1); - } else if (token == "vel_r_max_kmps") { - assert_always(columnindex == 1); - } else if (token.starts_with("pos_")) { - continue; - } else if (token == "logrho") { - // 1D models have log10(rho [g/cm3]) - assert_always(columnindex == 2); - assert_always(get_model_type() == GRID_SPHERICAL1D); - } else if (token == "rho") { - // 2D and 3D models have rho [g/cm3] - assert_always(get_model_type() != GRID_SPHERICAL1D); - assert_always((columnindex == 4 && get_model_type() == GRID_CARTESIAN3D) || - (columnindex == 3 && get_model_type() == GRID_CYLINDRICAL2D)); - continue; - } else if (token.starts_with("X_") && token != "X_Fegroup") { - colnames.push_back(token); - const int z = decay::get_nucstring_z(token.substr(2)); // + 2 skips the 'X_' - const int a = decay::get_nucstring_a(token.substr(2)); - assert_always(z >= 0); - assert_always(a >= 0); - // printout("Custom column: '%s' Z %d A %d\n", token.c_str(), z, a); - zlist.push_back(z); - alist.push_back(a); - } else { - // printout("Custom column: '%s' Z %d A %d\n", token.c_str(), -1, -1); - colnames.push_back(token); - zlist.push_back(-1); - alist.push_back(-1); + if (keepcell) { + nonemptymgi++; } + + mgi++; + } + if (mgi != npts_model_in) { + printout("ERROR in model.txt. Found %d cells instead of %d expected.\n", mgi, npts_model_in); + std::abort(); } -} -static auto get_token_count(std::string &line) -> int { - std::string token; - int abundcolcount = 0; - auto ssline = std::istringstream(line); - while (std::getline(ssline, token, ' ')) { - if (!std::ranges::all_of(token, isspace)) { // skip whitespace tokens - abundcolcount++; - } + // assert_always(posmatch_zyx ^ posmatch_xyz); // xor because if both match then probably an infinity occurred + if (posmatch_xyz) { + printout("Cell positions in model.txt are consistent with calculated values when x-y-z column order is used.\n"); + } + if (posmatch_zyx) { + printout("Cell positions in model.txt are consistent with calculated values when z-y-x column order is used.\n"); } - return abundcolcount; -} -static void read_model_radioabundances(std::fstream &fmodel, std::istringstream &ssline_in, const int mgi, - const bool keepcell, const std::vector &colnames, - const std::vector &nucindexlist, const bool one_line_per_cell) { - std::string line; - if (!one_line_per_cell) { - assert_always(std::getline(fmodel, line)); + if (!posmatch_xyz && !posmatch_zyx) { + printout( + "WARNING: Cell positions in model.txt are not consistent with calculated values in either x-y-z or z-y-x " + "order.\n"); } - auto ssline = one_line_per_cell ? std::move(ssline_in) : std::istringstream(line); + printout("min_den %g [g/cm3]\n", min_den); + printout("effectively used model grid cells: %d\n", nonemptymgi); +} - if (!keepcell) { - return; +void calc_modelinit_totmassradionuclides() { + mtot_input = 0.; + mfeg = 0.; + + assert_always(totmassradionuclide == nullptr); + totmassradionuclide = static_cast(malloc(decay::get_num_nuclides() * sizeof(double))); + assert_always(totmassradionuclide != nullptr); + + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + totmassradionuclide[nucindex] = 0.; } - for (size_t i = 0; i < colnames.size(); i++) { - double valuein = 0.; - assert_always(ssline >> valuein); // usually a mass fraction, but now can be anything + const double dcoord_rcyl = globals::vmax * t_model / ncoord_model[0]; // dr for input model + const double dcoord_z = 2. * globals::vmax * t_model / ncoord_model[1]; // dz for input model - if (nucindexlist[i] >= 0) { - assert_testmodeonly(valuein <= 1.); - set_modelinitradioabund(mgi, nucindexlist[i], valuein); - } else if (colnames[i] == "X_Fegroup") { - set_ffegrp(mgi, valuein); - } else if (colnames[i] == "cellYe") { - set_initelectronfrac(mgi, valuein); - } else if (colnames[i] == "q") { - // use value for t_model and adjust to tmin with expansion factor - set_initenergyq(mgi, valuein * t_model / globals::tmin); - } else if (colnames[i] == "tracercount") { - ; + for (int mgi = 0; mgi < get_npts_model(); mgi++) { + if (get_rho_tmin(mgi) <= 0.) { + continue; + } + double cellvolume = 0.; + if (get_model_type() == GRID_SPHERICAL1D) { + const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; + // mass_in_shell = rho_model[mgi] * (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(t_model, 3) / 3.; + cellvolume = (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(globals::tmin, 3) / 3.; + } else if (get_model_type() == GRID_CYLINDRICAL2D) { + const int n_r = mgi % ncoord_model[0]; + cellvolume = pow(globals::tmin / t_model, 3) * dcoord_z * PI * + (pow((n_r + 1) * dcoord_rcyl, 2.) - pow(n_r * dcoord_rcyl, 2.)); + } else if (get_model_type() == GRID_CARTESIAN3D) { + /// Assumes cells are cubes here - all same volume. + cellvolume = pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); } else { - if (mgi == 0) { - printout("WARNING: ignoring column '%s' nucindex %d valuein[mgi=0] %lg\n", colnames[i].c_str(), nucindexlist[i], - valuein); - } + printout("Unknown model type %d in function %s\n", get_model_type(), __func__); + std::abort(); } - } - double valuein = 0.; - assert_always(!(ssline >> valuein)); // should be no tokens left! -} -static auto read_model_columns(std::fstream &fmodel) -> std::tuple, std::vector, bool> { - auto pos_data_start = fmodel.tellg(); // get position in case we need to undo getline + const double mass_in_shell = get_rho_tmin(mgi) * cellvolume; - std::vector zlist; - std::vector alist; - std::vector colnames; + mtot_input += mass_in_shell; - std::string line; - std::getline(fmodel, line); + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + totmassradionuclide[nucindex] += mass_in_shell * get_modelinitradioabund(mgi, nucindex); + } - std::string headerline; + mfeg += mass_in_shell * get_ffegrp(mgi); + } - const bool header_specified = lineiscommentonly(line); + printout("Total input model mass: %9.3e [Msun]\n", mtot_input / MSUN); + printout("Nuclide masses at t=t_model_init [Msun]:"); + printout(" 56Ni: %9.3e 56Co: %9.3e 52Fe: %9.3e 48Cr: %9.3e\n", get_totmassradionuclide(28, 56) / MSUN, + get_totmassradionuclide(27, 56) / MSUN, get_totmassradionuclide(26, 52) / MSUN, + get_totmassradionuclide(24, 48) / MSUN); + printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfeg / MSUN, get_totmassradionuclide(28, 57) / MSUN, + get_totmassradionuclide(27, 57) / MSUN); +} - if (header_specified) { - // line is the header - headerline = line; - pos_data_start = fmodel.tellg(); - std::getline(fmodel, line); - } else { - // line is not a comment, so it must be the first line of data - // add a default header for unlabelled columns - switch (model_type) { - case GRID_SPHERICAL1D: - headerline = std::string("#inputcellid vel_r_max_kmps logrho"); - break; - case GRID_CYLINDRICAL2D: - headerline = std::string("#inputcellid pos_rcyl_mid pos_z_mid rho"); - break; - case GRID_CARTESIAN3D: - headerline = std::string("#inputcellid pos_x_min pos_y_min pos_z_min rho"); - break; - } - headerline += std::string(" X_Fegroup X_Ni56 X_Co56 X_Fe52 X_Cr48"); - } +void read_grid_restart_data(const int timestep) { + char filename[MAXFILENAMELENGTH]; + snprintf(filename, MAXFILENAMELENGTH, "gridsave_ts%d.tmp", timestep); - int colcount = get_token_count(line); - const bool one_line_per_cell = (colcount >= get_token_count(headerline)); + printout("READIN GRID SNAPSHOT from %s\n", filename); + FILE *gridsave_file = fopen_required(filename, "r"); - printout("model.txt has %s line per cell format\n", one_line_per_cell ? "one" : "two"); + int ntimesteps_in = -1; + assert_always(fscanf(gridsave_file, "%d ", &ntimesteps_in) == 1); + assert_always(ntimesteps_in == globals::ntimesteps); - if (!one_line_per_cell) { // add columns from the second line - std::getline(fmodel, line); - colcount += get_token_count(line); - } + int nprocs_in = -1; + assert_always(fscanf(gridsave_file, "%d ", &nprocs_in) == 1); + assert_always(nprocs_in == globals::nprocs); - if (!header_specified && colcount > get_token_count(headerline)) { - headerline += " X_Ni57 X_Co57"; + for (int nts = 0; nts < globals::ntimesteps; nts++) { + int pellet_decays = 0.; + assert_always(fscanf(gridsave_file, + "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", + &globals::timesteps[nts].gamma_dep, &globals::timesteps[nts].gamma_dep_discrete, + &globals::timesteps[nts].positron_dep, &globals::timesteps[nts].positron_dep_discrete, + &globals::timesteps[nts].positron_emission, &globals::timesteps[nts].eps_positron_ana_power, + &globals::timesteps[nts].electron_dep, &globals::timesteps[nts].electron_dep_discrete, + &globals::timesteps[nts].electron_emission, &globals::timesteps[nts].eps_electron_ana_power, + &globals::timesteps[nts].alpha_dep, &globals::timesteps[nts].alpha_dep_discrete, + &globals::timesteps[nts].alpha_emission, &globals::timesteps[nts].eps_alpha_ana_power, + &globals::timesteps[nts].qdot_betaminus, &globals::timesteps[nts].qdot_alpha, + &globals::timesteps[nts].qdot_total, &globals::timesteps[nts].gamma_emission, + &globals::timesteps[nts].cmf_lum, &pellet_decays) == 20); + globals::timesteps[nts].pellet_decays = pellet_decays; } - assert_always(colcount == get_token_count(headerline)); + int timestep_in = 0; + assert_always(fscanf(gridsave_file, "%d ", ×tep_in) == 1); + assert_always(timestep_in == timestep); - fmodel.seekg(pos_data_start); // get back to start of data + for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); + int mgi_in = -1; + float T_R = 0.; + float T_e = 0.; + float W = 0.; + float T_J = 0.; + int thick = 0; + double dep_estimator_gamma = 0.; - if (header_specified) { - printout("model.txt has header line: %s\n", headerline.c_str()); - } else { - printout("model.txt has no header line. Using default: %s\n", headerline.c_str()); - } + assert_always(fscanf(gridsave_file, "%d %a %a %a %a %d %la %a %a", &mgi_in, &T_R, &T_e, &W, &T_J, &thick, + &dep_estimator_gamma, &modelgrid[mgi].nne, &modelgrid[mgi].nnetot) == 9); - parse_model_headerline(headerline, zlist, alist, colnames); + if (mgi_in != mgi) { + printout("[fatal] read_grid_restart_data: cell mismatch in reading input gridsave.dat ... abort\n"); + printout("[fatal] read_grid_restart_data: read cellnumber %d, expected cellnumber %d\n", mgi_in, mgi); + assert_always(mgi_in == mgi); + } - decay::init_nuclides(zlist, alist); + assert_always(T_R >= 0.); + assert_always(T_e >= 0.); + assert_always(W >= 0.); + assert_always(T_J >= 0.); + assert_always(dep_estimator_gamma >= 0.); - std::vector nucindexlist(zlist.size()); - for (std::size_t i = 0; i < zlist.size(); i++) { - nucindexlist[i] = (zlist[i] > 0) ? decay::get_nucindex(zlist[i], alist[i]) : -1; - } + set_TR(mgi, T_R); + set_Te(mgi, T_e); + set_W(mgi, W); + set_TJ(mgi, T_J); + modelgrid[mgi].thick = thick; + globals::dep_estimator_gamma[nonemptymgi] = dep_estimator_gamma; - allocate_initradiobund(); + if constexpr (USE_LUT_PHOTOION) { + for (int i = 0; i < globals::nbfcontinua_ground; i++) { + const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; + assert_always(fscanf(gridsave_file, " %la %la", &globals::corrphotoionrenorm[estimindex], + &globals::gammaestimator[estimindex]) == 2); + } + } + } - return {colnames, nucindexlist, one_line_per_cell}; + // the order of these calls is very important! + radfield::read_restart_data(gridsave_file); + nonthermal::read_restart_data(gridsave_file); + nltepop_read_restart_data(gridsave_file); + fclose(gridsave_file); } -static void read_1d_model() -// Read in a 1D spherical model +void assign_initial_temperatures() +/// Routine for assigning temperatures to the grid cells at the start of the simulation. { - auto fmodel = fstream_required("model.txt", std::ios::in); +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif + /// For a simulation started from scratch we estimate the initial temperatures - std::string line; + /// We assume that for early times the material is so optically thick, that + /// all the radiation is trapped in the cell it originates from. This + /// means furthermore LTE, so that both temperatures can be evaluated + /// according to the local energy density resulting from the 56Ni decay. + /// The dilution factor is W=1 in LTE. - // 1st read the number of data points in the table of input model. - int npts_model_in = 0; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> npts_model_in; + printout("Assigning initial temperatures...\n"); - set_npts_model(npts_model_in); - ncoord_model[0] = npts_model_in; + const double tstart = globals::timesteps[0].mid; + int cells_below_mintemp = 0; + int cells_above_maxtemp = 0; - vout_model = static_cast(malloc((get_npts_model() + 1) * sizeof(double))); + for (int nonempymgi = 0; nonempymgi < get_nonempty_npts_model(); nonempymgi++) { + const int mgi = get_mgi_of_nonemptymgi(nonempymgi); - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; + double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(mgi, tstart); + if constexpr (INITIAL_PACKETS_ON && USE_MODEL_INITIAL_ENERGY) { + decayedenergy_per_mass += get_initenergyq(mgi); + } - // Now read in the lines of the model. Each line has 5 entries: the - // cell number (integer) the velocity at outer boundary of cell (float), - // the mass density in the cell (float), the abundance of Ni56 by mass - // in the cell (float) and the total abundance of all Fe-grp elements - // in the cell (float). For now, the last number is recorded but never - // used. + double T_initial = + pow(CLIGHT / 4 / STEBO * pow(globals::tmin / tstart, 3) * get_rho_tmin(mgi) * decayedenergy_per_mass, 1. / 4.); - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + if (T_initial < MINTEMP) { + // printout("mgi %d: T_initial of %g is below MINTEMP %g K, setting to MINTEMP.\n", mgi, T_initial, MINTEMP); + T_initial = MINTEMP; + cells_below_mintemp++; + } else if (T_initial > MAXTEMP) { + // printout("mgi %d: T_initial of %g is above MAXTEMP %g K, setting to MAXTEMP.\n", mgi, T_initial, MAXTEMP); + T_initial = MAXTEMP; + cells_above_maxtemp++; + } else if (!std::isfinite(T_initial)) { + printout("mgi %d: T_initial of %g is infinite!\n", mgi, T_initial); + } + assert_always(std::isfinite(T_initial)); - int mgi = 0; - while (std::getline(fmodel, line)) { - double vout_kmps{NAN}; - double log_rho{NAN}; - int cellnumberin = 0; - std::istringstream ssline(line); + set_Te(mgi, T_initial); + set_TJ(mgi, T_initial); + set_TR(mgi, T_initial); - if (ssline >> cellnumberin >> vout_kmps >> log_rho) { - if (mgi == 0) { - first_cellindex = cellnumberin; - printout("first_cellindex %d\n", first_cellindex); - } - assert_always(cellnumberin == mgi + first_cellindex); + set_W(mgi, 1.); + modelgrid[mgi].thick = 0; + } + printout(" cells below MINTEMP %g: %d\n", MINTEMP, cells_below_mintemp); + printout(" cells above MAXTEMP %g: %d\n", MAXTEMP, cells_above_maxtemp); +} - vout_model[mgi] = vout_kmps * 1.e5; +void setup_nstart_ndo() { + const int nprocesses = globals::nprocs; + const int npts_nonempty = get_nonempty_npts_model(); + const int min_nonempty_perproc = npts_nonempty / nprocesses; // integer division, minimum non-empty cells per process + const int n_remainder = npts_nonempty % nprocesses; + maxndo = 0; - const double rho_tmin = pow(10., log_rho) * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - } else { - printout("Unexpected number of values in model.txt\n"); - printout("line: %s\n", line.c_str()); - assert_always(false); + ranks_nstart.resize(nprocesses); + ranks_ndo.resize(nprocesses); + ranks_ndo_nonempty.resize(nprocesses); + + // begin with no cell assignments + std::ranges::fill(ranks_nstart, 0); + std::ranges::fill(ranks_ndo, 0); + std::ranges::fill(ranks_ndo_nonempty, 0); + + if (nprocesses >= get_npts_model()) { + // for convenience, rank == mgi when there is at least one rank per cell + maxndo = 1; + for (int r = 0; r < nprocesses; r++) { + if (r < get_npts_model()) { + const int mgi = r; + ranks_nstart[r] = mgi; + ranks_ndo[r] = 1; + ranks_ndo_nonempty[r] = (get_numassociatedcells(mgi) > 0) ? 1 : 0; + } } - read_model_radioabundances(fmodel, ssline, mgi, true, colnames, nucindexlist, one_line_per_cell); + } else { + // evenly divide up the non-empty cells among the ranks - mgi += 1; - if (mgi == get_npts_model()) { - break; + int rank = 0; + for (int mgi = 0; mgi < get_npts_model(); mgi++) { + const int target_nonempty_thisrank = (rank < n_remainder) ? min_nonempty_perproc + 1 : min_nonempty_perproc; + if ((rank < (nprocesses - 1)) && (ranks_ndo_nonempty[rank] >= target_nonempty_thisrank)) { + // current rank has enough non-empty cells, so start assigning cells to the next rank + rank++; + ranks_nstart[rank] = mgi; + } + + ranks_ndo[rank]++; + maxndo = std::max(maxndo, ranks_ndo[rank]); + if (get_numassociatedcells(mgi) > 0) { + ranks_ndo_nonempty[rank]++; + } } } - if (mgi != get_npts_model()) { - printout("ERROR in model.txt. Found only %d cells instead of %d expected.\n", mgi - 1, get_npts_model()); - std::abort(); + int npts_assigned = 0; + int npts_nonempty_assigned = 0; + for (int r = 0; r < nprocesses; r++) { + npts_assigned += ranks_ndo[r]; + npts_nonempty_assigned += ranks_ndo_nonempty[r]; } + assert_always(npts_assigned == get_npts_model()); + assert_always(npts_nonempty_assigned == get_nonempty_npts_model()); - globals::vmax = vout_model[get_npts_model() - 1]; + if (globals::rank_global == 0) { + auto fileout = std::ofstream("modelgridrankassignments.out"); + assert_always(fileout.is_open()); + fileout << "#rank nstart ndo ndo_nonempty\n"; + for (int r = 0; r < nprocesses; r++) { + fileout << r << " " << ranks_nstart[r] << " " << ranks_ndo[r] << " " << ranks_ndo_nonempty[r] << "\n"; + } + } } -static void read_2d_model() -// Read in a 2D axisymmetric spherical coordinate model +void setup_grid_cartesian_3d() +/// Routine for doing a uniform cuboidal grid. { - auto fmodel = fstream_required("model.txt", std::ios::in); - - std::string line; - - // 1st read the number of data points in the table of input model. - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> ncoord_model[0] >> ncoord_model[1]; // r and z (cylindrical polar) - ncoord_model[2] = 0.; - - set_npts_model(ncoord_model[0] * ncoord_model[1]); - - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; + // vmax is per coordinate, but the simulation volume corners will + // have a higher expansion velocity than the sides + const double vmax_corner = sqrt(3 * pow(globals::vmax, 2)); + printout("corner vmax %g [cm/s] (%.2fc)\n", vmax_corner, vmax_corner / CLIGHT); + if (!FORCE_SPHERICAL_ESCAPE_SURFACE) { + assert_always(vmax_corner < CLIGHT); + } - /// Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; + /// Set grid size for uniform xyz grid + if (get_model_type() == GRID_CARTESIAN3D) { + // if we used in a 3D ejecta model, the propagation grid must match the input grid exactly + ncoordgrid[0] = ncoord_model[0]; + ncoordgrid[1] = ncoord_model[1]; + ncoordgrid[2] = ncoord_model[2]; - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + // in case the user specified a grid size, we should ensure that it matches + assert_always(ncoordgrid[0] == CUBOID_NCOORDGRID_X || CUBOID_NCOORDGRID_X < 0); + assert_always(ncoordgrid[1] == CUBOID_NCOORDGRID_Y || CUBOID_NCOORDGRID_Y < 0); + assert_always(ncoordgrid[2] == CUBOID_NCOORDGRID_Z || CUBOID_NCOORDGRID_Z < 0); + } else { + ncoordgrid[0] = CUBOID_NCOORDGRID_X; + ncoordgrid[1] = CUBOID_NCOORDGRID_Y; + ncoordgrid[2] = CUBOID_NCOORDGRID_Z; + } - // Now read in the model. Each point in the model has two lines of input. - // First is an index for the cell then its r-mid point then its z-mid point - // then its total mass density. - // Second is the total FeG mass, initial 56Ni mass, initial 56Co mass + // artis assumes in some places that the cells are cubes, not cubioids + assert_always(ncoordgrid[0] == ncoordgrid[1]); + assert_always(ncoordgrid[0] == ncoordgrid[2]); - int mgi = 0; - int nonemptymgi = 0; - while (std::getline(fmodel, line)) { - int cellnumberin = 0; - float cell_r_in{NAN}; - float cell_z_in{NAN}; - double rho_tmodel{NAN}; - std::istringstream ssline(line); - assert_always(ssline >> cellnumberin >> cell_r_in >> cell_z_in >> rho_tmodel); + ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; + cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); - if (mgi == 0) { - first_cellindex = cellnumberin; + coordlabel[0] = 'X'; + coordlabel[1] = 'Y'; + coordlabel[2] = 'Z'; + std::array nxyz = {0, 0, 0}; + for (int n = 0; n < ngrid; n++) { + for (int axis = 0; axis < 3; axis++) { + assert_always(nxyz[axis] == get_cellcoordpointnum(n, axis)); + cell[n].pos_min[axis] = -globals::rmax + (2 * nxyz[axis] * globals::rmax / ncoordgrid[axis]); + // cell[n].xyz[axis] = nxyz[axis]; } - assert_always(cellnumberin == mgi + first_cellindex); - const int n_rcyl = (mgi % ncoord_model[0]); - const double pos_r_cyl_mid = (n_rcyl + 0.5) * globals::vmax * t_model / ncoord_model[0]; - assert_always(fabs(cell_r_in / pos_r_cyl_mid - 1) < 1e-3); - const int n_z = (mgi / ncoord_model[0]); - const double pos_z_mid = globals::vmax * t_model * (-1 + 2 * (n_z + 0.5) / ncoord_model[1]); - assert_always(fabs(cell_z_in / pos_z_mid - 1) < 1e-3); + assert_always(n == nxyz[2] * ncoordgrid[1] * ncoordgrid[2] + nxyz[1] * ncoordgrid[0] + nxyz[0]); - if (rho_tmodel < 0) { - printout("negative input density %g %d\n", rho_tmodel, mgi); - std::abort(); + nxyz[0]++; // increment x coordinate + if (nxyz[0] == ncoordgrid[0]) { + nxyz[0] = 0; + nxyz[1]++; // increment y coordinate } - - const bool keepcell = (rho_tmodel > 0); - const double rho_tmin = rho_tmodel * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - - read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - - if (keepcell) { - nonemptymgi++; + if (nxyz[1] == ncoordgrid[1]) { + nxyz[1] = 0; + nxyz[2]++; // increment z coordinate } - - mgi++; } +} - if (mgi != get_npts_model()) { - printout("ERROR in model.txt. Found %d only cells instead of %d expected.\n", mgi - 1, get_npts_model()); - std::abort(); - } +void setup_grid_spherical1d() { + assert_always(get_model_type() == GRID_SPHERICAL1D); + coordlabel[0] = 'r'; + coordlabel[1] = '_'; + coordlabel[2] = '_'; - printout("effectively used model grid cells: %d\n", nonemptymgi); -} + ncoordgrid[0] = get_npts_model(); + ncoordgrid[1] = 1; + ncoordgrid[2] = 1; -static void read_3d_model() -/// Subroutine to read in a 3-D model. -{ - auto fmodel = fstream_required("model.txt", std::ios::in); + ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; + cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); - std::string line; + // direct mapping, cellindex and modelgridindex are the same + for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { + const int mgi = cellindex; // interchangeable in this mode + const double v_inner = mgi > 0 ? vout_model[mgi - 1] : 0.; + set_cell_modelgridindex(cellindex, mgi); + cell[cellindex].pos_min[0] = v_inner * globals::tmin; + cell[cellindex].pos_min[1] = 0.; + cell[cellindex].pos_min[2] = 0.; + } +} - /// 1st read the number of data points in the table of input model. - /// This MUST be the same number as the maximum number of points used in the grid - if not, abort. - int npts_model_in = 0; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> npts_model_in; - set_npts_model(npts_model_in); +void setup_grid_cylindrical_2d() { + const double vmax_corner = sqrt(2 * pow(globals::vmax, 2)); + printout("corner vmax %g [cm/s] (%.2fc)\n", vmax_corner, vmax_corner / CLIGHT); + assert_always(vmax_corner < CLIGHT); - ncoord_model[0] = ncoord_model[1] = ncoord_model[2] = static_cast(round(pow(npts_model_in, 1 / 3.))); - assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_model_in); + assert_always(get_model_type() == GRID_CYLINDRICAL2D); + coordlabel[0] = 'r'; + coordlabel[1] = 'z'; + coordlabel[2] = '_'; - // for a 3D input model, the progation cells will match the input cells exactly ncoordgrid[0] = ncoord_model[0]; ncoordgrid[1] = ncoord_model[1]; ncoordgrid[2] = ncoord_model[2]; - ngrid = npts_model_in; - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; + ngrid = ncoordgrid[0] * ncoordgrid[1]; + cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); - /// Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; + // direct mapping, cellindex and modelgridindex are the same + for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { + const int mgi = cellindex; // interchangeable in this mode + set_cell_modelgridindex(cellindex, mgi); - const double xmax_tmodel = globals::vmax * t_model; + const int n_rcyl = get_cellcoordpointnum(cellindex, 0); + const int n_z = get_cellcoordpointnum(cellindex, 1); + + cell[cellindex].pos_min[0] = n_rcyl * globals::rmax / ncoord_model[0]; + cell[cellindex].pos_min[1] = globals::rmax * (-1 + n_z * 2. / ncoord_model[1]); + cell[cellindex].pos_min[2] = 0.; + } +} + +auto get_grid_type_name() -> std::string { + switch (GRID_TYPE) { + case GRID_SPHERICAL1D: + return "spherical"; + case GRID_CYLINDRICAL2D: + return "cylindrical"; + case GRID_CARTESIAN3D: + return "uniform cuboidal"; + default: { + return "unknown"; + } + } +} + +auto get_poscoordpointnum(const double pos, const double time, const int axis) -> int { + // pos must be position in grid coordinate system, not necessarily xyz + + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); + } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + if (axis == 0) { + return static_cast(pos / time / globals::vmax * ncoordgrid[axis]); + } + if (axis == 1) { + return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); + } + assert_always(false); + + } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + for (int n_r = 0; n_r < ncoordgrid[0]; n_r++) { + if ((pos >= grid::get_cellcoordmin(n_r, 0)) && (pos < grid::get_cellcoordmax(n_r, 0))) { + return n_r; + } + } + assert_always(false); + } else { + assert_always(false); + } +} + +constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { + auto posgridcoord = std::array{}; + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + posgridcoord[0] = pos_xyz[0]; + posgridcoord[1] = pos_xyz[1]; + posgridcoord[2] = pos_xyz[2]; + } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + posgridcoord[0] = std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)); + posgridcoord[1] = pos_xyz[2]; + posgridcoord[2] = 0.; + } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + posgridcoord[0] = vec_len(pos_xyz); + posgridcoord[1] = 0.; + posgridcoord[2] = 0.; + } + return posgridcoord; +} - /// Now read in the lines of the model. - min_den = -1.; +template +[[nodiscard]] [[gnu::pure]] constexpr auto expanding_shell_intersection( + const std::array pos, const std::array dir, const double speed, + const double shellradiuststart, const bool isinnerboundary, const double tstart) -> double +// find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are +// 3-vectors) or expanding circle (2D vectors) +// returns -1 if there are no forward intersections (or if the intersection +// is tangential to the shell) +{ + assert_always(shellradiuststart > 0); - // check if expected positions match in either xyz or zyx column order - // set false if a problem is detected - bool posmatch_xyz = true; - bool posmatch_zyx = true; + // quadratic equation for intersection of ray with sphere + // a*d^2 + b*d + c = 0 + const double a = dot(dir, dir) - pow(shellradiuststart / tstart / speed, 2); + const double b = 2 * (dot(dir, pos) - pow(shellradiuststart, 2) / tstart / speed); + const double c = dot(pos, pos) - pow(shellradiuststart, 2); - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + const double discriminant = pow(b, 2) - (4 * a * c); - // mgi is the index to the model grid - empty cells are sent to special value get_npts_model(), - // otherwise each input cell is one modelgrid cell - int mgi = 0; // corresponds to model.txt index column, but zero indexed! (model.txt might be 1-indexed) - int nonemptymgi = 0; - while (std::getline(fmodel, line)) { - int cellnumberin = 0; - std::array cellpos_in{}; - float rho_model{NAN}; - std::istringstream ssline(line); + if (discriminant < 0) { + // no intersection + assert_always(isinnerboundary); + assert_always(shellradiuststart < vec_len(pos)); + return -1; + } - assert_always(ssline >> cellnumberin >> cellpos_in[0] >> cellpos_in[1] >> cellpos_in[2] >> rho_model); - // printout("cell %d, posz %g, posy %g, posx %g, rho %g, rho_init %g\n",dum1,dum3,dum4,dum5,rho_model,rho_model* - // pow( (t_model/globals::tmin), 3.)); + if (discriminant > 0) { + // two intersections + double dist1 = (-b + sqrt(discriminant)) / 2 / a; + double dist2 = (-b - sqrt(discriminant)) / 2 / a; - if (mgi == 0) { - first_cellindex = cellnumberin; - } - assert_always(cellnumberin == mgi + first_cellindex); + auto posfinal1 = std::array{0.}; + auto posfinal2 = std::array{0.}; - if (mgi % (ncoord_model[1] * ncoord_model[2]) == 0) { - printout("read up to cell mgi %d\n", mgi); + for (size_t d = 0; d < pos.size(); d++) { + posfinal1[d] = pos[d] + dist1 * dir[d]; + posfinal2[d] = pos[d] + dist2 * dir[d]; } - // cell coordinates in the 3D model.txt file are sometimes reordered by the scaling script - // however, the cellindex always should increment X first, then Y, then Z + const double v_rad_shell = shellradiuststart / tstart; + const double v_rad_final1 = dot(dir, posfinal1) * speed / vec_len(posfinal1); + const double v_rad_final2 = dot(dir, posfinal2) * speed / vec_len(posfinal2); - for (int axis = 0; axis < 3; axis++) { - const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; - const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); - // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid - // %d\n", - // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, - // get_cellcoordpointnum(mgi, axis), ncoordgrid[axis]); - if (fabs(cellpos_expected - cellpos_in[axis]) > 0.5 * cellwidth) { - posmatch_xyz = false; + // invalidate any solutions that require entering the boundary from the wrong radial direction + if (isinnerboundary) { + // if the packet's radial velocity at intersection is greater than the inner shell's radial velocity, + // then it is catching up from below the inner shell and should pass through it + if (v_rad_final1 > v_rad_shell) { + dist1 = -1; } - if (fabs(cellpos_expected - cellpos_in[2 - axis]) > 0.5 * cellwidth) { - posmatch_zyx = false; + if (v_rad_final2 > v_rad_shell) { + dist2 = -1; + } + } else { + // if the packet's radial velocity at intersection is less than the outer shell's radial velocity, + // then it is coming from above the outer shell and should pass through it + if (v_rad_final1 < v_rad_shell) { + dist1 = -1; + } + if (v_rad_final2 < v_rad_shell) { + dist2 = -1; } } - if (rho_model < 0) { - printout("negative input density %g %d\n", rho_model, mgi); - std::abort(); +#if (TESTMODE) + if (dist1 >= 0) { + const double shellradiusfinal1 = shellradiuststart / tstart * (tstart + dist1 / speed); + assert_testmodeonly(fabs((vec_len(posfinal1) / shellradiusfinal1) - 1.) < 1e-3); } + if (dist2 >= 0) { + const double shellradiusfinal2 = shellradiuststart / tstart * (tstart + dist2 / speed); + assert_testmodeonly(fabs((vec_len(posfinal2) / shellradiusfinal2) - 1.) < 1e-3); + } +#endif - // in 3D cartesian, cellindex and modelgridindex are interchangeable - const bool keepcell = (rho_model > 0); - const double rho_tmin = rho_model * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - - if (min_den < 0. || min_den > rho_model) { - min_den = rho_model; + // negative d means in the reverse direction along the ray + // ignore negative d values, and if two are positive then return the smaller one + if (dist1 < 0 && dist2 < 0) { + return -1; + } + if (dist2 < 0) { + return dist1; + } + if (dist1 < 0) { + return dist2; } + return std::min(dist1, dist2); - read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); + } // exactly one intersection - if (keepcell) { - nonemptymgi++; - } + // one intersection + // ignore this and don't change which cell the packet is in + assert_always(shellradiuststart <= vec_len(pos)); + return -1.; +} - mgi++; - } - if (mgi != npts_model_in) { - printout("ERROR in model.txt. Found %d cells instead of %d expected.\n", mgi, npts_model_in); - std::abort(); - } +auto get_coordboundary_distances_cylindrical2d(const std::array pkt_pos, const std::array pkt_dir, + const std::array pktposgridcoord, + const std::array pktvelgridcoord, const int cellindex, + const double tstart, const std::array cellcoordmax) + -> std::tuple, std::array> { + // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the + // propagation speed set to the xy component of the 3-velocity - // assert_always(posmatch_zyx ^ posmatch_xyz); // xor because if both match then probably an infinity occurred - if (posmatch_xyz) { - printout("Cell positions in model.txt are consistent with calculated values when x-y-z column order is used.\n"); - } - if (posmatch_zyx) { - printout("Cell positions in model.txt are consistent with calculated values when z-y-x column order is used.\n"); + std::array d_coordminboundary{}; + std::array d_coordmaxboundary{}; + + const std::array posnoz = {pkt_pos[0], pkt_pos[1]}; + + const double dirxylen = std::sqrt((pkt_dir[0] * pkt_dir[0]) + (pkt_dir[1] * pkt_dir[1])); + const double xyspeed = dirxylen * CLIGHT_PROP; // r_cyl component of velocity + + // make a normalised direction vector in the xy plane + const std::array dirnoz = {pkt_dir[0] / dirxylen, pkt_dir[1] / dirxylen}; + + const double r_inner = grid::get_cellcoordmin(cellindex, 0) * tstart / globals::tmin; + d_coordminboundary[0] = -1; + // don't try to calculate the intersection if the inner radius is zero + if (r_inner > 0) { + const double d_rcyl_coordminboundary = expanding_shell_intersection(posnoz, dirnoz, xyspeed, r_inner, true, tstart); + if (d_rcyl_coordminboundary >= 0) { + const double d_z_coordminboundary = d_rcyl_coordminboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; + d_coordminboundary[0] = std::sqrt((d_rcyl_coordminboundary * d_rcyl_coordminboundary) + + (d_z_coordminboundary * d_z_coordminboundary)); + } } - if (!posmatch_xyz && !posmatch_zyx) { - printout( - "WARNING: Cell positions in model.txt are not consistent with calculated values in either x-y-z or z-y-x " - "order.\n"); + const double r_outer = cellcoordmax[0] * tstart / globals::tmin; + const double d_rcyl_coordmaxboundary = expanding_shell_intersection(posnoz, dirnoz, xyspeed, r_outer, false, tstart); + d_coordmaxboundary[0] = -1; + if (d_rcyl_coordmaxboundary >= 0) { + const double d_z_coordmaxboundary = d_rcyl_coordmaxboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; + d_coordmaxboundary[0] = + std::sqrt((d_rcyl_coordmaxboundary * d_rcyl_coordmaxboundary) + (d_z_coordmaxboundary * d_z_coordmaxboundary)); } - printout("min_den %g [g/cm3]\n", min_den); - printout("effectively used model grid cells: %d\n", nonemptymgi); + // z boundaries are the same as Cartesian + const double t_zcoordminboundary = + ((pktposgridcoord[1] - (pktvelgridcoord[1] * tstart)) / + ((grid::get_cellcoordmin(cellindex, 1)) - (pktvelgridcoord[1] * globals::tmin)) * globals::tmin) - + tstart; + d_coordminboundary[1] = CLIGHT_PROP * t_zcoordminboundary; + + const double t_zcoordmaxboundary = ((pktposgridcoord[1] - (pktvelgridcoord[1] * tstart)) / + ((cellcoordmax[1]) - (pktvelgridcoord[1] * globals::tmin)) * globals::tmin) - + tstart; + d_coordmaxboundary[1] = CLIGHT_PROP * t_zcoordmaxboundary; + + return {d_coordminboundary, d_coordmaxboundary}; } -static void calc_modelinit_totmassradionuclides() { - mtot_input = 0.; - mfeg = 0.; +} // anonymous namespace - assert_always(totmassradionuclide == nullptr); - totmassradionuclide = static_cast(malloc(decay::get_num_nuclides() * sizeof(double))); - assert_always(totmassradionuclide != nullptr); +auto wid_init(const int cellindex, const int axis) -> double +// for a uniform grid this is the extent along the x,y,z coordinate (x_2 - x_1, etc.) +// for spherical grid this is the radial extent (r_outer - r_inner) +// these values are at time globals::tmin +{ + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + return 2 * globals::rmax / ncoordgrid[axis]; + } - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - totmassradionuclide[nucindex] = 0.; + if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + return (axis == 0) ? globals::rmax / ncoordgrid[axis] : 2 * globals::rmax / ncoordgrid[axis]; } - const double dcoord_rcyl = globals::vmax * t_model / ncoord_model[0]; // dr for input model - const double dcoord_z = 2. * globals::vmax * t_model / ncoord_model[1]; // dz for input model + if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + const int modelgridindex = get_cell_modelgridindex(cellindex); + const double v_inner = modelgridindex > 0 ? vout_model[modelgridindex - 1] : 0.; + return (vout_model[modelgridindex] - v_inner) * globals::tmin; + } - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_rho_tmin(mgi) <= 0.) { - continue; - } - double cellvolume = 0.; - if (get_model_type() == GRID_SPHERICAL1D) { - const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; - // mass_in_shell = rho_model[mgi] * (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(t_model, 3) / 3.; - cellvolume = (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(globals::tmin, 3) / 3.; - } else if (get_model_type() == GRID_CYLINDRICAL2D) { - const int n_r = mgi % ncoord_model[0]; - cellvolume = pow(globals::tmin / t_model, 3) * dcoord_z * PI * - (pow((n_r + 1) * dcoord_rcyl, 2.) - pow(n_r * dcoord_rcyl, 2.)); - } else if (get_model_type() == GRID_CARTESIAN3D) { - /// Assumes cells are cubes here - all same volume. - cellvolume = pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); - } else { - printout("Unknown model type %d in function %s\n", get_model_type(), __func__); - std::abort(); - } + assert_always(false); +} + +auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double +// return the model cell volume (when mapped to the propagation cells) at globals::tmin +// for a uniform cubic grid this is constant +{ + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + return (wid_init(modelgridindex, 0) * wid_init(modelgridindex, 1) * wid_init(modelgridindex, 2)) * + get_numassociatedcells(modelgridindex); + } - const double mass_in_shell = get_rho_tmin(mgi) * cellvolume; + if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + return wid_init(modelgridindex, 1) * PI * + (pow(get_cellcoordmax(modelgridindex, 0), 2) - pow(get_cellcoordmin(modelgridindex, 0), 2)); + } - mtot_input += mass_in_shell; + if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + return 4. / 3. * PI * (pow(get_cellcoordmax(modelgridindex, 0), 3) - pow(get_cellcoordmin(modelgridindex, 0), 3)); + } - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - totmassradionuclide[nucindex] += mass_in_shell * get_modelinitradioabund(mgi, nucindex); - } + assert_always(false); +} - mfeg += mass_in_shell * get_ffegrp(mgi); +auto get_gridcell_volume_tmin(const int cellindex) -> double +// return the propagation cell volume at globals::tmin +// for a spherical grid, the cell index is required (and should be equivalent to a modelgridindex) +{ + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + return (wid_init(cellindex, 0) * wid_init(cellindex, 0) * wid_init(cellindex, 0)); } - printout("Total input model mass: %9.3e [Msun]\n", mtot_input / MSUN); - printout("Nuclide masses at t=t_model_init [Msun]:"); - printout(" 56Ni: %9.3e 56Co: %9.3e 52Fe: %9.3e 48Cr: %9.3e\n", get_totmassradionuclide(28, 56) / MSUN, - get_totmassradionuclide(27, 56) / MSUN, get_totmassradionuclide(26, 52) / MSUN, - get_totmassradionuclide(24, 48) / MSUN); - printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfeg / MSUN, get_totmassradionuclide(28, 57) / MSUN, - get_totmassradionuclide(27, 57) / MSUN); + // 2D and 1D with direct mapping to propagation cells + const int mgi = get_cell_modelgridindex(cellindex); + return get_modelcell_assocvolume_tmin(mgi); } -void read_ejecta_model() { - switch (get_model_type()) { - case GRID_SPHERICAL1D: { - printout("Read 1D model\n"); - read_1d_model(); - break; - } +auto get_cellcoordmax(const int cellindex, const int axis) -> double +// get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell +// e.g., the minimum x position in xyz coords, or the minimum radius +{ + if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(0, axis); + } - case GRID_CYLINDRICAL2D: { - printout("Read 2D model\n"); + if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + assert_testmodeonly(axis <= 1); + return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); + } - read_2d_model(); - break; - } + if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + assert_testmodeonly(axis == 0); + return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); + } - case GRID_CARTESIAN3D: { - printout("Read 3D model\n"); + assert_always(false); +} - read_3d_model(); - break; - } +auto get_cellcoordmin(const int cellindex, const int axis) -> double +// get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell +// e.g., the minimum x position in xyz coords, or the minimum radius +{ + return cell[cellindex].pos_min[axis]; + // return - coordmax[axis] + (2 * get_cellcoordpointnum(cellindex, axis) * coordmax[axis] / ncoordgrid[axis]); +} - default: { +auto get_coordcellindexincrement(const int axis) -> int +// how much do we change the cellindex to move along a coordinately axis (e.g., the x, y, z directions, or r +// direction) +{ + // assert_testmodeonly(axis < get_ngriddimensions()); + + switch (axis) { + case 0: + return 1; + + case 1: + return ncoordgrid[0]; + + case 2: + return ncoordgrid[0] * ncoordgrid[1]; + + default: if constexpr (TESTMODE) { - printout("ERROR: Unknown model type %d\n", get_model_type()); + printout("invalid coordinate index %d", axis); assert_testmodeonly(false); } else { __builtin_unreachable(); } - } } +} - printout("npts_model: %d\n", get_npts_model()); - globals::rmax = globals::vmax * globals::tmin; - printout("vmax %g [cm/s] (%.2fc)\n", globals::vmax, globals::vmax / CLIGHT); - assert_always(globals::vmax < CLIGHT); - printout("tmin %g [s] = %.2f [d]\n", globals::tmin, globals::tmin / 86400.); - printout("rmax %g [cm] (at t=tmin)\n", globals::rmax); +auto get_cellcoordpointnum(const int cellindex, const int axis) -> int +// convert a cell index number into an integer (x,y,z or r) coordinate index from 0 to ncoordgrid[axis] +{ + if constexpr (GRID_TYPE == GRID_CARTESIAN3D || GRID_TYPE == GRID_CYLINDRICAL2D) { + switch (axis) { + // 3D Cartesian: increment x first, then y, then z + // 2D Cylindrical: increment r first, then z + case 0: + return cellindex % ncoordgrid[0]; - calc_modelinit_totmassradionuclides(); + case 1: + return (cellindex / ncoordgrid[0]) % ncoordgrid[1]; - read_possible_yefile(); + case 2: + return (cellindex / (ncoordgrid[0] * ncoordgrid[1])) % ncoordgrid[2]; + + default: + if constexpr (TESTMODE) { + printout("invalid coordinate index %d", axis); + assert_testmodeonly(false); + } else { + __builtin_unreachable(); + } + } + } + + if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + return cellindex; + } + + assert_always(false); } -static void read_grid_restart_data(const int timestep) { - char filename[MAXFILENAMELENGTH]; - snprintf(filename, MAXFILENAMELENGTH, "gridsave_ts%d.tmp", timestep); +auto get_rho_tmin(const int modelgridindex) -> float { return modelgrid[modelgridindex].rhoinit; } - printout("READIN GRID SNAPSHOT from %s\n", filename); - FILE *gridsave_file = fopen_required(filename, "r"); +__host__ __device__ auto get_rho(const int modelgridindex) -> float { return modelgrid[modelgridindex].rho; } - int ntimesteps_in = -1; - assert_always(fscanf(gridsave_file, "%d ", &ntimesteps_in) == 1); - assert_always(ntimesteps_in == globals::ntimesteps); +__host__ __device__ auto get_nne(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); - int nprocs_in = -1; - assert_always(fscanf(gridsave_file, "%d ", &nprocs_in) == 1); - assert_always(nprocs_in == globals::nprocs); + const double nne = modelgrid[modelgridindex].nne; + assert_testmodeonly(std::isfinite(nne)); + return nne; +} - for (int nts = 0; nts < globals::ntimesteps; nts++) { - int pellet_decays = 0.; - assert_always(fscanf(gridsave_file, - "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", - &globals::timesteps[nts].gamma_dep, &globals::timesteps[nts].gamma_dep_discrete, - &globals::timesteps[nts].positron_dep, &globals::timesteps[nts].positron_dep_discrete, - &globals::timesteps[nts].positron_emission, &globals::timesteps[nts].eps_positron_ana_power, - &globals::timesteps[nts].electron_dep, &globals::timesteps[nts].electron_dep_discrete, - &globals::timesteps[nts].electron_emission, &globals::timesteps[nts].eps_electron_ana_power, - &globals::timesteps[nts].alpha_dep, &globals::timesteps[nts].alpha_dep_discrete, - &globals::timesteps[nts].alpha_emission, &globals::timesteps[nts].eps_alpha_ana_power, - &globals::timesteps[nts].qdot_betaminus, &globals::timesteps[nts].qdot_alpha, - &globals::timesteps[nts].qdot_total, &globals::timesteps[nts].gamma_emission, - &globals::timesteps[nts].cmf_lum, &pellet_decays) == 20); - globals::timesteps[nts].pellet_decays = pellet_decays; - } +__host__ __device__ auto get_nnetot(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); - int timestep_in = 0; - assert_always(fscanf(gridsave_file, "%d ", ×tep_in) == 1); - assert_always(timestep_in == timestep); + const double nnetot = modelgrid[modelgridindex].nnetot; + assert_always(std::isfinite(nnetot)); + return nnetot; +} - for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { - const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - int mgi_in = -1; - float T_R = 0.; - float T_e = 0.; - float W = 0.; - float T_J = 0.; - int thick = 0; - double dep_estimator_gamma = 0.; +__host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } - assert_always(fscanf(gridsave_file, "%d %a %a %a %a %d %la %a %a", &mgi_in, &T_R, &T_e, &W, &T_J, &thick, - &dep_estimator_gamma, &modelgrid[mgi].nne, &modelgrid[mgi].nnetot) == 9); +void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) +// mass fraction of an element (all isotopes combined) +{ + modelgrid[modelgridindex].composition[element].abundance = newabundance; +} - if (mgi_in != mgi) { - printout("[fatal] read_grid_restart_data: cell mismatch in reading input gridsave.dat ... abort\n"); - printout("[fatal] read_grid_restart_data: read cellnumber %d, expected cellnumber %d\n", mgi_in, mgi); - assert_always(mgi_in == mgi); - } +__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double +// mass fraction of an element (all isotopes combined) +{ + const double elem_meanweight = grid::get_element_meanweight(modelgridindex, element); + return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); +} - assert_always(T_R >= 0.); - assert_always(T_e >= 0.); - assert_always(W >= 0.); - assert_always(T_J >= 0.); - assert_always(dep_estimator_gamma >= 0.); +__host__ __device__ auto get_kappagrey(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex <= get_npts_model()); + return modelgrid[modelgridindex].kappagrey; +} - set_TR(mgi, T_R); - set_Te(mgi, T_e); - set_W(mgi, W); - set_TJ(mgi, T_J); - modelgrid[mgi].thick = thick; - globals::dep_estimator_gamma[nonemptymgi] = dep_estimator_gamma; +__host__ __device__ auto get_Te(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex <= get_npts_model()); + return modelgrid[modelgridindex].Te; +} - if constexpr (USE_LUT_PHOTOION) { - for (int i = 0; i < globals::nbfcontinua_ground; i++) { - const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; - assert_always(fscanf(gridsave_file, " %la %la", &globals::corrphotoionrenorm[estimindex], - &globals::gammaestimator[estimindex]) == 2); - } - } - } +__host__ __device__ auto get_TR(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex <= get_npts_model()); + return modelgrid[modelgridindex].TR; +} - // the order of these calls is very important! - radfield::read_restart_data(gridsave_file); - nonthermal::read_restart_data(gridsave_file); - nltepop_read_restart_data(gridsave_file); - fclose(gridsave_file); +__host__ __device__ auto get_TJ(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex <= get_npts_model()); + return modelgrid[modelgridindex].TJ; +} + +__host__ __device__ auto get_W(const int modelgridindex) -> float { + assert_testmodeonly(modelgridindex >= 0); + assert_testmodeonly(modelgridindex <= get_npts_model()); + return modelgrid[modelgridindex].W; +} + +void set_rho(const int modelgridindex, const float rho) { + assert_always(rho >= 0.); + assert_always(std::isfinite(rho)); + modelgrid[modelgridindex].rho = rho; } -void write_grid_restart_data(const int timestep) { - char filename[MAXFILENAMELENGTH]; - snprintf(filename, MAXFILENAMELENGTH, "gridsave_ts%d.tmp", timestep); +void set_nne(const int modelgridindex, const float nne) { + assert_always(nne >= 0.); + assert_always(std::isfinite(nne)); + modelgrid[modelgridindex].nne = nne; +} - const auto sys_time_start_write_restart = std::time(nullptr); - printout("Write grid restart data to %s...", filename); +void set_nnetot(const int modelgridindex, const float nnetot) { + assert_always(nnetot >= 0.); + assert_always(std::isfinite(nnetot)); + modelgrid[modelgridindex].nnetot = nnetot; +} - FILE *gridsave_file = fopen_required(filename, "w"); +void set_kappagrey(const int modelgridindex, const float kappagrey) { modelgrid[modelgridindex].kappagrey = kappagrey; } - fprintf(gridsave_file, "%d ", globals::ntimesteps); - fprintf(gridsave_file, "%d ", globals::nprocs); +void set_Te(const int modelgridindex, const float Te) { modelgrid[modelgridindex].Te = Te; } - for (int nts = 0; nts < globals::ntimesteps; nts++) { - fprintf(gridsave_file, "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", - globals::timesteps[nts].gamma_dep, globals::timesteps[nts].gamma_dep_discrete, - globals::timesteps[nts].positron_emission, globals::timesteps[nts].positron_dep, - globals::timesteps[nts].positron_dep_discrete, globals::timesteps[nts].eps_positron_ana_power, - globals::timesteps[nts].electron_dep, globals::timesteps[nts].electron_dep_discrete, - globals::timesteps[nts].electron_emission, globals::timesteps[nts].eps_electron_ana_power, - globals::timesteps[nts].alpha_dep, globals::timesteps[nts].alpha_dep_discrete, - globals::timesteps[nts].alpha_emission, globals::timesteps[nts].eps_alpha_ana_power, - globals::timesteps[nts].qdot_betaminus, globals::timesteps[nts].qdot_alpha, - globals::timesteps[nts].qdot_total, globals::timesteps[nts].gamma_emission, globals::timesteps[nts].cmf_lum, - globals::timesteps[nts].pellet_decays); - } +void set_TR(const int modelgridindex, const float TR) { modelgrid[modelgridindex].TR = TR; } - fprintf(gridsave_file, "%d ", timestep); +void set_TJ(const int modelgridindex, const float TJ) { modelgrid[modelgridindex].TJ = TJ; } - for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { - const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); +void set_W(const int modelgridindex, const float W) { modelgrid[modelgridindex].W = W; } - assert_always(globals::dep_estimator_gamma[nonemptymgi] >= 0.); - fprintf(gridsave_file, "%d %a %a %a %a %d %la %a %a", mgi, get_TR(mgi), get_Te(mgi), get_W(mgi), get_TJ(mgi), - modelgrid[mgi].thick, globals::dep_estimator_gamma[nonemptymgi], modelgrid[mgi].nne, modelgrid[mgi].nnetot); +auto get_model_type() -> enum gridtypes { return model_type; } - if constexpr (USE_LUT_PHOTOION) { - for (int i = 0; i < globals::nbfcontinua_ground; i++) { - const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; - fprintf(gridsave_file, " %la %la", globals::corrphotoionrenorm[estimindex], - globals::gammaestimator[estimindex]); - } - } - fprintf(gridsave_file, "\n"); - } +void set_model_type(const enum gridtypes model_type_value) { model_type = model_type_value; } - // the order of these calls is very important! - radfield::write_restart_data(gridsave_file); - nonthermal::write_restart_data(gridsave_file); - nltepop_write_restart_data(gridsave_file); - fclose(gridsave_file); - printout("done in %ld seconds.\n", std::time(nullptr) - sys_time_start_write_restart); +__host__ __device__ auto get_npts_model() -> int +// number of model grid cells +{ + assert_testmodeonly(npts_model > 0); + return npts_model; } -static void assign_initial_temperatures() -/// Routine for assigning temperatures to the grid cells at the start of the simulation. +auto get_nonempty_npts_model() -> int +// number of model grid cells { -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); -#endif - /// For a simulation started from scratch we estimate the initial temperatures + assert_testmodeonly(nonempty_npts_model > 0); + return nonempty_npts_model; +} - /// We assume that for early times the material is so optically thick, that - /// all the radiation is trapped in the cell it originates from. This - /// means furthermore LTE, so that both temperatures can be evaluated - /// according to the local energy density resulting from the 56Ni decay. - /// The dilution factor is W=1 in LTE. +auto get_t_model() -> double +// get time at which model input densities are defined +{ + assert_testmodeonly(t_model > 0.); + return t_model; +} - printout("Assigning initial temperatures...\n"); +__host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { + assert_testmodeonly(cellindex >= 0); + assert_testmodeonly(cellindex < ngrid); + const int mgi = cell[cellindex].modelgridindex; + assert_testmodeonly(mgi >= 0); + assert_testmodeonly(mgi < (get_npts_model() + 1)); + return mgi; +} - const double tstart = globals::timesteps[0].mid; - int cells_below_mintemp = 0; - int cells_above_maxtemp = 0; +__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int +// number of propagation cells associated with each modelgrid cell +{ + assert_testmodeonly(modelgridindex <= get_npts_model()); + return mg_associated_cells[modelgridindex]; +} - for (int nonempymgi = 0; nonempymgi < get_nonempty_npts_model(); nonempymgi++) { - const int mgi = get_mgi_of_nonemptymgi(nonempymgi); +__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int +// get the index in the list of non-empty cells for a given model grid cell +{ + assert_testmodeonly(get_nonempty_npts_model() > 0); + assert_testmodeonly(mgi < get_npts_model()); - double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(mgi, tstart); - if constexpr (INITIAL_PACKETS_ON && USE_MODEL_INITIAL_ENERGY) { - decayedenergy_per_mass += get_initenergyq(mgi); - } + const int nonemptymgi = nonemptymgi_of_mgi[mgi]; + // assert_testmodeonly(nonemptymgi >= 0 || get_numassociatedcells(mgi) == 0); + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); - double T_initial = - pow(CLIGHT / 4 / STEBO * pow(globals::tmin / tstart, 3) * get_rho_tmin(mgi) * decayedenergy_per_mass, 1. / 4.); + return nonemptymgi; +} - if (T_initial < MINTEMP) { - // printout("mgi %d: T_initial of %g is below MINTEMP %g K, setting to MINTEMP.\n", mgi, T_initial, MINTEMP); - T_initial = MINTEMP; - cells_below_mintemp++; - } else if (T_initial > MAXTEMP) { - // printout("mgi %d: T_initial of %g is above MAXTEMP %g K, setting to MAXTEMP.\n", mgi, T_initial, MAXTEMP); - T_initial = MAXTEMP; - cells_above_maxtemp++; - } else if (!std::isfinite(T_initial)) { - printout("mgi %d: T_initial of %g is infinite!\n", mgi, T_initial); - } - assert_always(std::isfinite(T_initial)); +__host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int +// get the index in the list of non-empty cells for a given model grid cell +{ + assert_testmodeonly(get_nonempty_npts_model() > 0); + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); - set_Te(mgi, T_initial); - set_TJ(mgi, T_initial); - set_TR(mgi, T_initial); + const int mgi = mgi_of_nonemptymgi[nonemptymgi]; - set_W(mgi, 1.); - modelgrid[mgi].thick = 0; - } - printout(" cells below MINTEMP %g: %d\n", MINTEMP, cells_below_mintemp); - printout(" cells above MAXTEMP %g: %d\n", MAXTEMP, cells_above_maxtemp); + assert_always(mgi >= 0); + return mgi; } -static void setup_nstart_ndo() { - const int nprocesses = globals::nprocs; - const int npts_nonempty = get_nonempty_npts_model(); - const int min_nonempty_perproc = npts_nonempty / nprocesses; // integer division, minimum non-empty cells per process - const int n_remainder = npts_nonempty % nprocesses; - maxndo = 0; - - ranks_nstart.resize(nprocesses); - ranks_ndo.resize(nprocesses); - ranks_ndo_nonempty.resize(nprocesses); +// the abundances below are initial abundances at t_model - // begin with no cell assignments - std::ranges::fill(ranks_nstart, 0); - std::ranges::fill(ranks_ndo, 0); - std::ranges::fill(ranks_ndo_nonempty, 0); +auto get_modelinitradioabund(const int modelgridindex, const int nucindex) -> float { + // get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index - if (nprocesses >= get_npts_model()) { - // for convenience, rank == mgi when there is at least one rank per cell - maxndo = 1; - for (int r = 0; r < nprocesses; r++) { - if (r < get_npts_model()) { - const int mgi = r; - ranks_nstart[r] = mgi; - ranks_ndo[r] = 1; - ranks_ndo_nonempty[r] = (get_numassociatedcells(mgi) > 0) ? 1 : 0; - } - } - } else { - // evenly divide up the non-empty cells among the ranks + assert_testmodeonly(modelgrid[modelgridindex].initradioabund != nullptr); + return modelgrid[modelgridindex].initradioabund[nucindex]; +} - int rank = 0; - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - const int target_nonempty_thisrank = (rank < n_remainder) ? min_nonempty_perproc + 1 : min_nonempty_perproc; - if ((rank < (nprocesses - 1)) && (ranks_ndo_nonempty[rank] >= target_nonempty_thisrank)) { - // current rank has enough non-empty cells, so start assigning cells to the next rank - rank++; - ranks_nstart[rank] = mgi; - } +auto get_stable_initabund(const int mgi, const int element) -> float { + assert_testmodeonly(modelgrid[mgi].initmassfracstable != nullptr); + return modelgrid[mgi].initmassfracstable[element]; +} - ranks_ndo[rank]++; - maxndo = std::max(maxndo, ranks_ndo[rank]); - if (get_numassociatedcells(mgi) > 0) { - ranks_ndo_nonempty[rank]++; - } +auto get_element_meanweight(const int mgi, const int element) -> float +// weight is in grams +{ + if (USE_CALCULATED_MEANATOMICWEIGHT) { + const double mu = modelgrid[mgi].elem_meanweight[element]; + if (mu > 0) { + return mu; } } + return globals::elements[element].initstablemeannucmass; +} - int npts_assigned = 0; - int npts_nonempty_assigned = 0; - for (int r = 0; r < nprocesses; r++) { - npts_assigned += ranks_ndo[r]; - npts_nonempty_assigned += ranks_ndo_nonempty[r]; - } - assert_always(npts_assigned == get_npts_model()); - assert_always(npts_nonempty_assigned == get_nonempty_npts_model()); +void set_element_meanweight(const int mgi, const int element, const float meanweight) +// weight is in grams +{ + assert_always(meanweight > 0.); + modelgrid[mgi].elem_meanweight[element] = meanweight; +} - if (globals::rank_global == 0) { - auto fileout = std::ofstream("modelgridrankassignments.out"); - assert_always(fileout.is_open()); - fileout << "#rank nstart ndo ndo_nonempty\n"; - for (int r = 0; r < nprocesses; r++) { - fileout << r << " " << ranks_nstart[r] << " " << ranks_ndo[r] << " " << ranks_ndo_nonempty[r] << "\n"; - } +auto get_electronfrac(const int modelgridindex) -> double { + double nucleondens = 0.; + for (int element = 0; element < get_nelements(); element++) { + nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(modelgridindex, element) / MH; } + return get_nnetot(modelgridindex) / nucleondens; } -auto get_maxndo() -> int { - if (ranks_ndo.empty()) { - setup_nstart_ndo(); +auto get_initelectronfrac(const int modelgridindex) -> double { return modelgrid[modelgridindex].initelectronfrac; } + +auto get_initenergyq(const int modelgridindex) -> double { + // q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] + + return modelgrid[modelgridindex].initenergyq; +} + +auto get_cellradialposmid(const int cellindex) -> double +// get the radial distance from the origin to the centre of the cell at time tmin +{ + if (GRID_TYPE == GRID_SPHERICAL1D) { + // mid point radius + // return get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); + // volume averaged mean radius is slightly complex for radial shells + const double r_inner = grid::get_cellcoordmin(cellindex, 0); + const double r_outer = r_inner + grid::wid_init(cellindex, 0); + return 3. / 4 * (pow(r_outer, 4.) - pow(r_inner, 4.)) / (pow(r_outer, 3) - pow(r_inner, 3.)); + } + + if (GRID_TYPE == GRID_CYLINDRICAL2D) { + const double rcyl_mid = get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); + const double z_mid = get_cellcoordmin(cellindex, 1) + (0.5 * wid_init(cellindex, 1)); + return std::sqrt(std::pow(rcyl_mid, 2) + std::pow(z_mid, 2)); } - return maxndo; -} -auto get_nstart(const int rank) -> int { - if (ranks_ndo.empty()) { - setup_nstart_ndo(); + // cubic grid requires taking the length of the 3D position vector + std::array dcen{}; + for (int axis = 0; axis < 3; axis++) { + dcen[axis] = get_cellcoordmin(cellindex, axis) + (0.5 * wid_init(cellindex, axis)); } - return ranks_nstart[rank]; + + return vec_len(dcen); } -auto get_ndo(const int rank) -> int { - if (ranks_ndo.empty()) { - setup_nstart_ndo(); - } - return ranks_ndo[rank]; +auto get_elements_uppermost_ion(const int modelgridindex, const int element) -> int { + return modelgrid[modelgridindex].elements_uppermost_ion[element]; } -auto get_ndo_nonempty(const int rank) -> int { - if (ranks_ndo.empty()) { - setup_nstart_ndo(); - } - return ranks_ndo_nonempty[rank]; +void set_elements_uppermost_ion(const int modelgridindex, const int element, const int newvalue) { + modelgrid[modelgridindex].elements_uppermost_ion[element] = newvalue; } -static void setup_grid_cartesian_3d() -/// Routine for doing a uniform cuboidal grid. -{ - // vmax is per coordinate, but the simulation volume corners will - // have a higher expansion velocity than the sides - const double vmax_corner = sqrt(3 * pow(globals::vmax, 2)); - printout("corner vmax %g [cm/s] (%.2fc)\n", vmax_corner, vmax_corner / CLIGHT); - if (!FORCE_SPHERICAL_ESCAPE_SURFACE) { - assert_always(vmax_corner < CLIGHT); +void calculate_kappagrey() { + double rho_sum = 0.; + double fe_sum = 0.; + double opcase3_sum = 0.; + const int empty_cells = 0; + + for (int n = 0; n < ngrid; n++) { + const int mgi = get_cell_modelgridindex(n); + rho_sum += get_rho_tmin(mgi); + fe_sum += get_ffegrp(mgi); + + if (globals::opacity_case == 3) { + if (get_rho_tmin(mgi) > 0.) { + double kappagrey = ((0.9 * get_ffegrp(mgi)) + 0.1); + + if (get_rho_tmin(mgi) > globals::rho_crit) { + kappagrey *= globals::rho_crit / get_rho_tmin(mgi); + } + + set_kappagrey(mgi, kappagrey); + } else if (get_rho_tmin(mgi) == 0.) { + set_kappagrey(mgi, 0.); + } else if (get_rho_tmin(mgi) < 0.) { + printout("Error: negative density. Abort.\n"); + std::abort(); + } + opcase3_sum += get_kappagrey(mgi) * get_rho_tmin(mgi); + } } - /// Set grid size for uniform xyz grid - if (get_model_type() == GRID_CARTESIAN3D) { - // if we used in a 3D ejecta model, the propagation grid must match the input grid exactly - ncoordgrid[0] = ncoord_model[0]; - ncoordgrid[1] = ncoord_model[1]; - ncoordgrid[2] = ncoord_model[2]; + /// Second pass through allows calculation of normalized chi_grey + double check1 = 0.; + double check2 = 0.; + for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); + if (get_rho_tmin(mgi) > 0) { + double kappa = 0.; + if (globals::opacity_case == 0) { + kappa = globals::GREY_OP; + } else if (globals::opacity_case == 1 || globals::opacity_case == 4) { + /// kappagrey used for initial grey approximation in case 4 + kappa = ((0.9 * get_ffegrp(mgi)) + 0.1) * globals::GREY_OP / ((0.9 * mfeg / mtot_input) + 0.1); + } else if (globals::opacity_case == 2) { + const double opcase2_normal = globals::GREY_OP * rho_sum / ((0.9 * fe_sum) + (0.1 * (ngrid - empty_cells))); + kappa = opcase2_normal / get_rho_tmin(mgi) * ((0.9 * get_ffegrp(mgi)) + 0.1); + } else if (globals::opacity_case == 3) { + globals::opcase3_normal = globals::GREY_OP * rho_sum / opcase3_sum; + kappa = get_kappagrey(mgi) * globals::opcase3_normal; + } else if (globals::opacity_case == 5) { + // electron-fraction-dependent opacities + // values from table 1 of Tanaka et al. (2020). + // const double Ye = get_electronfrac(mgi); + const double Ye = get_initelectronfrac(mgi); + if (Ye <= 0.1) { + kappa = 19.5; + } else if (Ye <= 0.15) { + kappa = 32.2; + } else if (Ye <= 0.20) { + kappa = 22.3; + } else if (Ye <= 0.25) { + kappa = 5.6; + } else if (Ye <= 0.30) { + kappa = 5.36; + } else if (Ye <= 0.35) { + kappa = 3.3; + } else { + kappa = 0.96; + } + } else if (globals::opacity_case == 6) { + // grey opacity used in Just+2022, https://ui.adsabs.harvard.edu/abs/2022MNRAS.510.2820J/abstract + // kappa is a simple analytic function of temperature and lanthanide mass fraction + // adapted to best fit lightcurves from Kasen+2017 in ALCAR simulations + const double T_rad = get_TR(mgi); + double X_lan = 0.; + for (int element = 0; element < get_nelements(); element++) { + const int z = get_atomicnumber(element); + if (z >= 57 && z <= 71) { + X_lan += get_elem_abundance(mgi, element); + } + } + // first step: temperature-independent factor + if (X_lan < 1e-7) { + kappa = 0.2; + } else if (X_lan < 1e-3) { + kappa = 3 * pow(X_lan / 1e-3, 0.3); + } else if (X_lan < 1e-1) { + kappa = 3 * pow(X_lan / 1e-3, 0.5); + } else { + kappa = 30 * pow(X_lan / 1e-1, 0.1); + } + // second step: multiply temperature-dependent factor + if (T_rad < 2000.) { + kappa *= pow(T_rad / 2000., 5.); + } + } else { + printout("Unknown opacity case. Abort.\n"); + std::abort(); + } - // in case the user specified a grid size, we should ensure that it matches - assert_always(ncoordgrid[0] == CUBOID_NCOORDGRID_X || CUBOID_NCOORDGRID_X < 0); - assert_always(ncoordgrid[1] == CUBOID_NCOORDGRID_Y || CUBOID_NCOORDGRID_Y < 0); - assert_always(ncoordgrid[2] == CUBOID_NCOORDGRID_Z || CUBOID_NCOORDGRID_Z < 0); - } else { - ncoordgrid[0] = CUBOID_NCOORDGRID_X; - ncoordgrid[1] = CUBOID_NCOORDGRID_Y; - ncoordgrid[2] = CUBOID_NCOORDGRID_Z; + set_kappagrey(mgi, kappa); + } else if (get_rho_tmin(mgi) == 0.) { + set_kappagrey(mgi, 0.); + } else if (get_rho_tmin(mgi) < 0.) { + printout("Error: negative density. Abort.\n"); + std::abort(); + } + + check1 = check1 + (get_kappagrey(mgi) * get_rho_tmin(mgi)); + check2 = check2 + get_rho_tmin(mgi); } - // artis assumes in some places that the cells are cubes, not cubioids - assert_always(ncoordgrid[0] == ncoordgrid[1]); - assert_always(ncoordgrid[0] == ncoordgrid[2]); + printout("Grey normalisation check: %g\n", check1 / check2); +} - ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); +void read_ejecta_model() { + switch (get_model_type()) { + case GRID_SPHERICAL1D: { + printout("Read 1D model\n"); + read_1d_model(); + break; + } - coordlabel[0] = 'X'; - coordlabel[1] = 'Y'; - coordlabel[2] = 'Z'; - std::array nxyz = {0, 0, 0}; - for (int n = 0; n < ngrid; n++) { - for (int axis = 0; axis < 3; axis++) { - assert_always(nxyz[axis] == get_cellcoordpointnum(n, axis)); - cell[n].pos_min[axis] = -globals::rmax + (2 * nxyz[axis] * globals::rmax / ncoordgrid[axis]); - // cell[n].xyz[axis] = nxyz[axis]; + case GRID_CYLINDRICAL2D: { + printout("Read 2D model\n"); + + read_2d_model(); + break; } - assert_always(n == nxyz[2] * ncoordgrid[1] * ncoordgrid[2] + nxyz[1] * ncoordgrid[0] + nxyz[0]); + case GRID_CARTESIAN3D: { + printout("Read 3D model\n"); - nxyz[0]++; // increment x coordinate - if (nxyz[0] == ncoordgrid[0]) { - nxyz[0] = 0; - nxyz[1]++; // increment y coordinate + read_3d_model(); + break; } - if (nxyz[1] == ncoordgrid[1]) { - nxyz[1] = 0; - nxyz[2]++; // increment z coordinate + + default: { + if constexpr (TESTMODE) { + printout("ERROR: Unknown model type %d\n", get_model_type()); + assert_testmodeonly(false); + } else { + __builtin_unreachable(); + } } } + + printout("npts_model: %d\n", get_npts_model()); + globals::rmax = globals::vmax * globals::tmin; + printout("vmax %g [cm/s] (%.2fc)\n", globals::vmax, globals::vmax / CLIGHT); + assert_always(globals::vmax < CLIGHT); + printout("tmin %g [s] = %.2f [d]\n", globals::tmin, globals::tmin / 86400.); + printout("rmax %g [cm] (at t=tmin)\n", globals::rmax); + + calc_modelinit_totmassradionuclides(); + + read_possible_yefile(); } -static void setup_grid_spherical1d() { - assert_always(get_model_type() == GRID_SPHERICAL1D); - coordlabel[0] = 'r'; - coordlabel[1] = '_'; - coordlabel[2] = '_'; +void write_grid_restart_data(const int timestep) { + char filename[MAXFILENAMELENGTH]; + snprintf(filename, MAXFILENAMELENGTH, "gridsave_ts%d.tmp", timestep); - ncoordgrid[0] = get_npts_model(); - ncoordgrid[1] = 1; - ncoordgrid[2] = 1; + const auto sys_time_start_write_restart = std::time(nullptr); + printout("Write grid restart data to %s...", filename); - ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); + FILE *gridsave_file = fopen_required(filename, "w"); - // direct mapping, cellindex and modelgridindex are the same - for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { - const int mgi = cellindex; // interchangeable in this mode - const double v_inner = mgi > 0 ? vout_model[mgi - 1] : 0.; - set_cell_modelgridindex(cellindex, mgi); - cell[cellindex].pos_min[0] = v_inner * globals::tmin; - cell[cellindex].pos_min[1] = 0.; - cell[cellindex].pos_min[2] = 0.; + fprintf(gridsave_file, "%d ", globals::ntimesteps); + fprintf(gridsave_file, "%d ", globals::nprocs); + + for (int nts = 0; nts < globals::ntimesteps; nts++) { + fprintf(gridsave_file, "%la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %la %d ", + globals::timesteps[nts].gamma_dep, globals::timesteps[nts].gamma_dep_discrete, + globals::timesteps[nts].positron_emission, globals::timesteps[nts].positron_dep, + globals::timesteps[nts].positron_dep_discrete, globals::timesteps[nts].eps_positron_ana_power, + globals::timesteps[nts].electron_dep, globals::timesteps[nts].electron_dep_discrete, + globals::timesteps[nts].electron_emission, globals::timesteps[nts].eps_electron_ana_power, + globals::timesteps[nts].alpha_dep, globals::timesteps[nts].alpha_dep_discrete, + globals::timesteps[nts].alpha_emission, globals::timesteps[nts].eps_alpha_ana_power, + globals::timesteps[nts].qdot_betaminus, globals::timesteps[nts].qdot_alpha, + globals::timesteps[nts].qdot_total, globals::timesteps[nts].gamma_emission, globals::timesteps[nts].cmf_lum, + globals::timesteps[nts].pellet_decays); } -} -static void setup_grid_cylindrical_2d() { - const double vmax_corner = sqrt(2 * pow(globals::vmax, 2)); - printout("corner vmax %g [cm/s] (%.2fc)\n", vmax_corner, vmax_corner / CLIGHT); - assert_always(vmax_corner < CLIGHT); + fprintf(gridsave_file, "%d ", timestep); - assert_always(get_model_type() == GRID_CYLINDRICAL2D); - coordlabel[0] = 'r'; - coordlabel[1] = 'z'; - coordlabel[2] = '_'; + for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - ncoordgrid[0] = ncoord_model[0]; - ncoordgrid[1] = ncoord_model[1]; - ncoordgrid[2] = ncoord_model[2]; + assert_always(globals::dep_estimator_gamma[nonemptymgi] >= 0.); + fprintf(gridsave_file, "%d %a %a %a %a %d %la %a %a", mgi, get_TR(mgi), get_Te(mgi), get_W(mgi), get_TJ(mgi), + modelgrid[mgi].thick, globals::dep_estimator_gamma[nonemptymgi], modelgrid[mgi].nne, modelgrid[mgi].nnetot); - ngrid = ncoordgrid[0] * ncoordgrid[1]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); + if constexpr (USE_LUT_PHOTOION) { + for (int i = 0; i < globals::nbfcontinua_ground; i++) { + const int estimindex = (nonemptymgi * globals::nbfcontinua_ground) + i; + fprintf(gridsave_file, " %la %la", globals::corrphotoionrenorm[estimindex], + globals::gammaestimator[estimindex]); + } + } + fprintf(gridsave_file, "\n"); + } - // direct mapping, cellindex and modelgridindex are the same - for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { - const int mgi = cellindex; // interchangeable in this mode - set_cell_modelgridindex(cellindex, mgi); + // the order of these calls is very important! + radfield::write_restart_data(gridsave_file); + nonthermal::write_restart_data(gridsave_file); + nltepop_write_restart_data(gridsave_file); + fclose(gridsave_file); + printout("done in %ld seconds.\n", std::time(nullptr) - sys_time_start_write_restart); +} - const int n_rcyl = get_cellcoordpointnum(cellindex, 0); - const int n_z = get_cellcoordpointnum(cellindex, 1); +auto get_maxndo() -> int { + if (ranks_ndo.empty()) { + setup_nstart_ndo(); + } + return maxndo; +} - cell[cellindex].pos_min[0] = n_rcyl * globals::rmax / ncoord_model[0]; - cell[cellindex].pos_min[1] = globals::rmax * (-1 + n_z * 2. / ncoord_model[1]); - cell[cellindex].pos_min[2] = 0.; +auto get_nstart(const int rank) -> int { + if (ranks_ndo.empty()) { + setup_nstart_ndo(); } + return ranks_nstart[rank]; } -static auto get_grid_type_name() -> std::string { - switch (GRID_TYPE) { - case GRID_SPHERICAL1D: - return "spherical"; - case GRID_CYLINDRICAL2D: - return "cylindrical"; - case GRID_CARTESIAN3D: - return "uniform cuboidal"; - default: { - return "unknown"; - } +auto get_ndo(const int rank) -> int { + if (ranks_ndo.empty()) { + setup_nstart_ndo(); + } + return ranks_ndo[rank]; +} + +auto get_ndo_nonempty(const int rank) -> int { + if (ranks_ndo.empty()) { + setup_nstart_ndo(); } + return ranks_ndo_nonempty[rank]; } void grid_init(const int my_rank) @@ -2303,50 +2498,6 @@ auto get_totmassradionuclide(const int z, const int a) -> double { return totmassradionuclide[decay::get_nucindex(z, a)]; } -static auto get_poscoordpointnum(const double pos, const double time, const int axis) -> int { - // pos must be position in grid coordinate system, not necessarily xyz - - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { - if (axis == 0) { - return static_cast(pos / time / globals::vmax * ncoordgrid[axis]); - } - if (axis == 1) { - return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); - } - assert_always(false); - - } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - for (int n_r = 0; n_r < ncoordgrid[0]; n_r++) { - if ((pos >= grid::get_cellcoordmin(n_r, 0)) && (pos < grid::get_cellcoordmax(n_r, 0))) { - return n_r; - } - } - assert_always(false); - } else { - assert_always(false); - } -} - -constexpr static auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { - auto posgridcoord = std::array{}; - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { - posgridcoord[0] = pos_xyz[0]; - posgridcoord[1] = pos_xyz[1]; - posgridcoord[2] = pos_xyz[2]; - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { - posgridcoord[0] = std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)); - posgridcoord[1] = pos_xyz[2]; - posgridcoord[2] = 0.; - } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { - posgridcoord[0] = vec_len(pos_xyz); - posgridcoord[1] = 0.; - posgridcoord[2] = 0.; - } - return posgridcoord; -} - [[nodiscard]] auto get_cellindex_from_pos(const std::array pos, const double time) -> int /// identify the cell index from an (x,y,z) position and a time. { @@ -2365,157 +2516,6 @@ constexpr static auto get_gridcoords_from_xyz(const std::array pos_xy return cellindex; } -template -[[nodiscard]] [[gnu::pure]] static constexpr auto expanding_shell_intersection( - const std::array pos, const std::array dir, const double speed, - const double shellradiuststart, const bool isinnerboundary, const double tstart) -> double -// find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are -// 3-vectors) or expanding circle (2D vectors) -// returns -1 if there are no forward intersections (or if the intersection -// is tangential to the shell) -{ - assert_always(shellradiuststart > 0); - - // quadratic equation for intersection of ray with sphere - // a*d^2 + b*d + c = 0 - const double a = dot(dir, dir) - pow(shellradiuststart / tstart / speed, 2); - const double b = 2 * (dot(dir, pos) - pow(shellradiuststart, 2) / tstart / speed); - const double c = dot(pos, pos) - pow(shellradiuststart, 2); - - const double discriminant = pow(b, 2) - (4 * a * c); - - if (discriminant < 0) { - // no intersection - assert_always(isinnerboundary); - assert_always(shellradiuststart < vec_len(pos)); - return -1; - } - - if (discriminant > 0) { - // two intersections - double dist1 = (-b + sqrt(discriminant)) / 2 / a; - double dist2 = (-b - sqrt(discriminant)) / 2 / a; - - auto posfinal1 = std::array{0.}; - auto posfinal2 = std::array{0.}; - - for (size_t d = 0; d < pos.size(); d++) { - posfinal1[d] = pos[d] + dist1 * dir[d]; - posfinal2[d] = pos[d] + dist2 * dir[d]; - } - - const double v_rad_shell = shellradiuststart / tstart; - const double v_rad_final1 = dot(dir, posfinal1) * speed / vec_len(posfinal1); - const double v_rad_final2 = dot(dir, posfinal2) * speed / vec_len(posfinal2); - - // invalidate any solutions that require entering the boundary from the wrong radial direction - if (isinnerboundary) { - // if the packet's radial velocity at intersection is greater than the inner shell's radial velocity, - // then it is catching up from below the inner shell and should pass through it - if (v_rad_final1 > v_rad_shell) { - dist1 = -1; - } - if (v_rad_final2 > v_rad_shell) { - dist2 = -1; - } - } else { - // if the packet's radial velocity at intersection is less than the outer shell's radial velocity, - // then it is coming from above the outer shell and should pass through it - if (v_rad_final1 < v_rad_shell) { - dist1 = -1; - } - if (v_rad_final2 < v_rad_shell) { - dist2 = -1; - } - } - -#if (TESTMODE) - if (dist1 >= 0) { - const double shellradiusfinal1 = shellradiuststart / tstart * (tstart + dist1 / speed); - assert_testmodeonly(fabs(vec_len(posfinal1) / shellradiusfinal1 - 1.) < 1e-3); - } - if (dist2 >= 0) { - const double shellradiusfinal2 = shellradiuststart / tstart * (tstart + dist2 / speed); - assert_testmodeonly(fabs(vec_len(posfinal2) / shellradiusfinal2 - 1.) < 1e-3); - } -#endif - - // negative d means in the reverse direction along the ray - // ignore negative d values, and if two are positive then return the smaller one - if (dist1 < 0 && dist2 < 0) { - return -1; - } - if (dist2 < 0) { - return dist1; - } - if (dist1 < 0) { - return dist2; - } - return std::min(dist1, dist2); - - } // exactly one intersection - - // one intersection - // ignore this and don't change which cell the packet is in - assert_always(shellradiuststart <= vec_len(pos)); - return -1.; -} - -static auto get_coordboundary_distances_cylindrical2d( - const std::array pkt_pos, const std::array pkt_dir, - const std::array pktposgridcoord, const std::array pktvelgridcoord, int cellindex, - const double tstart, - const std::array cellcoordmax) -> std::tuple, std::array> { - // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the - // propagation speed set to the xy component of the 3-velocity - - std::array d_coordminboundary{}; - std::array d_coordmaxboundary{}; - - const std::array posnoz = {pkt_pos[0], pkt_pos[1]}; - - const double dirxylen = std::sqrt((pkt_dir[0] * pkt_dir[0]) + (pkt_dir[1] * pkt_dir[1])); - const double xyspeed = dirxylen * CLIGHT_PROP; // r_cyl component of velocity - - // make a normalised direction vector in the xy plane - const std::array dirnoz = {pkt_dir[0] / dirxylen, pkt_dir[1] / dirxylen}; - - const double r_inner = grid::get_cellcoordmin(cellindex, 0) * tstart / globals::tmin; - d_coordminboundary[0] = -1; - // don't try to calculate the intersection if the inner radius is zero - if (r_inner > 0) { - const double d_rcyl_coordminboundary = expanding_shell_intersection(posnoz, dirnoz, xyspeed, r_inner, true, tstart); - if (d_rcyl_coordminboundary >= 0) { - const double d_z_coordminboundary = d_rcyl_coordminboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; - d_coordminboundary[0] = std::sqrt((d_rcyl_coordminboundary * d_rcyl_coordminboundary) + - (d_z_coordminboundary * d_z_coordminboundary)); - } - } - - const double r_outer = cellcoordmax[0] * tstart / globals::tmin; - const double d_rcyl_coordmaxboundary = expanding_shell_intersection(posnoz, dirnoz, xyspeed, r_outer, false, tstart); - d_coordmaxboundary[0] = -1; - if (d_rcyl_coordmaxboundary >= 0) { - const double d_z_coordmaxboundary = d_rcyl_coordmaxboundary / xyspeed * pkt_dir[2] * CLIGHT_PROP; - d_coordmaxboundary[0] = - std::sqrt((d_rcyl_coordmaxboundary * d_rcyl_coordmaxboundary) + (d_z_coordmaxboundary * d_z_coordmaxboundary)); - } - - // z boundaries are the same as Cartesian - const double t_zcoordminboundary = - ((pktposgridcoord[1] - (pktvelgridcoord[1] * tstart)) / - ((grid::get_cellcoordmin(cellindex, 1)) - (pktvelgridcoord[1] * globals::tmin)) * globals::tmin) - - tstart; - d_coordminboundary[1] = CLIGHT_PROP * t_zcoordminboundary; - - const double t_zcoordmaxboundary = ((pktposgridcoord[1] - (pktvelgridcoord[1] * tstart)) / - ((cellcoordmax[1]) - (pktvelgridcoord[1] * globals::tmin)) * globals::tmin) - - tstart; - d_coordmaxboundary[1] = CLIGHT_PROP * t_zcoordmaxboundary; - - return {d_coordminboundary, d_coordmaxboundary}; -} - [[nodiscard]] __host__ __device__ auto boundary_distance(const std::array dir, const std::array pos, const double tstart, const int cellindex, diff --git a/input.cc b/input.cc index 480c295f0..e15d31746 100644 --- a/input.cc +++ b/input.cc @@ -19,12 +19,14 @@ #include #include #include +#include #include #include #include #ifndef GPU_ON #include #endif +#include #include #include #include @@ -46,6 +48,7 @@ namespace { const int groundstate_index_in = 1; // starting level index in the input files int phixs_file_version = -1; +float *allphixsblock{}; struct Transitions { int *to; @@ -404,7 +407,7 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons } } -void read_ion_transitions(std::fstream &ftransitiondata, const int tottransitions_in_file, int *tottransitions, +void read_ion_transitions(std::fstream &ftransitiondata, const int tottransitions_in_file, int *const tottransitions, std::vector &transitiontable, const int nlevels_requiretransitions, const int nlevels_requiretransitions_upperlevels) { transitiontable.reserve(*tottransitions); @@ -658,7 +661,7 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons #endif } -auto calculate_nlevels_groundterm(int element, int ion) -> int { +auto calculate_nlevels_groundterm(const int element, const int ion) -> int { const int nlevels = get_nlevels(element, ion); if (nlevels == 1) { return 1; @@ -1128,62 +1131,56 @@ void read_atomicdata_files() { update_includedionslevels_maxnions(); } -auto search_groundphixslist(double nu_edge, int el, int in, int ll) -> int +auto search_groundphixslist(const double nu_edge, const int element_in, const int ion_in, const int level_in) -> int /// Return the closest ground level continuum index to the given edge /// frequency. If the given edge frequency is redder than the reddest /// continuum return -1. /// NB: groundphixslist must be in ascending order. { assert_always((USE_LUT_PHOTOION || USE_LUT_BFHEATING)); - int index = 0; if (nu_edge < globals::groundcont[0].nu_edge) { - index = -1; - } else { - int i = 1; - int element = -1; - int ion = -1; - for (i = 1; i < globals::nbfcontinua_ground; i++) { - if (nu_edge < globals::groundcont[i].nu_edge) { - break; - } + return -1; + } + + int i = 1; + for (i = 1; i < globals::nbfcontinua_ground; i++) { + if (nu_edge < globals::groundcont[i].nu_edge) { + break; } - if (i == globals::nbfcontinua_ground) { - element = globals::groundcont[i - 1].element; - ion = globals::groundcont[i - 1].ion; - if (element == el && ion == in && ll == 0) { - index = i - 1; - } else { - printout( - "[fatal] search_groundphixslist: element %d, ion %d, level %d has edge_frequency %g equal to the " - "bluest ground-level continuum\n", - el, in, ll, nu_edge); - printout( - "[fatal] search_groundphixslist: bluest ground level continuum is element %d, ion %d at " - "nu_edge %g\n", - element, ion, globals::groundcont[i - 1].nu_edge); - printout("[fatal] search_groundphixslist: i %d, nbfcontinua_ground %d\n", i, globals::nbfcontinua_ground); - printout( - "[fatal] This shouldn't happen, is hoewever possible if there are multiple levels in the adata file at " - "energy=0\n"); - for (int looplevels = 0; looplevels < get_nlevels(el, in); looplevels++) { - printout("[fatal] element %d, ion %d, level %d, energy %g\n", el, in, looplevels, - epsilon(el, in, looplevels)); - } - printout("[fatal] Abort omitted ... MAKE SURE ATOMIC DATA ARE CONSISTENT\n"); - index = i - 1; - // abort(); - } - } else { - const double left_diff = nu_edge - globals::groundcont[i - 1].nu_edge; - const double right_diff = globals::groundcont[i].nu_edge - nu_edge; - index = (left_diff <= right_diff) ? i - 1 : i; - element = globals::groundcont[index].element; - ion = globals::groundcont[index].ion; + } + + if (i == globals::nbfcontinua_ground) { + const int element = globals::groundcont[i - 1].element; + const int ion = globals::groundcont[i - 1].ion; + if (element == element_in && ion == ion_in && level_in == 0) { + return i - 1; + } + + printout( + "[fatal] search_groundphixslist: element %d, ion %d, level %d has edge_frequency %g equal to the " + "bluest ground-level continuum\n", + element_in, ion_in, level_in, nu_edge); + printout( + "[fatal] search_groundphixslist: bluest ground level continuum is element %d, ion %d at " + "nu_edge %g\n", + element, ion, globals::groundcont[i - 1].nu_edge); + printout("[fatal] search_groundphixslist: i %d, nbfcontinua_ground %d\n", i, globals::nbfcontinua_ground); + printout( + "[fatal] This shouldn't happen, is hoewever possible if there are multiple levels in the adata file at " + "energy=0\n"); + for (int looplevels = 0; looplevels < get_nlevels(element_in, ion_in); looplevels++) { + printout("[fatal] element %d, ion %d, level %d, energy %g\n", element_in, ion_in, looplevels, + epsilon(element_in, ion_in, looplevels)); } + printout("[fatal] Abort omitted ... MAKE SURE ATOMIC DATA ARE CONSISTENT\n"); + return i - 1; + // abort(); } - return index; + const double left_diff = nu_edge - globals::groundcont[i - 1].nu_edge; + const double right_diff = globals::groundcont[i].nu_edge - nu_edge; + return (left_diff <= right_diff) ? i - 1 : i; } void setup_cellcache() { @@ -1379,8 +1376,8 @@ void setup_phixs_list() { } } assert_always(groundcontindex == globals::nbfcontinua_ground); - std::stable_sort(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, - [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); + std::ranges::stable_sort(std::span(globals::groundcont, globals::nbfcontinua_ground), std::ranges::less{}, + &GroundPhotoion::nu_edge); } auto *nonconstallcont = @@ -1394,10 +1391,11 @@ void setup_phixs_list() { for (int ion = 0; ion < nions - 1; ion++) { if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { globals::elements[element].ions[ion].groundcontindex = - std::find_if( - globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, - [=](const auto &groundcont) { return (groundcont.element == element) && (groundcont.ion == ion); }) - - globals::groundcont; + static_cast(std::find_if(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, + [=](const auto &groundcont) { + return (groundcont.element == element) && (groundcont.ion == ion); + }) - + globals::groundcont); if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { globals::elements[element].ions[ion].groundcontindex = -1; } @@ -1441,8 +1439,8 @@ void setup_phixs_list() { globals::bfestimcount = 0; if (globals::nbfcontinua > 0) { // indicies above were temporary only. continum index should be to the sorted list - std::stable_sort(nonconstallcont, nonconstallcont + globals::nbfcontinua, - [](const auto &a, const auto &b) { return static_cast(a.nu_edge < b.nu_edge); }); + std::ranges::stable_sort(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, + &FullPhotoionTransition::nu_edge); globals::bfestim_nu_edge.clear(); for (int i = 0; i < globals::nbfcontinua; i++) { @@ -1466,7 +1464,6 @@ void setup_phixs_list() { if (globals::nbfcontinua > 0) { // copy the photoionisation tables into one contiguous block of memory #ifdef MPI_ON - float *allphixsblock{}; MPI_Win win_allphixsblock = MPI_WIN_NULL; auto size = static_cast((globals::rank_in_node == 0) ? nbftables * globals::NPHIXSPOINTS * sizeof(float) : 0); @@ -1477,7 +1474,7 @@ void setup_phixs_list() { MPI_Barrier(MPI_COMM_WORLD); #else - auto *allphixsblock = static_cast(malloc(nbftables * globals::NPHIXSPOINTS * sizeof(float))); + allphixsblock = static_cast(malloc(nbftables * globals::NPHIXSPOINTS * sizeof(float))); #endif assert_always(allphixsblock != nullptr); diff --git a/kpkt.cc b/kpkt.cc index 5c80957f0..a3283a804 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -32,21 +32,21 @@ enum coolingtype { COOLINGTYPE_COLLION = 3, }; -struct CellCachecoolinglist { +struct CellCacheCoolingList { enum coolingtype type; int level; int upperlevel; }; -CellCachecoolinglist *coolinglist; +CellCacheCoolingList *coolinglist; int n_kpktdiffusion_timesteps{0}; float kpktdiffusion_timescale{0.}; template auto calculate_cooling_rates_ion(const int modelgridindex, const int element, const int ion, const int indexionstart, - const int cellcacheslotid, double *C_ff, double *C_fb, double *C_exc, - double *C_ionization) -> double + const int cellcacheslotid, double *const C_ff, double *const C_fb, double *const C_exc, + double *const C_ionization) -> double // calculate the cooling contribution list of individual levels/processes for an ion // oldcoolingsum is the sum of lower ion (of same element or all ions of lower elements) cooling contributions { @@ -178,6 +178,88 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co return C_ion; } +void set_ncoolingterms() { + ncoolingterms = 0; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + int ionterms = 0; + globals::elements[element].ions[ion].coolingoffset = ncoolingterms; + + /// Ionised ions add one ff-cooling term + if (get_ionstage(element, ion) > 1) { + ionterms++; + } + /// Ionisinglevels below the closure ion add to bf and col ionisation + /// All the levels add number of col excitations + const int nlevels = get_nlevels(element, ion); + for (int level = 0; level < nlevels; level++) { + // if (ion < nions - 1) and (level < get_ionisinglevels(element,ion)) + if (ion < nions - 1) { + ionterms += 2 * get_nphixstargets(element, ion, level); + } + + if (get_nuptrans(element, ion, level) > 0) { + ionterms++; // level's coll. excitation cooling (all upper levels combined) + } + } + globals::elements[element].ions[ion].ncoolingterms = ionterms; + ncoolingterms += ionterms; + } + } +} + +auto sample_planck_analytic(const double T) -> double +// return a randomly chosen frequency according to the Planck distribution of temperature T using an analytic method. +// More testing of this function is needed. +{ + const double nu_peak = 5.879e10 * T; + if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { + printout("[warning] sample_planck: intensity peaks outside frequency range\n"); + } + + constexpr ptrdiff_t nubins = 500; + const auto delta_nu = (NU_MAX_R - NU_MIN_R) / (nubins - 1); + const auto integral_total = radfield::planck_integral_analytic(T, NU_MIN_R, NU_MAX_R, false); + + const double rand_partintegral = rng_uniform() * integral_total; + double prev_partintegral = 0.; + double part_integral = 0.; + double bin_nu_lower = NU_MIN_R; + for (ptrdiff_t i = 1; i < nubins; i++) { + bin_nu_lower = NU_MIN_R + (i - 1) * delta_nu; + const double nu_upper = NU_MIN_R + (i * delta_nu); + prev_partintegral = part_integral; + part_integral = radfield::planck_integral_analytic(T, NU_MIN_R, nu_upper, false); + if (rand_partintegral >= part_integral) { + break; + } + } + + // use a linear interpolation for the frequency within the bin + const double nuoffset = (rand_partintegral - prev_partintegral) / (part_integral - prev_partintegral) * delta_nu; + + return bin_nu_lower + nuoffset; +} + +auto sample_planck_montecarlo(const double T) -> double +// return a randomly chosen frequency according to the Planck distribution of temperature T using a Monte Carlo method +{ + const double nu_peak = 5.879e10 * T; + if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { + printout("[warning] sample_planck: intensity peaks outside frequency range\n"); + } + + const double B_peak = radfield::dbb(nu_peak, T, 1); + + while (true) { + const double nu = NU_MIN_R + (rng_uniform() * (NU_MAX_R - NU_MIN_R)); + if (rng_uniform() * B_peak <= radfield::dbb(nu, T, 1)) { + return nu; + } + // printout("[debug] sample_planck: planck_sampling %d\n", i); + } +} } // anonymous namespace void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heatingcoolingrates) @@ -215,44 +297,13 @@ void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heat } } -void set_kpktdiffusion(float kpktdiffusion_timescale_in, int n_kpktdiffusion_timesteps_in) { +void set_kpktdiffusion(const float kpktdiffusion_timescale_in, const int n_kpktdiffusion_timesteps_in) { kpktdiffusion_timescale = kpktdiffusion_timescale_in; n_kpktdiffusion_timesteps = n_kpktdiffusion_timesteps_in; printout("input: kpkts diffuse %g of a time step's length for the first %d time steps\n", kpktdiffusion_timescale, n_kpktdiffusion_timesteps); } -static void set_ncoolingterms() { - ncoolingterms = 0; - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - int ionterms = 0; - globals::elements[element].ions[ion].coolingoffset = ncoolingterms; - - /// Ionised ions add one ff-cooling term - if (get_ionstage(element, ion) > 1) { - ionterms++; - } - /// Ionisinglevels below the closure ion add to bf and col ionisation - /// All the levels add number of col excitations - const int nlevels = get_nlevels(element, ion); - for (int level = 0; level < nlevels; level++) { - // if (ion < nions - 1) and (level < get_ionisinglevels(element,ion)) - if (ion < nions - 1) { - ionterms += 2 * get_nphixstargets(element, ion, level); - } - - if (get_nuptrans(element, ion, level) > 0) { - ionterms++; // level's coll. excitation cooling (all upper levels combined) - } - } - globals::elements[element].ions[ion].ncoolingterms = ionterms; - ncoolingterms += ionterms; - } - } -} - void setup_coolinglist() { /// SET UP THE COOLING LIST ///====================================================== @@ -263,9 +314,9 @@ void setup_coolinglist() { /// \sum_{elements,ions}get_nlevels(element,ion) and free-free which is \sum_{elements} get_nions(element)-1 set_ncoolingterms(); - const size_t mem_usage_coolinglist = ncoolingterms * sizeof(CellCachecoolinglist); + const size_t mem_usage_coolinglist = ncoolingterms * sizeof(CellCacheCoolingList); assert_always(ncoolingterms > 0); - coolinglist = static_cast(malloc(ncoolingterms * sizeof(CellCachecoolinglist))); + coolinglist = static_cast(malloc(ncoolingterms * sizeof(CellCacheCoolingList))); printout("[info] mem_usage: coolinglist occupies %.3f MB\n", mem_usage_coolinglist / 1024. / 1024.); int i = 0; // cooling list index @@ -332,58 +383,6 @@ void setup_coolinglist() { printout("[info] read_atomicdata: number of coolingterms %d\n", ncoolingterms); } -static auto sample_planck_analytic(const double T) -> double -// return a randomly chosen frequency according to the Planck distribution of temperature T using an analytic method. -// More testing of this function is needed. -{ - const double nu_peak = 5.879e10 * T; - if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { - printout("[warning] sample_planck: intensity peaks outside frequency range\n"); - } - - constexpr ptrdiff_t nubins = 500; - const auto delta_nu = (NU_MAX_R - NU_MIN_R) / (nubins - 1); - const auto integral_total = radfield::planck_integral_analytic(T, NU_MIN_R, NU_MAX_R, false); - - const double rand_partintegral = rng_uniform() * integral_total; - double prev_partintegral = 0.; - double part_integral = 0.; - double bin_nu_lower = NU_MIN_R; - for (ptrdiff_t i = 1; i < nubins; i++) { - bin_nu_lower = NU_MIN_R + (i - 1) * delta_nu; - const double nu_upper = NU_MIN_R + (i * delta_nu); - prev_partintegral = part_integral; - part_integral = radfield::planck_integral_analytic(T, NU_MIN_R, nu_upper, false); - if (rand_partintegral >= part_integral) { - break; - } - } - - // use a linear interpolation for the frequency within the bin - const double nuoffset = (rand_partintegral - prev_partintegral) / (part_integral - prev_partintegral) * delta_nu; - - return bin_nu_lower + nuoffset; -} - -static auto sample_planck_montecarlo(const double T) -> double -// return a randomly chosen frequency according to the Planck distribution of temperature T using a Monte Carlo method -{ - const double nu_peak = 5.879e10 * T; - if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { - printout("[warning] sample_planck: intensity peaks outside frequency range\n"); - } - - const double B_peak = radfield::dbb(nu_peak, T, 1); - - while (true) { - const double nu = NU_MIN_R + (rng_uniform() * (NU_MAX_R - NU_MIN_R)); - if (rng_uniform() * B_peak <= radfield::dbb(nu, T, 1)) { - return nu; - } - // printout("[debug] sample_planck: planck_sampling %d\n", i); - } -} - __host__ __device__ void do_kpkt_blackbody(Packet &pkt) /// handle a k-packet (e.g., in a thick cell) by emitting according to the planck function { @@ -413,7 +412,7 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) pkt.nscatterings = 0; } -__host__ __device__ void do_kpkt(Packet &pkt, double t2, int nts) +__host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) /// handle a k-packet (kinetic energy of the free electrons) { const double t1 = pkt.prop_time; diff --git a/ltepop.cc b/ltepop.cc index 92d94231e..41fef45ca 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -121,49 +121,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, return phi; } -} // anonymous namespace - -[[nodiscard]] auto calculate_ionfractions(const int element, const int modelgridindex, const double nne, - const bool use_phi_lte) -> std::vector -// Calculate the fractions of an element's population in each ionization stage based on Saha LTE or ionisation -// equilibrium -{ - const int uppermost_ion = grid::get_elements_uppermost_ion(modelgridindex, element); - assert_testmodeonly(modelgridindex < grid::get_npts_model()); - assert_testmodeonly(element < get_nelements()); - assert_testmodeonly(uppermost_ion <= std::max(0, get_nions(element) - 1)); - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - - if (uppermost_ion < 0) { - return {}; - } - - std::vector ionfractions(uppermost_ion + 1); - ionfractions[uppermost_ion] = 1; - - double normfactor = 1.; - - for (int ion = uppermost_ion - 1; ion >= 0; ion--) { - const auto phifactor = use_phi_lte ? phi_lte(element, ion, modelgridindex) - : phi_ion_equilib(element, ion, modelgridindex, nonemptymgi); - ionfractions[ion] = ionfractions[ion + 1] * nne * phifactor; - normfactor += ionfractions[ion]; - } - - for (int ion = 0; ion <= uppermost_ion; ion++) { - ionfractions[ion] = ionfractions[ion] / normfactor; - - if (normfactor == 0. || !std::isfinite(ionfractions[ion])) { - printout("[warning] ionfract set to zero for ionstage %d of Z=%d in cell %d with T_e %g, T_R %g\n", - get_ionstage(element, ion), get_atomicnumber(element), modelgridindex, grid::get_Te(modelgridindex), - grid::get_TR(modelgridindex)); - ionfractions[ion] = 0; - } - } - return ionfractions; -} - -static auto get_element_nne_contrib(const int modelgridindex, const int element) +auto get_element_nne_contrib(const int modelgridindex, const int element) -> double { // calculate number density of the current element (abundances are given by mass) // Use ionization fractions to calculate the free electron contributions if (grid::get_elem_numberdens(modelgridindex, element) <= 0.) { @@ -179,11 +137,11 @@ static auto get_element_nne_contrib(const int modelgridindex, const int element) return nne; } -static auto nne_solution_f(double nne_assumed, void *voidparas) -> double +auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double // assume a value for nne and then calculate the resulting nne // the difference between the assumed and calculated nne is returned { - const auto *paras = static_cast(voidparas); + const auto *paras = static_cast(voidparas); const int modelgridindex = paras->modelgridindex; const bool force_lte = paras->force_lte; @@ -213,47 +171,8 @@ static auto nne_solution_f(double nne_assumed, void *voidparas) -> double return nne_after - nne_assumed; } -auto get_groundlevelpop(int modelgridindex, int element, int ion) -> double -/// Returns the given ions groundlevel population for modelgridindex which was precalculated -/// during update_grid and stored to the grid. -{ - assert_testmodeonly(modelgridindex < grid::get_npts_model()); - assert_testmodeonly(element < get_nelements()); - assert_testmodeonly(ion < get_nions(element)); - - const double nn = grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion]; - if (nn < MINPOP) { - if (grid::get_elem_abundance(modelgridindex, element) > 0) { - return MINPOP; - } - return 0.; - } - return nn; -} - -auto calculate_levelpop_lte(int modelgridindex, int element, int ion, int level) -> double -/// Calculates occupation population of a level assuming LTE excitation -{ - assert_testmodeonly(modelgridindex < grid::get_npts_model()); - assert_testmodeonly(element < get_nelements()); - assert_testmodeonly(ion < get_nions(element)); - assert_testmodeonly(level < get_nlevels(element, ion)); - - const auto nnground = get_groundlevelpop(modelgridindex, element, ion); - if (level == 0) { - return nnground; - } - - const auto T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(modelgridindex) : grid::get_Te(modelgridindex); - - const double E_aboveground = epsilon(element, ion, level) - epsilon(element, ion, 0); - - return (nnground * stat_weight(element, ion, level) / stat_weight(element, ion, 0) * - exp(-E_aboveground / KB / T_exc)); -} - -static auto calculate_levelpop_nominpop(int modelgridindex, int element, int ion, int level, - bool *skipminpop) -> double { +auto calculate_levelpop_nominpop(const int modelgridindex, const int element, const int ion, const int level, + bool *const skipminpop) -> double { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -318,38 +237,7 @@ static auto calculate_levelpop_nominpop(int modelgridindex, int element, int ion return nn; } -auto calculate_levelpop(int modelgridindex, int element, int ion, int level) -> double { - bool skipminpop = false; - double nn = calculate_levelpop_nominpop(modelgridindex, element, ion, level, &skipminpop); - if (!skipminpop && nn < MINPOP) { - if (grid::get_elem_abundance(modelgridindex, element) > 0) { - nn = MINPOP; - } else { - nn = 0.; - } - } - - return nn; -} - -__host__ __device__ auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double -/// Calculates the population of a level from either LTE or NLTE information -{ - double nn = 0.; - if (use_cellcache) { - assert_testmodeonly(modelgridindex == globals::cellcache[cellcacheslotid].cellnumber); - nn = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].population; - } else { - nn = calculate_levelpop(modelgridindex, element, ion, level); - } - - assert_testmodeonly(nn >= 0.); - assert_testmodeonly(std::isfinite(nn)); - - return nn; -} - -static auto calculate_partfunct(int element, int ion, int modelgridindex) -> double +auto calculate_partfunct(const int element, const int ion, const int modelgridindex) -> double /// Calculates the partition function for ion=ion of element=element in /// cell modelgridindex { @@ -396,49 +284,7 @@ static auto calculate_partfunct(int element, int ion, int modelgridindex) -> dou return U; } -void calculate_cellpartfuncts(const int modelgridindex, const int element) -/// The partition functions depend only on T_R and W. This means they don't -/// change during any iteration on T_e. Therefore their precalculation was -/// taken out of calculate_ion_balance_nne to save runtime. -// TODO: not true if LTEPOP_EXCITATION_USE_TJ is true unless LTE mode only (TJ=TR=Te) -{ - /// Precalculate partition functions for each ion in every cell - /// this saves a factor 10 in calculation time of Saha-Boltzman populations - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - grid::modelgrid[modelgridindex].composition[element].partfunct[ion] = - calculate_partfunct(element, ion, modelgridindex); - } -} - -__host__ __device__ auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, - double E_threshold) -> double -/// calculates saha factor in LTE: Phi_level,ion,element = nn_level,ion,element/(nne*nn_upper,ion+1,element) -{ - const double g_lower = stat_weight(element, ion, level); - const double g_upper = stat_weight(element, ion + 1, upperionlevel); - const double sf = SAHACONST * g_lower / g_upper * pow(T, -1.5) * exp(E_threshold / KB / T); - // printout("element %d, ion %d, level %d, T, %g, E %g has sf %g (g_l %g g_u %g)\n", element, ion, level, T, - // E_threshold, sf,stat_weight(element,ion,level),stat_weight(element,ion+1,0) ); - if (sf < 0) { - printout( - "[fatal] calculate_sahafact: Negative Saha factor. sfac %g element %d ion %d level %d upperionlevel %d " - "g_lower %g g_upper %g T %g E_threshold %g exppart %g\n", - sf, element, ion, level, upperionlevel, g_lower, g_upper, T, E_threshold, exp(E_threshold / KB / T)); - std::abort(); - } - return sf; -} - -[[nodiscard]] __host__ __device__ auto get_nnion(int modelgridindex, int element, int ion) -> double -/// Use the ground level population and partition function to get an ion population -{ - return get_groundlevelpop(modelgridindex, element, ion) * - grid::modelgrid[modelgridindex].composition[element].partfunct[ion] / stat_weight(element, ion, 0); -} - -static auto find_uppermost_ion(const int modelgridindex, const int element, const double nne_hi, - const bool force_lte) -> int { +auto find_uppermost_ion(const int modelgridindex, const int element, const double nne_hi, const bool force_lte) -> int { const int nions = get_nions(element); if (nions == 0) { return -1; @@ -483,7 +329,7 @@ static auto find_uppermost_ion(const int modelgridindex, const int element, cons return uppermost_ion; } -static void set_calculated_nne(const int modelgridindex) { +void set_calculated_nne(const int modelgridindex) { double nne = 0.; // free electron density for (int element = 0; element < get_nelements(); element++) { @@ -493,50 +339,7 @@ static void set_calculated_nne(const int modelgridindex) { grid::set_nne(modelgridindex, std::max(MINPOP, nne)); } -void set_groundlevelpops(const int modelgridindex, const int element, const float nne, const bool force_lte) { - /// If not already set by the NLTE solver, set the ground level populations from either Saha LTE or - /// ionization/recombination balance (Photoionization Equilibrium) - const int nions = get_nions(element); - - if (nions <= 0) { - return; - } - - /// calculate number density of the current element (abundances are given by mass) - const double nnelement = grid::get_elem_numberdens(modelgridindex, element); - - const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); - - const auto ionfractions = - (nnelement > 0) ? calculate_ionfractions(element, modelgridindex, nne, use_phi_lte) : std::vector(); - - const int uppermost_ion = static_cast(ionfractions.size() - 1); - - /// Use ion fractions to calculate the groundlevel populations - for (int ion = 0; ion < nions; ion++) { - double nnion{NAN}; - if (ion <= uppermost_ion) { - if (nnelement > 0) { - nnion = std::max(MINPOP, nnelement * ionfractions[ion]); - } else { - nnion = 0.; - } - } else { - nnion = MINPOP; - } - - const double groundpop = - nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].composition[element].partfunct[ion]; - - if (!std::isfinite(groundpop)) { - printout("[warning] calculate_ion_balance_nne: groundlevelpop infinite in connection with MINPOP\n"); - } - - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = groundpop; - } -} - -static void set_groundlevelpops_neutral(const int modelgridindex) { +void set_groundlevelpops_neutral(const int modelgridindex) { /// Special case of only neutral ions, set nne to some finite value that /// packets are not lost in kpkts printout("[warning] calculate_ion_balance_nne: only neutral ions in cell modelgridindex %d\n", modelgridindex); @@ -561,7 +364,7 @@ static void set_groundlevelpops_neutral(const int modelgridindex) { } } -static auto find_converged_nne(const int modelgridindex, double nne_hi, const bool force_lte) -> float { +auto find_converged_nne(const int modelgridindex, double nne_hi, const bool force_lte) -> float { /// Search solution for nne in [nne_lo,nne_hi] nne_solution_paras paras = {.modelgridindex = modelgridindex, .force_lte = force_lte}; @@ -619,6 +422,203 @@ static auto find_converged_nne(const int modelgridindex, double nne_hi, const bo return std::max(MINPOP, nne_solution); } +} // anonymous namespace + +[[nodiscard]] auto calculate_ionfractions(const int element, const int modelgridindex, const double nne, + const bool use_phi_lte) -> std::vector +// Calculate the fractions of an element's population in each ionization stage based on Saha LTE or ionisation +// equilibrium +{ + const int uppermost_ion = grid::get_elements_uppermost_ion(modelgridindex, element); + assert_testmodeonly(modelgridindex < grid::get_npts_model()); + assert_testmodeonly(element < get_nelements()); + assert_testmodeonly(uppermost_ion <= std::max(0, get_nions(element) - 1)); + const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + + if (uppermost_ion < 0) { + return {}; + } + + std::vector ionfractions(uppermost_ion + 1); + ionfractions[uppermost_ion] = 1; + + double normfactor = 1.; + + for (int ion = uppermost_ion - 1; ion >= 0; ion--) { + const auto phifactor = use_phi_lte ? phi_lte(element, ion, modelgridindex) + : phi_ion_equilib(element, ion, modelgridindex, nonemptymgi); + ionfractions[ion] = ionfractions[ion + 1] * nne * phifactor; + normfactor += ionfractions[ion]; + } + + for (int ion = 0; ion <= uppermost_ion; ion++) { + ionfractions[ion] = ionfractions[ion] / normfactor; + + if (normfactor == 0. || !std::isfinite(ionfractions[ion])) { + printout("[warning] ionfract set to zero for ionstage %d of Z=%d in cell %d with T_e %g, T_R %g\n", + get_ionstage(element, ion), get_atomicnumber(element), modelgridindex, grid::get_Te(modelgridindex), + grid::get_TR(modelgridindex)); + ionfractions[ion] = 0; + } + } + return ionfractions; +} + +auto get_groundlevelpop(const int modelgridindex, const int element, const int ion) -> double +/// Returns the given ions groundlevel population for modelgridindex which was precalculated +/// during update_grid and stored to the grid. +{ + assert_testmodeonly(modelgridindex < grid::get_npts_model()); + assert_testmodeonly(element < get_nelements()); + assert_testmodeonly(ion < get_nions(element)); + + const double nn = grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion]; + if (nn < MINPOP) { + if (grid::get_elem_abundance(modelgridindex, element) > 0) { + return MINPOP; + } + return 0.; + } + return nn; +} + +auto calculate_levelpop_lte(const int modelgridindex, const int element, const int ion, const int level) -> double +/// Calculates occupation population of a level assuming LTE excitation +{ + assert_testmodeonly(modelgridindex < grid::get_npts_model()); + assert_testmodeonly(element < get_nelements()); + assert_testmodeonly(ion < get_nions(element)); + assert_testmodeonly(level < get_nlevels(element, ion)); + + const auto nnground = get_groundlevelpop(modelgridindex, element, ion); + if (level == 0) { + return nnground; + } + + const auto T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(modelgridindex) : grid::get_Te(modelgridindex); + + const double E_aboveground = epsilon(element, ion, level) - epsilon(element, ion, 0); + + return (nnground * stat_weight(element, ion, level) / stat_weight(element, ion, 0) * + exp(-E_aboveground / KB / T_exc)); +} + +auto calculate_levelpop(const int modelgridindex, const int element, const int ion, const int level) -> double { + bool skipminpop = false; + double nn = calculate_levelpop_nominpop(modelgridindex, element, ion, level, &skipminpop); + if (!skipminpop && nn < MINPOP) { + if (grid::get_elem_abundance(modelgridindex, element) > 0) { + nn = MINPOP; + } else { + nn = 0.; + } + } + + return nn; +} + +__host__ __device__ auto get_levelpop(const int modelgridindex, const int element, const int ion, + const int level) -> double +/// Calculates the population of a level from either LTE or NLTE information +{ + double nn = 0.; + if (use_cellcache) { + assert_testmodeonly(modelgridindex == globals::cellcache[cellcacheslotid].cellnumber); + nn = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].population; + } else { + nn = calculate_levelpop(modelgridindex, element, ion, level); + } + + assert_testmodeonly(nn >= 0.); + assert_testmodeonly(std::isfinite(nn)); + + return nn; +} + +void calculate_cellpartfuncts(const int modelgridindex, const int element) +/// The partition functions depend only on T_R and W. This means they don't +/// change during any iteration on T_e. Therefore their precalculation was +/// taken out of calculate_ion_balance_nne to save runtime. +// TODO: not true if LTEPOP_EXCITATION_USE_TJ is true unless LTE mode only (TJ=TR=Te) +{ + /// Precalculate partition functions for each ion in every cell + /// this saves a factor 10 in calculation time of Saha-Boltzman populations + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + grid::modelgrid[modelgridindex].composition[element].partfunct[ion] = + calculate_partfunct(element, ion, modelgridindex); + } +} + +__host__ __device__ auto calculate_sahafact(const int element, const int ion, const int level, const int upperionlevel, + const double T, const double E_threshold) -> double +/// calculates saha factor in LTE: Phi_level,ion,element = nn_level,ion,element/(nne*nn_upper,ion+1,element) +{ + const double g_lower = stat_weight(element, ion, level); + const double g_upper = stat_weight(element, ion + 1, upperionlevel); + const double sf = SAHACONST * g_lower / g_upper * pow(T, -1.5) * exp(E_threshold / KB / T); + // printout("element %d, ion %d, level %d, T, %g, E %g has sf %g (g_l %g g_u %g)\n", element, ion, level, T, + // E_threshold, sf,stat_weight(element,ion,level),stat_weight(element,ion+1,0) ); + if (sf < 0) { + printout( + "[fatal] calculate_sahafact: Negative Saha factor. sfac %g element %d ion %d level %d upperionlevel %d " + "g_lower %g g_upper %g T %g E_threshold %g exppart %g\n", + sf, element, ion, level, upperionlevel, g_lower, g_upper, T, E_threshold, exp(E_threshold / KB / T)); + std::abort(); + } + return sf; +} + +[[nodiscard]] __host__ __device__ auto get_nnion(const int modelgridindex, const int element, const int ion) -> double +/// Use the ground level population and partition function to get an ion population +{ + return get_groundlevelpop(modelgridindex, element, ion) * + grid::modelgrid[modelgridindex].composition[element].partfunct[ion] / stat_weight(element, ion, 0); +} + +void set_groundlevelpops(const int modelgridindex, const int element, const float nne, const bool force_lte) { + /// If not already set by the NLTE solver, set the ground level populations from either Saha LTE or + /// ionization/recombination balance (Photoionization Equilibrium) + const int nions = get_nions(element); + + if (nions <= 0) { + return; + } + + /// calculate number density of the current element (abundances are given by mass) + const double nnelement = grid::get_elem_numberdens(modelgridindex, element); + + const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); + + const auto ionfractions = + (nnelement > 0) ? calculate_ionfractions(element, modelgridindex, nne, use_phi_lte) : std::vector(); + + const int uppermost_ion = static_cast(ionfractions.size() - 1); + + /// Use ion fractions to calculate the groundlevel populations + for (int ion = 0; ion < nions; ion++) { + double nnion{NAN}; + if (ion <= uppermost_ion) { + if (nnelement > 0) { + nnion = std::max(MINPOP, nnelement * ionfractions[ion]); + } else { + nnion = 0.; + } + } else { + nnion = MINPOP; + } + + const double groundpop = + nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].composition[element].partfunct[ion]; + + if (!std::isfinite(groundpop)) { + printout("[warning] calculate_ion_balance_nne: groundlevelpop infinite in connection with MINPOP\n"); + } + + grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = groundpop; + } +} + auto calculate_ion_balance_nne(const int modelgridindex) -> void /// Determines the electron number density for a given cell using one of /// libgsl's root_solvers and calculates the depending level populations. diff --git a/macroatom.cc b/macroatom.cc index ecd65ceed..158ba4c34 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -156,7 +156,7 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele processrates[MA_ACTION_INTERNALUPHIGHER] = sum_up_higher; } -auto do_macroatom_internal_down_same(int element, int ion, int level) -> int { +auto do_macroatom_internal_down_same(const int element, const int ion, const int level) -> int { const int ndowntrans = get_ndowntrans(element, ion, level); // printout("[debug] do_ma: internal downward jump within current ionstage\n"); @@ -229,7 +229,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, pkt.nscatterings = 0; } -void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int element, int *ion, int *level, +void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int element, int *const ion, int *const level, const double rad_recomb) { const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); @@ -289,7 +289,7 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele pkt.nscatterings = 0; } -void do_macroatom_ionisation(const int modelgridindex, const int element, int *ion, int *level, +void do_macroatom_ionisation(const int modelgridindex, const int element, int *const ion, int *const level, const double epsilon_current, const double internal_up_higher) { const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); @@ -405,8 +405,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast const double randomrate = rng_uniform() * cumulative_transitions[MA_ACTION_COUNT - 1]; // first cumulative_transitions[i] such that cumulative_transitions[i] > randomrate - const int selected_action = - std::ranges::upper_bound(cumulative_transitions, randomrate) - cumulative_transitions.cbegin(); + const int selected_action = static_cast(std::ranges::upper_bound(cumulative_transitions, randomrate) - + cumulative_transitions.cbegin()); assert_always(selected_action < MA_ACTION_COUNT); assert_always(cumulative_transitions[selected_action] > randomrate); @@ -710,7 +710,7 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con } auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, - const int uptransindex, const double epsilon_trans, int lineindex, + const int uptransindex, const double epsilon_trans, const int lineindex, const double t_current) -> double /// radiative excitation rate: paperII 3.5.2 // multiply by lower level population to get a rate per second @@ -875,8 +875,8 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen return C; } -auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, int element, int ion, - int upper, const LevelTransition &downtransition) -> double +auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, const int element, + const int ion, const int upper, const LevelTransition &downtransition) -> double // multiply by upper level population to get a rate per second { const int lower = downtransition.targetlevelindex; @@ -926,8 +926,9 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e return nne * 8.629e-6 * coll_str_thisline / upperstatweight / std::sqrt(T_e); } -auto col_excitation_ratecoeff(const float T_e, const float nne, int element, int ion, int lower, int uptransindex, - const double epsilon_trans, const double lowerstatweight) -> double +auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, + const int uptransindex, const double epsilon_trans, + const double lowerstatweight) -> double // multiply by lower level population to get a rate per second { // assert_testmodeonly(i < get_nuptrans(element, ion, lower)); diff --git a/md5.cc b/md5.cc index 233d4f3f5..d2a98e432 100644 --- a/md5.cc +++ b/md5.cc @@ -48,7 +48,8 @@ } /*********************** FUNCTION DEFINITIONS ***********************/ -static void md5_transform(MD5_CTX *ctx, const BYTE data[]) { +namespace { +void md5_transform(MD5_CTX *ctx, const BYTE data[]) { WORD a = 0; WORD b = 0; WORD c = 0; @@ -143,6 +144,8 @@ static void md5_transform(MD5_CTX *ctx, const BYTE data[]) { ctx->state[3] += d; } +} // anonymous namespace + void md5_init(MD5_CTX *ctx) { ctx->datalen = 0; ctx->bitlen = 0; @@ -220,8 +223,9 @@ void md5_file(const char filename[], char hashout[(2 * MD5_BLOCK_SIZE) + 1]) { BYTE buffer[1024]; long numbytes = -1; - while (numbytes != 0) { + while (numbytes != 0 && feof(infile) == 0) { numbytes = fread(buffer, sizeof(char), 1024, infile); + assert_always(ferror(infile) == 0); md5_update(&ctx, buffer, numbytes); } diff --git a/md5.h b/md5.h index cbf60f759..0c3b904a8 100644 --- a/md5.h +++ b/md5.h @@ -14,7 +14,7 @@ #include /****************************** MACROS ******************************/ -#define MD5_BLOCK_SIZE 16 // MD5 outputs a 16 byte digest +constexpr int MD5_BLOCK_SIZE = 16; // MD5 outputs a 16 byte digest /**************************** DATA TYPES ****************************/ using BYTE = unsigned char; // 8-bit byte diff --git a/nltepop.cc b/nltepop.cc index 1c0140dec..e92182e24 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -26,12 +26,13 @@ #include "ratecoeff.h" #include "sn3d.h" -static FILE *nlte_file{}; +namespace { +FILE *nlte_file{}; // can save memory by using a combined rate matrix at the cost of diagnostic information -static constexpr bool individual_process_matricies = true; +constexpr bool individual_process_matricies = true; -static auto get_nlte_vector_index(const int element, const int ion, const int level) -> int +auto get_nlte_vector_index(const int element, const int ion, const int level) -> int // this is the index for the NLTE solver that is handling all ions of a single element // This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements { @@ -47,7 +48,7 @@ static auto get_nlte_vector_index(const int element, const int ion, const int le return level_index; } -static void get_ion_level_of_nlte_vector_index(const int index, const int element, int *ion, int *level) { +void get_ion_level_of_nlte_vector_index(const int index, const int element, int *const ion, int *const level) { // this could easily be optimized if need be for (int dion = 0; dion < get_nions(element); dion++) { for (int dlevel = 0; dlevel < get_nlevels(element, dion); dlevel++) { @@ -60,8 +61,8 @@ static void get_ion_level_of_nlte_vector_index(const int index, const int elemen } } -static void eliminate_nlte_matrix_rowcol(const int index, const int gs_index, gsl_matrix *rate_matrix, - gsl_vector *balance_vector) { +void eliminate_nlte_matrix_rowcol(const int index, const int gs_index, gsl_matrix *rate_matrix, + gsl_vector *balance_vector) { const gsl_matrix rate_matrix_var = *rate_matrix; const int colcount = rate_matrix_var.size2; @@ -79,8 +80,8 @@ static void eliminate_nlte_matrix_rowcol(const int index, const int gs_index, gs gsl_vector_set(balance_vector, index, 0.0); } -static void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector *balance_vector, - const gsl_vector * /*pop_norm_factor_vec*/) +void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector *balance_vector, + const gsl_vector * /*pop_norm_factor_vec*/) // find rows and columns that barely interaction with other levels, and effectively // removing them by zeroing their interactions and setting their departure // coeff to 1.0 @@ -121,9 +122,8 @@ static void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_v } } -static auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, const gsl_vector *popvec, - const bool into_level, const bool only_levels_below, - const bool only_levels_above) -> double { +auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, const gsl_vector *popvec, + const bool into_level, const bool only_levels_below, const bool only_levels_above) -> double { double total_rate = 0.; assert_always(!only_levels_below || !only_levels_above); @@ -173,20 +173,19 @@ static auto get_total_rate(const int index_selected, const gsl_matrix *rate_matr return total_rate; } -static auto get_total_rate_in(const int index_to, const gsl_matrix *rate_matrix, const gsl_vector *popvec) -> double { +auto get_total_rate_in(const int index_to, const gsl_matrix *rate_matrix, const gsl_vector *popvec) -> double { return get_total_rate(index_to, rate_matrix, popvec, true, false, false); } -static auto get_total_rate_out(const int index_from, const gsl_matrix *rate_matrix, - const gsl_vector *popvec) -> double { +auto get_total_rate_out(const int index_from, const gsl_matrix *rate_matrix, const gsl_vector *popvec) -> double { return get_total_rate(index_from, rate_matrix, popvec, false, false, false); } -static void print_level_rates_summary(const int element, const int selected_ion, const int selected_level, - const gsl_vector *popvec, const gsl_matrix *rate_matrix_rad_bb, - const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, - const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, - const gsl_matrix *rate_matrix_ntcoll_bf) { +void print_level_rates_summary(const int element, const int selected_ion, const int selected_level, + const gsl_vector *popvec, const gsl_matrix *rate_matrix_rad_bb, + const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, + const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, + const gsl_matrix *rate_matrix_ntcoll_bf) { const int selected_index = get_nlte_vector_index(element, selected_ion, selected_level); for (int i = 0; i <= 3; i++) { @@ -241,12 +240,11 @@ static void print_level_rates_summary(const int element, const int selected_ion, } } -static void print_element_rates_summary(const int element, const int modelgridindex, const int timestep, - const int nlte_iter, const gsl_vector *popvec, - const gsl_matrix *rate_matrix_rad_bb, const gsl_matrix *rate_matrix_coll_bb, - const gsl_matrix *rate_matrix_ntcoll_bb, const gsl_matrix *rate_matrix_rad_bf, - const gsl_matrix *rate_matrix_coll_bf, - const gsl_matrix *rate_matrix_ntcoll_bf) { +void print_element_rates_summary(const int element, const int modelgridindex, const int timestep, const int nlte_iter, + const gsl_vector *popvec, const gsl_matrix *rate_matrix_rad_bb, + const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, + const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, + const gsl_matrix *rate_matrix_ntcoll_bf) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); @@ -280,11 +278,11 @@ static void print_element_rates_summary(const int element, const int modelgridin } } -static void print_level_rates(const int modelgridindex, const int timestep, const int element, const int selected_ion, - const int selected_level, const gsl_vector *popvec, const gsl_matrix *rate_matrix_rad_bb, - const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, - const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, - const gsl_matrix *rate_matrix_ntcoll_bf) { +void print_level_rates(const int modelgridindex, const int timestep, const int element, const int selected_ion, + const int selected_level, const gsl_vector *popvec, const gsl_matrix *rate_matrix_rad_bb, + const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, + const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, + const gsl_matrix *rate_matrix_ntcoll_bf) { // very detailed output of the NLTE processes for a particular levels if (element > get_nelements() - 1 || selected_ion > get_nions(element) - 1 || @@ -390,7 +388,7 @@ static void print_level_rates(const int modelgridindex, const int timestep, cons printout("\n"); } -static void nltepop_reset_element(const int modelgridindex, const int element) { +void nltepop_reset_element(const int modelgridindex, const int element) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { const int nlte_start = globals::elements[element].ions[ion].first_nlte; @@ -399,7 +397,7 @@ static void nltepop_reset_element(const int modelgridindex, const int element) { } } -static auto get_element_superlevelpartfuncs(const int modelgridindex, const int element) -> std::vector { +auto get_element_superlevelpartfuncs(const int modelgridindex, const int element) -> std::vector { const int nions = get_nions(element); auto superlevel_partfuncs = std::vector(nions, 0.); for (int ion = 0; ion < nions; ion++) { @@ -415,7 +413,7 @@ static auto get_element_superlevelpartfuncs(const int modelgridindex, const int return superlevel_partfuncs; } -static auto get_element_nlte_dimension(const int element) -> int { +auto get_element_nlte_dimension(const int element) -> int { int nlte_dimension = 0; const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -432,10 +430,9 @@ static auto get_element_nlte_dimension(const int element) -> int { return nlte_dimension; } -static void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const int ion, - const double t_mid, const std::vector &s_renorm, - gsl_matrix *rate_matrix_rad_bb, gsl_matrix *rate_matrix_coll_bb, - gsl_matrix *rate_matrix_ntcoll_bb) { +void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const int ion, const double t_mid, + const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bb, + gsl_matrix *rate_matrix_coll_bb, gsl_matrix *rate_matrix_ntcoll_bb) { const auto T_e = grid::get_Te(modelgridindex); const float nne = grid::get_nne(modelgridindex); const int nlevels = get_nlevels(element, ion); @@ -512,9 +509,9 @@ static void nltepop_matrix_add_boundbound(const int modelgridindex, const int el } } -static void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const int ion, - const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bf, - gsl_matrix *rate_matrix_coll_bf) { +void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const int ion, + const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bf, + gsl_matrix *rate_matrix_coll_bf) { assert_always(ion + 1 < get_nions(element)); // can't ionise the top ion const auto T_e = grid::get_Te(modelgridindex); const float nne = grid::get_nne(modelgridindex); @@ -571,8 +568,8 @@ static void nltepop_matrix_add_ionisation(const int modelgridindex, const int el } } -static void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int element, const int ion, - const std::vector &s_renorm, gsl_matrix *rate_matrix_ntcoll_bf) { +void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int element, const int ion, + const std::vector &s_renorm, gsl_matrix *rate_matrix_ntcoll_bf) { // collisional ionization by non-thermal electrons assert_always(ion + 1 < get_nions(element)); // can't ionise the top ion @@ -600,8 +597,8 @@ static void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int } } -static void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_matrix *rate_matrix, - gsl_vector *pop_norm_factor_vec) { +void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_matrix *rate_matrix, + gsl_vector *pop_norm_factor_vec) { const size_t nlte_dimension = pop_norm_factor_vec->size; assert_always(pop_norm_factor_vec->size == nlte_dimension); assert_always(rate_matrix->size1 == nlte_dimension); @@ -638,14 +635,14 @@ static void nltepop_matrix_normalise(const int modelgridindex, const int element } } -static void set_element_pops_lte(const int modelgridindex, const int element) { +void set_element_pops_lte(const int modelgridindex, const int element) { nltepop_reset_element(modelgridindex, element); // set NLTE pops as invalid so that LTE pops will be used instead calculate_cellpartfuncts(modelgridindex, element); set_groundlevelpops(modelgridindex, element, grid::get_nne(modelgridindex), true); } -static auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { +auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { size_t const n = LU->size1; bool is_singular = false; @@ -669,8 +666,8 @@ static auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> boo return is_singular; } -static auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, - gsl_vector *popvec, const gsl_vector *pop_normfactor_vec) -> bool +auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, + gsl_vector *popvec, const gsl_vector *pop_normfactor_vec) -> bool // solve rate_matrix * x = balance_vector, // then popvec[i] = x[i] / pop_norm_factor_vec[i] { @@ -788,6 +785,7 @@ static auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matri return completed_solution; } +} // anonymous namespace void solve_nlte_pops_element(const int element, const int modelgridindex, const int timestep, const int nlte_iter) // solves the statistical balance equations to find NLTE level populations for all ions of an element diff --git a/nonthermal.cc b/nonthermal.cc index c7d7540f7..84266ce70 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -232,13 +233,13 @@ void read_binding_energies() { } } -auto get_auger_probability(int modelgridindex, int element, int ion, int naugerelec) -> double { +auto get_auger_probability(const int modelgridindex, const int element, const int ion, const int naugerelec) -> double { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); return nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; } -auto get_ion_auger_enfrac(int modelgridindex, int element, int ion, int naugerelec) -> double { +auto get_ion_auger_enfrac(const int modelgridindex, const int element, const int ion, const int naugerelec) -> double { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); return nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; @@ -1334,7 +1335,7 @@ auto calculate_nt_excitation_ratecoeff_perdeposition(const int modelgridindex, c return 0.; } -auto ion_ntion_energyrate(int modelgridindex, int element, int lowerion) -> double { +auto ion_ntion_energyrate(const int modelgridindex, const int element, const int lowerion) -> double { // returns the energy rate [erg/cm3/s] going toward non-thermal ionisation of lowerion const double nnlowerion = get_nnion(modelgridindex, element, lowerion); double enrate = 0.; @@ -1356,7 +1357,7 @@ auto ion_ntion_energyrate(int modelgridindex, int element, int lowerion) -> doub return gamma_nt * enrate; } -auto get_ntion_energyrate(int modelgridindex) -> double { +auto get_ntion_energyrate(const int modelgridindex) -> double { // returns the energy rate [erg/s] going toward non-thermal ionisation in a modelgrid cell double ratetotal = 0.; for (int ielement = 0; ielement < get_nelements(); ielement++) { @@ -1368,7 +1369,7 @@ auto get_ntion_energyrate(int modelgridindex) -> double { return ratetotal; } -auto select_nt_ionization(int modelgridindex) -> std::tuple { +auto select_nt_ionization(const int modelgridindex) -> std::tuple { const double zrand = rng_uniform(); // // select based on stored frac_deposition for each ion @@ -1572,9 +1573,8 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo if constexpr (NT_EXCITATION_ON && (MAX_NT_EXCITATIONS_STORED > 0)) { // sort by descending frac_deposition - std::stable_sort(nt_solution[modelgridindex].frac_excitations_list.begin(), - nt_solution[modelgridindex].frac_excitations_list.end(), - [](const auto &a, const auto &b) { return a.frac_deposition > b.frac_deposition; }); + std::ranges::stable_sort(nt_solution[modelgridindex].frac_excitations_list, std::ranges::greater{}, + &nt_excitation_struct::frac_deposition); // the excitation list is now sorted by frac_deposition descending const double deposition_rate_density = get_deposition_rate_density(modelgridindex); @@ -1631,9 +1631,8 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::stable_sort(nt_solution[modelgridindex].frac_excitations_list.begin(), - nt_solution[modelgridindex].frac_excitations_list.end(), - [](const auto &a, const auto &b) { return a.lineindex < b.lineindex; }); + std::ranges::stable_sort(nt_solution[modelgridindex].frac_excitations_list, std::ranges::less{}, + &nt_excitation_struct::lineindex); } // NT_EXCITATION_ON @@ -2169,7 +2168,7 @@ __host__ __device__ auto nt_ionization_upperion_probability(const int modelgridi if (energyweighted) { assert_always(fabs(prob_remaining - nt_solution[modelgridindex] - .ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + numaugerelec]) < + .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]) < 0.001); } else { if (fabs(prob_remaining - @@ -2179,7 +2178,7 @@ __host__ __device__ auto nt_ionization_upperion_probability(const int modelgridi get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, upperion)); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { printout(" a %d prob %g\n", a, - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a]); + nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]); } std::abort(); } @@ -2297,8 +2296,7 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const // binary search, assuming the excitation list is sorted by lineindex ascending auto ntexclist = nt_solution[modelgridindex].frac_excitations_list; - auto ntexcitation = std::lower_bound(ntexclist.cbegin(), ntexclist.cend(), lineindex, - [](const auto &exc, const int lineindex) { return exc.lineindex < lineindex; }); + auto ntexcitation = std::ranges::lower_bound(ntexclist, lineindex, {}, &nt_excitation_struct::lineindex); if (ntexcitation == ntexclist.end() || ntexcitation->lineindex != lineindex) { return 0.; } @@ -2689,9 +2687,9 @@ void read_restart_data(FILE *gridsave_file) { for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { assert_always( fscanf(gridsave_file, "%a %a ", - &nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a], + &nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a], &nt_solution[modelgridindex] - .ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1) + a]) == 2); + .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]) == 2); } } diff --git a/packet.cc b/packet.cc index f313fc057..15b780fde 100644 --- a/packet.cc +++ b/packet.cc @@ -25,7 +25,9 @@ #include "sn3d.h" #include "vectors.h" -static void place_pellet(const double e0, const int cellindex, const int pktnumber, Packet &pkt) +namespace { + +void place_pellet(const double e0, const int cellindex, const int pktnumber, Packet &pkt) /// This subroutine places pellet n with energy e0 in cell m { /// First choose a position for the pellet. In the cell. @@ -84,6 +86,8 @@ static void place_pellet(const double e0, const int cellindex, const int pktnumb pkt.trueemissiontype = EMTYPE_NOTSET; } +} // anonymous namespace + void packet_init(Packet *pkt) /// Subroutine that initialises the packets if we start a new simulation. { @@ -139,12 +143,11 @@ void packet_init(Packet *pkt) printout("Placing pellets...\n"); auto allpkts = std::ranges::iota_view{0, globals::npkts}; - std::for_each(allpkts.begin(), allpkts.end(), [&, norm, e0](const int n) { + std::ranges::for_each(allpkts, [&, norm, e0](const int n) { const double targetval = rng_uniform() * norm; // first i such that en_cumulative[i] > targetval - const int cellindex = - std::upper_bound(en_cumulative.cbegin(), en_cumulative.cend(), targetval) - en_cumulative.cbegin(); + const int cellindex = static_cast(std::ranges::upper_bound(en_cumulative, targetval) - en_cumulative.cbegin()); assert_always(cellindex < grid::ngrid); place_pellet(e0, cellindex, n, pkt[n]); diff --git a/radfield.cc b/radfield.cc index c57e33a71..3f44e97c5 100644 --- a/radfield.cc +++ b/radfield.cc @@ -106,7 +106,7 @@ struct gsl_T_R_solver_paras { FILE *radfieldfile{}; -constexpr auto get_bin_nu_upper(int binindex) -> double { +constexpr auto get_bin_nu_upper(const int binindex) -> double { assert_testmodeonly(binindex < RADFIELDBINCOUNT); if (binindex == RADFIELDBINCOUNT - 1) { return nu_upper_superbin; @@ -114,7 +114,7 @@ constexpr auto get_bin_nu_upper(int binindex) -> double { return nu_lower_first_initial + ((binindex + 1) * radfieldbins_delta_nu); } -constexpr auto get_bin_nu_lower(int binindex) -> double { +constexpr auto get_bin_nu_lower(const int binindex) -> double { if (binindex > 0) { return get_bin_nu_upper(binindex - 1); } @@ -195,7 +195,7 @@ void add_detailed_line(const int lineindex) // printout("Added Jblue estimator for lineindex %d count %d\n", lineindex, detailed_linecount); } -auto get_bin_J(int modelgridindex, int binindex) -> double +auto get_bin_J(const int modelgridindex, const int binindex) -> double // get the normalised J_nu { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); @@ -206,7 +206,7 @@ auto get_bin_J(int modelgridindex, int binindex) -> double return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].J_raw * J_normfactor[nonemptymgi]; } -auto get_bin_nuJ(int modelgridindex, int binindex) -> double { +auto get_bin_nuJ(const int modelgridindex, const int binindex) -> double { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); assert_testmodeonly(modelgridindex < grid::get_npts_model()); @@ -215,7 +215,7 @@ auto get_bin_nuJ(int modelgridindex, int binindex) -> double { return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].nuJ_raw * J_normfactor[nonemptymgi]; } -auto get_bin_nu_bar(int modelgridindex, int binindex) -> double +auto get_bin_nu_bar(const int modelgridindex, const int binindex) -> double // importantly, this is average beween the current and previous timestep { const double nuJ_sum = get_bin_nuJ(modelgridindex, binindex); @@ -223,17 +223,17 @@ auto get_bin_nu_bar(int modelgridindex, int binindex) -> double return nuJ_sum / J_sum; } -auto get_bin_contribcount(int modelgridindex, int binindex) -> int { +auto get_bin_contribcount(const int modelgridindex, const int binindex) -> int { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].contribcount; } -auto get_bin_W(int modelgridindex, int binindex) -> float { +auto get_bin_W(const int modelgridindex, const int binindex) -> float { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].W; } -auto get_bin_T_R(int modelgridindex, int binindex) -> float { +auto get_bin_T_R(const int modelgridindex, const int binindex) -> float { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].T_R; } @@ -251,9 +251,231 @@ constexpr auto gsl_integrand_planck(const double nu, void *voidparas) -> double return integrand; } +void update_bfestimators(const int nonemptymgi, const double distance_e_cmf, const double nu_cmf, + const double doppler_nucmf_on_nurf, const Phixslist &phixslist) { + assert_testmodeonly(DETAILED_BF_ESTIMATORS_ON); + + const double distance_e_cmf_over_nu = + distance_e_cmf / nu_cmf * doppler_nucmf_on_nurf; // TODO: Luke: why did I put a doppler factor here? + + // I think the nu_cmf slightly differs from when the phixslist was calculated + // so the nu condition on this nu_cmf can truncate the list further compared to what was used in the calculation + // of phixslist.gamma_contr + + const auto bfestimend = std::upper_bound(globals::bfestim_nu_edge.data(), + globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf) - + globals::bfestim_nu_edge.data(); + + const auto bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, + globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, + [](const double nu_edge, const double nu_cmf) { + return nu_edge * last_phixs_nuovernuedge < nu_cmf; + }) - + globals::bfestim_nu_edge.data(); + + const auto bfestimcount = globals::bfestimcount; + for (auto bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { + atomicadd(bfrate_raw[(nonemptymgi * bfestimcount) + bfestimindex], + phixslist.gamma_contr[bfestimindex] * distance_e_cmf_over_nu); + } +} + +auto planck_integral(const double T_R, const double nu_lower, const double nu_upper, const bool times_nu) -> double { + double integral = 0.; + + double error = 0.; + const double epsrel = 1e-10; + const double epsabs = 0.; + + const gsl_planck_integral_paras intparas = {.T_R = T_R, .times_nu = times_nu}; + + gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); + + const int status = integrator(intparas, nu_lower, nu_upper, epsabs, epsrel, GSL_INTEG_GAUSS61, + &integral, &error); + if (status != 0) { + printout("planck_integral integrator status %d, GSL_FAILURE= %d. Integral value %g, setting to zero.\n", status, + GSL_FAILURE, integral); + integral = 0.; + } + gsl_set_error_handler(previous_handler); + + return integral; +} + +auto delta_nu_bar(const double T_R, void *const paras) -> double +// difference between the average nu and the average nu of a Planck function +// at temperature T_R, in the frequency range corresponding to a bin +{ + const auto *params = static_cast(paras); + const int modelgridindex = params->modelgridindex; + const int binindex = params->binindex; + + const double nu_lower = get_bin_nu_lower(binindex); + const double nu_upper = get_bin_nu_upper(binindex); + + const double nu_bar_estimator = get_bin_nu_bar(modelgridindex, binindex); + + const double nu_times_planck_numerical = planck_integral(T_R, nu_lower, nu_upper, true); + const double planck_integral_numerical = planck_integral(T_R, nu_lower, nu_upper, false); + const double nu_bar_planck_T_R = nu_times_planck_numerical / planck_integral_numerical; + + // double nu_times_planck_integral = planck_integral_analytic(T_R, nu_lower, nu_upper, true); + // double planck_integral_result = planck_integral_analytic(T_R, nu_lower, nu_upper, false); + // double nu_bar_planck = nu_times_planck_integral / planck_integral_result; + + // // printout("nu_bar %g nu_bar_planck(T=%g) %g\n",nu_bar,T_R,nu_bar_planck); + + // if (!std::isfinite(nu_bar_planck)) { + // double nu_times_planck_numerical = planck_integral(T_R, nu_lower, nu_upper, true); + // double planck_integral_numerical = planck_integral(T_R, nu_lower, nu_upper, false); + // double nu_bar_planck_numerical = nu_times_planck_numerical / planck_integral_numerical; + + // printout("planck_integral_analytic is %g. Replacing with numerical result of %g.\n", nu_bar_planck, + // nu_bar_planck_numerical); + // nu_bar_planck = nu_bar_planck_numerical; + // } + + const double delta_nu_bar = nu_bar_planck_T_R - nu_bar_estimator; + + if (!std::isfinite(delta_nu_bar)) { + printout( + "delta_nu_bar is %g. nu_bar_planck_T_R %g nu_times_planck_numerical %g planck_integral_numerical %g " + "nu_bar_estimator %g\n", + delta_nu_bar, nu_bar_planck_T_R, nu_times_planck_numerical, planck_integral_numerical, nu_bar_estimator); + } + + return delta_nu_bar; +} + +auto find_T_R(const int modelgridindex, const int binindex) -> float { + double T_R = 0.; + + gsl_T_R_solver_paras paras{}; + paras.modelgridindex = modelgridindex; + paras.binindex = binindex; + + /// Check whether the equation has a root in [T_min,T_max] + double delta_nu_bar_min = delta_nu_bar(T_R_min, ¶s); + double delta_nu_bar_max = delta_nu_bar(T_R_max, ¶s); + + // printout("find_T_R: bin %4d delta_nu_bar(T_R_min) %g, delta_nu_bar(T_R_max) %g\n", + // binindex, delta_nu_bar_min,delta_nu_bar_max); + + if (!std::isfinite(delta_nu_bar_min) || !std::isfinite(delta_nu_bar_max)) { + delta_nu_bar_max = delta_nu_bar_min = -1; + } + + if (delta_nu_bar_min * delta_nu_bar_max < 0) { + /// If there is a root in the interval, solve for T_R + + const double epsrel = 1e-4; + const double epsabs = 0.; + const int maxit = 100; + + gsl_function find_T_R_f = {.function = &delta_nu_bar, .params = ¶s}; + + /// one dimensional gsl root solver, bracketing type + gsl_root_fsolver *T_R_solver = gsl_root_fsolver_alloc(gsl_root_fsolver_brent); + gsl_root_fsolver_set(T_R_solver, &find_T_R_f, T_R_min, T_R_max); + int status = 0; + for (int iteration_num = 0; iteration_num <= maxit; iteration_num++) { + gsl_root_fsolver_iterate(T_R_solver); + T_R = gsl_root_fsolver_root(T_R_solver); + + const double T_R_lower = gsl_root_fsolver_x_lower(T_R_solver); + const double T_R_upper = gsl_root_fsolver_x_upper(T_R_solver); + status = gsl_root_test_interval(T_R_lower, T_R_upper, epsabs, epsrel); + + // printout("find_T_R: bin %4d iter %d, T_R is between %7.1f and %7.1f, guess %7.1f, delta_nu_bar %g, status + // %d\n", + // binindex,iteration_num,T_R_lower,T_R_upper,T_R,delta_nu_bar(T_R,¶s),status); + if (status != GSL_CONTINUE) { + break; + } + } + + if (status == GSL_CONTINUE) { + printout("[warning] find_T_R: T_R did not converge within %d iterations\n", maxit); + } + + gsl_root_fsolver_free(T_R_solver); + } else if (delta_nu_bar_max < 0) { + /// Thermal balance equation always negative ===> T_R = T_min + /// Calculate the rates again at this T_e to print them to file + T_R = T_R_max; + printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_max=%g\n", modelgridindex, binindex, + T_R_max); + } else { + T_R = T_R_min; + printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_min=%g\n", modelgridindex, binindex, + T_R_min); + } + + return T_R; +} // namespace radfield + +void set_params_fullspec(const int modelgridindex, const int timestep) { + const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const double nubar = nuJ[nonemptymgi] / J[nonemptymgi]; + if (!std::isfinite(nubar) || nubar == 0.) { + printout("[warning] T_R estimator infinite in cell %d, keep T_R, T_J, W of last timestep. J = %g. nuJ = %g\n", + modelgridindex, J[nonemptymgi], nuJ[nonemptymgi]); + } else { + float T_J = pow(J[nonemptymgi] * PI / STEBO, 1 / 4.); + if (T_J > MAXTEMP) { + printout("[warning] temperature estimator T_J = %g exceeds T_max %g in cell %d. Setting T_J = T_max!\n", T_J, + MAXTEMP, modelgridindex); + T_J = MAXTEMP; + } else if (T_J < MINTEMP) { + printout("[warning] temperature estimator T_J = %g below T_min %g in cell %d. Setting T_J = T_min!\n", T_J, + MINTEMP, modelgridindex); + T_J = MINTEMP; + } + grid::set_TJ(modelgridindex, T_J); + + float T_R = H * nubar / KB / 3.832229494; + if (T_R > MAXTEMP) { + printout("[warning] temperature estimator T_R = %g exceeds T_max %g in cell %d. Setting T_R = T_max!\n", T_R, + MAXTEMP, modelgridindex); + T_R = MAXTEMP; + } else if (T_R < MINTEMP) { + printout("[warning] temperature estimator T_R = %g below T_min %g in cell %d. Setting T_R = T_min!\n", T_R, + MINTEMP, modelgridindex); + T_R = MINTEMP; + } + grid::set_TR(modelgridindex, T_R); + + const float W = J[nonemptymgi] * PI / STEBO / pow(T_R, 4); + grid::set_W(modelgridindex, W); + + printout( + "Full-spectrum fit radfield for cell %d at timestep %d: J %g, nubar %5.1f Angstrom, T_J %g, T_R %g, W %g\n", + modelgridindex, timestep, J[nonemptymgi], 1e8 * CLIGHT / nubar, T_J, T_R, W); + } +} + +auto get_bfcontindex(const int element, const int lowerion, const int lower, const int phixstargetindex) -> int { + // simple linear search seems to be faster than the binary search + // possibly because lower frequency transitions near start of list are more likely to be called? + const auto bfcontindex = static_cast(std::find_if(globals::allcont, globals::allcont + globals::nbfcontinua, + [=](const auto &bf) { + return (bf.element == element) && (bf.ion == lowerion) && + (bf.level == lower) && + (bf.phixstargetindex == phixstargetindex); + }) - + globals::allcont); + + if (bfcontindex < globals::nbfcontinua) { + return bfcontindex; + } + // not found in the continua list + return -1; +} + } // anonymous namespace -void init(int my_rank, int ndo_nonempty) +void init(const int my_rank, const int ndo_nonempty) // this should be called only after the atomic data is in memory { const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); @@ -503,7 +725,7 @@ auto get_Jb_lu_contribcount(const int modelgridindex, const int jblueindex) -> i return prev_Jb_lu_normed[modelgridindex][jblueindex].contribcount; } -void write_to_file(int modelgridindex, int timestep) { +void write_to_file(const int modelgridindex, const int timestep) { assert_always(MULTIBIN_RADFIELD_MODEL_ON); const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); #ifdef _OPENMP @@ -635,35 +857,6 @@ void zero_estimators() } } -static void update_bfestimators(const int nonemptymgi, const double distance_e_cmf, const double nu_cmf, - const double doppler_nucmf_on_nurf, const Phixslist &phixslist) { - assert_testmodeonly(DETAILED_BF_ESTIMATORS_ON); - - const double distance_e_cmf_over_nu = - distance_e_cmf / nu_cmf * doppler_nucmf_on_nurf; // TODO: Luke: why did I put a doppler factor here? - - // I think the nu_cmf slightly differs from when the phixslist was calculated - // so the nu condition on this nu_cmf can truncate the list further compared to what was used in the calculation - // of phixslist.gamma_contr - - const auto bfestimend = std::upper_bound(globals::bfestim_nu_edge.data(), - globals::bfestim_nu_edge.data() + phixslist.bfestimend, nu_cmf) - - globals::bfestim_nu_edge.data(); - - const auto bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, - globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, - [](const double nu_edge, const double nu_cmf) { - return nu_edge * last_phixs_nuovernuedge < nu_cmf; - }) - - globals::bfestim_nu_edge.data(); - - const auto bfestimcount = globals::bfestimcount; - for (auto bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { - atomicadd(bfrate_raw[(nonemptymgi * bfestimcount) + bfestimindex], - phixslist.gamma_contr[bfestimindex] * distance_e_cmf_over_nu); - } -} - __host__ __device__ void update_estimators(const int nonemptymgi, const double distance_e_cmf, const double nu_cmf, const double doppler_nucmf_on_nurf, const Phixslist &phixslist, const bool thickcell) { @@ -706,7 +899,7 @@ __host__ __device__ void update_lineestimator(const int modelgridindex, const in } } -__host__ __device__ auto radfield(double nu, int modelgridindex) -> double +__host__ __device__ auto radfield(const double nu, const int modelgridindex) -> double // returns mean intensity J_nu [ergs/s/sr/cm2/Hz] { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { @@ -730,29 +923,6 @@ __host__ __device__ auto radfield(double nu, int modelgridindex) -> double return J_nu_fullspec; } -static auto planck_integral(double T_R, double nu_lower, double nu_upper, const bool times_nu) -> double { - double integral = 0.; - - double error = 0.; - const double epsrel = 1e-10; - const double epsabs = 0.; - - const gsl_planck_integral_paras intparas = {.T_R = T_R, .times_nu = times_nu}; - - gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); - - const int status = integrator(intparas, nu_lower, nu_upper, epsabs, epsrel, GSL_INTEG_GAUSS61, - &integral, &error); - if (status != 0) { - printout("planck_integral integrator status %d, GSL_FAILURE= %d. Integral value %g, setting to zero.\n", status, - GSL_FAILURE, integral); - integral = 0.; - } - gsl_set_error_handler(previous_handler); - - return integral; -} - auto planck_integral_analytic(const double T_R, const double nu_lower, const double nu_upper, const bool times_nu) -> double { // return the integral of nu^3 / (exp(h nu / k T) - 1) from nu_lower to nu_upper @@ -791,159 +961,7 @@ auto planck_integral_analytic(const double T_R, const double nu_lower, const dou return integral; } -static auto delta_nu_bar(double T_R, void *paras) -> double -// difference between the average nu and the average nu of a Planck function -// at temperature T_R, in the frequency range corresponding to a bin -{ - const auto *params = static_cast(paras); - const int modelgridindex = params->modelgridindex; - const int binindex = params->binindex; - - const double nu_lower = get_bin_nu_lower(binindex); - const double nu_upper = get_bin_nu_upper(binindex); - - const double nu_bar_estimator = get_bin_nu_bar(modelgridindex, binindex); - - const double nu_times_planck_numerical = planck_integral(T_R, nu_lower, nu_upper, true); - const double planck_integral_numerical = planck_integral(T_R, nu_lower, nu_upper, false); - const double nu_bar_planck_T_R = nu_times_planck_numerical / planck_integral_numerical; - - // double nu_times_planck_integral = planck_integral_analytic(T_R, nu_lower, nu_upper, true); - // double planck_integral_result = planck_integral_analytic(T_R, nu_lower, nu_upper, false); - // double nu_bar_planck = nu_times_planck_integral / planck_integral_result; - - // // printout("nu_bar %g nu_bar_planck(T=%g) %g\n",nu_bar,T_R,nu_bar_planck); - - // if (!std::isfinite(nu_bar_planck)) { - // double nu_times_planck_numerical = planck_integral(T_R, nu_lower, nu_upper, true); - // double planck_integral_numerical = planck_integral(T_R, nu_lower, nu_upper, false); - // double nu_bar_planck_numerical = nu_times_planck_numerical / planck_integral_numerical; - - // printout("planck_integral_analytic is %g. Replacing with numerical result of %g.\n", nu_bar_planck, - // nu_bar_planck_numerical); - // nu_bar_planck = nu_bar_planck_numerical; - // } - - const double delta_nu_bar = nu_bar_planck_T_R - nu_bar_estimator; - - if (!std::isfinite(delta_nu_bar)) { - printout( - "delta_nu_bar is %g. nu_bar_planck_T_R %g nu_times_planck_numerical %g planck_integral_numerical %g " - "nu_bar_estimator %g\n", - delta_nu_bar, nu_bar_planck_T_R, nu_times_planck_numerical, planck_integral_numerical, nu_bar_estimator); - } - - return delta_nu_bar; -} - -static auto find_T_R(int modelgridindex, int binindex) -> float { - double T_R = 0.; - - gsl_T_R_solver_paras paras{}; - paras.modelgridindex = modelgridindex; - paras.binindex = binindex; - - /// Check whether the equation has a root in [T_min,T_max] - double delta_nu_bar_min = delta_nu_bar(T_R_min, ¶s); - double delta_nu_bar_max = delta_nu_bar(T_R_max, ¶s); - - // printout("find_T_R: bin %4d delta_nu_bar(T_R_min) %g, delta_nu_bar(T_R_max) %g\n", - // binindex, delta_nu_bar_min,delta_nu_bar_max); - - if (!std::isfinite(delta_nu_bar_min) || !std::isfinite(delta_nu_bar_max)) { - delta_nu_bar_max = delta_nu_bar_min = -1; - } - - if (delta_nu_bar_min * delta_nu_bar_max < 0) { - /// If there is a root in the interval, solve for T_R - - const double epsrel = 1e-4; - const double epsabs = 0.; - const int maxit = 100; - - gsl_function find_T_R_f = {.function = &delta_nu_bar, .params = ¶s}; - - /// one dimensional gsl root solver, bracketing type - gsl_root_fsolver *T_R_solver = gsl_root_fsolver_alloc(gsl_root_fsolver_brent); - gsl_root_fsolver_set(T_R_solver, &find_T_R_f, T_R_min, T_R_max); - int status = 0; - for (int iteration_num = 0; iteration_num <= maxit; iteration_num++) { - gsl_root_fsolver_iterate(T_R_solver); - T_R = gsl_root_fsolver_root(T_R_solver); - - const double T_R_lower = gsl_root_fsolver_x_lower(T_R_solver); - const double T_R_upper = gsl_root_fsolver_x_upper(T_R_solver); - status = gsl_root_test_interval(T_R_lower, T_R_upper, epsabs, epsrel); - - // printout("find_T_R: bin %4d iter %d, T_R is between %7.1f and %7.1f, guess %7.1f, delta_nu_bar %g, status - // %d\n", - // binindex,iteration_num,T_R_lower,T_R_upper,T_R,delta_nu_bar(T_R,¶s),status); - if (status != GSL_CONTINUE) { - break; - } - } - - if (status == GSL_CONTINUE) { - printout("[warning] find_T_R: T_R did not converge within %d iterations\n", maxit); - } - - gsl_root_fsolver_free(T_R_solver); - } else if (delta_nu_bar_max < 0) { - /// Thermal balance equation always negative ===> T_R = T_min - /// Calculate the rates again at this T_e to print them to file - T_R = T_R_max; - printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_max=%g\n", modelgridindex, binindex, - T_R_max); - } else { - T_R = T_R_min; - printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_min=%g\n", modelgridindex, binindex, - T_R_min); - } - - return T_R; -} // namespace radfield - -static void set_params_fullspec(const int modelgridindex, const int timestep) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - const double nubar = nuJ[nonemptymgi] / J[nonemptymgi]; - if (!std::isfinite(nubar) || nubar == 0.) { - printout("[warning] T_R estimator infinite in cell %d, keep T_R, T_J, W of last timestep. J = %g. nuJ = %g\n", - modelgridindex, J[nonemptymgi], nuJ[nonemptymgi]); - } else { - float T_J = pow(J[nonemptymgi] * PI / STEBO, 1 / 4.); - if (T_J > MAXTEMP) { - printout("[warning] temperature estimator T_J = %g exceeds T_max %g in cell %d. Setting T_J = T_max!\n", T_J, - MAXTEMP, modelgridindex); - T_J = MAXTEMP; - } else if (T_J < MINTEMP) { - printout("[warning] temperature estimator T_J = %g below T_min %g in cell %d. Setting T_J = T_min!\n", T_J, - MINTEMP, modelgridindex); - T_J = MINTEMP; - } - grid::set_TJ(modelgridindex, T_J); - - float T_R = H * nubar / KB / 3.832229494; - if (T_R > MAXTEMP) { - printout("[warning] temperature estimator T_R = %g exceeds T_max %g in cell %d. Setting T_R = T_max!\n", T_R, - MAXTEMP, modelgridindex); - T_R = MAXTEMP; - } else if (T_R < MINTEMP) { - printout("[warning] temperature estimator T_R = %g below T_min %g in cell %d. Setting T_R = T_min!\n", T_R, - MINTEMP, modelgridindex); - T_R = MINTEMP; - } - grid::set_TR(modelgridindex, T_R); - - const float W = J[nonemptymgi] * PI / STEBO / pow(T_R, 4); - grid::set_W(modelgridindex, W); - - printout( - "Full-spectrum fit radfield for cell %d at timestep %d: J %g, nubar %5.1f Angstrom, T_J %g, T_R %g, W %g\n", - modelgridindex, timestep, J[nonemptymgi], 1e8 * CLIGHT / nubar, T_J, T_R, W); - } -} - -void fit_parameters(int modelgridindex, int timestep) +void fit_parameters(const int modelgridindex, const int timestep) // finds the best fitting W and temperature parameters in each spectral bin // using J and nuJ { @@ -1039,7 +1057,7 @@ void normalise_J(const int modelgridindex, const double estimator_normfactor_ove } } -void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, double deltat) { +void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, const double deltat) { if (nts != globals::timestep_initial || titer != 0) { for (int mgi = 0; mgi < grid::get_npts_model(); mgi++) { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); @@ -1060,23 +1078,6 @@ void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, } } -static auto get_bfcontindex(const int element, const int lowerion, const int lower, const int phixstargetindex) -> int { - // simple linear search seems to be faster than the binary search - // possibly because lower frequency transitions near start of list are more likely to be called? - const auto bfcontindex = std::find_if(globals::allcont, globals::allcont + globals::nbfcontinua, - [=](const auto &bf) { - return (bf.element == element) && (bf.ion == lowerion) && - (bf.level == lower) && (bf.phixstargetindex == phixstargetindex); - }) - - globals::allcont; - - if (bfcontindex < globals::nbfcontinua) { - return bfcontindex; - } - // not found in the continua list - return -1; -} - auto get_bfrate_estimator(const int element, const int lowerion, const int lower, const int phixstargetindex, const int modelgridindex) -> double { if constexpr (DETAILED_BF_ESTIMATORS_ON) { @@ -1197,7 +1198,7 @@ void reduce_estimators() MPI_Barrier(MPI_COMM_WORLD); } -void do_MPI_Bcast(const int modelgridindex, const int root, int root_node_id) +void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) // broadcast computed radfield results including parameters // from the cells belonging to root process to all processes { diff --git a/ratecoeff.cc b/ratecoeff.cc index 2753274c3..d7f168ac3 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -52,71 +52,7 @@ char adatafile_hash[33]; char compositionfile_hash[33]; std::array phixsfile_hash; -} // anonymous namespace - -void setup_photoion_luts() { - size_t mem_usage_photoionluts = 2 * TABLESIZE * globals::nbfcontinua * sizeof(double); - - if (globals::nbfcontinua > 0) { -#ifdef MPI_ON - MPI_Win win = MPI_WIN_NULL; - MPI_Aint size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &spontrecombcoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &spontrecombcoeffs) == MPI_SUCCESS); -#else - spontrecombcoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif - assert_always(spontrecombcoeffs != nullptr); - - if constexpr (USE_LUT_PHOTOION) { -#ifdef MPI_ON - size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &corrphotoioncoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &corrphotoioncoeffs) == MPI_SUCCESS); -#else - corrphotoioncoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif - assert_always(corrphotoioncoeffs != nullptr); - mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); - } - - if constexpr (USE_LUT_BFHEATING) { -#ifdef MPI_ON - size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &globals::bfheating_coeff, &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &globals::bfheating_coeff) == MPI_SUCCESS); -#else - globals::bfheating_coeff = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif - assert_always(globals::bfheating_coeff != nullptr); - mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); - } - -#ifdef MPI_ON - size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &bfcooling_coeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &bfcooling_coeffs) == MPI_SUCCESS); -#else - bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif - assert_always(bfcooling_coeffs != nullptr); - } - - printout( - "[info] mem_usage: lookup tables derived from photoionisation (spontrecombcoeff, bfcooling and " - "corrphotoioncoeff/bfheating if enabled) occupy %.3f MB\n", - mem_usage_photoionluts / 1024. / 1024.); -} - -static auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool +auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool /// Try to read in the precalculated rate coefficients from file /// return true if successful or false otherwise { @@ -283,7 +219,7 @@ static auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool return true; } -static void write_ratecoeff_dat() { +void write_ratecoeff_dat() { FILE *ratecoeff_file = fopen_required("ratecoeff.dat", "w"); fprintf(ratecoeff_file, "%32s\n", adatafile_hash); fprintf(ratecoeff_file, "%32s\n", compositionfile_hash); @@ -326,7 +262,7 @@ static void write_ratecoeff_dat() { fclose(ratecoeff_file); } -static auto alpha_sp_integrand_gsl(const double nu, void *const voidparas) -> double +auto alpha_sp_integrand_gsl(const double nu, void *const voidparas) -> double /// Integrand to calculate the rate coefficient for spontaneous recombination /// using gsl integrators. { @@ -341,7 +277,7 @@ static auto alpha_sp_integrand_gsl(const double nu, void *const voidparas) -> do return x; } -static auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> double +auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> double /// Integrand to calculate the rate coefficient for spontaneous recombination /// using gsl integrators. { @@ -359,7 +295,7 @@ static auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> return x; } -static auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> double +auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> double /// Integrand to calculate the rate coefficient for photoionization /// using gsl integrators. Corrected for stimulated recombination. { @@ -376,7 +312,7 @@ static auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> d return sigma_bf * ONEOVERH / nu * radfield::dbb(nu, T, 1) * (1 - exp(-HOVERKB * nu / T)); } -static auto approx_bfheating_integrand_gsl(const double nu, void *const voidparas) -> double +auto approx_bfheating_integrand_gsl(const double nu, void *const voidparas) -> double /// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way /// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation /// formula. The radiation fields dependence on W is taken into account by multiplying @@ -395,7 +331,7 @@ static auto approx_bfheating_integrand_gsl(const double nu, void *const voidpara return x; } -static auto bfcooling_integrand_gsl(const double nu, void *const voidparas) -> double +auto bfcooling_integrand_gsl(const double nu, void *const voidparas) -> double /// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way /// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation /// formula. The radiation fields dependence on W is taken into account by multiplying @@ -412,7 +348,7 @@ static auto bfcooling_integrand_gsl(const double nu, void *const voidparas) -> d return sigma_bf * (nu - nu_edge) * TWOHOVERCLIGHTSQUARED * nu * nu * exp(-HOVERKB * nu / T); } -static void precalculate_rate_coefficient_integrals() { +void precalculate_rate_coefficient_integrals() { // target fractional accuracy of the integrator //=1e-5 took 8 hours with Fe I to V! const double epsrelwarning = 1e-2; // fractional error to emit a warning @@ -549,189 +485,7 @@ static void precalculate_rate_coefficient_integrals() { } } -__host__ __device__ auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel, - float T_e) -> double { - const int phixstargetindex = get_phixtargetindex(element, lowerion, lower, upperionlevel); - const double E_threshold = get_phixs_threshold(element, lowerion, lower, phixstargetindex); - const double nu_threshold = ONEOVERH * E_threshold; - - const double nu_max_phixs = nu_threshold * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table - - const int npieces = globals::NPHIXSPOINTS; - - const GSLIntegrationParas intparas = { - .nu_edge = nu_threshold, - .T = T_e, - .photoion_xs = globals::elements[element].ions[lowerion].levels[lower].photoion_xs}; - - const double zrand = 1. - rng_uniform(); // Make sure that 0 < zrand <= 1 - - const double deltanu = (nu_max_phixs - nu_threshold) / npieces; - double error{NAN}; - -#if !USE_SIMPSON_INTEGRATOR - gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); -#endif - - double total_alpha_sp = 0.; - integrator(intparas, nu_threshold, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, - GSL_INTEG_GAUSS31, &total_alpha_sp, &error); - - double alpha_sp_old = total_alpha_sp; - double alpha_sp = total_alpha_sp; - - int i = 1; - for (i = 1; i < npieces; i++) { - alpha_sp_old = alpha_sp; - const double xlow = nu_threshold + (i * deltanu); - - // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field - integrator(intparas, xlow, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, - GSL_INTEG_GAUSS31, &alpha_sp, &error); - - if (zrand >= alpha_sp / total_alpha_sp) { - break; - } - } - -#if !USE_SIMPSON_INTEGRATOR - gsl_set_error_handler(previous_handler); -#endif - - const double nuoffset = - (alpha_sp != alpha_sp_old) ? (total_alpha_sp * zrand - alpha_sp_old) / (alpha_sp - alpha_sp_old) * deltanu : 0.; - const double nu_lower = nu_threshold + ((i - 1) * deltanu) + nuoffset; - - assert_testmodeonly(std::isfinite(nu_lower)); - - return nu_lower; -} - -__host__ __device__ auto get_spontrecombcoeff(int element, int ion, int level, int phixstargetindex, - float T_e) -> double -/// Returns the rate coefficient for spontaneous recombination. -{ - double Alpha_sp{NAN}; - const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); - assert_always(lowerindex >= 0); - if (lowerindex < TABLESIZE - 1) { - const int upperindex = lowerindex + 1; - const double T_lower = MINTEMP * exp(lowerindex * T_step_log); - const double T_upper = MINTEMP * exp(upperindex * T_step_log); - - const double f_upper = spontrecombcoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; - const double f_lower = spontrecombcoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - // printout("interpolate_spontrecombcoeff element %d, ion %d, level %d, upper %g, lower %g\n", - // element,ion,level,f_upper,f_lower); - Alpha_sp = (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower)); - } else { - Alpha_sp = spontrecombcoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; - } - return Alpha_sp; -} - -auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const int element, const int upperion, - const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, - const bool lower_superlevel_only, const bool per_groundmultipletpop, - const bool stimonly) -> double -// multiply by upper ion population (or ground population if per_groundmultipletpop is true) and nne to get a rate -{ - const int lowerion = upperion - 1; - if (lowerion < 0) { - return 0.; - } - - double alpha = 0.; - if (lowerion < get_nions(element) - 1) { - // this gets divided and cancelled out in the radiative case anyway - const double nne = (modelgridindex >= 0) ? grid::get_nne(modelgridindex) : 1.; - - double nnupperion = 0; - // nnupperion = get_groundmultiplet_pop(modelgridindex, T_e, element, upperion, assume_lte); - int upper_nlevels = 0; - if (per_groundmultipletpop) { - // assume that photoionisation of the ion below is only to the ground multiplet levels of the current ion - // const int nphixstargets = get_nphixstargets(element, lowerion, 0); - // upper_nlevels = get_phixsupperlevel(element, lowerion, 0, nphixstargets - 1) + 1; - - upper_nlevels = get_nlevels_groundterm(element, lowerion + 1); - } else { - upper_nlevels = get_nlevels(element, lowerion + 1); - } - - for (int upper = 0; upper < upper_nlevels; upper++) { - double nnupperlevel{NAN}; - if (assume_lte) { - const double T_exc = T_e; - const double E_level = epsilon(element, lowerion + 1, upper); - const double E_ground = epsilon(element, lowerion + 1, 0); - const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; - - nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * - exp(-(E_level - E_ground) / KB / T_exc)); - } else { - nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); - } - nnupperion += nnupperlevel; - } - - if (nnupperion <= 0.) { - return 0.; - } - - double nnupperlevel_so_far = 0.; - const int maxrecombininglevel = get_maxrecombininglevel(element, lowerion + 1); - for (int upper = 0; upper <= maxrecombininglevel; upper++) { - double nnupperlevel{NAN}; - if (assume_lte) { - const double T_exc = T_e; - const double E_level = epsilon(element, lowerion + 1, upper); - const double E_ground = epsilon(element, lowerion + 1, 0); - const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; - - nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * - exp(-(E_level - E_ground) / KB / T_exc)); - } else { - nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); - } - nnupperlevel_so_far += nnupperlevel; - for (int lower = 0; lower < get_nlevels(element, lowerion); lower++) { - if (lower_superlevel_only && (!level_isinsuperlevel(element, lowerion, lower))) { - continue; - } - - double recomb_coeff = 0.; - if (collisional_not_radiative) { - const double epsilon_trans = epsilon(element, lowerion + 1, upper) - epsilon(element, lowerion, lower); - recomb_coeff += col_recombination_ratecoeff(modelgridindex, element, upperion, upper, lower, epsilon_trans); - } else if (!stimonly) { - recomb_coeff += rad_recombination_ratecoeff(T_e, nne, element, lowerion + 1, upper, lower, modelgridindex); - } else { - recomb_coeff += stim_recombination_ratecoeff(nne, element, upperion, upper, lower, modelgridindex); - } - - const double alpha_level = recomb_coeff / nne; - const double alpha_ion_contrib = alpha_level * nnupperlevel / nnupperion; - alpha += alpha_ion_contrib; - if (printdebug && alpha_ion_contrib > 0. && lower < 50) { - printout( - "recomb: Z=%d ionstage %d->%d upper+1 %5d lower+1 %5d alpha_level %7.2e alpha_ion_contrib %7.2e sum " - "%7.2e nnlevel %7.2e nnionfrac %7.2e\n", - get_atomicnumber(element), get_ionstage(element, lowerion + 1), get_ionstage(element, lowerion), - upper + 1, lower + 1, alpha_level, alpha_ion_contrib, alpha, nnupperlevel, - nnupperlevel_so_far / nnupperion); - } - } - } - } - if (printdebug) { - printout("recomb: Z=%2d ionstage %d->%d upper+1 [all] lower+1 [all] Alpha %g\n\n", get_atomicnumber(element), - get_ionstage(element, lowerion + 1), get_ionstage(element, lowerion), alpha); - } - return alpha; -} - -static void scale_level_phixs(const int element, const int ion, const int level, const double factor) +void scale_level_phixs(const int element, const int ion, const int level, const double factor) // multiply the cross sections associated with a level by some factor and // also update the quantities integrated from (and proportional to) the cross sections { @@ -760,7 +514,7 @@ static void scale_level_phixs(const int element, const int ion, const int level, } } -static void read_recombrate_file() +void read_recombrate_file() // calibrate the recombination rates to tabulated values by scaling the photoionisation cross sections { use_cellcache = false; @@ -900,7 +654,7 @@ static void read_recombrate_file() fclose(recombrate_file); } -static void precalculate_ion_alpha_sp() { +void precalculate_ion_alpha_sp() { for (int iter = 0; iter < TABLESIZE; iter++) { const float T_e = MINTEMP * exp(iter * T_step_log); for (int element = 0; element < get_nelements(); element++) { @@ -921,96 +675,7 @@ static void precalculate_ion_alpha_sp() { } } -void ratecoefficients_init() -/// Precalculates the rate coefficients for stimulated and spontaneous -/// recombination and photoionisation on a given temperature grid using -/// libgsl integrators. -/// NB: with the nebular approximation they only depend on T_e, T_R and W. -/// W is easily factored out. For stimulated recombination we must assume -/// T_e = T_R for this precalculation. -{ - printout("time before tabulation of rate coefficients %ld\n", std::time(nullptr)); - /// Determine the temperture grids gridsize - T_step_log = (log(MAXTEMP) - log(MINTEMP)) / (TABLESIZE - 1.); - - md5_file("adata.txt", adatafile_hash); - md5_file("compositiondata.txt", compositionfile_hash); - for (int phixsver = 1; phixsver <= 2; phixsver++) { - if (phixs_file_version_exists[phixsver]) { - md5_file(phixsdata_filenames[phixsver], phixsfile_hash[phixsver]); - } - } - - /// Check if we need to calculate the ratecoefficients or if we were able to read them from file - bool ratecoeff_match = false; - if (globals::rank_in_node == 0) { - FILE *ratecoeff_file = fopen("ratecoeff.dat", "r"); - if (ratecoeff_file != nullptr) { - ratecoeff_match = read_ratecoeff_dat(ratecoeff_file); - if (!ratecoeff_match) { - printout("[info] ratecoefficients_init: ratecoeff.dat does not match current simulation. Recalculating...\n"); - } - fclose(ratecoeff_file); - } else { - printout("[info] ratecoefficients_init: ratecoeff.dat file not found. Creating a new one...\n"); - } - } -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); - // all node-rank 0 should agree, but to be sure, - // world rank 0 will decide if we need to regenerate rate coefficient tables - MPI_Bcast(&ratecoeff_match, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); -#endif - - if (!ratecoeff_match) { - precalculate_rate_coefficient_integrals(); - - // And the master process writes them to file in a serial operation -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); -#endif - if (globals::rank_global == 0) { - write_ratecoeff_dat(); - } - } - - read_recombrate_file(); - - precalculate_ion_alpha_sp(); - - printout("time after tabulation of rate coefficients %ld\n", std::time(nullptr)); -} - -auto interpolate_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, double T) -> double { - assert_always(USE_LUT_PHOTOION); - const int lowerindex = floor(log(T / MINTEMP) / T_step_log); - if (lowerindex < TABLESIZE - 1) { - const int upperindex = lowerindex + 1; - const double T_lower = MINTEMP * exp(lowerindex * T_step_log); - const double T_upper = MINTEMP * exp(upperindex * T_step_log); - - const double f_upper = corrphotoioncoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; - const double f_lower = corrphotoioncoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - - return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower))); - } - return corrphotoioncoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; -} - -auto get_corrphotoioncoeff_ana(int element, int ion, int level, int phixstargetindex, int modelgridindex) -> double -/// Returns the for stimulated emission corrected photoionisation rate coefficient. -{ - assert_always(USE_LUT_PHOTOION); - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! - const double W = grid::get_W(modelgridindex); - const double T_R = grid::get_TR(modelgridindex); - - return W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); -} - -static auto integrand_stimrecombination_custom_radfield(const double nu, void *voidparas) -> double { +auto integrand_stimrecombination_custom_radfield(const double nu, void *voidparas) -> double { { const gsl_integral_paras_gammacorr *const params = static_cast(voidparas); const int modelgridindex = params->modelgridindex; @@ -1025,8 +690,8 @@ static auto integrand_stimrecombination_custom_radfield(const double nu, void *v } } -static auto calculate_stimrecombcoeff_integral(int element, int lowerion, int level, int phixstargetindex, - int modelgridindex) -> double { +auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, const int level, + const int phixstargetindex, const int modelgridindex) -> double { const double epsrel = 1e-3; const double epsabs = 0.; @@ -1070,57 +735,7 @@ static auto calculate_stimrecombcoeff_integral(int element, int lowerion, int le return stimrecombcoeff; } -auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetindex, int modelgridindex) -> double -/// Returns the stimulated recombination rate coefficient -// multiple by upper level population and nne to get rate -{ - double stimrecombcoeff = -1.; -#if (SEPARATE_STIMRECOMB) - if (use_cellcache) { - stimrecombcoeff = globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[lowerion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .stimrecombcoeff; - } -#endif - - if (!use_cellcache || stimrecombcoeff < 0) { - stimrecombcoeff = calculate_stimrecombcoeff_integral(element, lowerion, level, phixstargetindex, modelgridindex); - -#if (SEPARATE_STIMRECOMB) - if (use_cellcache) { - globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[lowerion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .stimrecombcoeff = stimrecombcoeff; - } -#endif - } - - return stimrecombcoeff; -} - -__host__ __device__ auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, - float T_e) -> double { - const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); - if (lowerindex < TABLESIZE - 1) { - const int upperindex = lowerindex + 1; - const double T_lower = MINTEMP * exp(lowerindex * T_step_log); - const double T_upper = MINTEMP * exp(upperindex * T_step_log); - - const double f_upper = bfcooling_coeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; - const double f_lower = bfcooling_coeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - - return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower))); - } - return bfcooling_coeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; -} - -static auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *const voidparas) -> double +auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *const voidparas) -> double /// Integrand to calculate the rate coefficient for photoionization /// using gsl integrators. Corrected for stimulated recombination. { @@ -1145,8 +760,8 @@ static auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *c return ONEOVERH * sigma_bf / nu * Jnu * corrfactor; } -static auto calculate_corrphotoioncoeff_integral(int element, int ion, int level, int phixstargetindex, - int modelgridindex) -> double { +auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int level, const int phixstargetindex, + int modelgridindex) -> double { constexpr double epsrel = 1e-3; constexpr double epsrelwarning = 1e-1; constexpr double epsabs = 0.; @@ -1205,59 +820,8 @@ static auto calculate_corrphotoioncoeff_integral(int element, int ion, int level return gammacorr; } -__host__ __device__ auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, - int modelgridindex) -> double -/// Returns the photoionisation rate coefficient (corrected for stimulated emission) -{ - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! - double gammacorr = (use_cellcache) ? globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[ion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .corrphotoioncoeff - : -1; - - if (!use_cellcache || gammacorr < 0) { - if (DETAILED_BF_ESTIMATORS_ON && globals::timestep >= DETAILED_BF_ESTIMATORS_USEFROMTIMESTEP) { - gammacorr = radfield::get_bfrate_estimator(element, ion, level, phixstargetindex, modelgridindex); - // gammacorr will be -1 if no estimators available - } - - if (!DETAILED_BF_ESTIMATORS_ON || gammacorr < 0) { - if constexpr (!USE_LUT_PHOTOION) { - gammacorr = calculate_corrphotoioncoeff_integral(element, ion, level, phixstargetindex, modelgridindex); - } else { - const double W = grid::get_W(modelgridindex); - const double T_R = grid::get_TR(modelgridindex); - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - - gammacorr = W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); - const int index_in_groundlevelcontestimator = - globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; - if (index_in_groundlevelcontestimator >= 0) { - gammacorr *= globals::corrphotoionrenorm[(nonemptymgi * globals::nbfcontinua_ground) + - index_in_groundlevelcontestimator]; - } - } - } - if (use_cellcache) { - globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[ion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .corrphotoioncoeff = gammacorr; - } - } - - return gammacorr; -} - -static auto get_nlevels_important(const int modelgridindex, const int element, const int ion, const bool assume_lte, - const float T_e) -> std::tuple +auto get_nlevels_important(const int modelgridindex, const int element, const int ion, const bool assume_lte, + const float T_e) -> std::tuple // get the number of levels that make up a fraction of the ion population // of at least IONGAMMA_POPFRAC_LEVELS_INCLUDED { @@ -1297,6 +861,445 @@ static auto get_nlevels_important(const int modelgridindex, const int element, c return {nlevels_important, nnlevelsum}; } +} // anonymous namespace + +void setup_photoion_luts() { + size_t mem_usage_photoionluts = 2 * TABLESIZE * globals::nbfcontinua * sizeof(double); + + if (globals::nbfcontinua > 0) { +#ifdef MPI_ON + MPI_Win win = MPI_WIN_NULL; + MPI_Aint size = + (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + int disp_unit = sizeof(double); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &spontrecombcoeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &spontrecombcoeffs) == MPI_SUCCESS); +#else + spontrecombcoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); +#endif + assert_always(spontrecombcoeffs != nullptr); + + if constexpr (USE_LUT_PHOTOION) { +#ifdef MPI_ON + size = + (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &corrphotoioncoeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &corrphotoioncoeffs) == MPI_SUCCESS); +#else + corrphotoioncoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); +#endif + assert_always(corrphotoioncoeffs != nullptr); + mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); + } + + if constexpr (USE_LUT_BFHEATING) { +#ifdef MPI_ON + size = + (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &globals::bfheating_coeff, &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &globals::bfheating_coeff) == MPI_SUCCESS); +#else + globals::bfheating_coeff = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); +#endif + assert_always(globals::bfheating_coeff != nullptr); + mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); + } + +#ifdef MPI_ON + size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &bfcooling_coeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &bfcooling_coeffs) == MPI_SUCCESS); +#else + bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); +#endif + assert_always(bfcooling_coeffs != nullptr); + } + + printout( + "[info] mem_usage: lookup tables derived from photoionisation (spontrecombcoeff, bfcooling and " + "corrphotoioncoeff/bfheating if enabled) occupy %.3f MB\n", + mem_usage_photoionluts / 1024. / 1024.); +} + +__host__ __device__ auto select_continuum_nu(int element, const int lowerion, const int lower, const int upperionlevel, + float T_e) -> double { + const int phixstargetindex = get_phixtargetindex(element, lowerion, lower, upperionlevel); + const double E_threshold = get_phixs_threshold(element, lowerion, lower, phixstargetindex); + const double nu_threshold = ONEOVERH * E_threshold; + + const double nu_max_phixs = nu_threshold * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table + + const int npieces = globals::NPHIXSPOINTS; + + const GSLIntegrationParas intparas = { + .nu_edge = nu_threshold, + .T = T_e, + .photoion_xs = globals::elements[element].ions[lowerion].levels[lower].photoion_xs}; + + const double zrand = 1. - rng_uniform(); // Make sure that 0 < zrand <= 1 + + const double deltanu = (nu_max_phixs - nu_threshold) / npieces; + double error{NAN}; + +#if !USE_SIMPSON_INTEGRATOR + gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); +#endif + + double total_alpha_sp = 0.; + integrator(intparas, nu_threshold, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, + GSL_INTEG_GAUSS31, &total_alpha_sp, &error); + + double alpha_sp_old = total_alpha_sp; + double alpha_sp = total_alpha_sp; + + int i = 1; + for (i = 1; i < npieces; i++) { + alpha_sp_old = alpha_sp; + const double xlow = nu_threshold + (i * deltanu); + + // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field + integrator(intparas, xlow, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, + GSL_INTEG_GAUSS31, &alpha_sp, &error); + + if (zrand >= alpha_sp / total_alpha_sp) { + break; + } + } + +#if !USE_SIMPSON_INTEGRATOR + gsl_set_error_handler(previous_handler); +#endif + + const double nuoffset = + (alpha_sp != alpha_sp_old) ? (total_alpha_sp * zrand - alpha_sp_old) / (alpha_sp - alpha_sp_old) * deltanu : 0.; + const double nu_lower = nu_threshold + ((i - 1) * deltanu) + nuoffset; + + assert_testmodeonly(std::isfinite(nu_lower)); + + return nu_lower; +} + +__host__ __device__ auto get_spontrecombcoeff(int element, const int ion, const int level, const int phixstargetindex, + float T_e) -> double +/// Returns the rate coefficient for spontaneous recombination. +{ + double Alpha_sp{NAN}; + const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); + assert_always(lowerindex >= 0); + if (lowerindex < TABLESIZE - 1) { + const int upperindex = lowerindex + 1; + const double T_lower = MINTEMP * exp(lowerindex * T_step_log); + const double T_upper = MINTEMP * exp(upperindex * T_step_log); + + const double f_upper = spontrecombcoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; + const double f_lower = spontrecombcoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; + // printout("interpolate_spontrecombcoeff element %d, ion %d, level %d, upper %g, lower %g\n", + // element,ion,level,f_upper,f_lower); + Alpha_sp = (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower)); + } else { + Alpha_sp = spontrecombcoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; + } + return Alpha_sp; +} + +auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const int element, const int upperion, + const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, + const bool lower_superlevel_only, const bool per_groundmultipletpop, + const bool stimonly) -> double +// multiply by upper ion population (or ground population if per_groundmultipletpop is true) and nne to get a rate +{ + const int lowerion = upperion - 1; + if (lowerion < 0) { + return 0.; + } + + double alpha = 0.; + if (lowerion < get_nions(element) - 1) { + // this gets divided and cancelled out in the radiative case anyway + const double nne = (modelgridindex >= 0) ? grid::get_nne(modelgridindex) : 1.; + + double nnupperion = 0; + // nnupperion = get_groundmultiplet_pop(modelgridindex, T_e, element, upperion, assume_lte); + int upper_nlevels = 0; + if (per_groundmultipletpop) { + // assume that photoionisation of the ion below is only to the ground multiplet levels of the current ion + // const int nphixstargets = get_nphixstargets(element, lowerion, 0); + // upper_nlevels = get_phixsupperlevel(element, lowerion, 0, nphixstargets - 1) + 1; + + upper_nlevels = get_nlevels_groundterm(element, lowerion + 1); + } else { + upper_nlevels = get_nlevels(element, lowerion + 1); + } + + for (int upper = 0; upper < upper_nlevels; upper++) { + double nnupperlevel{NAN}; + if (assume_lte) { + const double T_exc = T_e; + const double E_level = epsilon(element, lowerion + 1, upper); + const double E_ground = epsilon(element, lowerion + 1, 0); + const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; + + nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * + exp(-(E_level - E_ground) / KB / T_exc)); + } else { + nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); + } + nnupperion += nnupperlevel; + } + + if (nnupperion <= 0.) { + return 0.; + } + + double nnupperlevel_so_far = 0.; + const int maxrecombininglevel = get_maxrecombininglevel(element, lowerion + 1); + for (int upper = 0; upper <= maxrecombininglevel; upper++) { + double nnupperlevel{NAN}; + if (assume_lte) { + const double T_exc = T_e; + const double E_level = epsilon(element, lowerion + 1, upper); + const double E_ground = epsilon(element, lowerion + 1, 0); + const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; + + nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * + exp(-(E_level - E_ground) / KB / T_exc)); + } else { + nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); + } + nnupperlevel_so_far += nnupperlevel; + for (int lower = 0; lower < get_nlevels(element, lowerion); lower++) { + if (lower_superlevel_only && (!level_isinsuperlevel(element, lowerion, lower))) { + continue; + } + + double recomb_coeff = 0.; + if (collisional_not_radiative) { + const double epsilon_trans = epsilon(element, lowerion + 1, upper) - epsilon(element, lowerion, lower); + recomb_coeff += col_recombination_ratecoeff(modelgridindex, element, upperion, upper, lower, epsilon_trans); + } else if (!stimonly) { + recomb_coeff += rad_recombination_ratecoeff(T_e, nne, element, lowerion + 1, upper, lower, modelgridindex); + } else { + recomb_coeff += stim_recombination_ratecoeff(nne, element, upperion, upper, lower, modelgridindex); + } + + const double alpha_level = recomb_coeff / nne; + const double alpha_ion_contrib = alpha_level * nnupperlevel / nnupperion; + alpha += alpha_ion_contrib; + if (printdebug && alpha_ion_contrib > 0. && lower < 50) { + printout( + "recomb: Z=%d ionstage %d->%d upper+1 %5d lower+1 %5d alpha_level %7.2e alpha_ion_contrib %7.2e sum " + "%7.2e nnlevel %7.2e nnionfrac %7.2e\n", + get_atomicnumber(element), get_ionstage(element, lowerion + 1), get_ionstage(element, lowerion), + upper + 1, lower + 1, alpha_level, alpha_ion_contrib, alpha, nnupperlevel, + nnupperlevel_so_far / nnupperion); + } + } + } + } + if (printdebug) { + printout("recomb: Z=%2d ionstage %d->%d upper+1 [all] lower+1 [all] Alpha %g\n\n", get_atomicnumber(element), + get_ionstage(element, lowerion + 1), get_ionstage(element, lowerion), alpha); + } + return alpha; +} + +void ratecoefficients_init() +/// Precalculates the rate coefficients for stimulated and spontaneous +/// recombination and photoionisation on a given temperature grid using +/// libgsl integrators. +/// NB: with the nebular approximation they only depend on T_e, T_R and W. +/// W is easily factored out. For stimulated recombination we must assume +/// T_e = T_R for this precalculation. +{ + printout("time before tabulation of rate coefficients %ld\n", std::time(nullptr)); + /// Determine the temperture grids gridsize + T_step_log = (log(MAXTEMP) - log(MINTEMP)) / (TABLESIZE - 1.); + + md5_file("adata.txt", adatafile_hash); + md5_file("compositiondata.txt", compositionfile_hash); + for (int phixsver = 1; phixsver <= 2; phixsver++) { + if (phixs_file_version_exists[phixsver]) { + md5_file(phixsdata_filenames[phixsver], phixsfile_hash[phixsver]); + } + } + + /// Check if we need to calculate the ratecoefficients or if we were able to read them from file + bool ratecoeff_match = false; + if (globals::rank_in_node == 0) { + FILE *ratecoeff_file = fopen("ratecoeff.dat", "r"); + if (ratecoeff_file != nullptr) { + ratecoeff_match = read_ratecoeff_dat(ratecoeff_file); + if (!ratecoeff_match) { + printout("[info] ratecoefficients_init: ratecoeff.dat does not match current simulation. Recalculating...\n"); + } + fclose(ratecoeff_file); + } else { + printout("[info] ratecoefficients_init: ratecoeff.dat file not found. Creating a new one...\n"); + } + } +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); + // all node-rank 0 should agree, but to be sure, + // world rank 0 will decide if we need to regenerate rate coefficient tables + MPI_Bcast(&ratecoeff_match, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); +#endif + + if (!ratecoeff_match) { + precalculate_rate_coefficient_integrals(); + + // And the master process writes them to file in a serial operation +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif + if (globals::rank_global == 0) { + write_ratecoeff_dat(); + } + } + + read_recombrate_file(); + + precalculate_ion_alpha_sp(); + + printout("time after tabulation of rate coefficients %ld\n", std::time(nullptr)); +} + +auto interpolate_corrphotoioncoeff(const int element, const int ion, const int level, const int phixstargetindex, + const double T) -> double { + assert_always(USE_LUT_PHOTOION); + const int lowerindex = floor(log(T / MINTEMP) / T_step_log); + if (lowerindex < TABLESIZE - 1) { + const int upperindex = lowerindex + 1; + const double T_lower = MINTEMP * exp(lowerindex * T_step_log); + const double T_upper = MINTEMP * exp(upperindex * T_step_log); + + const double f_upper = corrphotoioncoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; + const double f_lower = corrphotoioncoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; + + return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower))); + } + return corrphotoioncoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; +} + +auto get_corrphotoioncoeff_ana(int element, const int ion, const int level, const int phixstargetindex, + const int modelgridindex) -> double +/// Returns the for stimulated emission corrected photoionisation rate coefficient. +{ + assert_always(USE_LUT_PHOTOION); + /// The correction factor for stimulated emission in gammacorr is set to its + /// LTE value. Because the T_e dependence of gammacorr is weak, this correction + /// correction may be evaluated at T_R! + const double W = grid::get_W(modelgridindex); + const double T_R = grid::get_TR(modelgridindex); + + return W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); +} + +auto get_stimrecombcoeff(int element, const int lowerion, const int level, const int phixstargetindex, + const int modelgridindex) -> double +/// Returns the stimulated recombination rate coefficient +// multiple by upper level population and nne to get rate +{ + double stimrecombcoeff = -1.; +#if (SEPARATE_STIMRECOMB) + if (use_cellcache) { + stimrecombcoeff = globals::cellcache[cellcacheslotid] + .chelements[element] + .chions[lowerion] + .chlevels[level] + .chphixstargets[phixstargetindex] + .stimrecombcoeff; + } +#endif + + if (!use_cellcache || stimrecombcoeff < 0) { + stimrecombcoeff = calculate_stimrecombcoeff_integral(element, lowerion, level, phixstargetindex, modelgridindex); + +#if (SEPARATE_STIMRECOMB) + if (use_cellcache) { + globals::cellcache[cellcacheslotid] + .chelements[element] + .chions[lowerion] + .chlevels[level] + .chphixstargets[phixstargetindex] + .stimrecombcoeff = stimrecombcoeff; + } +#endif + } + + return stimrecombcoeff; +} + +__host__ __device__ auto get_bfcoolingcoeff(const int element, const int ion, const int level, + const int phixstargetindex, const float T_e) -> double { + const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); + if (lowerindex < TABLESIZE - 1) { + const int upperindex = lowerindex + 1; + const double T_lower = MINTEMP * exp(lowerindex * T_step_log); + const double T_upper = MINTEMP * exp(upperindex * T_step_log); + + const double f_upper = bfcooling_coeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; + const double f_lower = bfcooling_coeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; + + return (f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower))); + } + return bfcooling_coeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; +} + +__host__ __device__ auto get_corrphotoioncoeff(const int element, const int ion, const int level, + const int phixstargetindex, const int modelgridindex) -> double +/// Returns the photoionisation rate coefficient (corrected for stimulated emission) +{ + /// The correction factor for stimulated emission in gammacorr is set to its + /// LTE value. Because the T_e dependence of gammacorr is weak, this correction + /// correction may be evaluated at T_R! + double gammacorr = (use_cellcache) ? globals::cellcache[cellcacheslotid] + .chelements[element] + .chions[ion] + .chlevels[level] + .chphixstargets[phixstargetindex] + .corrphotoioncoeff + : -1; + + if (!use_cellcache || gammacorr < 0) { + if (DETAILED_BF_ESTIMATORS_ON && globals::timestep >= DETAILED_BF_ESTIMATORS_USEFROMTIMESTEP) { + gammacorr = radfield::get_bfrate_estimator(element, ion, level, phixstargetindex, modelgridindex); + // gammacorr will be -1 if no estimators available + } + + if (!DETAILED_BF_ESTIMATORS_ON || gammacorr < 0) { + if constexpr (!USE_LUT_PHOTOION) { + gammacorr = calculate_corrphotoioncoeff_integral(element, ion, level, phixstargetindex, modelgridindex); + } else { + const double W = grid::get_W(modelgridindex); + const double T_R = grid::get_TR(modelgridindex); + const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + + gammacorr = W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); + const int index_in_groundlevelcontestimator = + globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; + if (index_in_groundlevelcontestimator >= 0) { + gammacorr *= globals::corrphotoionrenorm[(nonemptymgi * globals::nbfcontinua_ground) + + index_in_groundlevelcontestimator]; + } + } + } + if (use_cellcache) { + globals::cellcache[cellcacheslotid] + .chelements[element] + .chions[ion] + .chlevels[level] + .chphixstargets[phixstargetindex] + .corrphotoioncoeff = gammacorr; + } + } + + return gammacorr; +} + auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) -> bool { const int nions = get_nions(element); if (ion >= nions - 1) { diff --git a/rpkt.cc b/rpkt.cc index 4da70ef21..ac5a664c2 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -33,7 +33,7 @@ #ifdef GPU_ON #define THREADLOCALONHOST #else -#define THREADLOCALONHOST thread_local +#define THREADLOCALONHOST thread_local static #endif namespace { @@ -54,93 +54,8 @@ MPI_Win win_expansionopacities = MPI_WIN_NULL; MPI_Win win_expansionopacity_planck_cumulative = MPI_WIN_NULL; #endif -} // anonymous namespace - -void allocate_expansionopacities() { - const auto npts_nonempty = grid::get_nonempty_npts_model(); - float *expansionopacities_data{}; - double *expansionopacity_planck_cumulative_data{}; -#ifdef MPI_ON - int my_rank_nonemptycells = npts_nonempty / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_nonemptycells += npts_nonempty - (my_rank_nonemptycells * globals::node_nprocs); - } - MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(float)); - int disp_unit = sizeof(float); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &expansionopacities_data, &win_expansionopacities) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_expansionopacities, 0, &size, &disp_unit, &expansionopacities_data) == - MPI_SUCCESS); - - if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { - MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &expansionopacity_planck_cumulative_data, - &win_expansionopacity_planck_cumulative) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_expansionopacity_planck_cumulative, 0, &size, &disp_unit, - &expansionopacity_planck_cumulative_data) == MPI_SUCCESS); - } - -#else - expansionopacities_data = static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(float))); - if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { - expansionopacity_planck_cumulative_data = - static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(double))); - } -#endif - expansionopacities = std::span{expansionopacities_data, static_cast(npts_nonempty * expopac_nbins)}; - expansionopacity_planck_cumulative = std::span{ - expansionopacity_planck_cumulative_data, - static_cast(expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins)}; -} - -auto closest_transition(const double nu_cmf, const int next_trans) -> int -/// for the propagation through non empty cells -// find the next transition lineindex redder than nu_cmf -// return -1 if no transition can be reached -{ - if (next_trans > (globals::nlines - 1)) { - // packet is tagged as having no more line interactions - return -1; - } - /// if nu_cmf is smaller than the lowest frequency in the linelist, - /// no line interaction is possible: return negative value as a flag - if (nu_cmf < globals::linelist[globals::nlines - 1].nu) { - return -1; - } - - if (next_trans > 0) [[likely]] { - /// if next_trans > 0 we know the next line we should interact with, independent of the packets - /// current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors - return next_trans; - } - if (nu_cmf >= globals::linelist[0].nu) { - /// if nu_cmf is larger than the highest frequency in the the linelist, - /// interaction with the first line occurs - no search - return 0; - } - /// otherwise go through the list until nu_cmf is located between two - /// entries in the line list and get the index of the closest line - /// to lower frequencies - - // will find the highest frequency (lowest index) line with nu_line <= nu_cmf - // lower_bound matches the first element where the comparison function is false - const int matchindex = - std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, - [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - - globals::linelist; - - if (matchindex >= globals::nlines) [[unlikely]] { - return -1; - } - - return matchindex; -} - -static auto get_nu_cmf_abort(const std::array pos, const std::array dir, const double prop_time, - const double nu_rf, const double abort_dist) -> double { +auto get_nu_cmf_abort(const std::array pos, const std::array dir, const double prop_time, + const double nu_rf, const double abort_dist) -> double { // get the frequency change per distance travelled assuming linear change to the abort distance // this is done is two parts to get identical results to do_rpkt_step() const auto half_abort_dist = abort_dist / 2.; @@ -157,23 +72,23 @@ static auto get_nu_cmf_abort(const std::array pos, const std::array double { +constexpr auto get_expopac_bin_nu_upper(const size_t binindex) -> double { const auto lambda_lower = expopac_lambdamin + (binindex * expopac_deltalambda); return 1e8 * CLIGHT / lambda_lower; } -static constexpr auto get_expopac_bin_nu_lower(const size_t binindex) -> double { +constexpr auto get_expopac_bin_nu_lower(const size_t binindex) -> double { const auto lambda_upper = expopac_lambdamin + ((binindex + 1) * expopac_deltalambda); return 1e8 * CLIGHT / lambda_upper; } -static auto get_event(const int modelgridindex, - const Packet &pkt, // pointer to packet object - const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, MacroAtomState &mastate, - const double tau_rnd, // random optical depth until which the packet travels - const double abort_dist, // maximal travel distance before packet leaves cell or time step ends - const double nu_cmf_abort, const double d_nu_on_d_l, - const double doppler) -> std::tuple +auto get_event(const int modelgridindex, + const Packet &pkt, // pointer to packet object + const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, MacroAtomState &mastate, + const double tau_rnd, // random optical depth until which the packet travels + const double abort_dist, // maximal travel distance before packet leaves cell or time step ends + const double nu_cmf_abort, const double d_nu_on_d_l, + const double doppler) -> std::tuple // returns edist, the distance to the next physical event (continuum or bound-bound) and is_boundbound_event, a // boolean BE AWARE THAT THIS PROCEDURE SHOULD BE ONLY CALLED FOR NON EMPTY CELLS!! { @@ -302,7 +217,7 @@ static auto get_event(const int modelgridindex, assert_always(false); } -static auto get_event_expansion_opacity( +auto get_event_expansion_opacity( const int modelgridindex, const int nonemptymgi, const Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, // NOLINT(misc-unused-parameters) MacroAtomState &mastate, const double tau_rnd, const double nu_cmf_abort, const double d_nu_on_d_l, @@ -395,7 +310,7 @@ static auto get_event_expansion_opacity( return {std::numeric_limits::max(), next_trans, false}; } -static void electron_scatter_rpkt(Packet &pkt) { +void electron_scatter_rpkt(Packet &pkt) { /// now make the packet a r-pkt and set further flags pkt.type = TYPE_RPKT; pkt.last_cross = BOUNDARY_NONE; /// allow all further cell crossings @@ -521,8 +436,7 @@ static void electron_scatter_rpkt(Packet &pkt) { pkt.e_rf = pkt.e_cmf / dopplerfactor; } -static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, - const int modelgridindex) { +void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const int modelgridindex) { const double nu = pkt.nu_cmf; const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -585,9 +499,9 @@ static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoe const double chi_bf_rand = rng_uniform() * chi_bf_inrest; // first chi_bf_sum[i] such that chi_bf_sum[i] > chi_bf_rand - const int allcontindex = std::upper_bound(phixslist.chi_bf_sum.data() + phixslist.allcontbegin, - phixslist.chi_bf_sum.data() + phixslist.allcontend - 1, chi_bf_rand) - - phixslist.chi_bf_sum.data(); + const auto allcontindex = std::upper_bound(phixslist.chi_bf_sum.data() + phixslist.allcontbegin, + phixslist.chi_bf_sum.data() + phixslist.allcontend - 1, chi_bf_rand) - + phixslist.chi_bf_sum.data(); assert_always(allcontindex < phixslist.allcontend); const double nu_edge = globals::allcont[allcontindex].nu_edge; @@ -632,7 +546,7 @@ static void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoe } } -static void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const int mgi) { +void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const int mgi) { /// bound-bound transition occured /// activate macro-atom in corresponding upper-level. Actually all the information /// about the macro atoms state has already been set by closest_transition, so @@ -671,29 +585,7 @@ static void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, do_macroatom(pkt, pktmastate); } -auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double -// returns a randomly chosen frequency with a distribution of Planck function times the expansion opacity -{ - assert_testmodeonly(RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.); - - const auto *kappa_planck_bins = &expansionopacity_planck_cumulative[nonemptymgi * expopac_nbins]; - - const auto rnd_integral = rng_uniform() * kappa_planck_bins[expopac_nbins - 1]; - const auto *selected_partintegral = - std::upper_bound(kappa_planck_bins, kappa_planck_bins + expopac_nbins, rnd_integral); - const auto binindex = std::min(selected_partintegral - kappa_planck_bins, expopac_nbins - 1); - assert_testmodeonly(binindex >= 0); - assert_testmodeonly(binindex < expopac_nbins); - - // use a linear interpolation for the frequency within the bin - const auto bin_nu_lower = get_expopac_bin_nu_lower(binindex); - const auto delta_nu = get_expopac_bin_nu_upper(binindex) - bin_nu_lower; - const double nuoffset = rng_uniform() * delta_nu; - const double nu = bin_nu_lower + nuoffset; - return nu; -} - -static void rpkt_event_thickcell(Packet &pkt) +void rpkt_event_thickcell(Packet &pkt) /// Event handling for optically thick cells. Those cells are treated in a grey /// approximation with electron scattering only. /// The packet stays an R_PKT of same nu_cmf than before (coherent scattering) @@ -712,9 +604,9 @@ static void rpkt_event_thickcell(Packet &pkt) pkt.em_time = pkt.prop_time; } -static void update_estimators(const double e_cmf, const double nu_cmf, const double distance, - const double doppler_nucmf_on_nurf, const int nonemptymgi, - const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const bool thickcell) +void update_estimators(const double e_cmf, const double nu_cmf, const double distance, + const double doppler_nucmf_on_nurf, const int nonemptymgi, + const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const bool thickcell) /// Update the volume estimators J and nuJ /// This is done in another routine than move, as we sometimes move dummy /// packets which do not contribute to the radiation field. @@ -756,7 +648,7 @@ static void update_estimators(const double e_cmf, const double nu_cmf, const dou } } -static auto do_rpkt_step(Packet &pkt, const double t2) -> bool +auto do_rpkt_step(Packet &pkt, const double t2) -> bool // Update an r-packet and return true if no mgi change (or it goes into an empty cell) and no pkttype change and not // reached end of timestep, otherwise false { @@ -954,53 +846,7 @@ static auto do_rpkt_step(Packet &pkt, const double t2) -> bool std::abort(); } -__host__ __device__ void do_rpkt(Packet &pkt, const double t2) { - while (do_rpkt_step(pkt, t2)) { - { - } - } -} - -void emit_rpkt(Packet &pkt) { - /// now make the packet a r-pkt and set further flags - pkt.type = TYPE_RPKT; - pkt.last_cross = BOUNDARY_NONE; /// allow all further cell crossings - - /// Need to assign a new direction. Assume isotropic emission in the cmf - - const auto dir_cmf = get_rand_isotropic_unitvec(); - - /// This direction is in the cmf - we want to convert it to the rest - /// frame - use aberation of angles. We want to convert from cmf to - /// rest so need -ve velocity. - const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.prop_time); - /// negative time since we want the backwards transformation here - - pkt.dir = angle_ab(dir_cmf, vel_vec); - // printout("[debug] pkt.dir in RF: %g %g %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); - - /// Finally we want to put in the rest frame energy and frequency. And record - /// that it's now a r-pkt. - - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); - pkt.nu_rf = pkt.nu_cmf / dopplerfactor; - pkt.e_rf = pkt.e_cmf / dopplerfactor; - - // Reset polarization information - pkt.stokes[0] = 1.; - pkt.stokes[1] = 0.; - pkt.stokes[2] = 0.; - - pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); - - if ((dot(pkt.pol_dir, pkt.pol_dir)) < 1.e-8) { - pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 1., 0.}); - } - - pkt.pol_dir = vec_norm(pkt.pol_dir); -} - -static auto calculate_chi_ffheat_nnionpart(const int modelgridindex) -> double { +auto calculate_chi_ffheat_nnionpart(const int modelgridindex) -> double { const double g_ff = 1; double chi_ff_nnionpart = 0.; const int nelements = get_nelements(); @@ -1017,7 +863,7 @@ static auto calculate_chi_ffheat_nnionpart(const int modelgridindex) -> double { return chi_ff_nnionpart * 3.69255e8 / sqrt(T_e); } -static auto get_chi_ff_nnionpart(const int modelgridindex) -> double { +auto get_chi_ff_nnionpart(const int modelgridindex) -> double { if (!use_cellcache || globals::cellcache[cellcacheslotid].cellnumber != modelgridindex) { return calculate_chi_ffheat_nnionpart(modelgridindex); } @@ -1029,7 +875,7 @@ static auto get_chi_ff_nnionpart(const int modelgridindex) -> double { return globals::cellcache[cellcacheslotid].chi_ff_nnionpart; } -static auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> double +auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> double // calculate the free-free absorption (to kpkt heating) coefficient [cm^-1] // = kappa(free-free) * nne { @@ -1045,7 +891,7 @@ static auto calculate_chi_ffheating(const int modelgridindex, const double nu) - } template -static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phixslist *phixslist) -> double +auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phixslist *phixslist) -> double // bound-free opacity { assert_always(!USECELLHISTANDUPDATEPHIXSLIST || phixslist != nullptr); @@ -1065,8 +911,8 @@ static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double n // break the list into nu >= nu_edge and the remainder (nu < nu_edge) int i = 0; - const int allcontend = std::upper_bound(globals::allcont_nu_edge.cbegin(), globals::allcont_nu_edge.cend(), nu) - - globals::allcont_nu_edge.cbegin(); + const int allcontend = + static_cast(std::ranges::upper_bound(globals::allcont_nu_edge, nu) - globals::allcont_nu_edge.cbegin()); const int allcontbegin = std::lower_bound( @@ -1082,8 +928,8 @@ static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double n phixslist->allcontbegin = allcontbegin; phixslist->allcontend = allcontend; - phixslist->bfestimend = std::upper_bound(globals::bfestim_nu_edge.cbegin(), globals::bfestim_nu_edge.cend(), nu) - - globals::bfestim_nu_edge.cbegin(); + phixslist->bfestimend = + static_cast(std::ranges::upper_bound(globals::bfestim_nu_edge, nu) - globals::bfestim_nu_edge.cbegin()); phixslist->bfestimbegin = std::lower_bound( @@ -1172,6 +1018,159 @@ static auto calculate_chi_bf_gammacontr(const int modelgridindex, const double n return chi_bf_sum; } +} // anonymous namespace + +void allocate_expansionopacities() { + const auto npts_nonempty = grid::get_nonempty_npts_model(); + float *expansionopacities_data{}; + double *expansionopacity_planck_cumulative_data{}; +#ifdef MPI_ON + int my_rank_nonemptycells = npts_nonempty / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_nonemptycells += npts_nonempty - (my_rank_nonemptycells * globals::node_nprocs); + } + MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(float)); + int disp_unit = sizeof(float); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &expansionopacities_data, &win_expansionopacities) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_expansionopacities, 0, &size, &disp_unit, &expansionopacities_data) == + MPI_SUCCESS); + + if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { + MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(double)); + int disp_unit = sizeof(double); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &expansionopacity_planck_cumulative_data, + &win_expansionopacity_planck_cumulative) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_expansionopacity_planck_cumulative, 0, &size, &disp_unit, + &expansionopacity_planck_cumulative_data) == MPI_SUCCESS); + } + +#else + expansionopacities_data = static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(float))); + if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { + expansionopacity_planck_cumulative_data = + static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(double))); + } +#endif + expansionopacities = std::span{expansionopacities_data, static_cast(npts_nonempty * expopac_nbins)}; + expansionopacity_planck_cumulative = std::span{ + expansionopacity_planck_cumulative_data, + static_cast(expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins)}; +} + +__host__ __device__ auto closest_transition(const double nu_cmf, const int next_trans) -> int +/// for the propagation through non empty cells +// find the next transition lineindex redder than nu_cmf +// return -1 if no transition can be reached +{ + if (next_trans > (globals::nlines - 1)) { + // packet is tagged as having no more line interactions + return -1; + } + /// if nu_cmf is smaller than the lowest frequency in the linelist, + /// no line interaction is possible: return negative value as a flag + if (nu_cmf < globals::linelist[globals::nlines - 1].nu) { + return -1; + } + + if (next_trans > 0) [[likely]] { + /// if next_trans > 0 we know the next line we should interact with, independent of the packets + /// current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors + return next_trans; + } + if (nu_cmf >= globals::linelist[0].nu) { + /// if nu_cmf is larger than the highest frequency in the the linelist, + /// interaction with the first line occurs - no search + return 0; + } + /// otherwise go through the list until nu_cmf is located between two + /// entries in the line list and get the index of the closest line + /// to lower frequencies + + // will find the highest frequency (lowest index) line with nu_line <= nu_cmf + // lower_bound matches the first element where the comparison function is false + const int matchindex = static_cast( + std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, + [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - + globals::linelist); + + if (matchindex >= globals::nlines) [[unlikely]] { + return -1; + } + + return matchindex; +} + +__host__ __device__ auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double +// returns a randomly chosen frequency with a distribution of Planck function times the expansion opacity +{ + assert_testmodeonly(RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.); + + const auto *kappa_planck_bins = &expansionopacity_planck_cumulative[nonemptymgi * expopac_nbins]; + + const auto rnd_integral = rng_uniform() * kappa_planck_bins[expopac_nbins - 1]; + const auto *selected_partintegral = + std::upper_bound(kappa_planck_bins, kappa_planck_bins + expopac_nbins, rnd_integral); + const auto binindex = std::min(selected_partintegral - kappa_planck_bins, expopac_nbins - 1); + assert_testmodeonly(binindex >= 0); + assert_testmodeonly(binindex < expopac_nbins); + + // use a linear interpolation for the frequency within the bin + const auto bin_nu_lower = get_expopac_bin_nu_lower(binindex); + const auto delta_nu = get_expopac_bin_nu_upper(binindex) - bin_nu_lower; + const double nuoffset = rng_uniform() * delta_nu; + const double nu = bin_nu_lower + nuoffset; + return nu; +} + +__host__ __device__ void do_rpkt(Packet &pkt, const double t2) { + while (do_rpkt_step(pkt, t2)) { + { + } + } +} + +__host__ __device__ void emit_rpkt(Packet &pkt) { + /// now make the packet a r-pkt and set further flags + pkt.type = TYPE_RPKT; + pkt.last_cross = BOUNDARY_NONE; /// allow all further cell crossings + + /// Need to assign a new direction. Assume isotropic emission in the cmf + + const auto dir_cmf = get_rand_isotropic_unitvec(); + + /// This direction is in the cmf - we want to convert it to the rest + /// frame - use aberation of angles. We want to convert from cmf to + /// rest so need -ve velocity. + const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.prop_time); + /// negative time since we want the backwards transformation here + + pkt.dir = angle_ab(dir_cmf, vel_vec); + // printout("[debug] pkt.dir in RF: %g %g %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); + + /// Finally we want to put in the rest frame energy and frequency. And record + /// that it's now a r-pkt. + + const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + pkt.nu_rf = pkt.nu_cmf / dopplerfactor; + pkt.e_rf = pkt.e_cmf / dopplerfactor; + + // Reset polarization information + pkt.stokes[0] = 1.; + pkt.stokes[1] = 0.; + pkt.stokes[2] = 0.; + + pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); + + if ((dot(pkt.pol_dir, pkt.pol_dir)) < 1.e-8) { + pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 1., 0.}); + } + + pkt.pol_dir = vec_norm(pkt.pol_dir); +} + void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const int modelgridindex) { assert_testmodeonly(modelgridindex != grid::get_npts_model()); @@ -1265,10 +1264,10 @@ void calculate_expansion_opacities(const int modelgridindex) { const auto t_mid = globals::timesteps[globals::timestep].mid; // find the first line with nu below the upper limit of the first bin - int lineindex = + int lineindex = static_cast( std::lower_bound(&globals::linelist[0], &globals::linelist[globals::nlines], get_expopac_bin_nu_upper(0), [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - - globals::linelist; + globals::linelist); double kappa_planck_cumulative = 0.; diff --git a/sn3d.h b/sn3d.h index 639a98f74..256bcb7c2 100644 --- a/sn3d.h +++ b/sn3d.h @@ -25,11 +25,11 @@ #ifdef STDPAR_ON #include -#ifndef __cpp_lib_execution -// homebrew llvm doesn't support execution policy yet, so brew install onedpl tbb -#include -#include -#endif +// #ifndef __cpp_lib_execution +// // homebrew llvm doesn't support execution policy yet, so brew install onedpl tbb +// #include +// #include +// #endif #define EXEC_PAR_UNSEQ std::execution::par_unseq, #define EXEC_PAR std::execution::par, diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 38a16372f..ee17036be 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -61,8 +62,8 @@ void printout_tracemission_stats() { traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceemission_totalenergy); } else { - std::ranges::stable_sort(traceemissionabsorption, - [](const auto &a, const auto &b) { return a.energyabsorbed > b.energyabsorbed; }); + std::ranges::stable_sort(traceemissionabsorption, std::ranges::greater{}, + &emissionabsorptioncontrib::energyabsorbed); printout("Top line absorption contributions in the range lambda [%5.1f, %5.1f] time [%5.1fd, %5.1fd] (%g erg)\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceabsorption_totalenergy); @@ -294,7 +295,7 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co } #ifdef MPI_ON -void mpi_reduce_spectra(int my_rank, Spectra &spectra, int numtimesteps) { +void mpi_reduce_spectra(int my_rank, Spectra &spectra, const int numtimesteps) { for (int n = 0; n < numtimesteps; n++) { MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.timesteps[n].flux, spectra.timesteps[n].flux, MNUBINS, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); @@ -316,7 +317,7 @@ void mpi_reduce_spectra(int my_rank, Spectra &spectra, int numtimesteps) { void write_spectrum(const std::string &spec_filename, const std::string &emission_filename, const std::string &trueemission_filename, const std::string &absorption_filename, - const Spectra &spectra, int numtimesteps) { + const Spectra &spectra, const int numtimesteps) { FILE *spec_file = fopen_required(spec_filename, "w"); FILE *emission_file{}; @@ -573,7 +574,7 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co } } -void add_to_spec_res(const Packet &pkt, int current_abin, Spectra &spectra, const Spectra *stokes_i, +void add_to_spec_res(const Packet &pkt, const int current_abin, Spectra &spectra, const Spectra *stokes_i, const Spectra *stokes_q, const Spectra *stokes_u) // Routine to add a packet to the outgoing spectrum. { @@ -589,7 +590,7 @@ void add_to_spec_res(const Packet &pkt, int current_abin, Spectra &spectra, cons } } -void write_partial_lightcurve_spectra(int my_rank, int nts, const Packet *pkts) { +void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Packet *pkts) { const auto time_func_start = std::time(nullptr); std::vector rpkt_light_curve_lum(globals::ntimesteps, 0.); @@ -687,7 +688,7 @@ void write_light_curve(const std::string &lc_filename, const int current_abin, } } -void add_to_lc_res(const Packet &pkt, int current_abin, std::vector &light_curve_lum, +void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector &light_curve_lum, std::vector &light_curve_lumcmf) // add a packet to the outgoing light-curve. { diff --git a/thermalbalance.cc b/thermalbalance.cc index 1d5ae6be2..2229727ed 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -38,7 +38,7 @@ struct gsl_integral_paras_bfheating { float *photoion_xs; }; -auto integrand_bfheatingcoeff_custom_radfield(double nu, void *voidparas) -> double +auto integrand_bfheatingcoeff_custom_radfield(const double nu, void *const voidparas) -> double /// Integrand to calculate the rate coefficient for bfheating using gsl integrators. { const auto *const params = static_cast(voidparas); @@ -57,7 +57,8 @@ auto integrand_bfheatingcoeff_custom_radfield(double nu, void *voidparas) -> dou return sigma_bf * (1 - nu_edge / nu) * radfield::radfield(nu, modelgridindex) * (1 - exp(-HOVERKB * nu / T_R)); } -auto calculate_bfheatingcoeff(int element, int ion, int level, int phixstargetindex, int modelgridindex) -> double { +auto calculate_bfheatingcoeff(const int element, const int ion, const int level, const int phixstargetindex, + const int modelgridindex) -> double { double error = 0.; const double epsrel = 1e-3; const double epsrelwarning = 1e-1; @@ -104,82 +105,8 @@ auto calculate_bfheatingcoeff(int element, int ion, int level, int phixstargetin return bfheating; } -} // anonymous namespace - -auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, double W) -> double { - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! - assert_always(USE_LUT_BFHEATING); - double bfheatingcoeff = 0.; - - const int lowerindex = floor(log(T_R / MINTEMP) / T_step_log); - if (lowerindex < TABLESIZE - 1) { - const int upperindex = lowerindex + 1; - const double T_lower = MINTEMP * exp(lowerindex * T_step_log); - const double T_upper = MINTEMP * exp(upperindex * T_step_log); - - const double f_upper = globals::bfheating_coeff[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; - const double f_lower = globals::bfheating_coeff[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - - bfheatingcoeff = (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_R - T_lower)); - } else { - bfheatingcoeff = globals::bfheating_coeff[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; - } - - return W * bfheatingcoeff; -} - -void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs) { - // depends only the radiation field - // no dependence on T_e or populations - - bfheatingcoeffs.resize(get_includedlevels()); - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); - const double minelfrac = 0.01; - for (int element = 0; element < get_nelements(); element++) { - if (grid::get_elem_abundance(modelgridindex, element) <= minelfrac && !USE_LUT_BFHEATING) { - printout("skipping Z=%d X=%g, ", get_atomicnumber(element), grid::get_elem_abundance(modelgridindex, element)); - } - - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - const int nlevels = get_nlevels(element, ion); - for (int level = 0; level < nlevels; level++) { - double bfheatingcoeff = 0.; - if (grid::get_elem_abundance(modelgridindex, element) > minelfrac || USE_LUT_BFHEATING) { - const auto nphixstargets = get_nphixstargets(element, ion, level); - for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - if constexpr (!USE_LUT_BFHEATING) { - bfheatingcoeff += calculate_bfheatingcoeff(element, ion, level, phixstargetindex, modelgridindex); - } else { - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! - const double T_R = grid::get_TR(modelgridindex); - const double W = grid::get_W(modelgridindex); - bfheatingcoeff += get_bfheatingcoeff_ana(element, ion, level, phixstargetindex, T_R, W); - } - } - assert_always(std::isfinite(bfheatingcoeff)); - - if constexpr (USE_LUT_BFHEATING) { - const int index_in_groundlevelcontestimator = - globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; - if (index_in_groundlevelcontestimator >= 0) { - bfheatingcoeff *= globals::bfheatingestimator[(nonemptymgi * globals::nbfcontinua_ground) + - index_in_groundlevelcontestimator]; - } - } - } - bfheatingcoeffs[get_uniquelevelindex(element, ion, level)] = bfheatingcoeff; - } - } - } -} - -static auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, const int ion, const double T_e, - const double nne) -> double { +auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, const int ion, const double T_e, + const double nne) -> double { double C_deexc = 0.; const int nlevels = get_nlevels(element, ion); @@ -205,9 +132,8 @@ static auto get_heating_ion_coll_deexc(const int modelgridindex, const int eleme return C_deexc; } -static void calculate_heating_rates(const int modelgridindex, const double T_e, const double nne, - HeatingCoolingRates *heatingcoolingrates, - const std::vector &bfheatingcoeffs) +void calculate_heating_rates(const int modelgridindex, const double T_e, const double nne, + HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) /// Calculate the heating rates for a given cell. Results are returned /// via the elements of the heatingrates data structure. { @@ -261,7 +187,7 @@ static void calculate_heating_rates(const int modelgridindex, const double T_e, heatingcoolingrates->heating_ff = ffheating; } -static auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double +auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double /// Thermal balance equation on which we have to iterate to get T_e { const Te_solution_paras *const params = static_cast(paras); @@ -301,6 +227,81 @@ static auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> doub return total_heating_rate - total_coolingrate; } +} // anonymous namespace + +auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, const int phixstargetindex, + const double T_R, const double W) -> double { + /// The correction factor for stimulated emission in gammacorr is set to its + /// LTE value. Because the T_e dependence of gammacorr is weak, this correction + /// correction may be evaluated at T_R! + assert_always(USE_LUT_BFHEATING); + double bfheatingcoeff = 0.; + + const int lowerindex = floor(log(T_R / MINTEMP) / T_step_log); + if (lowerindex < TABLESIZE - 1) { + const int upperindex = lowerindex + 1; + const double T_lower = MINTEMP * exp(lowerindex * T_step_log); + const double T_upper = MINTEMP * exp(upperindex * T_step_log); + + const double f_upper = globals::bfheating_coeff[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; + const double f_lower = globals::bfheating_coeff[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; + + bfheatingcoeff = (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_R - T_lower)); + } else { + bfheatingcoeff = globals::bfheating_coeff[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; + } + + return W * bfheatingcoeff; +} + +void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs) { + // depends only the radiation field + // no dependence on T_e or populations + + bfheatingcoeffs.resize(get_includedlevels()); + const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const double minelfrac = 0.01; + for (int element = 0; element < get_nelements(); element++) { + if (grid::get_elem_abundance(modelgridindex, element) <= minelfrac && !USE_LUT_BFHEATING) { + printout("skipping Z=%d X=%g, ", get_atomicnumber(element), grid::get_elem_abundance(modelgridindex, element)); + } + + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + const int nlevels = get_nlevels(element, ion); + for (int level = 0; level < nlevels; level++) { + double bfheatingcoeff = 0.; + if (grid::get_elem_abundance(modelgridindex, element) > minelfrac || USE_LUT_BFHEATING) { + const auto nphixstargets = get_nphixstargets(element, ion, level); + for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { + if constexpr (!USE_LUT_BFHEATING) { + bfheatingcoeff += calculate_bfheatingcoeff(element, ion, level, phixstargetindex, modelgridindex); + } else { + /// The correction factor for stimulated emission in gammacorr is set to its + /// LTE value. Because the T_e dependence of gammacorr is weak, this correction + /// correction may be evaluated at T_R! + const double T_R = grid::get_TR(modelgridindex); + const double W = grid::get_W(modelgridindex); + bfheatingcoeff += get_bfheatingcoeff_ana(element, ion, level, phixstargetindex, T_R, W); + } + } + assert_always(std::isfinite(bfheatingcoeff)); + + if constexpr (USE_LUT_BFHEATING) { + const int index_in_groundlevelcontestimator = + globals::elements[element].ions[ion].levels[level].closestgroundlevelcont; + if (index_in_groundlevelcontestimator >= 0) { + bfheatingcoeff *= globals::bfheatingestimator[(nonemptymgi * globals::nbfcontinua_ground) + + index_in_groundlevelcontestimator]; + } + } + } + bfheatingcoeffs[get_uniquelevelindex(element, ion, level)] = bfheatingcoeff; + } + } + } +} + void call_T_e_finder(const int modelgridindex, const int timestep, const double t_current, const double T_min, const double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { diff --git a/update_grid.cc b/update_grid.cc index 317c1108b..5458b50a1 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1033,7 +1033,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in const float nne = grid::get_nne(mgi); const double compton_optical_depth = SIGMA_T * nne * grid::wid_init(mgi, 0) * tratmid; - double const radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum * tratmid / assoc_cells; + const double radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum * tratmid / assoc_cells; const double grey_optical_deptha = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * grid::wid_init(mgi, 0) * tratmid; // cube corners will have radial pos > rmax, so clamp to 0. const double dist_to_obs = std::max(0., (globals::rmax * tratmid) - radial_pos); diff --git a/update_packets.cc b/update_packets.cc index 39aee9501..7cfc9d3d1 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "artisoptions.h" diff --git a/vpkt.cc b/vpkt.cc index 458e9a6ab..34f097a10 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -495,7 +495,7 @@ void write_vspecpol(FILE *specpol_file) { } } -void read_vspecpol(int my_rank, int nts) { +void read_vspecpol(const int my_rank, const int nts) { char filename[MAXFILENAMELENGTH]; snprintf(filename, MAXFILENAMELENGTH, "vspecpol_%.4d_ts%d.tmp", my_rank, nts); From c4121e8994697d3ddf7591943eb8b83b6fe4342c Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 15 Aug 2024 09:46:47 +0100 Subject: [PATCH 016/117] Convert more raw pointers to std::vectors, flatten nested arrays, and simplify naming (#104) --- .github/workflows/ci.yml | 2 + atomic.h | 2 +- decay.cc | 35 ++--- globals.h | 29 ++--- grid.cc | 274 +++++++++++++++++---------------------- grid.h | 49 ++++--- input.cc | 64 ++++----- kpkt.cc | 35 ++--- ltepop.cc | 48 ++++--- nltepop.cc | 19 +-- ratecoeff.cc | 4 +- rpkt.cc | 8 +- sn3d.cc | 76 +++++------ update_grid.cc | 10 +- vpkt.cc | 16 +-- 15 files changed, 316 insertions(+), 355 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54fb76841..b2df61896 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,6 +139,7 @@ jobs: run: cat job0/output_0-0.txt - name: Checksum job0 output files + #if: always() if: always() && matrix.testmode == 'OFF' working-directory: tests/${{ matrix.testname }}_testrun run: | @@ -205,6 +206,7 @@ jobs: cat exspec.txt - name: Checksum job1 output files + #if: always() if: always() && matrix.testmode == 'OFF' working-directory: tests/${{ matrix.testname }}_testrun run: | diff --git a/atomic.h b/atomic.h index 7fc63e015..4ee7471e8 100644 --- a/atomic.h +++ b/atomic.h @@ -274,7 +274,7 @@ inline auto get_elementindex(const int Z) -> int const auto elem = std::ranges::find_if(globals::elements, [Z](const Element &element) { return element.anumber == Z; }); if (elem != globals::elements.end()) { - return elem - globals::elements.begin(); + return static_cast(elem - globals::elements.begin()); } // printout("[debug] get_elementindex: element Z=%d was not found in atomic data ... skip readin of cross sections diff --git a/decay.cc b/decay.cc index 550551644..939b276a3 100644 --- a/decay.cc +++ b/decay.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -131,7 +132,7 @@ std::vector decaypaths; // decaypath_energy_per_mass points to an array of length npts_model * num_decaypaths // the index [mgi * num_decaypaths + i] will hold the decay energy per mass [erg/g] released by chain i in cell mgi // during the simulation time range -double *decaypath_energy_per_mass{}; +std::span decaypath_energy_per_mass{}; #ifdef MPI_ON MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; #endif @@ -591,7 +592,7 @@ auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const const int a_top = decaypath.a[0]; const int nucindex_top = decaypath.nucindex[0]; - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); + const double top_initabund = grid::get_modelinitnucmassfrac(modelgridindex, nucindex_top) / nucmass(z_top, a_top); assert_always(top_initabund >= 0.); if (top_initabund <= 0.) { continue; @@ -616,7 +617,7 @@ auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const // for stable nuclei in the network, we need to contribute the initial abundance if (nuc_exists_z_a && get_meanlife(nucindex) <= 0.) { - nuctotal += grid::get_modelinitradioabund(modelgridindex, nucindex); + nuctotal += grid::get_modelinitnucmassfrac(modelgridindex, nucindex); } return nuctotal; @@ -638,7 +639,7 @@ auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const const int a_top = decaypaths[decaypathindex].a[0]; const int nucindex_top = decaypaths[decaypathindex].nucindex[0]; - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); + const double top_initabund = grid::get_modelinitnucmassfrac(modelgridindex, nucindex_top) / nucmass(z_top, a_top); if (top_initabund <= 0.) { return 0.; } @@ -749,7 +750,7 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode const int a_top = decaypaths[decaypathindex].a[0]; const int nucindex_top = decaypaths[decaypathindex].nucindex[0]; - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top); + const double top_initabund = grid::get_modelinitnucmassfrac(modelgridindex, nucindex_top); assert_always(top_initabund >= 0.); if (top_initabund <= 0.) { return 0.; @@ -1044,7 +1045,7 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridinde const int a_top = decaypath.a[0]; const int nucindex_top = decaypath.nucindex[0]; - const double top_initabund = grid::get_modelinitradioabund(modelgridindex, nucindex_top) / nucmass(z_top, a_top); + const double top_initabund = grid::get_modelinitnucmassfrac(modelgridindex, nucindex_top) / nucmass(z_top, a_top); const double chain_endecay = (decaypath.branchproduct * calculate_decaychain(top_initabund, decaypath.lambdas, decaypathlength + 1, @@ -1074,6 +1075,7 @@ void setup_decaypath_energy_per_mass() { "[info] mem_usage: decaypath_energy_per_mass[nonempty_npts_model*num_decaypaths] occupies %.1f MB (node " "shared)...", nonempty_npts_model * get_num_decaypaths() * sizeof(double) / 1024. / 1024.); + double *decaypath_energy_per_mass_data{nullptr}; #ifdef MPI_ON size_t my_rank_cells = nonempty_npts_model / globals::node_nprocs; // rank_in_node 0 gets any remainder @@ -1081,16 +1083,17 @@ void setup_decaypath_energy_per_mass() { my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); } auto size = static_cast(my_rank_cells * get_num_decaypaths() * sizeof(double)); - int disp_unit = sizeof(double); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &decaypath_energy_per_mass, &win_decaypath_energy_per_mass) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_decaypath_energy_per_mass, 0, &size, &disp_unit, &decaypath_energy_per_mass) == - MPI_SUCCESS); + &decaypath_energy_per_mass_data, + &win_decaypath_energy_per_mass) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_decaypath_energy_per_mass, 0, &size, &disp_unit, + &decaypath_energy_per_mass_data) == MPI_SUCCESS); #else - decaypath_energy_per_mass = + decaypath_energy_per_mass_data = static_cast(malloc(nonempty_npts_model * get_num_decaypaths() * sizeof(double))); #endif + decaypath_energy_per_mass = std::span(decaypath_energy_per_mass_data, nonempty_npts_model * get_num_decaypaths()); printout("done.\n"); #ifdef MPI_ON @@ -1123,12 +1126,12 @@ void free_decaypath_energy_per_mass() { win_decaypath_energy_per_mass = MPI_WIN_NULL; } #else - if (decaypath_energy_per_mass != nullptr) { + if (decaypath_energy_per_mass.data() != nullptr) { printout("[info] mem_usage: decaypath_energy_per_mass was freed\n"); - free(decaypath_energy_per_mass); - decaypath_energy_per_mass = nullptr; + free(decaypath_energy_per_mass.data()); } #endif + decaypath_energy_per_mass = {}; } [[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) -> double @@ -1298,11 +1301,11 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl // for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) // { // const auto [z, a] = get_nuc_z_a(nucindex); - // initnucfracsum += grid::get_modelinitradioabund(modelgridindex, z, a); + // initnucfracsum += grid::get_modelinitnucmassfrac(modelgridindex, z, a); // nucfracsum += get_nuc_massfrac(modelgridindex, z, a, t_current); // // // printout_nuclidename(z, a); - // // printout(" init: %g now: %g\n", grid::get_modelinitradioabund(modelgridindex, z, a), + // // printout(" init: %g now: %g\n", grid::get_modelinitnucmassfrac(modelgridindex, z, a), // get_nuc_massfrac(modelgridindex, z, a, t_current)); // // for (int dectypeindex = 0; dectypeindex < decaytypes::DECAYTYPE_COUNT; dectypeindex++) diff --git a/globals.h b/globals.h index 97dddd7ea..4e10f4f87 100644 --- a/globals.h +++ b/globals.h @@ -124,7 +124,6 @@ struct Element { /// Be aware that this must not be used outside of the update_grid routine /// and their daughters. Neither it will work with OpenMP threads. int uniqueionindexstart{-1}; /// Index of the lowest ionisation stage of this element - float abundance{0.}; /// float initstablemeannucmass = {0.}; /// Atomic mass number in multiple of MH bool has_nlte_levels{false}; }; @@ -200,8 +199,8 @@ struct CellCacheElements { struct CellCache { double *cooling_contrib{}; /// Cooling contributions by the different processes. CellCacheElements *chelements{}; - CellCacheLevels *ch_all_levels{}; - double *ch_allcont_departureratios{}; + std::vector ch_all_levels; + std::vector ch_allcont_departureratios; double chi_ff_nnionpart{-1}; int cellnumber{-1}; /// Identifies the cell the data is valid for. }; @@ -227,22 +226,22 @@ inline double *corrphotoionrenorm{}; inline MPI_Win win_corrphotoionrenorm{MPI_WIN_NULL}; #endif -inline double *gammaestimator{}; +inline std::vector gammaestimator; // for USE_LUT_BFHEATING = true -inline double *bfheatingestimator{}; +inline std::vector bfheatingestimator{}; -inline double *ffheatingestimator{}; -inline double *colheatingestimator{}; +inline std::vector ffheatingestimator{}; +inline std::vector colheatingestimator{}; #ifdef DO_TITER -inline double *gammaestimator_save{}; -inline double *bfheatingestimator_save{}; -inline double *ffheatingestimator_save{}; -inline double *colheatingestimator_save{}; +inline std::vector gammaestimator_save{}; +inline std::vector bfheatingestimator_save{}; +inline std::vector ffheatingestimator_save{}; +inline std::vector colheatingestimator_save{}; #endif -inline int *ecounter{}; -inline int *acounter{}; +inline std::vector ecounter{}; +inline std::vector acounter{}; inline int nprocs_exspec{1}; inline bool do_emission_res{true}; @@ -274,7 +273,7 @@ inline std::vector allcont_nu_edge; inline const FullPhotoionTransition *allcont{}; // for either USE_LUT_PHOTOION = true or !USE_LUT_BFHEATING = false -inline GroundPhotoion *groundcont{}; +inline std::vector groundcont{}; inline int nbfcontinua{-1}; // number of bf-continua inline int nbfcontinua_ground{-1}; // number of bf-continua from ground levels @@ -282,7 +281,7 @@ inline int nbfcontinua_ground{-1}; // number of bf-continua from ground levels inline int NPHIXSPOINTS{-1}; inline double NPHIXSNUINCREMENT{-1}; -inline CellCache *cellcache{}; +inline std::vector cellcache{}; #ifdef MPI_ON inline MPI_Comm mpi_comm_node{MPI_COMM_NULL}; diff --git a/grid.cc b/grid.cc index cc2d14126..12ad560e7 100644 --- a/grid.cc +++ b/grid.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -49,12 +50,12 @@ size_t npts_model = 0; // number of model grid cells size_t nonempty_npts_model = 0; // number of allocated non-empty model grid cells double t_model = -1.; // time at which densities in input model are correct. -double *vout_model{}; +std::vector vout_model{}; std::array ncoord_model{0}; // the model.txt input grid dimensions double min_den; // minimum model density -double mfeg; /// Total mass of Fe group elements in ejecta +double mfegroup = 0.; /// Total mass of Fe group elements in ejecta int first_cellindex = -1; // auto-dermine first cell index in model.txt (usually 1 or 0) @@ -63,21 +64,21 @@ struct PropGridCell { int modelgridindex{-1}; }; -struct PropGridCell *cell{}; +std::vector cell{}; std::vector mg_associated_cells; std::vector nonemptymgi_of_mgi; std::vector mgi_of_nonemptymgi; -double *totmassradionuclide{}; /// total mass of each radionuclide in the ejecta +std::span totmassradionuclide{}; /// total mass of each radionuclide in the ejecta #ifdef MPI_ON MPI_Win win_nltepops_allcells = MPI_WIN_NULL; -MPI_Win win_initradioabund_allcells = MPI_WIN_NULL; +MPI_Win win_initnucmassfrac_allcells = MPI_WIN_NULL; #endif -float *initradioabund_allcells{}; -float *initmassfracstable_allcells{}; +float *initnucmassfrac_allcells{}; +float *initmassfracuntrackedstable_allcells{}; float *elem_meanweight_allcells{}; std::vector ranks_nstart; @@ -119,9 +120,9 @@ void read_possible_yefile() { void set_npts_model(const int new_npts_model) { npts_model = new_npts_model; - assert_always(modelgrid == nullptr); - modelgrid = static_cast(calloc(npts_model + 1, sizeof(ModelGridCell))); - assert_always(modelgrid != nullptr); + assert_always(modelgrid.data() == nullptr); + modelgrid = std::span(static_cast(calloc(npts_model + 1, sizeof(ModelGridCell))), npts_model + 1); + assert_always(modelgrid.data() != nullptr); mg_associated_cells.resize(npts_model + 1, 0); nonemptymgi_of_mgi.resize(npts_model + 1, -1); } @@ -133,21 +134,24 @@ void allocate_initradiobund() { const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); #ifdef MPI_ON - auto my_rank_cells = (npts_model + 1) / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += (npts_model + 1) - (my_rank_cells * globals::node_nprocs); - } + const auto my_rank_cells = [] { + auto my_rank_cells = (npts_model + 1) / globals::node_nprocs; + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_cells += (npts_model + 1) - (my_rank_cells * globals::node_nprocs); + } + return my_rank_cells; + }(); MPI_Aint size = my_rank_cells * num_nuclides * sizeof(float); int disp_unit = sizeof(float); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initradioabund_allcells, &win_initradioabund_allcells) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_initradioabund_allcells, 0, &size, &disp_unit, &initradioabund_allcells) == + &initnucmassfrac_allcells, &win_initnucmassfrac_allcells) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_initnucmassfrac_allcells, 0, &size, &disp_unit, &initnucmassfrac_allcells) == MPI_SUCCESS); #else - initradioabund_allcells = static_cast(malloc(totalradioabundsize)); + initnucmassfrac_allcells = static_cast(malloc(totalradioabundsize)); #endif printout( "[info] mem_usage: radioabundance data for %zu nuclides for %zu cells occupies %.3f MB (node shared memory)\n", @@ -157,13 +161,13 @@ void allocate_initradiobund() { MPI_Barrier(globals::mpi_comm_node); #endif - assert_always(initradioabund_allcells != nullptr); + assert_always(initnucmassfrac_allcells != nullptr); for (size_t mgi = 0; mgi < (npts_model + 1); mgi++) { - modelgrid[mgi].initradioabund = &initradioabund_allcells[mgi * num_nuclides]; + modelgrid[mgi].initnucmassfrac = &initnucmassfrac_allcells[mgi * num_nuclides]; if (mgi % static_cast(globals::node_nprocs) == static_cast(globals::rank_in_node)) { for (int i = 0; i < decay::get_num_nuclides(); i++) { - modelgrid[mgi].initradioabund[i] = 0.; + modelgrid[mgi].initnucmassfrac[i] = 0.; } } } @@ -209,9 +213,9 @@ void set_cell_modelgridindex(const int cellindex, const int new_modelgridindex) cell[cellindex].modelgridindex = new_modelgridindex; } -void set_modelinitradioabund(const int modelgridindex, const int nucindex, float abund) { +void set_modelinitnucmassfrac(const int modelgridindex, const int nucindex, float abund) { // set the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index - // initradioabund array is in node shared memory + // initnucmassfrac array is in node shared memory assert_always(nucindex >= 0); if (!(abund >= 0.)) { printout("WARNING: nuclear mass fraction for nucindex %d = %g is negative in cell %d\n", nucindex, abund, @@ -223,15 +227,15 @@ void set_modelinitradioabund(const int modelgridindex, const int nucindex, float assert_always(abund >= 0.); assert_always(abund <= 1.); - assert_always(modelgrid[modelgridindex].initradioabund != nullptr); - modelgrid[modelgridindex].initradioabund[nucindex] = abund; + assert_always(modelgrid[modelgridindex].initnucmassfrac != nullptr); + modelgrid[modelgridindex].initnucmassfrac[nucindex] = abund; } void set_initenergyq(const int modelgridindex, const double initenergyq) { modelgrid[modelgridindex].initenergyq = initenergyq; } -void set_elem_stable_abund_from_total(const int mgi, const int element, const float elemabundance) { +void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, const float elemabundance) { // set the stable mass fraction of an element from the total element mass fraction // by subtracting the abundances of radioactive isotopes. // if the element Z=anumber has no specific stable abundance variable then the function does nothing @@ -242,13 +246,13 @@ void set_elem_stable_abund_from_total(const int mgi, const int element, const fl for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { if (decay::get_nuc_z(nucindex) == atomic_number) { // radioactive isotope of this element - isofracsum += get_modelinitradioabund(mgi, nucindex); + isofracsum += get_modelinitnucmassfrac(mgi, nucindex); } } - double massfracstable = elemabundance - isofracsum; + double massfrac_untrackedstable = elemabundance - isofracsum; - if (massfracstable < 0.) { + if (massfrac_untrackedstable < 0.) { //  allow some roundoff error before we complain if ((isofracsum - elemabundance - 1.) > 1e-4 && std::abs(isofracsum - elemabundance) > 1e-6) { printout("WARNING: cell %d Z=%d element abundance is less than the sum of its radioisotope abundances \n", mgi, @@ -256,15 +260,16 @@ void set_elem_stable_abund_from_total(const int mgi, const int element, const fl printout(" massfrac(Z) %g massfrac_radioisotopes(Z) %g\n", elemabundance, isofracsum); printout(" increasing elemental abundance to %g and setting stable isotopic abundance to zero\n", isofracsum); } - assert_always(massfracstable >= -1e-2); // result is allowed to be slightly negative due to roundoff error - massfracstable = 0.; // bring up to zero if negative + assert_always(massfrac_untrackedstable >= + -1e-2); // result is allowed to be slightly negative due to roundoff error + massfrac_untrackedstable = 0.; // bring up to zero if negative } // if (globals::rank_in_node == 0) - { modelgrid[mgi].initmassfracstable[element] = massfracstable; } + { modelgrid[mgi].initmassfracuntrackedstable[element] = massfrac_untrackedstable; } // (isofracsum + massfracstable) might not exactly match elemabundance if we had to boost it to reach isofracsum - modelgrid[mgi].composition[element].abundance = isofracsum + massfracstable; + set_elem_abundance(mgi, element, isofracsum + massfrac_untrackedstable); } void allocate_nonemptycells_composition_cooling() @@ -294,8 +299,9 @@ void allocate_nonemptycells_composition_cooling() int disp_unit = sizeof(float); MPI_Win mpiwin = MPI_WIN_NULL; assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initmassfracstable_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &initmassfracstable_allcells) == MPI_SUCCESS); + &initmassfracuntrackedstable_allcells, &mpiwin) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &initmassfracuntrackedstable_allcells) == + MPI_SUCCESS); } { @@ -309,7 +315,7 @@ void allocate_nonemptycells_composition_cooling() MPI_Barrier(globals::mpi_comm_node); } #else - initmassfracstable_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); + initmassfracuntrackedstable_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); elem_meanweight_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); #endif @@ -337,82 +343,53 @@ void allocate_nonemptycells_composition_cooling() assert_always(modelgrid[modelgridindex].elements_uppermost_ion != nullptr); - modelgrid[modelgridindex].composition = - static_cast(malloc(get_nelements() * sizeof(ModelCellElement))); + modelgrid[modelgridindex].elem_massfracs = static_cast(malloc(get_nelements() * sizeof(float))); - if (modelgrid[modelgridindex].composition == nullptr) { + if (modelgrid[modelgridindex].elem_massfracs == nullptr) { printout("[fatal] input: not enough memory to initialize compositionlist for cell %d... abort\n", modelgridindex); std::abort(); } - modelgrid[modelgridindex].initmassfracstable = &initmassfracstable_allcells[nonemptymgi * get_nelements()]; + modelgrid[modelgridindex].initmassfracuntrackedstable = + &initmassfracuntrackedstable_allcells[nonemptymgi * get_nelements()]; - assert_always(modelgrid[modelgridindex].initmassfracstable != nullptr); + assert_always(modelgrid[modelgridindex].initmassfracuntrackedstable != nullptr); modelgrid[modelgridindex].elem_meanweight = &elem_meanweight_allcells[nonemptymgi * get_nelements()]; assert_always(modelgrid[modelgridindex].elem_meanweight != nullptr); if (globals::total_nlte_levels > 0) { - modelgrid[modelgridindex].nlte_pops = &nltepops_allcells[nonemptymgi * globals::total_nlte_levels]; - assert_always(modelgrid[modelgridindex].nlte_pops != nullptr); - - for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { - modelgrid[modelgridindex].nlte_pops[nlteindex] = -1.; /// flag to indicate that there is - /// currently no information on the nlte populations - } - } else { - modelgrid[modelgridindex].nlte_pops = nullptr; - } - - for (int element = 0; element < get_nelements(); element++) { - /// Set initial abundances to zero - modelgrid[modelgridindex].composition[element].abundance = 0.; - - /// and allocate memory to store the ground level populations for each ionisation stage - modelgrid[modelgridindex].composition[element].groundlevelpop = - static_cast(calloc(get_nions(element), sizeof(float))); - if (modelgrid[modelgridindex].composition[element].groundlevelpop == nullptr) { - printout( - "[fatal] input: not enough memory to initialize groundlevelpoplist for element %d in cell %d... abort\n", - element, modelgridindex); - std::abort(); - } + modelgrid[modelgridindex].nlte_pops = + std::span(&nltepops_allcells[nonemptymgi * globals::total_nlte_levels], globals::total_nlte_levels); + assert_always(modelgrid[modelgridindex].nlte_pops.data() != nullptr); - modelgrid[modelgridindex].composition[element].partfunct = - static_cast(calloc(get_nions(element), sizeof(float))); - - if (modelgrid[modelgridindex].composition[element].partfunct == nullptr) { - printout("[fatal] input: not enough memory to initialize partfunctlist for element %d in cell %d... abort\n", - element, modelgridindex); - std::abort(); - } + /// -1 indicates that there is currently no information on the nlte populations + std::ranges::fill(modelgrid[modelgridindex].nlte_pops, -1.); } - modelgrid[modelgridindex].cooling_contrib_ion = static_cast(malloc(get_nelements() * sizeof(double *))); + std::fill_n(modelgrid[modelgridindex].elem_massfracs, get_nelements(), -1.); - if (modelgrid[modelgridindex].cooling_contrib_ion == nullptr) { - printout("[fatal] input: not enough memory to initialize coolinglist for cell %d... abort\n", modelgridindex); + modelgrid[modelgridindex].ion_groundlevelpops = static_cast(calloc(get_includedions(), sizeof(float))); + if (modelgrid[modelgridindex].ion_groundlevelpops == nullptr) { + printout("[fatal] input: not enough memory to initialize ion_groundlevelpops in cell %d... abort\n", + modelgridindex); std::abort(); } - modelgrid[modelgridindex].cooling_contrib_ion[0] = - static_cast(malloc(get_includedions() * sizeof(double))); + modelgrid[modelgridindex].ion_partfuncts = static_cast(calloc(get_includedions(), sizeof(float))); - for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { - modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex] = -1.; // flag as invalid + if (modelgrid[modelgridindex].ion_partfuncts == nullptr) { + printout("[fatal] input: not enough memory to initialize partfunctlist in cell %d... abort\n", modelgridindex); + std::abort(); } - int allionindex = 0; - for (int element = 0; element < get_nelements(); element++) { - /// and allocate memory to store the ground level populations for each ionisation stage + modelgrid[modelgridindex].ion_cooling_contribs = static_cast(malloc(get_includedions() * sizeof(double))); - modelgrid[modelgridindex].cooling_contrib_ion[element] = - &modelgrid[modelgridindex].cooling_contrib_ion[0][allionindex]; - - assert_always(modelgrid[modelgridindex].cooling_contrib_ion[element] != nullptr); - - allionindex += get_nions(element); + if (modelgrid[modelgridindex].ion_cooling_contribs == nullptr) { + printout("[fatal] input: not enough memory to initialize ion_cooling_contribs for cell %d... abort\n", + modelgridindex); + std::abort(); } } } @@ -469,9 +446,9 @@ void allocate_nonemptymodelcells() { nonemptymgi_of_mgi[mgi] = -1; set_rho_tmin(mgi, 0.); set_rho(mgi, 0.); - if (modelgrid[mgi].initradioabund != nullptr) { + if (modelgrid[mgi].initnucmassfrac != nullptr) { for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - set_modelinitradioabund(mgi, nucindex, 0.); + set_modelinitnucmassfrac(mgi, nucindex, 0.); } } } @@ -488,7 +465,8 @@ void allocate_nonemptymodelcells() { globals::dep_estimator_electron.resize(nonempty_npts_model, 0.); globals::dep_estimator_alpha.resize(nonempty_npts_model, 0.); - auto ionestimsize = nonempty_npts_model * globals::nbfcontinua_ground * sizeof(double); + const auto ionestimcount = nonempty_npts_model * globals::nbfcontinua_ground; + const auto ionestimsize = ionestimcount * sizeof(double); if (USE_LUT_PHOTOION && ionestimsize > 0) { #ifdef MPI_ON @@ -509,35 +487,35 @@ void allocate_nonemptymodelcells() { globals::corrphotoionrenorm = static_cast(malloc(ionestimsize)); #endif - globals::gammaestimator = static_cast(malloc(ionestimsize)); + globals::gammaestimator.resize(ionestimcount, 0.); #ifdef DO_TITER - globals::gammaestimator_save = static_cast(malloc(ionestimsize)); + globals::gammaestimator_save.resize(nonempty_npts_model, 0.); #endif } else { globals::corrphotoionrenorm = nullptr; - globals::gammaestimator = nullptr; + globals::gammaestimator.clear(); #ifdef DO_TITER - globals::gammaestimator_save = nullptr; + globals::gammaestimator_save.clear(); #endif } if (USE_LUT_BFHEATING && ionestimsize > 0) { - globals::bfheatingestimator = static_cast(malloc(ionestimsize)); + globals::bfheatingestimator.resize(ionestimcount, 0.); #ifdef DO_TITER - globals::bfheatingestimator_save = static_cast(malloc(ionestimsize)); + globals::bfheatingestimator_save.resize(nonempty_npts_model, 0.); #endif } else { - globals::bfheatingestimator = nullptr; + globals::bfheatingestimator.clear(); #ifdef DO_TITER - globals::bfheatingestimator_save = nullptr; + globals::bfheatingestimator_save.clear(); #endif } - globals::ffheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); - globals::colheatingestimator = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::ffheatingestimator.resize(nonempty_npts_model, 0.); + globals::colheatingestimator.resize(nonempty_npts_model, 0.); #ifdef DO_TITER - globals::ffheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); - globals::colheatingestimator_save = static_cast(malloc(nonempty_npts_model * sizeof(double))); + globals::ffheatingestimator_save.resize(nonempty_npts_model, 0.); + globals::colheatingestimator_save.resize(nonempty_npts_model, 0.); #endif #ifdef MPI_ON @@ -560,13 +538,15 @@ void map_1dmodelto3dgrid() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; - const int mgi = static_cast(std::find_if_not(vout_model, vout_model + get_npts_model(), - [cellvmid](double v_outer) { return v_outer < cellvmid; }) - - vout_model); + const int mgi = static_cast(std::ranges::lower_bound(vout_model, cellvmid) - vout_model.begin()); if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { set_cell_modelgridindex(cellindex, mgi); + assert_always(vout_model[mgi] >= cellvmid); + assert_always((mgi > 0 ? vout_model[mgi - 1] : 0.0) <= cellvmid); } else { + // corner cells outside of the outermost model shell are empty + // and so are any shells with zero density set_cell_modelgridindex(cellindex, get_npts_model()); } } @@ -576,27 +556,27 @@ void map_2dmodelto3dgrid() // Map 2D cylindrical model onto propagation grid { for (int cellindex = 0; cellindex < ngrid; cellindex++) { - int mgi = get_npts_model(); // default to empty unless set - // map to 3D Cartesian grid std::array pos_mid{}; for (int d = 0; d < 3; d++) { pos_mid[d] = (get_cellcoordmin(cellindex, d) + (0.5 * wid_init(cellindex, d))); } - // 2D grid is uniform so rcyl and z positions can easily be calculated const double rcylindrical = std::sqrt(std::pow(pos_mid[0], 2) + std::pow(pos_mid[1], 2)); + // 2D grid is uniform so rcyl and z indicies can be calculated with no lookup const int n_rcyl = static_cast(rcylindrical / globals::tmin / globals::vmax * ncoord_model[0]); const int n_z = static_cast((pos_mid[2] / globals::tmin + globals::vmax) / (2 * globals::vmax) * ncoord_model[1]); if (n_rcyl >= 0 && n_rcyl < ncoord_model[0] && n_z >= 0 && n_z < ncoord_model[1]) { - mgi = (n_z * ncoord_model[0]) + n_rcyl; - } + const int mgi = (n_z * ncoord_model[0]) + n_rcyl; - if (modelgrid[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); + if (modelgrid[mgi].rhoinit > 0) { + set_cell_modelgridindex(cellindex, mgi); + } else { + set_cell_modelgridindex(cellindex, get_npts_model()); + } } else { set_cell_modelgridindex(cellindex, get_npts_model()); } @@ -604,16 +584,12 @@ void map_2dmodelto3dgrid() } void map_modeltogrid_direct() -// mgi and cellindex are interchangeable in this mode +// mgi and cellindex are interchangeable in this mode (except for empty cells that associated with mgi == +// get_npts_model()) { for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const int mgi = cellindex; // direct mapping - - if (modelgrid[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); - } else { - set_cell_modelgridindex(cellindex, get_npts_model()); - } + const int mgi = (modelgrid[cellindex].rhoinit > 0) ? cellindex : get_npts_model(); + set_cell_modelgridindex(cellindex, mgi); } } @@ -679,7 +655,7 @@ void abundances_read() { assert_always(elemabundance >= 0.); // radioactive nuclide abundances should have already been set by read_??_model - set_elem_stable_abund_from_total(mgi, element, elemabundance); + set_elem_untrackedstable_abund_from_total(mgi, element, elemabundance); } } } @@ -774,7 +750,7 @@ void read_model_radioabundances(std::fstream &fmodel, std::istringstream &ssline if (nucindexlist[i] >= 0) { assert_testmodeonly(valuein <= 1.); - set_modelinitradioabund(mgi, nucindexlist[i], valuein); + set_modelinitnucmassfrac(mgi, nucindexlist[i], valuein); } else if (colnames[i] == "X_Fegroup") { set_ffegrp(mgi, valuein); } else if (colnames[i] == "cellYe") { @@ -884,7 +860,7 @@ void read_1d_model() set_npts_model(npts_model_in); ncoord_model[0] = npts_model_in; - vout_model = static_cast(malloc((get_npts_model() + 1) * sizeof(double))); + vout_model.resize(get_npts_model()); // Now read the time (in days) at which the model is specified. double t_model_days{NAN}; @@ -1154,11 +1130,12 @@ void read_3d_model() void calc_modelinit_totmassradionuclides() { mtot_input = 0.; - mfeg = 0.; + mfegroup = 0.; - assert_always(totmassradionuclide == nullptr); - totmassradionuclide = static_cast(malloc(decay::get_num_nuclides() * sizeof(double))); - assert_always(totmassradionuclide != nullptr); + assert_always(totmassradionuclide.data() == nullptr); + totmassradionuclide = + std::span(static_cast(malloc(decay::get_num_nuclides() * sizeof(double))), decay::get_num_nuclides()); + assert_always(totmassradionuclide.data() != nullptr); for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { totmassradionuclide[nucindex] = 0.; @@ -1193,10 +1170,10 @@ void calc_modelinit_totmassradionuclides() { mtot_input += mass_in_shell; for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - totmassradionuclide[nucindex] += mass_in_shell * get_modelinitradioabund(mgi, nucindex); + totmassradionuclide[nucindex] += mass_in_shell * get_modelinitnucmassfrac(mgi, nucindex); } - mfeg += mass_in_shell * get_ffegrp(mgi); + mfegroup += mass_in_shell * get_ffegrp(mgi); } printout("Total input model mass: %9.3e [Msun]\n", mtot_input / MSUN); @@ -1204,7 +1181,7 @@ void calc_modelinit_totmassradionuclides() { printout(" 56Ni: %9.3e 56Co: %9.3e 52Fe: %9.3e 48Cr: %9.3e\n", get_totmassradionuclide(28, 56) / MSUN, get_totmassradionuclide(27, 56) / MSUN, get_totmassradionuclide(26, 52) / MSUN, get_totmassradionuclide(24, 48) / MSUN); - printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfeg / MSUN, get_totmassradionuclide(28, 57) / MSUN, + printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfegroup / MSUN, get_totmassradionuclide(28, 57) / MSUN, get_totmassradionuclide(27, 57) / MSUN); } @@ -1446,7 +1423,7 @@ void setup_grid_cartesian_3d() assert_always(ncoordgrid[0] == ncoordgrid[2]); ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); + cell.resize(ngrid); coordlabel[0] = 'X'; coordlabel[1] = 'Y'; @@ -1484,13 +1461,11 @@ void setup_grid_spherical1d() { ncoordgrid[2] = 1; ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); + cell.resize(ngrid); - // direct mapping, cellindex and modelgridindex are the same for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { const int mgi = cellindex; // interchangeable in this mode const double v_inner = mgi > 0 ? vout_model[mgi - 1] : 0.; - set_cell_modelgridindex(cellindex, mgi); cell[cellindex].pos_min[0] = v_inner * globals::tmin; cell[cellindex].pos_min[1] = 0.; cell[cellindex].pos_min[2] = 0.; @@ -1512,13 +1487,9 @@ void setup_grid_cylindrical_2d() { ncoordgrid[2] = ncoord_model[2]; ngrid = ncoordgrid[0] * ncoordgrid[1]; - cell = static_cast(malloc(ngrid * sizeof(PropGridCell))); + cell.resize(ngrid); - // direct mapping, cellindex and modelgridindex are the same for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { - const int mgi = cellindex; // interchangeable in this mode - set_cell_modelgridindex(cellindex, mgi); - const int n_rcyl = get_cellcoordpointnum(cellindex, 0); const int n_z = get_cellcoordpointnum(cellindex, 1); @@ -1910,7 +1881,7 @@ __host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) // mass fraction of an element (all isotopes combined) { - modelgrid[modelgridindex].composition[element].abundance = newabundance; + modelgrid[modelgridindex].elem_massfracs[element] = newabundance; } __host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double @@ -2048,16 +2019,16 @@ __host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int // the abundances below are initial abundances at t_model -auto get_modelinitradioabund(const int modelgridindex, const int nucindex) -> float { +auto get_modelinitnucmassfrac(const int modelgridindex, const int nucindex) -> float { // get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index - assert_testmodeonly(modelgrid[modelgridindex].initradioabund != nullptr); - return modelgrid[modelgridindex].initradioabund[nucindex]; + assert_testmodeonly(modelgrid[modelgridindex].initnucmassfrac != nullptr); + return modelgrid[modelgridindex].initnucmassfrac[nucindex]; } auto get_stable_initabund(const int mgi, const int element) -> float { - assert_testmodeonly(modelgrid[mgi].initmassfracstable != nullptr); - return modelgrid[mgi].initmassfracstable[element]; + assert_testmodeonly(modelgrid[mgi].initmassfracuntrackedstable != nullptr); + return modelgrid[mgi].initmassfracuntrackedstable[element]; } auto get_element_meanweight(const int mgi, const int element) -> float @@ -2171,7 +2142,7 @@ void calculate_kappagrey() { kappa = globals::GREY_OP; } else if (globals::opacity_case == 1 || globals::opacity_case == 4) { /// kappagrey used for initial grey approximation in case 4 - kappa = ((0.9 * get_ffegrp(mgi)) + 0.1) * globals::GREY_OP / ((0.9 * mfeg / mtot_input) + 0.1); + kappa = ((0.9 * get_ffegrp(mgi)) + 0.1) * globals::GREY_OP / ((0.9 * mfegroup / mtot_input) + 0.1); } else if (globals::opacity_case == 2) { const double opcase2_normal = globals::GREY_OP * rho_sum / ((0.9 * fe_sum) + (0.1 * (ngrid - empty_cells))); kappa = opcase2_normal / get_rho_tmin(mgi) * ((0.9 * get_ffegrp(mgi)) + 0.1); @@ -2405,7 +2376,6 @@ void grid_init(const int my_rank) if (get_model_type() == GRID_TYPE) { if (get_model_type() == GRID_CARTESIAN3D) { - assert_always(GRID_TYPE == GRID_CARTESIAN3D); assert_always(ncoord_model[0] == ncoordgrid[0]); assert_always(ncoord_model[1] == ncoordgrid[1]); assert_always(ncoord_model[2] == ncoordgrid[2]); @@ -2466,7 +2436,7 @@ void grid_init(const int my_rank) for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); totmassradionuclide_actual += - get_modelinitradioabund(mgi, nucindex) * get_rho_tmin(mgi) * get_modelcell_assocvolume_tmin(mgi); + get_modelinitnucmassfrac(mgi, nucindex) * get_rho_tmin(mgi) * get_modelcell_assocvolume_tmin(mgi); } if (totmassradionuclide_actual > 0.) { @@ -2474,9 +2444,9 @@ void grid_init(const int my_rank) // printout("nuclide %d ratio %g\n", nucindex, ratio); for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const double prev_abund = get_modelinitradioabund(mgi, nucindex); + const double prev_abund = get_modelinitnucmassfrac(mgi, nucindex); const double new_abund = prev_abund * ratio; - set_modelinitradioabund(mgi, nucindex, new_abund); + set_modelinitnucmassfrac(mgi, nucindex, new_abund); } } } diff --git a/grid.h b/grid.h index 72bba2793..1c6c09fe1 100644 --- a/grid.h +++ b/grid.h @@ -1,4 +1,5 @@ #pragma once +#include #ifndef GRIDINIT_H #define GRIDINIT_H @@ -13,14 +14,6 @@ namespace grid { -struct ModelCellElement { - float abundance; /// Abundance of the element (by mass!). - float *groundlevelpop; /// Pointer to an array of floats which contains the groundlevel populations - /// of all included ionisation stages for the element. - float *partfunct; /// Pointer to an array of floats which contains the partition functions - /// of all included ionisation stages for the element. -}; - struct ModelGridCell { float Te = -1.; float TR = -1.; @@ -32,26 +25,26 @@ struct ModelGridCell { float rho = -1.; // modelgrid nn_tot float nnetot = -1.; // total electron density (free + bound). - float *initradioabund{}; - float *initmassfracstable{}; + float *initnucmassfrac{}; + float *initmassfracuntrackedstable{}; float *elem_meanweight{}; float initelectronfrac = -1; // Ye: electrons (or protons) per nucleon float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] float ffegrp = 0.; float kappagrey = 0.; - float grey_depth = 0.; /// Grey optical depth to surface of the modelgridcell - /// This is only stored to print it outside the OpenMP loop in update_grid to the - /// estimatorsfile so there is no need to communicate it via MPI so far! - int *elements_uppermost_ion{}; /// Highest ionisation stage which has a decent population for a particular - /// element in a given cell. - ModelCellElement *composition{}; /// Pointer to an array which contains the time dependent - /// abundances of all included elements and all the groundlevel - /// populations and partition functions for their ions - double *nlte_pops{}; /// Pointer to an array that contains the nlte-level - /// populations for this cell - + float grey_depth = 0.; /// Grey optical depth to surface of the modelgridcell + /// This is only stored to print it outside the OpenMP loop in update_grid to the + /// estimatorsfile so there is no need to communicate it via MPI so far! + int *elements_uppermost_ion{}; /// Highest ionisation stage which has a decent population for a particular + /// element in a given cell. + float *elem_massfracs{}; /// Pointer to an array which contains the time dependent + /// abundances of all included elements and all the groundlevel + + float *ion_groundlevelpops{}; /// groundlevel populations of all included ions + float *ion_partfuncts{}; /// partition functions for all included ions + std::span nlte_pops; /// Pointer to an array that contains the nlte-level populations for this cell double totalcooling = -1; - double **cooling_contrib_ion{}; + double *ion_cooling_contribs{}; uint_fast8_t thick = 0; }; @@ -65,14 +58,15 @@ constexpr auto get_ngriddimensions() -> int { return 3; default: assert_always(false); + return -1; } } -inline ModelGridCell *modelgrid{}; +inline std::span modelgrid{}; inline int ngrid{0}; -inline double mtot_input; +inline double mtot_input{0.}; [[nodiscard]] auto get_elements_uppermost_ion(int modelgridindex, int element) -> int; void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); @@ -107,7 +101,7 @@ void set_TR(int modelgridindex, float TR); void set_TJ(int modelgridindex, float TJ); void set_W(int modelgridindex, float W); void grid_init(int my_rank); -[[nodiscard]] auto get_modelinitradioabund(int modelgridindex, int nucindex) -> float; +[[nodiscard]] auto get_modelinitnucmassfrac(int modelgridindex, int nucindex) -> float; [[nodiscard]] auto get_stable_initabund(int mgi, int element) -> float; [[nodiscard]] auto get_element_meanweight(int mgi, int element) -> float; void set_element_meanweight(int mgi, int element, float meanweight); @@ -135,8 +129,11 @@ void write_grid_restart_data(int timestep); [[nodiscard]] inline auto get_elem_abundance(int modelgridindex, int element) -> float // mass fraction of an element (all isotopes combined) { - return modelgrid[modelgridindex].composition[element].abundance; + const auto massfrac = modelgrid[modelgridindex].elem_massfracs[element]; + assert_testmodeonly(massfrac >= 0.0); + return massfrac; } + void calculate_kappagrey(); inline void change_cell(Packet &pkt, const int snext) diff --git a/input.cc b/input.cc index e15d31746..076c04688 100644 --- a/input.cc +++ b/input.cc @@ -102,7 +102,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input assert_always(upperlevel >= 0); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets == 0); globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = 1; - *mem_usage_phixs += sizeof(grid::ModelCellElement); + *mem_usage_phixs += sizeof(PhotoionTarget); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets == nullptr); globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = @@ -744,22 +744,21 @@ void read_atomicdata_files() { int lowermost_ionstage = 0; int uppermost_ionstage = 0; int nlevelsmax_readin = 0; - double abundance{NAN}; + double uniformabundance{NAN}; // no longer in use mode for setting uniform abundances double mass_amu{NAN}; assert_always(compositiondata >> Z >> nions >> lowermost_ionstage >> uppermost_ionstage >> nlevelsmax_readin >> - abundance >> mass_amu); + uniformabundance >> mass_amu); printout("readin compositiondata: next element Z %d, nions %d, lowermost %d, uppermost %d, nlevelsmax %d\n", Z, nions, lowermost_ionstage, uppermost_ionstage, nlevelsmax_readin); assert_always(Z > 0); assert_always(nions >= 0); assert_always(nions == 0 || (nions == uppermost_ionstage - lowermost_ionstage + 1)); - assert_always(abundance >= 0); + assert_always(uniformabundance >= 0); assert_always(mass_amu >= 0); /// write this element's data to memory globals::elements[element].anumber = Z; globals::elements[element].nions = nions; - globals::elements[element].abundance = abundance; /// abundances are expected to be given by mass globals::elements[element].initstablemeannucmass = mass_amu * MH; globals::elements[element].uniqueionindexstart = uniqueionindex; @@ -1188,8 +1187,7 @@ void setup_cellcache() { // const int num_cellcache_slots = get_max_threads(); const int num_cellcache_slots = 1; - globals::cellcache = static_cast(malloc(num_cellcache_slots * sizeof(CellCache))); - assert_always(globals::cellcache != nullptr); + globals::cellcache.resize(num_cellcache_slots); for (int cellcachenum = 0; cellcachenum < num_cellcache_slots; cellcachenum++) { size_t mem_usage_cellcache = 0; @@ -1212,14 +1210,14 @@ void setup_cellcache() { assert_always(globals::cellcache[cellcachenum].chelements != nullptr); - size_t chlevelblocksize = 0; + size_t chlevelcount = 0; size_t chphixsblocksize = 0; int chtransblocksize = 0; for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); - chlevelblocksize += nlevels * sizeof(CellCacheLevels); + chlevelcount += nlevels; for (int level = 0; level < nlevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); @@ -1231,11 +1229,11 @@ void setup_cellcache() { } } } - assert_always(chlevelblocksize > 0); - globals::cellcache[cellcachenum].ch_all_levels = static_cast(malloc(chlevelblocksize)); + assert_always(chlevelcount > 0); + globals::cellcache[cellcachenum].ch_all_levels.resize(chlevelcount); chphixstargetsblock = chphixsblocksize > 0 ? static_cast(malloc(chphixsblocksize)) : nullptr; - mem_usage_cellcache += chlevelblocksize + chphixsblocksize; + mem_usage_cellcache += chlevelcount * sizeof(CellCacheLevels) + chphixsblocksize; mem_usage_cellcache += chtransblocksize * sizeof(double); double *const chtransblock = @@ -1260,31 +1258,31 @@ void setup_cellcache() { alllevelindex += nlevels; for (int level = 0; level < nlevels; level++) { - CellCacheLevels *chlevel = &globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level]; const int nphixstargets = get_nphixstargets(element, ion, level); - chlevel->chphixstargets = chphixsblocksize > 0 ? &chphixstargetsblock[allphixstargetindex] : nullptr; + globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].chphixstargets = + chphixsblocksize > 0 ? &chphixstargetsblock[allphixstargetindex] : nullptr; allphixstargetindex += nphixstargets; } for (int level = 0; level < nlevels; level++) { - CellCacheLevels *chlevel = &globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level]; const int ndowntrans = get_ndowntrans(element, ion, level); - chlevel->sum_epstrans_rad_deexc = &chtransblock[chtransindex]; + globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_epstrans_rad_deexc = + &chtransblock[chtransindex]; chtransindex += ndowntrans; } for (int level = 0; level < nlevels; level++) { - CellCacheLevels *chlevel = &globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level]; const int ndowntrans = get_ndowntrans(element, ion, level); - chlevel->sum_internal_down_same = &chtransblock[chtransindex]; + globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_internal_down_same = + &chtransblock[chtransindex]; chtransindex += ndowntrans; } for (int level = 0; level < nlevels; level++) { - CellCacheLevels *chlevel = &globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level]; const int nuptrans = get_nuptrans(element, ion, level); - chlevel->sum_internal_up_same = &chtransblock[chtransindex]; + globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_internal_up_same = + &chtransblock[chtransindex]; chtransindex += nuptrans; } } @@ -1292,8 +1290,7 @@ void setup_cellcache() { assert_always(chtransindex == chtransblocksize); assert_always(globals::nbfcontinua >= 0); - globals::cellcache[cellcachenum].ch_allcont_departureratios = - static_cast(malloc(globals::nbfcontinua * sizeof(double))); + globals::cellcache[cellcachenum].ch_allcont_departureratios.resize(globals::nbfcontinua); mem_usage_cellcache += globals::nbfcontinua * sizeof(double); printout("[info] mem_usage: cellcache for thread %d occupies %.3f MB\n", cellcachenum, @@ -1354,8 +1351,7 @@ void setup_phixs_list() { printout("[info] read_atomicdata: number of ground-level bfcontinua %d\n", globals::nbfcontinua_ground); if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::groundcont = static_cast(malloc(globals::nbfcontinua_ground * sizeof(GroundPhotoion))); - assert_always(globals::groundcont != nullptr); + globals::groundcont.resize(globals::nbfcontinua_ground); int groundcontindex = 0; for (int element = 0; element < get_nelements(); element++) { @@ -1376,8 +1372,7 @@ void setup_phixs_list() { } } assert_always(groundcontindex == globals::nbfcontinua_ground); - std::ranges::stable_sort(std::span(globals::groundcont, globals::nbfcontinua_ground), std::ranges::less{}, - &GroundPhotoion::nu_edge); + std::ranges::stable_sort(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); } auto *nonconstallcont = @@ -1391,11 +1386,11 @@ void setup_phixs_list() { for (int ion = 0; ion < nions - 1; ion++) { if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { globals::elements[element].ions[ion].groundcontindex = - static_cast(std::find_if(globals::groundcont, globals::groundcont + globals::nbfcontinua_ground, - [=](const auto &groundcont) { - return (groundcont.element == element) && (groundcont.ion == ion); - }) - - globals::groundcont); + static_cast(std::ranges::find_if(globals::groundcont, + [=](const auto &groundcont) { + return (groundcont.element == element) && (groundcont.ion == ion); + }) - + globals::groundcont.begin()); if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { globals::elements[element].ions[ion].groundcontindex = -1; } @@ -1523,11 +1518,8 @@ void read_atomicdata() { /// INITIALISE THE ABSORPTION/EMISSION COUNTERS ARRAYS if constexpr (RECORD_LINESTAT) { - globals::ecounter = static_cast(malloc(globals::nlines * sizeof(int))); - assert_always(globals::ecounter != nullptr); - - globals::acounter = static_cast(malloc(globals::nlines * sizeof(int))); - assert_always(globals::acounter != nullptr); + globals::ecounter.resize(globals::nlines); + globals::acounter.resize(globals::nlines); } kpkt::setup_coolinglist(); diff --git a/kpkt.cc b/kpkt.cc index a3283a804..6c890263b 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include "artisoptions.h" #include "atomic.h" @@ -21,6 +22,7 @@ #include "thermalbalance.h" #include "vectors.h" #include "vpkt.h" + namespace kpkt { namespace { @@ -38,7 +40,7 @@ struct CellCacheCoolingList { int upperlevel; }; -CellCacheCoolingList *coolinglist; +std::vector coolinglist; int n_kpktdiffusion_timesteps{0}; float kpktdiffusion_timescale{0.}; @@ -270,22 +272,17 @@ void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heat double C_fb_all = 0.; /// free-bound creation of rpkt double C_exc_all = 0.; /// collisional excitation of macroatoms double C_ionization_all = 0.; /// collisional ionisation of macroatoms - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion] = calculate_cooling_rates_ion( - modelgridindex, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, &C_exc_all, &C_ionization_all); - } + for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { + const auto [element, ion] = get_ionfromuniqueionindex(allionindex); + grid::modelgrid[modelgridindex].ion_cooling_contribs[allionindex] = calculate_cooling_rates_ion( + modelgridindex, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, &C_exc_all, &C_ionization_all); } // this loop is made separate for future parallelisation of upper loop. // the ion contributions must be added in this exact order double C_total = 0.; - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - C_total += grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]; - } + for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { + C_total += grid::modelgrid[modelgridindex].ion_cooling_contribs[allionindex]; } grid::modelgrid[modelgridindex].totalcooling = C_total; @@ -316,7 +313,7 @@ void setup_coolinglist() { set_ncoolingterms(); const size_t mem_usage_coolinglist = ncoolingterms * sizeof(CellCacheCoolingList); assert_always(ncoolingterms > 0); - coolinglist = static_cast(malloc(ncoolingterms * sizeof(CellCacheCoolingList))); + coolinglist.resize(ncoolingterms); printout("[info] mem_usage: coolinglist occupies %.3f MB\n", mem_usage_coolinglist / 1024. / 1024.); int i = 0; // cooling list index @@ -448,7 +445,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) for (element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (ion = 0; ion < nions; ion++) { - coolingsum += grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]; + const int uniqueionindex = get_uniqueionindex(element, ion); + coolingsum += grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]; // printout("Z=%d, ionstage %d, coolingsum %g\n", get_atomicnumber(element), get_ionstage(element, ion), // coolingsum); if (coolingsum > rndcool_ion) { @@ -470,8 +468,9 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) for (element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (ion = 0; ion < nions; ion++) { + const int uniqueionindex = get_uniqueionindex(element, ion); printout("do_kpkt: element %d, ion %d, coolingcontr %g\n", element, ion, - grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]); + grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]); } } std::abort(); @@ -487,8 +486,10 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) // modelgridindex, element, ion, ilow, high, oldcoolingsum); C_ion_procsum = calculate_cooling_rates_ion(modelgridindex, element, ion, ilow, cellcacheslotid, nullptr, nullptr, nullptr, nullptr); - assert_testmodeonly((std::fabs(C_ion_procsum - grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]) / - C_ion_procsum) < 1e-3); + assert_testmodeonly( + (std::fabs(C_ion_procsum - + grid::modelgrid[modelgridindex].ion_cooling_contribs[get_uniqueionindex(element, ion)]) / + C_ion_procsum) < 1e-3); } // with the ion selected, we now select a level and transition type diff --git a/ltepop.cc b/ltepop.cc index 41fef45ca..9e4321987 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -23,7 +23,7 @@ namespace { -struct nne_solution_paras { +struct nneSolutionParas { int modelgridindex; bool force_lte; }; @@ -48,8 +48,9 @@ auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const d auto phi_lte(const int element, const int ion, const int modelgridindex) -> double { // use Saha equation for LTE ionization balance - auto partfunc_ion = grid::modelgrid[modelgridindex].composition[element].partfunct[ion]; - auto partfunc_upperion = grid::modelgrid[modelgridindex].composition[element].partfunct[ion + 1]; + const int uniqueionindex = get_uniqueionindex(element, ion); + auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; + auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; const auto T_e = grid::get_Te(modelgridindex); const double ionpot = epsilon(element, ion + 1, 0) - epsilon(element, ion, 0); @@ -70,8 +71,9 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, assert_testmodeonly(!elem_has_nlte_levels(element)); // don't use this function if the NLTE solver is active - auto partfunc_ion = grid::modelgrid[modelgridindex].composition[element].partfunct[ion]; - auto partfunc_upperion = grid::modelgrid[modelgridindex].composition[element].partfunct[ion + 1]; + const int uniqueionindex = get_uniqueionindex(element, ion); + auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; + auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; const auto T_e = grid::get_Te(modelgridindex); @@ -86,8 +88,8 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const double Gamma_ion = Gamma * stat_weight(element, ion, 0) / partfunc_ion; if (Gamma == 0. && (!NT_ON || (globals::dep_estimator_gamma[nonemptymgi] == 0. && - grid::get_modelinitradioabund(modelgridindex, decay::get_nucindex(24, 48)) == 0. && - grid::get_modelinitradioabund(modelgridindex, decay::get_nucindex(28, 56)) == 0.))) { + grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(24, 48)) == 0. && + grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(28, 56)) == 0.))) { printout("Fatal: Gamma = 0 for element %d, ion %d in phi ... abort\n", element, ion); std::abort(); } @@ -141,7 +143,7 @@ auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double // assume a value for nne and then calculate the resulting nne // the difference between the assumed and calculated nne is returned { - const auto *paras = static_cast(voidparas); + const auto *paras = static_cast(voidparas); const int modelgridindex = paras->modelgridindex; const bool force_lte = paras->force_lte; @@ -245,7 +247,8 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); double pop_store{NAN}; - // double E_level, E_ground, test; + + const int uniqueionindex = get_uniqueionindex(element, ion); bool initial = false; if (get_groundlevelpop(modelgridindex, element, ion) < MINPOP) { @@ -254,7 +257,7 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin // of groundlevelpop for this calculation doesn't matter, so long as it's not zero! pop_store = get_groundlevelpop(modelgridindex, element, ion); initial = true; - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = 1.; + grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = 1.; } double U = 1.; @@ -278,7 +281,7 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin if (initial) { // put back the zero, just in case it matters for something - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = pop_store; + grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = pop_store; } return U; @@ -302,8 +305,8 @@ auto find_uppermost_ion(const int modelgridindex, const int element, const doubl for (int ion = 0; ion < nions - 1; ion++) { if (iongamma_is_zero(nonemptymgi, element, ion) && (!NT_ON || ((globals::dep_estimator_gamma[nonemptymgi] == 0.) && - (grid::get_modelinitradioabund(modelgridindex, decay::get_nucindex(24, 48)) == 0.) && - (grid::get_modelinitradioabund(modelgridindex, decay::get_nucindex(28, 56)) == 0.)))) { + (grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(24, 48)) == 0.) && + (grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(28, 56)) == 0.)))) { uppermost_ion = ion; break; } @@ -348,6 +351,7 @@ void set_groundlevelpops_neutral(const int modelgridindex) { const int nions = get_nions(element); /// Assign the species population to the neutral ion and set higher ions to MINPOP for (int ion = 0; ion < nions; ion++) { + const int uniqueionindex = get_uniqueionindex(element, ion); double nnion{NAN}; if (ion == 0) { nnion = nnelement; @@ -357,9 +361,9 @@ void set_groundlevelpops_neutral(const int modelgridindex) { nnion = 0.; } const double groundpop = - (nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].composition[element].partfunct[ion]); + (nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]); - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = groundpop; + grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = groundpop; } } } @@ -367,7 +371,7 @@ void set_groundlevelpops_neutral(const int modelgridindex) { auto find_converged_nne(const int modelgridindex, double nne_hi, const bool force_lte) -> float { /// Search solution for nne in [nne_lo,nne_hi] - nne_solution_paras paras = {.modelgridindex = modelgridindex, .force_lte = force_lte}; + nneSolutionParas paras = {.modelgridindex = modelgridindex, .force_lte = force_lte}; gsl_function f = {.function = &nne_solution_f, .params = ¶s}; double nne_lo = 0.; // MINPOP; @@ -472,7 +476,7 @@ auto get_groundlevelpop(const int modelgridindex, const int element, const int i assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); - const double nn = grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion]; + const double nn = grid::modelgrid[modelgridindex].ion_groundlevelpops[get_uniqueionindex(element, ion)]; if (nn < MINPOP) { if (grid::get_elem_abundance(modelgridindex, element) > 0) { return MINPOP; @@ -545,7 +549,7 @@ void calculate_cellpartfuncts(const int modelgridindex, const int element) /// this saves a factor 10 in calculation time of Saha-Boltzman populations const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - grid::modelgrid[modelgridindex].composition[element].partfunct[ion] = + grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] = calculate_partfunct(element, ion, modelgridindex); } } @@ -573,7 +577,8 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co /// Use the ground level population and partition function to get an ion population { return get_groundlevelpop(modelgridindex, element, ion) * - grid::modelgrid[modelgridindex].composition[element].partfunct[ion] / stat_weight(element, ion, 0); + grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] / + stat_weight(element, ion, 0); } void set_groundlevelpops(const int modelgridindex, const int element, const float nne, const bool force_lte) { @@ -597,6 +602,7 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa /// Use ion fractions to calculate the groundlevel populations for (int ion = 0; ion < nions; ion++) { + const int uniqueionindex = get_uniqueionindex(element, ion); double nnion{NAN}; if (ion <= uppermost_ion) { if (nnelement > 0) { @@ -609,13 +615,13 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa } const double groundpop = - nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].composition[element].partfunct[ion]; + nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; if (!std::isfinite(groundpop)) { printout("[warning] calculate_ion_balance_nne: groundlevelpop infinite in connection with MINPOP\n"); } - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = groundpop; + grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = groundpop; } } diff --git a/nltepop.cc b/nltepop.cc index e92182e24..3afc829bc 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -823,7 +823,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const "nnelement %.2e cm^-3)\n", modelgridindex, timestep, nlte_iter, atomic_number, grid::get_elem_abundance(modelgridindex, element), nnelement); - auto superlevel_partfunc = std::vector(nions) = get_element_superlevelpartfuncs(modelgridindex, element); + const auto superlevel_partfunc = get_element_superlevelpartfuncs(modelgridindex, element); const int nlte_dimension = get_element_nlte_dimension(element); // printout("NLTE: the vector dimension is %d", nlte_dimension); @@ -996,7 +996,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } // store the ground level population - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion] = gsl_vector_get(popvec, index_gs); + grid::modelgrid[modelgridindex].ion_groundlevelpops[get_uniqueionindex(element, ion)] = + gsl_vector_get(popvec, index_gs); // solution_ion_pop += gsl_vector_get(popvec, index_gs); calculate_cellpartfuncts(modelgridindex, element); @@ -1172,10 +1173,11 @@ void nltepop_write_restart_data(FILE *restart_file) { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { + const int uniqueionindex = get_uniqueionindex(element, ion); fprintf(restart_file, "%d %a %a %la\n", ion, - grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion], - grid::modelgrid[modelgridindex].composition[element].partfunct[ion], - grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]); + grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex], + grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex], + grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]); } } for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { @@ -1215,10 +1217,11 @@ void nltepop_read_restart_data(FILE *restart_file) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { int ion_in = 0; + const int uniqueionindex = get_uniqueionindex(element, ion); assert_always(fscanf(restart_file, "%d %a %a %la\n", &ion_in, - &grid::modelgrid[modelgridindex].composition[element].groundlevelpop[ion], - &grid::modelgrid[modelgridindex].composition[element].partfunct[ion], - &grid::modelgrid[modelgridindex].cooling_contrib_ion[element][ion]) == 4); + &grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex], + &grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex], + &grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]) == 4); if (ion_in != ion) { printout("ERROR: expected data for ion %d but found ion %d\n", ion, ion_in); std::abort(); diff --git a/ratecoeff.cc b/ratecoeff.cc index d7f168ac3..71cd356e9 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -675,9 +675,9 @@ void precalculate_ion_alpha_sp() { } } -auto integrand_stimrecombination_custom_radfield(const double nu, void *voidparas) -> double { +auto integrand_stimrecombination_custom_radfield(const double nu, void *const voidparas) -> double { { - const gsl_integral_paras_gammacorr *const params = static_cast(voidparas); + const auto *const params = static_cast(voidparas); const int modelgridindex = params->modelgridindex; const float T_e = params->T_e; diff --git a/rpkt.cc b/rpkt.cc index ac5a664c2..3943eb5d7 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -1054,10 +1054,10 @@ void allocate_expansionopacities() { static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(double))); } #endif - expansionopacities = std::span{expansionopacities_data, static_cast(npts_nonempty * expopac_nbins)}; - expansionopacity_planck_cumulative = std::span{ - expansionopacity_planck_cumulative_data, - static_cast(expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins)}; + expansionopacities = std::span(expansionopacities_data, npts_nonempty * expopac_nbins); + expansionopacity_planck_cumulative = + std::span(expansionopacity_planck_cumulative_data, + expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins); } __host__ __device__ auto closest_transition(const double nu_cmf, const int next_trans) -> int diff --git a/sn3d.cc b/sn3d.cc index 5d041d074..3a28a28ed 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -241,8 +241,8 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const nonthermal::nt_MPI_Bcast(modelgridindex, root, my_rank); if (globals::total_nlte_levels > 0 && globals::rank_in_node == 0) { - MPI_Bcast(grid::modelgrid[modelgridindex].nlte_pops, globals::total_nlte_levels, MPI_DOUBLE, root_node_id, - globals::mpi_comm_internode); + MPI_Bcast(grid::modelgrid[modelgridindex].nlte_pops.data(), globals::total_nlte_levels, MPI_DOUBLE, + root_node_id, globals::mpi_comm_internode); } if (USE_LUT_PHOTOION && globals::nbfcontinua_ground > 0) { @@ -255,8 +255,7 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_Barrier(MPI_COMM_WORLD); - assert_always(globals::gammaestimator != nullptr); - MPI_Bcast(globals::gammaestimator + (nonemptymgi * globals::nbfcontinua_ground), globals::nbfcontinua_ground, + MPI_Bcast(&globals::gammaestimator[nonemptymgi * globals::nbfcontinua_ground], globals::nbfcontinua_ground, MPI_DOUBLE, root, MPI_COMM_WORLD); } @@ -297,16 +296,12 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_SHORT, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - for (int element = 0; element < get_nelements(); element++) { - if (get_nions(element) > 0) { - MPI_Pack(grid::modelgrid[mgi].composition[element].groundlevelpop, get_nions(element), MPI_FLOAT, - mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].composition[element].partfunct, get_nions(element), MPI_FLOAT, - mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].cooling_contrib_ion[element], get_nions(element), MPI_DOUBLE, - mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - } - } + MPI_Pack(grid::modelgrid[mgi].ion_groundlevelpops, get_includedions(), MPI_FLOAT, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack(grid::modelgrid[mgi].ion_partfuncts, get_includedions(), MPI_FLOAT, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack(grid::modelgrid[mgi].ion_cooling_contribs, get_includedions(), MPI_DOUBLE, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); } } printout("[info] mem_usage: MPI_BUFFER: used %d of %zu bytes allocated to mpi_grid_buffer\n", position, @@ -346,19 +341,12 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_SHORT, MPI_COMM_WORLD); - for (int element = 0; element < get_nelements(); element++) { - if (get_nions(element) > 0) { - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, - grid::modelgrid[mgi].composition[element].groundlevelpop, get_nions(element), MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, - grid::modelgrid[mgi].composition[element].partfunct, get_nions(element), MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, - grid::modelgrid[mgi].cooling_contrib_ion[element], get_nions(element), MPI_DOUBLE, - MPI_COMM_WORLD); - } - } + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_groundlevelpops, + get_includedions(), MPI_FLOAT, MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_partfuncts, + get_includedions(), MPI_FLOAT, MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_cooling_contribs, + get_includedions(), MPI_DOUBLE, MPI_COMM_WORLD); } } } @@ -369,32 +357,36 @@ void mpi_reduce_estimators(int nts) { const int nonempty_npts_model = grid::get_nonempty_npts_model(); radfield::reduce_estimators(); MPI_Barrier(MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, globals::ffheatingestimator, nonempty_npts_model, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, globals::colheatingestimator, nonempty_npts_model, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + assert_always(!globals::ffheatingestimator.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::ffheatingestimator.data(), globals::ffheatingestimator.size(), MPI_DOUBLE, + MPI_SUM, MPI_COMM_WORLD); + assert_always(!globals::colheatingestimator.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::colheatingestimator.data(), globals::colheatingestimator.size(), MPI_DOUBLE, + MPI_SUM, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); if (globals::nbfcontinua_ground > 0) { if constexpr (USE_LUT_PHOTOION) { MPI_Barrier(MPI_COMM_WORLD); - assert_always(globals::gammaestimator != nullptr); - MPI_Allreduce(MPI_IN_PLACE, globals::gammaestimator, nonempty_npts_model * globals::nbfcontinua_ground, - MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + assert_always(!globals::gammaestimator.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::gammaestimator.data(), globals::gammaestimator.size(), MPI_DOUBLE, MPI_SUM, + MPI_COMM_WORLD); } if constexpr (USE_LUT_BFHEATING) { MPI_Barrier(MPI_COMM_WORLD); - assert_always(globals::bfheatingestimator != nullptr); - MPI_Allreduce(MPI_IN_PLACE, globals::bfheatingestimator, nonempty_npts_model * globals::nbfcontinua_ground, + assert_always(!globals::bfheatingestimator.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::bfheatingestimator.data(), nonempty_npts_model * globals::nbfcontinua_ground, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); } } if constexpr (RECORD_LINESTAT) { MPI_Barrier(MPI_COMM_WORLD); - assert_always(globals::ecounter != nullptr); - MPI_Allreduce(MPI_IN_PLACE, globals::ecounter, globals::nlines, MPI_INT, MPI_SUM, MPI_COMM_WORLD); - assert_always(globals::acounter != nullptr); - MPI_Allreduce(MPI_IN_PLACE, globals::acounter, globals::nlines, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + assert_always(!globals::ecounter.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::ecounter.data(), globals::ecounter.size(), MPI_INT, MPI_SUM, MPI_COMM_WORLD); + assert_always(!globals::acounter.empty()); + MPI_Allreduce(MPI_IN_PLACE, globals::acounter.data(), globals::acounter.size(), MPI_INT, MPI_SUM, MPI_COMM_WORLD); } assert_always(static_cast(globals::dep_estimator_gamma.size()) == nonempty_npts_model); @@ -607,19 +599,19 @@ void zero_estimators() { } } - std::fill_n(globals::ffheatingestimator, grid::get_nonempty_npts_model(), 0.); - std::fill_n(globals::colheatingestimator, grid::get_nonempty_npts_model(), 0.); + std::ranges::fill(globals::ffheatingestimator, 0.); + std::ranges::fill(globals::colheatingestimator, 0.); std::ranges::fill(globals::dep_estimator_gamma, 0.); if constexpr (USE_LUT_PHOTOION) { if (globals::nbfcontinua_ground > 0) { - std::fill_n(globals::gammaestimator, grid::get_nonempty_npts_model() * globals::nbfcontinua_ground, 0.); + std::ranges::fill(globals::gammaestimator, 0.); } } if constexpr (USE_LUT_BFHEATING) { if (globals::nbfcontinua_ground > 0) { - std::fill_n(globals::bfheatingestimator, grid::get_nonempty_npts_model() * globals::nbfcontinua_ground, 0.); + std::ranges::fill(globals::bfheatingestimator, 0.); } } diff --git a/update_grid.cc b/update_grid.cc index 5458b50a1..4c9f6b977 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1062,17 +1062,13 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // cooling rates calculation can be skipped for thick cells // flag with negative numbers to indicate that the rates are invalid grid::modelgrid[mgi].totalcooling = -1.; - const int element = 0; - const int ion = 0; - grid::modelgrid[mgi].cooling_contrib_ion[element][ion] = -1.; + grid::modelgrid[mgi].ion_cooling_contribs[0] = -1.; } else if (globals::simulation_continued_from_saved && nts == globals::timestep_initial) { // cooling rates were read from the gridsave file for this timestep // make sure they are valid printout("cooling rates read from gridsave file for timestep %d cell %d...", nts, mgi); assert_always(grid::modelgrid[mgi].totalcooling >= 0.); - const int element = 0; - const int ion = 0; - assert_always(grid::modelgrid[mgi].cooling_contrib_ion[element][ion] >= 0.); + assert_always(grid::modelgrid[mgi].ion_cooling_contribs[0] >= 0.); } else { /// Cooling rates depend only on cell properties, precalculate total cooling /// and ion contributions inside update grid and communicate between MPI tasks @@ -1255,6 +1251,6 @@ void cellcache_change_cell(const int modelgridindex) { } if (modelgridindex >= 0) { - std::fill_n(globals::cellcache[cellcacheslotid].ch_allcont_departureratios, globals::nbfcontinua, -1); + std::ranges::fill(globals::cellcache[cellcacheslotid].ch_allcont_departureratios, -1.); } } diff --git a/vpkt.cc b/vpkt.cc index 34f097a10..17a881d50 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -24,19 +24,19 @@ namespace { -struct stokeparams { +struct StokesParams { double i = 0.; double q = 0.; double u = 0.; }; struct VSpecPol { - stokeparams flux[VMNUBINS]; + StokesParams flux[VMNUBINS]; float lower_time{NAN}; float delta_t{NAN}; }; -VSpecPol **vspecpol{}; +std::vector> vspecpol{}; float lower_freq_vspec[VMNUBINS]; float delta_freq_vspec[VMNUBINS]; @@ -427,11 +427,11 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar } void init_vspecpol() { - vspecpol = static_cast(malloc(VMTBINS * sizeof(VSpecPol *))); + vspecpol.resize(VMTBINS); const int indexmax = Nspectra * Nobs; for (int p = 0; p < VMTBINS; p++) { - vspecpol[p] = static_cast(malloc(indexmax * sizeof(VSpecPol))); + vspecpol[p].resize(indexmax); } dlogt_vspec = (log(VSPEC_TIMEMAX) - log(VSPEC_TIMEMIN)) / VMTBINS; @@ -566,9 +566,9 @@ void init_vpkt_grid() { vgrid_q[n][m].flux.resize(Nrange_grid, {}); vgrid_u[n][m].flux.resize(Nrange_grid, {}); for (int wlbin = 0; wlbin < Nrange_grid; wlbin++) { - vgrid_i[n][m].flux[wlbin] = std::vector(Nobs, 0.); - vgrid_q[n][m].flux[wlbin] = std::vector(Nobs, 0.); - vgrid_u[n][m].flux[wlbin] = std::vector(Nobs, 0.); + vgrid_i[n][m].flux[wlbin].resize(Nobs, 0.); + vgrid_q[n][m].flux[wlbin].resize(Nobs, 0.); + vgrid_u[n][m].flux[wlbin].resize(Nobs, 0.); } } } From 1b668896ab9478dde7f999f0421948e9c3002e11 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 16 Aug 2024 11:30:09 +0100 Subject: [PATCH 017/117] Communicate elemental abundance updates between ranks (#105) Elemental abundances are set to the snapshot values for all ranks on startup. The elemental abundance changes due to radioactive decays for each cell are calculated by one of the ranks, and then not propagated to all ranks before packet propagation. The elemental mass fractions were not used in many places (the ion and level populations were based on the correct updated elemental abundances and communicated), but do get checked for being either zero or greater than zero for certain features, which could be important with elemental abundances of zero the input snapshot that become non-zero due to radioactive decays. Consequences: - A zero abundance check will disable detailed bound-free estimator accumulation on all but one rank if the initial abundance is 0.0 while the true abundance is >0. - For small ( int { /// Initialise the exchange buffer /// The factor 4 comes from the fact that our buffer should contain elements of 4 byte /// instead of 1 byte chars. But the MPI routines don't care about the buffers datatype - mpi_grid_buffer_size = 4 * ((12 + 4 * get_includedions()) * (maxndo) + 1); + mpi_grid_buffer_size = 4 * ((12 + 4 * get_includedions() + get_nelements()) * (maxndo) + 1); printout("reserve mpi_grid_buffer_size %zu space for MPI communication buffer\n", mpi_grid_buffer_size); mpi_grid_buffer = static_cast(malloc(mpi_grid_buffer_size * sizeof(char))); assert_always(mpi_grid_buffer != nullptr); diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index 6cd761e8c..7e0e4cf37 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -73a673c95bc1593acf754f8c02d5f804 absorption.out -57ebd62f64cc92da4d9365e72a4cef02 absorption_res_00.out -f1ee522d66760fdbd7750d2a5a965e19 absorption_res_01.out -3a2c509fe14035475f328b2cb4f5fb22 absorption_res_02.out -a54bd0b5675a814bd967f49092e16977 absorption_res_03.out -9ecac20f93d03365cd1f4cc52a7c1c92 absorption_res_04.out -9cbff5c61d786150f9f7ef8b8d6c22e5 absorption_res_05.out -8b54a9338e668439b48b73b52bb65fa5 absorption_res_06.out -e4d4a8ecc64c5d4be7368d423133e30b absorption_res_07.out -c2ea4361964c3bb571f4f29ef09cc99d absorption_res_08.out -f9b2376726cea600c5a8fbad943e538c absorption_res_09.out -1a4106001d5bcf2bec6a9d85d57d67b8 absorption_res_10.out -dd74853a68c5fa001b4615de62ef8a21 absorption_res_11.out -4a7cdd84ee7e0af239e5135e556da5f3 absorption_res_12.out -eb6186e5894f216875c2040d841264cf absorption_res_13.out -a69081647d5a3c2ce325c4d0d18ca37e absorption_res_14.out -0a26f7d72b90c9a1e57b5133bc973c77 absorption_res_15.out -27d8a7eec6a0c89963d4b51f7deb7ac1 absorption_res_16.out -09b2edb0585b874f9cfdb179b29663a1 absorption_res_17.out -04aba6c7d08a79cbb4e302804b161510 absorption_res_18.out -33bc33d96239de005d7c3cfa08b96c63 absorption_res_19.out -de1dabfab78e0f8fc864d1c4e09763fe absorption_res_20.out -59f4ddbb66da30788727163d327689be absorption_res_21.out -f2f1d5ae8e7794322ae81c893e4c2fcb absorption_res_22.out -3989afdd8d8ba08570bb91293d5fc5c4 absorption_res_23.out -b5ac821ba8ce67d5063d39e6e29ddec9 absorption_res_24.out -593f4b4dc3d97dbe242cb09a4a252247 absorption_res_25.out -e280959170dfe29c2a23a073d41cd6b3 absorption_res_26.out -00461795b3290287ea08b8b9d94652c3 absorption_res_27.out -dab473f749a02a43da4f154ead02208f absorption_res_28.out -68d85e1c70bf91fb6644c65319581e59 absorption_res_29.out -8a0218da2d5f1122d9f3da6e106e6843 absorption_res_30.out -1ef38a581462854e16af7070a7f95ff4 absorption_res_31.out -17e7e1f36203baf2651df1495e716150 absorption_res_32.out -65a8bb2d01fb3ebef14b6bf94365a255 absorption_res_33.out -21e897eecf1917fc6ceb874df0d3a91d absorption_res_34.out -d372647e5dc5f4a5dc1bfc62efad89c8 absorption_res_35.out -d1e2c0418a30e80e23e42de37cb6434c absorption_res_36.out -80309c3af967cc07549da2c1f96e75b9 absorption_res_37.out -60664f1bdb7d28ecbc628163415a285c absorption_res_38.out -c23ee8bff6a8978a12105de73bec938d absorption_res_39.out -12092e986abc49007b04289344450b49 absorption_res_40.out -2e0de564ae95bd949bc134811f8b20f7 absorption_res_41.out -3a5339fa61291f37df739f2729828789 absorption_res_42.out -7c7b1be72341a97ea9d6452b237e85b7 absorption_res_43.out -9a2bcc3fa42243d268e997937ec18510 absorption_res_44.out -1bca72c8d90c67166e05944099934044 absorption_res_45.out -5e0a05afb3cca622ec47fa691cf83c6d absorption_res_46.out -0c6de37d2bcacb094f872b8723b93576 absorption_res_47.out -fe5274e09314a5da209db679e737a770 absorption_res_48.out -df6a4f41b7be822b3e35997dce6cf47c absorption_res_49.out -361f8b68d2e17599efc69d6894083dba absorption_res_50.out -229784d71bd4be4b9d2d67d5f5b4c376 absorption_res_51.out -8ddf2b1a21c324f975af093bd82e0343 absorption_res_52.out -6b203ed1ce84a5b06337bbfa5112bffc absorption_res_53.out -6954c457db66a5a772304b07228a44e3 absorption_res_54.out -35e84f36e34a50db3227ea4d559155bf absorption_res_55.out -e77555fa98a6d42d6107d5a99767f159 absorption_res_56.out -a264f44109fc87fd9ec615c0b8b90fd0 absorption_res_57.out -fa44b80d9405d03c80e7db71bec14176 absorption_res_58.out -253cb3daaf06e15a1dca09ff2f83a50a absorption_res_59.out -213531480ef9d40a06642f52563ac292 absorption_res_60.out -8de6412aad4785fe752086ce4b19a7aa absorption_res_61.out -a06c903aef091949c46c41d344956da1 absorption_res_62.out -5527f6bd82ea723fe06a18f76e7b0ac1 absorption_res_63.out -4880765d17fd504800f2ba00f8273f85 absorption_res_64.out -5c261b53c267fb9f73a366fb3916081c absorption_res_65.out -453ae7c71d3836ef8108680aeb55e803 absorption_res_66.out -f732fd1ea044593db37d3a821e016d1f absorption_res_67.out -875337d140097d998c4feebe0471319f absorption_res_68.out -70c20ea58ec9eb737728d3b1f37416d4 absorption_res_69.out -4ec9e532652eff5f1dfd05d30ec5ed72 absorption_res_70.out -1e99d7c2bfd984f21470a25f6091f894 absorption_res_71.out -ecd129c3affb789b4cd61952750f2781 absorption_res_72.out -1e00770b3bdf563c43cd8dceaf1b12b5 absorption_res_73.out -9ec60deda551bc05289d3bf0ee21c6b4 absorption_res_74.out -883f4743717f70167163e7abeb68e1fc absorption_res_75.out -8f0a92889b24bae7079ab65986002332 absorption_res_76.out -c5c599348784446068da2fbef3d977a3 absorption_res_77.out -3e04db75fab41b3c68b7697cd521ce9d absorption_res_78.out -24cb6b352c72c70597c1b931307a9db9 absorption_res_79.out -66f9049c225b6cc53356e4669717e705 absorption_res_80.out -e786ed288df32e02061b067585469f32 absorption_res_81.out -baf8ac891bbf60fbc6083512b2340782 absorption_res_82.out -863ab3fea004f0f95655f42fe6e5d9d0 absorption_res_83.out -716d303ae352fbeba7ce0106168ac8cf absorption_res_84.out -7824b85365510a8fe2e287228d67cb3f absorption_res_85.out -dfd47ca581c86f3535499f20c12bc97d absorption_res_86.out -84ff2e9aed4055e27fc47f15856457d6 absorption_res_87.out -b6df8f98364a6c37a9694d84965a30fd absorption_res_88.out -11c991824633f02a47191a47fc4dd1a6 absorption_res_89.out -a57e222288ca56cd5f45716c26780ed2 absorption_res_90.out -170a20d3fff79527e8eb0e18fc9073ea absorption_res_91.out -5cbf4ebc576bede07378709f508cebd2 absorption_res_92.out -5a18d5ac96dfeae71259e187cb16b3fd absorption_res_93.out -9be8f0efb3c7fb8ebb054aeacceb1430 absorption_res_94.out -7406bd1b4e70cab14c368d4b6e91c6f0 absorption_res_95.out -d0687a0a05583b02f6ea54755049cfbe absorption_res_96.out -b0e4aa5c8cf52271ce96a49b3fbeeeab absorption_res_97.out -fe3db3c1e4aa70b0e4b34331d91d2051 absorption_res_98.out -cf414873dbea6dd809c3c215120f6110 absorption_res_99.out +2e7b663f164bdd72fe716b7d135750ef absorption.out +6ecf11a47a87cad40b429e9338b734bd absorption_res_00.out +6407a4a3b29ab902bebd654a7b7c3c68 absorption_res_01.out +bb5ed8764e5e2eed5ebd6071b9375f42 absorption_res_02.out +22a8dd64be413bd1664b7eded2386c8d absorption_res_03.out +116fdd38a2e04fcff3935a05aed76a4f absorption_res_04.out +67e4c15ccd610ddf68e464c636b6cad2 absorption_res_05.out +e9875f312fdce351e061fc174176390c absorption_res_06.out +88a0ed55f55e89791e7762a857e018a5 absorption_res_07.out +43eb1eca351d728939fb69ff495b4117 absorption_res_08.out +07fe46786a77629f4dd2db0c3fa640eb absorption_res_09.out +53d09b154b5a73bf5c98dca3fdc85983 absorption_res_10.out +40662db2a132755d8364a7fbc0cdd9fa absorption_res_11.out +d6d650b29413712984316bd91a33e6be absorption_res_12.out +8f9c1f752cbf7ca70c6bbecfd8017915 absorption_res_13.out +5e360d40e941279f1437e1eda46b8ea1 absorption_res_14.out +7f745061478c02fc1a5a8379f47306ce absorption_res_15.out +568faae2e909c096c890c112a7aa40d2 absorption_res_16.out +f7ae8820520f4b742111071957058b39 absorption_res_17.out +e085e3cc6fe466427026168727c933b9 absorption_res_18.out +10b1e73f5cfaeddafa84ae606c7aa8cd absorption_res_19.out +938e38d23771034e6e09d0130daaabe6 absorption_res_20.out +1faff481aca7b77a38b67de3ddc627c0 absorption_res_21.out +c21d82c2ebd6b760168b43167324c231 absorption_res_22.out +91040148a57801904d696f1adfba6f3d absorption_res_23.out +1af98527fecd5422b2963167c9bc4da0 absorption_res_24.out +2d7a408af3d3278764d2a62eb961ede7 absorption_res_25.out +790d6f70af8287223d67e4b81c0b7e60 absorption_res_26.out +ea785cb54e989aa9a8d66fc8fae6de9c absorption_res_27.out +6c7e1434d3d82059b9c99d2dcdb03458 absorption_res_28.out +01749ddb5eec5e2e880990cddce44cd2 absorption_res_29.out +05810c3ad79fc0cfebf5f2e91e441811 absorption_res_30.out +b5b61e79f1e08db8b532fc03bc1adad6 absorption_res_31.out +8f88b3d35c682e706982acfe2df41168 absorption_res_32.out +28f7bf92f6d4c9bd7753febeebb08478 absorption_res_33.out +860979413f2ef4a30705e283046f7b06 absorption_res_34.out +c44951d480a759207cf11d7de48bf1ec absorption_res_35.out +07d960e109e8f9716c41e1e25699b50e absorption_res_36.out +9c62d1b053f08ac57552e726e9d4741e absorption_res_37.out +96eca3daa261eda6ca3e5a0ee849b3a5 absorption_res_38.out +1cf4f88396dbeb183425e4b6d6361c5c absorption_res_39.out +46cb681361080900802d742706a2275e absorption_res_40.out +07e02c06d0a417ee0a5cff195e85bb59 absorption_res_41.out +07c5f65abf0eed12c47a356addaab54c absorption_res_42.out +42ebe5b9861cae4c9a1b576db4522659 absorption_res_43.out +0f96a678990a026c2fe90fc00cd20789 absorption_res_44.out +8b321c3f8fd79b76174caf6c3828eeaf absorption_res_45.out +f763d23d48ed0e81d9bdd3704894994f absorption_res_46.out +bc52d9d599fcbb19a720c0946d1436ef absorption_res_47.out +001db24cc0e6c404ad00ae45d412e59c absorption_res_48.out +c37dd834cff3259a5be3549bdfee9a25 absorption_res_49.out +44456faf931e883398319edb172652f3 absorption_res_50.out +7056ac2e8d893cd1ad030a4bb49362e3 absorption_res_51.out +2da4499b204de7b2211779243c6b6775 absorption_res_52.out +795c43851b2a6d42a803de2fd7851ce1 absorption_res_53.out +d24bbb846487a1464a2861a6ff8b8016 absorption_res_54.out +28aacc2c2e23c2acdde412d52942a8b5 absorption_res_55.out +fe409acc060f0d87073cd51ab4b6c5d3 absorption_res_56.out +1fbba6029ccd64bf2c80fd9131056c90 absorption_res_57.out +352a79d31035ee042eccb8e6181d9150 absorption_res_58.out +f6c9751ed3b232b7aa2983dacdf19aec absorption_res_59.out +8feab73450c286589bd18b967fc26437 absorption_res_60.out +e617a6576a411f7a93287f4402514f18 absorption_res_61.out +20f3ebe500b107629adcaaedf9250301 absorption_res_62.out +798c0fb74f4e4a6f3ffa3820ff9e4c17 absorption_res_63.out +78d566eb62fdba1dbd86c9fb97ef0c30 absorption_res_64.out +df84b07365eec4dcbcdf4254abc7d624 absorption_res_65.out +c8264148eb0ae635559777c3bc4bb81c absorption_res_66.out +4c7d55792fe893a86db91bd29757010a absorption_res_67.out +95ab118d3ada53147e28412925197c6f absorption_res_68.out +20889c4c79dd5061ff9b3f699fbd4df0 absorption_res_69.out +223f27852af47a1245c2e7ac8d32e749 absorption_res_70.out +f030adeab0506e171e6db328099a3cac absorption_res_71.out +eb338409d285fcb174c125151da034d1 absorption_res_72.out +dc8cafe880e06b74907470f54e5c8788 absorption_res_73.out +a2a8746d9724131275c21acad44b1afc absorption_res_74.out +a3ae5b4e45a2ff30024b8e6f53693547 absorption_res_75.out +3c73cff3ac03f77e1e0a5c5bf87e503e absorption_res_76.out +7ff77a451d11fd16553a2c7af73926ba absorption_res_77.out +fa20bea5cc6016e2d691fa28344e0d74 absorption_res_78.out +bea0552e1dfe5b36946d4bcf956af2bb absorption_res_79.out +d6430e1b0f6fd6233abe4560f7707263 absorption_res_80.out +78071b5cc87534d33f3f6f50632acf72 absorption_res_81.out +cc03d6d2470438b117352adbe08758a1 absorption_res_82.out +8ba76eb04ee787ba2da486e29b7e362a absorption_res_83.out +18cee9a228d1cd540af45d0647166943 absorption_res_84.out +63584942292285c061fc2d23070390b0 absorption_res_85.out +e5283e4fdd7178073415acc86215f0f6 absorption_res_86.out +04e3c2643735bc19c821a584c1e5d8d1 absorption_res_87.out +8dfaf6eab14e20d07aedcf6127343ab6 absorption_res_88.out +516b771f2034e088efa3a07ad9ea30a0 absorption_res_89.out +4ce0fea7d880ae5866c42d5354c74ee1 absorption_res_90.out +f04020b3354c482b666e1e353a0ade12 absorption_res_91.out +69ff1797e1f695e047e764286d5c3de9 absorption_res_92.out +47068749b5f58ce5c95d2c84073baea9 absorption_res_93.out +4732e4145032fd628d51c96f0bdc373c absorption_res_94.out +3fd4955f3a8f20b06cefe05846f2decf absorption_res_95.out +6e1166394c267d7387429e5079fa4bef absorption_res_96.out +9ec2e5dbee3fb47d1f82ae4a326f3afa absorption_res_97.out +b75385a68294590db24314feb36f21c5 absorption_res_98.out +150efdd908168411b9a358899ea73ed9 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -75971c72789adfc8396f1d1db429ffb4 deposition.out -a2f872a2ab6c8764ba84a0a038da7834 emission.out -4c52b7730d02998f5bac7201edb0e3f3 emission_res_00.out -c3d2072cef2b736bb34c7804015cc192 emission_res_01.out -26ecd91e4bd9829bfa192604e9e7b475 emission_res_02.out -d6b59da6b2c1b1f774d813f180ead45e emission_res_03.out -39e0325c3003ee4f26c73bfce84c3872 emission_res_04.out -4009ade69d3d7cb5f34f5fc410122ede emission_res_05.out -3c7195c1ef608fd6ea486bdc8c1f2f20 emission_res_06.out -6c838516989f679e7b15ece9173cadaf emission_res_07.out -cd8fcaec794f0eab824ab41847ba98de emission_res_08.out -e794790e8b42a617bebb59bcb907c786 emission_res_09.out -1dc61f1598cb33ac2f49307c4840ed16 emission_res_10.out -2df63eea44205a91c42fdbdbb49fde73 emission_res_11.out -0b0ae528d23fed51aa5da674e21e6425 emission_res_12.out -f8789dce46ed788ae26488fc0104831d emission_res_13.out -cff871e30c2471ed6201df4ce840cc24 emission_res_14.out -16e2c3285b8b88ab046dff2a74f87adc emission_res_15.out -5afde660e7298586300c9a2aaf354587 emission_res_16.out -c82850a7257ad8c870ccf480e6272602 emission_res_17.out -9cb473e85289d6b7e6023abe7208cb80 emission_res_18.out -3cdf5517932a55f5760d66a6571c3269 emission_res_19.out -c4f61776e492442927d359dc8afbbc25 emission_res_20.out -592822e50be18d73f364198d7604c426 emission_res_21.out -ae19676de49dfd32c6cd5eda63c1b66d emission_res_22.out -31e66b26946b75243ed42e947e203283 emission_res_23.out -a0e48f6890a45f252e2a5abee9a0d89a emission_res_24.out -c5938618e283ec382742374946af33ba emission_res_25.out -f164901106f1584205d60d439b03043b emission_res_26.out -3ab2b5c2869842856b336b990d4ce54f emission_res_27.out -ae2bbe221312807bc8702a7f7008596e emission_res_28.out -94010cffb6e64dd14ad381304e853a2a emission_res_29.out -985394f4b2602681da7f7776aa7545e2 emission_res_30.out -79b25d59f6c710a97c29c62aacb528e7 emission_res_31.out -a5f68ebaf83b8be76117a6d861f861f6 emission_res_32.out -c1fa6bd2e0343b5529b5e6f47297733f emission_res_33.out -f833bb44f065a7723aea931608fddbf8 emission_res_34.out -98c880cedda2b50e89df6caeef21c456 emission_res_35.out -f10deeb5c4705a69491096390821314f emission_res_36.out -9cd447c8a77b15b294a7f0ddf12b1d90 emission_res_37.out -246a3d197c6c6a2a536e0e2f44b1446e emission_res_38.out -9c8adbfeede3cb0e8dc0930f80f0104a emission_res_39.out -e162aefd6e47b8ed7e936e329bb12838 emission_res_40.out -aaeaa726a6765b9ea8a1b4ab9f53f73d emission_res_41.out -5f4514b28b093c8639a852c14c5fc052 emission_res_42.out -d6b5f4b613b6c6ed1e182e3d32a10a87 emission_res_43.out -05be39fa9a02a50f6d8b77ebd6157877 emission_res_44.out -88dc63cf460f14cd49546268fc78a6db emission_res_45.out -4e7975c80cbdbaa7f8ff2bdc2392bde1 emission_res_46.out -08be29f80297107edda7923b26960ff7 emission_res_47.out -974ecd68fbf504533e2618d7d8d8348d emission_res_48.out -cfbea031c116ebe368f7e87bc3b17753 emission_res_49.out -906649981efb65d5e35da8dc3bcd70b2 emission_res_50.out -d62a53cb0ea3a05f442ea9a4f4eeb442 emission_res_51.out -613514cfd30d77490d025ae8ad536b0e emission_res_52.out -b5fcba42c6f529bef9b1fc61fbb6dae3 emission_res_53.out -51ed25e723f4e12dba10e3e3bd646e12 emission_res_54.out -b201787cc5bb2dffafd7d014df2b79ef emission_res_55.out -792935dfc6b41c476bf7335f192c98f6 emission_res_56.out -4910c8d30a240d9a51545f310cda2b7b emission_res_57.out -310393cd63eddfceddad00dd76e129fc emission_res_58.out -2d81b2f3bb2c5352062485288e72d563 emission_res_59.out -8387632456a7c3f7a7991c20b442e7a6 emission_res_60.out -4342d626b6baf9267d39a87608577315 emission_res_61.out -5a4d31adb0a4ff6d830edc8a4b0bd8e1 emission_res_62.out -383018cb3f7fd574c8ebda11483522a5 emission_res_63.out -7d914e4b015a9de22e18ffbcd10b499f emission_res_64.out -bc192e7385916b5bc8e5e86a16068e80 emission_res_65.out -9fa08ce00c34b68ee0563f4328c17ee2 emission_res_66.out -5a435e687ed6d6192400805ff0786c38 emission_res_67.out -a95847373ce9ae9c629253527f269a57 emission_res_68.out -e83f0035a4c3138e2c30761bbe505dbf emission_res_69.out -aa2446a7c7a28dbb3c47c76e41e5e366 emission_res_70.out -125742b7f4d639a218ca76a99203c68f emission_res_71.out -ec120cd58afab1366d3d0825a1da6ca0 emission_res_72.out -48fd4cfbb060e8fdba36c6027ab3ac25 emission_res_73.out -f7c5365a29458920bd39f34c335e7199 emission_res_74.out -7df5bb82d9d439e85caf80b23a104653 emission_res_75.out -8252464da3b82f51eb6377a91c53312a emission_res_76.out -2708fe27a5b71d03218fd224c096d2f0 emission_res_77.out -cd210a55d6692b5a4be8462b63717a2a emission_res_78.out -2897a9249ae46ca94dc4e7a080aaef96 emission_res_79.out -6c6ee07d1c8b022d7a28f9af2e77261e emission_res_80.out -40c60cad3d7b74a10cd3e766f5bf86e5 emission_res_81.out -f71eb64693418b37e842679d0ad57979 emission_res_82.out -62d4391961370e49495b729f974c8482 emission_res_83.out -e90a8b49e4c951f698bc0471ea503db9 emission_res_84.out -da7c88dbafd963e465da24e023765a98 emission_res_85.out -e8a89d6e8d15e7284b0fef9451880ef2 emission_res_86.out -b8bf59745200d06d95b969e70fafa0ed emission_res_87.out -bdc9306faf248619735e084da23bccad emission_res_88.out -bc5ec160a5a82958882115b482fc407d emission_res_89.out -6089d149a2d6d0c6751991ba03275dd4 emission_res_90.out -8598f429197f57b390684ee490e4d97b emission_res_91.out -5e7a33b687423ef5120cfa554eb7264a emission_res_92.out -702c210afce6f19960984cad701198e2 emission_res_93.out -787ce6f2037b4d84b3ed42194d317cc0 emission_res_94.out -6b92b55a3cd37b5128cdb2db7dc87e77 emission_res_95.out -7785f9e5a6c04bebe2c495a8736e7e1a emission_res_96.out -408ca8ecf5979f78ac855012eea72d38 emission_res_97.out -ee5863d361e8ccd89b2d4b1e0b87cf3c emission_res_98.out -b1ed4cb38d5ab14051f5f211b11af0df emission_res_99.out -bb61d3e6bc64f419e2689f722a0fa758 emissiontrue.out -3f0144f6e9cfdf376233240d4fb98abd emissiontrue_res_00.out -47b58ef2fe0799741b2a9bf5db7af3d4 emissiontrue_res_01.out -c9934c7491842ddfcecc92cca61e7819 emissiontrue_res_02.out -39bbdee3d7e537966a03edb090d275f0 emissiontrue_res_03.out -d7c3e9ce57f70d64b35ff9bc26ab155f emissiontrue_res_04.out -dd549e393641628c94bf28a35bf39a7f emissiontrue_res_05.out -9558e5f4e0af1051dcd0ed583e2f9bf2 emissiontrue_res_06.out -a40cf16c08249c6bb0d50a9cf093f0e8 emissiontrue_res_07.out -7ca8a53b6ffd7c8f12e19da3a84ab9c8 emissiontrue_res_08.out -153bfc688deba154e894570176662b86 emissiontrue_res_09.out -3f9bf7335d1c7a5d22fc8c88e31dcb21 emissiontrue_res_10.out -a7f29be96bd28f7ec250cb75506663e4 emissiontrue_res_11.out -2c535f393c20cc74c87cceac13d7dd5e emissiontrue_res_12.out -2168dfcfcad6f3318d85a053fbdaa885 emissiontrue_res_13.out -f56e2adb4c285d1b372fad8fc05715e9 emissiontrue_res_14.out -464c9bc4604a8ab1bf6291410b4a8a12 emissiontrue_res_15.out -de4dec7d7db7c160881f4fdbe09df472 emissiontrue_res_16.out -8e784a79fd9a72f71cd181cfd3202b05 emissiontrue_res_17.out -6b100d63b825652997c94636923ff869 emissiontrue_res_18.out -310b16f1c60aeb6186681bb68abf33d3 emissiontrue_res_19.out -ec580d356a0b6300b352bd2e0545c937 emissiontrue_res_20.out -835027931e6b70269168276fba737f6f emissiontrue_res_21.out -3a52dc8eed7ec2076a78dd309997bf3c emissiontrue_res_22.out -dc343bd91e93a3e2409dabe630742000 emissiontrue_res_23.out -a9e1715d965770b5f9a427998d689f0a emissiontrue_res_24.out -c02410d98b5d61fc28b77cfe4a9e4cad emissiontrue_res_25.out -a2d4b36b77b2642b1782b26fdcaccd1d emissiontrue_res_26.out -654b575a4026d5cb39b8b4c36a8e4468 emissiontrue_res_27.out -31f15226dadcae0c71c688cd6ef5a12f emissiontrue_res_28.out -9373325dba7dfb218b723b4c73fe28eb emissiontrue_res_29.out -a3c4f88d5de93185af7b4bfb66a45a17 emissiontrue_res_30.out -0d000c7ded03608e47216ca68ee6e1cd emissiontrue_res_31.out -10e58f9a080663532e52dc0239aa926e emissiontrue_res_32.out -96757e7eafd9eb6f95e70177bfb40cef emissiontrue_res_33.out -76503205f89ed62cef4ab94d21c6c396 emissiontrue_res_34.out -ed24b0a48704db2f565f485784341373 emissiontrue_res_35.out -a98b0d15ec3481741ae2155fb878b7f2 emissiontrue_res_36.out -50f08762cb5a4ef3e06f6de5702c56df emissiontrue_res_37.out -178779f1990ffca44fad02b0409dc7f9 emissiontrue_res_38.out -d5a5bd9059cda656bddb3f567e4e94bd emissiontrue_res_39.out -a6a125b4d52887a72f93ced0d6a6a6da emissiontrue_res_40.out -087cadaef27bce9cbab09104fe60598c emissiontrue_res_41.out -8169d7ba81f17cbb9fdfd45cedfbd3d2 emissiontrue_res_42.out -76796c0945a0522e1bd6f8c7fe1584b4 emissiontrue_res_43.out -f10c7ef60a723d38117dbb808164151a emissiontrue_res_44.out -ef0e2c00f453cc87c9f69f2ea987fcce emissiontrue_res_45.out -f36d04814660179e0895364642559ed5 emissiontrue_res_46.out -54a683202e51a46801c0f8e96dc64fdd emissiontrue_res_47.out -4aff3e79635e44e061a07b5eb54fa939 emissiontrue_res_48.out -0388487769e1fa0c61bf7d44fd15935a emissiontrue_res_49.out -2756c3cef1ea3a63f43273dee78641f0 emissiontrue_res_50.out -886ae27cf3c549acf67dd5ff4d2d3770 emissiontrue_res_51.out -3b0f141af0a486213953448ba4b3ecde emissiontrue_res_52.out -75edd7f33ec5cc2266362928277a5a80 emissiontrue_res_53.out -828727fece567684cd9e48c5d867f865 emissiontrue_res_54.out -3bca274e882428e737eb0adde08dc27c emissiontrue_res_55.out -584c1a4b92befa47496618c1de0728a6 emissiontrue_res_56.out -29e767d139416cd843dbd3e51dc41483 emissiontrue_res_57.out -d8290e65f7cfe35de6fe3bcf456a1dfd emissiontrue_res_58.out -525107cf94ddd00abe2401b2e50beffc emissiontrue_res_59.out -679ac07b6dfc70b754742a8150f95a0f emissiontrue_res_60.out -a693433bb4eacd652b9cd392f44ca4d3 emissiontrue_res_61.out -869256b97ecf91aadcff25481301573e emissiontrue_res_62.out -803d0ae2f13ae7158c1be1ae18fff6b3 emissiontrue_res_63.out -9fea8078617d214c1811853387f4f8bb emissiontrue_res_64.out -35007efc7ceacef428d970fa193815fe emissiontrue_res_65.out -a657581d41e51dc58347b50518d3b1e2 emissiontrue_res_66.out -b74a89f66563e1e84cacc22eec1ce031 emissiontrue_res_67.out -1db390e1ac6f0c9a9aefb9a234c79806 emissiontrue_res_68.out -d56419153cfb0e95887d8b57a1e41ebc emissiontrue_res_69.out -0cae0c49ff00fb323b1806e8bab9c8f9 emissiontrue_res_70.out -dd35ed9c209daf16edfc6502bb0cacf8 emissiontrue_res_71.out -7724ad91c6be3071594b20228aef652f emissiontrue_res_72.out -0833ffbb50f75ed710d13994ebed1ac5 emissiontrue_res_73.out -488664d33f245893ab1df3ea9e618633 emissiontrue_res_74.out -02bff5fa69059b681606dbd7b75ddff2 emissiontrue_res_75.out -de16229631944c5592891efedaeec71c emissiontrue_res_76.out -81c663c7656db3d3060d8f01ba549761 emissiontrue_res_77.out -36ac119600cdd7a4bfecabcea1530a08 emissiontrue_res_78.out -25ceea3c278cd72a4d62d0b185d8c6e6 emissiontrue_res_79.out -a05ace1a3c3172b34852ccec4c44a3f8 emissiontrue_res_80.out -dc7e59db13b05a7d5bcfb5decd1758aa emissiontrue_res_81.out -bdfea8c02934fac10416e0d2d40afa58 emissiontrue_res_82.out -5db89a73f4407c7f0118fa2b345f275a emissiontrue_res_83.out -ac13f555c6a1cf7a7ee8032146680703 emissiontrue_res_84.out -67b9e8eeab14a3acf5839a40724a8f90 emissiontrue_res_85.out -a9d8a5af407e1d094af1980d8f41dd73 emissiontrue_res_86.out -4c53588a8c123e1dcd4cf3f3f9005fe3 emissiontrue_res_87.out -c7bd6663569708e68836fb4a03ac3342 emissiontrue_res_88.out -15693f57b437cf857fec2ac3d1692b04 emissiontrue_res_89.out -307d42be9100824c7cff00944b842d39 emissiontrue_res_90.out -a0be179e1ea1099a9f32790c5efc0c6d emissiontrue_res_91.out -66ef1d5ba15ce66e28ef84299899ea16 emissiontrue_res_92.out -d127a6983a9aa786b13531133eb8209c emissiontrue_res_93.out -c0cd6b35736ac661f85c27874ec16683 emissiontrue_res_94.out -aaf153e621a38b95e1f51a25b6bdb359 emissiontrue_res_95.out -3d8161f87191464ce2b7ea2e1dac02cd emissiontrue_res_96.out -25d96adb9355fba3629c9b6ba13dc2b0 emissiontrue_res_97.out -5928c4e91c9457d83d2480adbadf636f emissiontrue_res_98.out -280e5d8f7da54d1d203afb1ec19fbeed emissiontrue_res_99.out -73089da35f724273c17e1f107a66d870 gamma_light_curve.out -e69908c43dad66f2e0ddf2c94e5ecbef gamma_spec.out +a3c0bf87b4453de34b3a9341b3b11f5b deposition.out +df2411bf53d9e8a65897b9176011aaf2 emission.out +01350f3129565d1472dc8705cc30fe54 emission_res_00.out +a48a26db68581485e30b75773bec9bb9 emission_res_01.out +724578ad36aaad4fd238f8042b85f2e8 emission_res_02.out +8e759f96584bb8debdc7c1f83629bc50 emission_res_03.out +79277a8eac3d3c6a5961f9b76ba96d10 emission_res_04.out +9e9466be83f7eed6d1271412ce916979 emission_res_05.out +0aaa29aad041ae1865f44fb752951526 emission_res_06.out +60b3168fa24555d595e5f2e1efde7c8f emission_res_07.out +deabae82e894941c822b6fdd078b224a emission_res_08.out +945be6245196152b08ff06dcad9de2db emission_res_09.out +295c062bf01df7706113652487cde520 emission_res_10.out +71ee2c539c12d5fca8dc20b3d21bcbf4 emission_res_11.out +2a54aef7a8ae040b9980e064427f1421 emission_res_12.out +0c98ca415a90724dcf87273e6eb26111 emission_res_13.out +2985961691ed7b57a8fc3ee303dae87b emission_res_14.out +2d67bdf1cd9cd7e6e140f3b7428cc62a emission_res_15.out +a70ad565b692d7f30c5892164163fc0b emission_res_16.out +f25e0df40069ab8f8827f3075e4c8bac emission_res_17.out +85f54006eaf0fdce59b376acab655c27 emission_res_18.out +f46f3e9ba8f53d4b638492d1f99431e0 emission_res_19.out +e10dd39e3f8189e48345b58472bf9b8e emission_res_20.out +e3c64840b1b8ed87e985a66f596ccdc1 emission_res_21.out +abf97707c78048b99853bdc0339fa779 emission_res_22.out +958552fb091897733fdfc93561bed0ea emission_res_23.out +4b866591450232dd718f40470dca2897 emission_res_24.out +38f49a2b49f5bbba5cfb6bf5a321bee8 emission_res_25.out +e988aed28e287f9b69192f817b15a488 emission_res_26.out +440a9a423c90b9bc812f3073354965ef emission_res_27.out +a1fd901ea10d0e4603dc6cad63a12b20 emission_res_28.out +4ad66e267376d4498eed495d64d76a6e emission_res_29.out +61ab17da0175872af239676e43482b26 emission_res_30.out +6b60d9b399f2e282fcad023cb8632829 emission_res_31.out +30dcec8a52f61748d1edd2781da0e5d3 emission_res_32.out +7ddb90954353841186358361abb68dfb emission_res_33.out +6653ccf8a8e14559e215ea40a36c010b emission_res_34.out +d7c593e8fb0f824c911f8cb536c2f7a5 emission_res_35.out +f3426c8d52cd679b5702ae46c2acad2c emission_res_36.out +943774d7f68e3adbea2ffc8d9f5a7d5d emission_res_37.out +9502ea22491234192cd167d5ca8fb1af emission_res_38.out +6086e867686df38fd936d7132d76979e emission_res_39.out +94ede1526c0caa99af4003e9c2b64403 emission_res_40.out +9ec4aba491e50c31d14cd2d21117ea69 emission_res_41.out +5d15934f27dff46bbb7aa07282734f7c emission_res_42.out +3b6aa93f40a91ca301cbee53321691e2 emission_res_43.out +b948908006ec407b1b2eeb79779d4c74 emission_res_44.out +065d1917e8c3a45e44337f4f5f9db27c emission_res_45.out +7990f5c5f5929e43c0c627d47459cd4d emission_res_46.out +82104e216ac7dc875880cb6d239c1f67 emission_res_47.out +06da0b2ca79ec79fb83b10cacbd2334c emission_res_48.out +0718719ca98be1a02901ad8c0c449c69 emission_res_49.out +c6c06becd04625247906e9577f90e998 emission_res_50.out +e0fb2119f99c3bbd88f073c4c5f930d3 emission_res_51.out +63753e84b3460505ca0525c711cb2646 emission_res_52.out +27af4e1d69abb46db89a2b5d2ec420b2 emission_res_53.out +2204414b178a31f8feeef3e683944815 emission_res_54.out +212b14f6d30191be02bb6ee96a1be5f3 emission_res_55.out +f03473a4256262154b395f5f08b603dd emission_res_56.out +ff476d1c73e1c9348e9c5887162a3ead emission_res_57.out +8ef5a65dfe635940c25d2230624b1f65 emission_res_58.out +5f81ce79f11befeac373c60b59e4e070 emission_res_59.out +b258268d94879a0868abc244da6ae45a emission_res_60.out +6b3b3697b4540ace5088f39056ba03bf emission_res_61.out +367d9151365662f8b2b591bb6553d79e emission_res_62.out +e52ca5fe46620aa3a2db85be0f03d9f0 emission_res_63.out +0186d08c4cde468f90c72bf82a7830fd emission_res_64.out +84fad345fabca98140fcf106f5da755b emission_res_65.out +8839287e54b06f85ad92334a80fe5473 emission_res_66.out +447d33a80233cb41b6fa5c7c8df814c5 emission_res_67.out +a2363156955a2b1e94289c4a37be0130 emission_res_68.out +43955369157d30af813b2a4d43ece4d9 emission_res_69.out +90789ebf70db9c3beaaf39bb9c49c609 emission_res_70.out +429c80bc04bbfb1752c3a0275102d397 emission_res_71.out +9f51ecfe04c4aa82c4560308089c0459 emission_res_72.out +4b07fe32035dd071e2bfee5069c4a711 emission_res_73.out +5670012a476d356170b1a2def25b2b07 emission_res_74.out +2adfc7dfaaf8b85c22ab23ad830fb773 emission_res_75.out +14c9be6a82d39cb0ab62f779b2801302 emission_res_76.out +c771314fc05f66db1dfcab73c345b449 emission_res_77.out +43625dc5aeb13349ccf4f622e27942e2 emission_res_78.out +63e411d7ce30b0686917f96802c753d1 emission_res_79.out +0555634b1055f134e18a75956e4c123b emission_res_80.out +c6b9df9921b3de02e8fbc6b050590d12 emission_res_81.out +3a21b21061d064b42e81621996ca3445 emission_res_82.out +68b2c942bd014353568e607c68893c7d emission_res_83.out +4a9ffda7dc7c2557ddc9281bb33f2287 emission_res_84.out +fc44d709571377cff3972152e1d3861a emission_res_85.out +e572786cfabab03f69a135441eb6a60a emission_res_86.out +39048b2bb718d96bd20dc501515a5024 emission_res_87.out +35821d991547227f9b08dfbfdb08bbf8 emission_res_88.out +ddccb05c6cd5341b5e86562da26c447f emission_res_89.out +c56efd1a4a628512240239982da477e0 emission_res_90.out +a6a268dabd04912cc259f265b5291984 emission_res_91.out +1f6e229e859889c534f82b78bea882d0 emission_res_92.out +c12d41bbf3ce6c4161a513f306757966 emission_res_93.out +83cd9792b1fb8da0894cc45f35806135 emission_res_94.out +7486ace72c54890a96b163f25059dc02 emission_res_95.out +3f92049c4a266a313f31e6c4bd32c7b6 emission_res_96.out +b8c3d1563e890ad5e2e5849ba470b4f2 emission_res_97.out +87d07a3744dcefb5d91c65b67e9648be emission_res_98.out +f64642cebbe63806d3172a97a9fa4f48 emission_res_99.out +540a7bf037980e462f8d3711712c0606 emissiontrue.out +dd2f166b12726e264876f8f29c07cbf6 emissiontrue_res_00.out +eeb418bafc872f498f4b52e8f805e0e4 emissiontrue_res_01.out +053286aae7bea4820959cdb5794184a0 emissiontrue_res_02.out +8dac36a1f78dc85e4a6917e4b72d49a5 emissiontrue_res_03.out +720dfc0cfa99aa2e8870ac5e99c49650 emissiontrue_res_04.out +54570cbeb15009957833cda024981975 emissiontrue_res_05.out +794e5fb1d4d4d044a86d984c0ff1c194 emissiontrue_res_06.out +2264dfd2960e837234e0f5d7725fd2a7 emissiontrue_res_07.out +7fb37fd41ccbf08a63ced7f5fc1fa917 emissiontrue_res_08.out +d31f927d2e98c5524d4a41fc369dca03 emissiontrue_res_09.out +85ef25dc6190246cc6db1701d7feee13 emissiontrue_res_10.out +4ab4d8fb3d5f9c33e7614a99e15be51d emissiontrue_res_11.out +4bc17d5bb946ec1f9adebb9161a5153e emissiontrue_res_12.out +13e2ab8f2266b02cdb57846b237faef8 emissiontrue_res_13.out +1c0072a7c3c6807956ae431ac3c5a2e9 emissiontrue_res_14.out +4246b93a2b6112cdb9eda3add6be172b emissiontrue_res_15.out +bb5a57ac115688a130d6f292afac3493 emissiontrue_res_16.out +9e2468ecf0e8dd7ccb4251877dde4f78 emissiontrue_res_17.out +0775bb802633f59bce72d4ad4b99f707 emissiontrue_res_18.out +808fbc0cd01bc4665089fb105c6b9365 emissiontrue_res_19.out +25f223f9b52b4de21aa2b9d293c4ec7c emissiontrue_res_20.out +666b7bcc699efbb169d2a1b9c4c04b1d emissiontrue_res_21.out +d0c8d1ae7d196a73168a6c3a78b21026 emissiontrue_res_22.out +58291bf08665e2c10644573a6fea446b emissiontrue_res_23.out +3dbef62cbc57f6f7cea4b18f6d28ddd6 emissiontrue_res_24.out +df00e04269f7c24f1a75af748bdf0e4a emissiontrue_res_25.out +e22595c9ddf56eb6ec656d0b917e3096 emissiontrue_res_26.out +4a9ad6bc539fe26af73dbdaa8bf7850e emissiontrue_res_27.out +c5f4f31a269ec4f9a08053ebfdb3031a emissiontrue_res_28.out +12ad315bdb7ea4022c506364fcca3e73 emissiontrue_res_29.out +2fda140d5b095085f17cf73e97343997 emissiontrue_res_30.out +372dd2b477d715847a024eb1d23c2472 emissiontrue_res_31.out +740e3fdaffcfb5d0b877966e97e9af2c emissiontrue_res_32.out +0d45c4ad72fd1d2af1cee91edae97127 emissiontrue_res_33.out +78f801801ed410044a10378c8ad9c7ad emissiontrue_res_34.out +0904c8eb5133eee2faeebee6ef7d9ba1 emissiontrue_res_35.out +0f6b452a99ef1d14c84c625cdf93dd11 emissiontrue_res_36.out +bc48ca1b1b1929a6d425a671bf05d757 emissiontrue_res_37.out +d314c6af0126184130f86ac4978e1f99 emissiontrue_res_38.out +bb5f178f281aefa4e6a93cfb760ca2b4 emissiontrue_res_39.out +6b2c86d13f484f62a77f662013850f30 emissiontrue_res_40.out +195ea97aeb26b7fdb98b517dcb636603 emissiontrue_res_41.out +ec3d1e60b1d4ab6b9e3b3dda81c613cb emissiontrue_res_42.out +e564c5f938ea729bad79820edd2beb6d emissiontrue_res_43.out +e04ea3d1c00f355db49d5682cb66c534 emissiontrue_res_44.out +65ef30974aa46f7b36982218e4a36488 emissiontrue_res_45.out +5c7a6ae80ad998c8b70d30b95a1808ab emissiontrue_res_46.out +536b29f5dc30df8d899183f93a35dc76 emissiontrue_res_47.out +0521d32f609c16dc8b779133f1a2ba07 emissiontrue_res_48.out +2fc1ac8e9e74267a5997ed3d6134618a emissiontrue_res_49.out +776cbef30cc2db594e1b5d64da48d903 emissiontrue_res_50.out +ab3526171b5743f50e06628284679535 emissiontrue_res_51.out +69d0d747f69baca53f395a15fd30591c emissiontrue_res_52.out +b006c620d8a874a8a57c44432b7c7bb3 emissiontrue_res_53.out +863d9dc2c491b0e85de290556415c0cb emissiontrue_res_54.out +bc2cd9e3e47a2efcf061849167f9e62e emissiontrue_res_55.out +0d980ac6b592b178233a54ad62cfcd04 emissiontrue_res_56.out +bd079fe68daa7d482ffa2383b4675285 emissiontrue_res_57.out +b2c299c80a0e5cd094da5c8969294892 emissiontrue_res_58.out +2aa62481a9278334cd6222a162adfb57 emissiontrue_res_59.out +65cdf14d3f14e1751bc340f7670cd6d2 emissiontrue_res_60.out +ee5fa7a9703c429e9a8ab55006f9593c emissiontrue_res_61.out +6f6a0a849aa564a42cb8575f628e9ae4 emissiontrue_res_62.out +bc812faec076deae43b9ddf073d043ed emissiontrue_res_63.out +d6b179b165d4d0d9d88bdc868b8a7660 emissiontrue_res_64.out +b3762653c9cc2936e81efb945104be9b emissiontrue_res_65.out +f420a017ce7bc0182e6860f8ddb1e93c emissiontrue_res_66.out +ef0a4e2b758ce718292a6ed41586ec3d emissiontrue_res_67.out +d78039d02e4cbf99be8bba1df8927e7b emissiontrue_res_68.out +7788710bee7289714acbf3eb70f110bc emissiontrue_res_69.out +bb6611cc8427c1415ed66b73cf7722c7 emissiontrue_res_70.out +aa2b1532839d7a5ab07f1dd95f9856e1 emissiontrue_res_71.out +4340b45a21d728bc4f33aaaad1ef133c emissiontrue_res_72.out +4018a659fef94947d1699b9ac5e7ec57 emissiontrue_res_73.out +e3098c2db8ac98c0492b4ab3ec8093fa emissiontrue_res_74.out +16e4fc326470d3d8efd4cfb9ab62ba92 emissiontrue_res_75.out +2ec330979739777b625650005b219186 emissiontrue_res_76.out +d3d64acddf367de39723b9dab1ad537f emissiontrue_res_77.out +06bac0c3246059482229af9630b3b11b emissiontrue_res_78.out +04abfcf860ef9be8eb1b93832ac79434 emissiontrue_res_79.out +c2ee36a45d0106502179c5dd001e7b4d emissiontrue_res_80.out +8fe00b92c1210ac615a9c057c2dc5eda emissiontrue_res_81.out +e7cd2477c5eab1b517cfcf4443d3a19b emissiontrue_res_82.out +0e7f17de4779ac70bab0a00a6b16299c emissiontrue_res_83.out +7482fe56667250179d9c0a7afaaf0082 emissiontrue_res_84.out +4e184b1077db35b92fb39791c56d3da2 emissiontrue_res_85.out +1aa26c01090d5d4dda9d6c7da081e68e emissiontrue_res_86.out +67d9b2b664dbdcc48385d84f6244b921 emissiontrue_res_87.out +e6635781905d77d3495017a32f7506ab emissiontrue_res_88.out +304a727f6caa2a1f71595915e43534ae emissiontrue_res_89.out +d758ed01696467c8f9e2d69e963802b6 emissiontrue_res_90.out +1e4d458465e3be8e994dc407aa9349b7 emissiontrue_res_91.out +3d5c1497e3f073b5b6aa2d677a481fe9 emissiontrue_res_92.out +78a9fa4f2d7fc4bc6a673b2513c3f492 emissiontrue_res_93.out +2cf49123f8d03f89a700024343834d71 emissiontrue_res_94.out +b94c76380b1b62c8382e89131d5e8480 emissiontrue_res_95.out +df3ff20df7fcb220169b36198147f1fc emissiontrue_res_96.out +c7d59db7e83a3c394a2e3fc9479eba6d emissiontrue_res_97.out +957d2d25952450b47a817f128444ae51 emissiontrue_res_98.out +3c34789461da4884157b5c4f6160d9fc emissiontrue_res_99.out +811d9e2b2a8752f84e78b5d39ca7ca29 gamma_light_curve.out +7089f1479b4fd210d618b87c561eed68 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -7bc4f0781f4758bae2d13ff4d0aa321e light_curve.out -f6b59f6864b93d62611502f6c1e955bb light_curve_res.out +921bee473309a3ce383491ae0e960973 light_curve.out +45367bb87fbb87d83a989dd396432059 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -3787a94e0d776d975879a491d231cd24 packets00_0000.out -53c2e9a1c5052a57dea47fbae245ffce packets00_0001.out -df05d69d21d24a536cd43258f04b0ad5 packets00_0002.out -4f90fa221b0b625480cfc1b8c5968b51 packets00_0003.out -57f35904b8ce66d0280d76b19350cccd spec.out -096b48197101531a2e77246f4313861e spec_res.out +5f4673ed07b99575ce686a3dd9c0d9ad packets00_0000.out +67104d4b06c8170db6a487091f826506 packets00_0001.out +f3458bdeaf2f5cb207dcbee103dda567 packets00_0002.out +945a661db635f34f23b10ed8e800586b packets00_0003.out +bb247a6213ff848ca038d6c7368d9762 spec.out +f51cbb087c29f30368ed94046f8080e1 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -b6346e495f1bccf8b0c3ba0d31d7c122 job1/estimators_0000.out -bec5a267110c6f1432fbd817030f3928 job1/estimators_0001.out -720896de818b9b0bf52b7c6a07898292 job1/estimators_0002.out -c1dd5690ebe3a24e6753f48d3eba5c63 job1/estimators_0003.out +1173c9b839971f9bd6de1c47c3c52cfc job1/estimators_0000.out +50405bde5f9f744708e33f9c37838119 job1/estimators_0001.out +68b39af44a830dc018d3b50e617181f5 job1/estimators_0002.out +aa6b1301009d451e0930d801f6409aaa job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index 196f3491b..be6fc3902 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -9ce61b3c4fff199ff39faf4377180234 absorption.out +ecb663d454dac15eb2ff74b4ca4c581d absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -5abf030d9a1e628153f416f935ba8169 deposition.out -6b548ead4025ba2a3cd16011d1bc56bf emission.out -4dc6b9a8bcf3c051700393b7f7ae0423 emissiontrue.out -f4c1297950f7a4de53b3c6ea46341f16 gamma_light_curve.out +4390433658071b1024615d76491f7e4d deposition.out +22eaa6841bd5831a2087097c379f5c4e emission.out +2da765a27454802fe49aafb0b7978540 emissiontrue.out +8a96d831cb9626b727029d980ad1bb4d gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -f0560aac1cc23c1ef20d936f4d03b2f8 light_curve.out +5e36aef9929f8ab61fa35cba5969663b light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -06f78283ab6c70372b5623c03c324e60 packets00_0000.out -7bc7b7f13abcfc0d9c9b607201fadadf packets00_0001.out -8a11dad99e2bcc445c7c1b17a7ecdb1d packets00_0002.out -c6ff00913b6991c00ac3914845303e55 packets00_0003.out -1a56005ffb39f1e11225d16ad7e6b5fd spec.out +18756de76903d456aac7a3ae3f1068ca packets00_0000.out +6cfdd8a322075d58586bc3a8548f5040 packets00_0001.out +b3d6d74cd0c4fbe6519294af8e63ebac packets00_0002.out +933be7818c864b6314faca6a2ceafb82 packets00_0003.out +bb3e8856c519696a8af781915be05c81 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -62acea9eb4b1f63068932890202f52d0 job0/estimators_0000.out -ac22c6d53430692779dd3ab027cd82e1 job0/estimators_0001.out -2637ca75ee400f2c0913cc6c047ed233 job0/estimators_0002.out -b7f556b98a9b4ea15a850576ffbff76b job0/estimators_0003.out +f78175259b7d9db94d3dd67f42b17c92 job0/estimators_0000.out +1e7320ea490f461c5f5006fdf30babb5 job0/estimators_0001.out +965159afc4c97de3079614a6ac5a144c job0/estimators_0002.out +e8885682ef93e0104f1779dcf24c1861 job0/estimators_0003.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index beb846c3a..75c3846d4 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -2f49e5377a3d06fd34268f5c302f3140 absorption.out +1a45b3c04b542f49ae27d4d54e9688c7 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -5829cb3d83a3181ce87d10aab2ef571a deposition.out -a4ba89eafd095c3b1d1aa61e969fd08f emission.out -9af0101468fd7d7c3efb0d07cb4a14cd emissiontrue.out -e5bd8b74708d70302232e7454839955c gamma_light_curve.out -b46d2fe763c220aed7a2392f0f4f1a2b gamma_spec.out +57ac877a8c87629fbd11739e54c67daf deposition.out +1c02b034e6c568c158be8b34230c040d emission.out +2de88edda4f95630136d81deb821ec84 emissiontrue.out +2a636a749f5313433bcbcb67d48317ea gamma_light_curve.out +c3ad1c8e879c9f24318d604edb33ce11 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -32d9e350690d4ecf12d2b6ad715c41ad light_curve.out +35cef386fee0b62db5f858ee0d0e2425 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -1f24db4701861dad5978e575fdadee78 packets00_0000.out -2418d26a487c6576632b1ba568c49d17 packets00_0001.out -3bb68d5b38b5f4ceca390d13089c3f92 packets00_0002.out -2284490ade972c38c015cd653c24174f packets00_0003.out -69e8b3178e6be6f7e78ae73f3bbd873a spec.out +c1a6cec53ad08507a3d33d26da81f5a0 packets00_0000.out +82de8a66326c3e03921a1c8a202964cd packets00_0001.out +c991bc240721279875b2936204a3bfc4 packets00_0002.out +1f3dfaafc02a8cbb47a3e62ba1f5f577 packets00_0003.out +5ebe9a852e9975574a6c946396b2a493 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -fb95afe60e57121b5bb3c1cd062ce60d job1/estimators_0000.out -9dffdd580798be16aa7cd445ca41b553 job1/estimators_0001.out -2d3a4e11fd7f0aa346562fe599cc588e job1/estimators_0002.out -543f1eeed777a9fe2c81c492d9460bfd job1/nlte_0000.out -b4041ef65fd2705ecf820e14e2013fff job1/nlte_0001.out -8c53f992c35cfac925d48bc30ff2caa2 job1/nlte_0002.out +41a368446a406a721a6f9e8ba501f688 job1/estimators_0000.out +d4944478ee048e90c97b36d446da524d job1/estimators_0001.out +b7425d047198d784b042fe7ccaaa76a3 job1/estimators_0002.out +68bc097a9846683d70a6ea4c05409b6c job1/nlte_0000.out +d3ed010a31599ee2b89923280f964ecd job1/nlte_0001.out +87baf1e0392e88950f8eb63611b1c8f4 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -76cff3ddbf99d2cff8838e16c3046e6f job1/radfield_0000.out -e1537e18e673cc57741a4c2bb7d5eda9 job1/radfield_0001.out -64d02d654732b412aaf336604294868d job1/radfield_0002.out +0373cda8e4acd2b1c49d343de9212f2f job1/radfield_0000.out +84376d4c46df0c412ab15509b55f94e9 job1/radfield_0001.out +6d4f5acbd6cc5c2d28fe336dbc4c944d job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index c5ca526a8..1f3ffbf81 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -131cbf501b5a645fb0f6b7d5935a332e absorption.out +4bdbc3fce442065843b75ccba8eb743c absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -dcbf9412ab83a18e2035666b616e89d4 deposition.out -54a9b747ca68dd130eb1efbc9f7e13bf emission.out -859c4997aa7d3c9f62878dcd9f535e33 emissiontrue.out -d521daee1fa89b99c7e548b36c8603b2 gamma_light_curve.out +51e6ebef8f4a7ef46a6a07fdb4d629a1 deposition.out +664c267df1eebce02213cea5de6c07d3 emission.out +3738629c1d3d5ad08aa3ec2e47aac010 emissiontrue.out +13c9966c51be68d7e8b1f3429b9b2e3b gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -b27913a2d317f53f0e99d38b6ab3f0e4 light_curve.out +b2550978a93cc4b3e90784b845f03e03 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -4d889f720bcd204a789317918cd19ce3 packets00_0000.out -c443dd6213110f138f769e8c8797b5d2 packets00_0001.out -0035bf7388ea6cc4e605456c10c0f84c packets00_0002.out -dbe137676dbe07dbeda3521b329b45f0 packets00_0003.out -cb0993f79ecd0cf650337525143bde5b spec.out +193f160d32272bceded94c3947b515db packets00_0000.out +3f7dff609efc917105d94844cb174449 packets00_0001.out +13ff1a6dd1731a2afcde09d70bc08c31 packets00_0002.out +51e103a37a3af8019e6eeba00688f4cc packets00_0003.out +90898a3ef561472bdcedd584014c63ef spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -42b5ee39f991a3499a39d18b0676cac7 job0/estimators_0000.out -68295a40ce0ff8dade91ed0a2068dbef job0/estimators_0001.out -b6d7da56b3b3f9e61d17044898302d2b job0/estimators_0002.out -edac9d99f6066ccf019da96a84f92c80 job0/nlte_0000.out -77ea65d6004d9c04888846a0ce2121fc job0/nlte_0001.out -f05f0d7c9d5b814f18ca9cf43e73ccbd job0/nlte_0002.out +d5be89a8d1af7fd6be5c43872e445d6f job0/estimators_0000.out +c10f74a61fbd197aad25725bb48c5168 job0/estimators_0001.out +d688dd4c1320e4b17285afc409889085 job0/estimators_0002.out +784108881cb7cd2ab9f880ba22105f1c job0/nlte_0000.out +2ef5f4bd1f7f18e105c00c9c14f60372 job0/nlte_0001.out +41e8612ead2de71745aa862549c8738c job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -a229397eef43b789830071c02bae4eec job0/radfield_0000.out -b5bb2a5f69d1ce47fb6446a085d8d3d8 job0/radfield_0001.out -6f70f10c8a9c99aa95678433b13b92c4 job0/radfield_0002.out +a246460b3f977ebc4075b332fc883a85 job0/radfield_0000.out +557988c63e95c5fd7c1afe44facdb6b0 job0/radfield_0001.out +23af1dc66920467d2dfae6f70272029f job0/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index fb4b3db91..320e4b183 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -208c12670db21e2b1292ccd272daa9d1 absorption.out +16a7f8ef6a92defc1b5481963e5de5c2 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -e25747048f8502665f23520c5bfb4328 deposition.out -93c8fbf8185a3b45a96883d15d57a051 emission.out -5871be78febfb9cce9659e3d686c3771 emissiontrue.out -0c8a3fbb1473b818d0cab8aff5294092 gamma_light_curve.out -774211c072a2c67dd17707a0e355b0ad gamma_spec.out +cc0a6fd9e6f9ad648b3390d4b44b8354 deposition.out +587660bdb3b97f6b66d7317aabce2022 emission.out +613e3769666b9d43690aa370f2327b64 emissiontrue.out +707ad83631c3818fd5ed337022eebac6 gamma_light_curve.out +58abd1e96234d7897c4ebd1714b17625 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -906adfb01fdaa2f5946c64a504511420 light_curve.out +2fbe87a317801b68d8097d3d0083fc1f light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -9bb900b56efd416799deb7c725a3b17c packets00_0000.out -6320adc4ce70eeb64d233f310a844f0c packets00_0001.out -646fbdb744361e548bb3ad760d586f59 packets00_0002.out -465222336cefe78f1dcfc49c75402375 packets00_0003.out -d7cab8edbffe1afc767d7b98e84ce387 spec.out +c9bcddf85fd37d293d1fea9f8228bc64 packets00_0000.out +9a394b36a5a54b61817beb6c0f6940ca packets00_0001.out +d596b43bdad55241ef176d6831209d9f packets00_0002.out +d7d3895079e60e383f3addadf81e0e63 packets00_0003.out +c794b14a31f6c47464b0bbe72c5ce0fb spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -076c670c54d8fb04182a41a0906e0c02 job1/estimators_0000.out -0e59f5c370cfb0f99de36082f48b8e9c job1/estimators_0001.out -7c8ddc14ec60ab347d59f3728e200c63 job1/estimators_0002.out -d1fb48b49884d8177e6af38b40593d68 job1/nlte_0000.out -44a0595547c92454f9e24f85c0ae8326 job1/nlte_0001.out -71cd27d0a8918f127f28cfc5fd72e6f0 job1/nlte_0002.out +cd82cf5f2a867ec6f1ee328533c3db31 job1/estimators_0000.out +cabb6379d0aa3af3c696b3ac76ef395b job1/estimators_0001.out +deafe1934c00b337a086488f189a9c76 job1/estimators_0002.out +60319cc607d07450d133097ffc047733 job1/nlte_0000.out +9e28edade1e73d51c3fb8c480d615961 job1/nlte_0001.out +dcc7a3c1dae628b793eb7ae1410ca39e job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -2eb4624dd5c1369fcbd28c9d5a1bbed0 job1/radfield_0000.out -f26f80533a25880b53870ffd2a1ccae3 job1/radfield_0001.out -98e5090a68555676241a2f5924b247f1 job1/radfield_0002.out +69d3a85085154dbc2f4bcbe1cc10d311 job1/radfield_0000.out +5281dd710252b0c2c08ed50355ba3987 job1/radfield_0001.out +6e9074af85aba3a62555b01052581671 job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index 113ef9c5e..ca7335899 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -86974870567c9f3afec4d0c91f06c0f2 absorption.out +dbad535e3a31ab55a0e3bd7eff082468 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -7dc09f050d647fa589e5a776d2b079e2 deposition.out -24a88918d6417447b45e72f6714067b4 emission.out -799e3f35257a3338d73bed4f7167d189 emissiontrue.out -83723fbf0ca46aa72d07f1d8af2b11d4 gamma_light_curve.out +cacc8737b397653578dc03be41d5629f deposition.out +9b1deaf1cae7c7e75e6a8c9c0578e361 emission.out +2bea2f08ea2c1591360c69be60a96f5a emissiontrue.out +4ded7840283c11cbc6571fa429522bb9 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -f19b0cecf67575b042a3de2318eb2cda light_curve.out +a0593185f1a88664c8df5ca8db65160f light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -66e71b732fa464b5f4c1be95c1d597a8 packets00_0000.out -01fec475ece90544cb04edb4c1418981 packets00_0001.out -ee423894bf4cc220ccf167f537205cff packets00_0002.out -d5cdf7fe11f27ea0fe0951e63f948555 packets00_0003.out -7846d067675fb864fde871e2f9547449 spec.out +e1a43ad7854ba07c3039aa219120879f packets00_0000.out +6e8dc1d1c515cc44e291e725a68d2bef packets00_0001.out +4a36a1cb05e6935777d8b2b12183aca6 packets00_0002.out +0912a606740de431a0d3164cb8657f2e packets00_0003.out +4bb17284dbfe23d42f9eaecd7c9cdb44 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -a100df93a414fe49230617583f0eb1d5 job0/estimators_0000.out -5d5971e62e23c5d9e96093840c15447e job0/estimators_0001.out -b96da6e56966046c66102d86dfeccdb4 job0/estimators_0002.out -0e877b1417b452a7ebda2d53ac267d1a job0/nlte_0000.out -a8fb6228e23298597b71c60c12319a11 job0/nlte_0001.out -4b516ae17c600afc38dd8a63cbfa03e0 job0/nlte_0002.out +e831f0a4a820c3932f54196718e229e4 job0/estimators_0000.out +340dc15b95391780cc400bfef074f00c job0/estimators_0001.out +e8d5416218afc33407ef1029fb74d791 job0/estimators_0002.out +95bd6cac6bf694cf9ec3534741686129 job0/nlte_0000.out +5d63a6fab6ce324a98b58cc75e328edd job0/nlte_0001.out +98466294358c997c37029fee6fd96e75 job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -6fbabfb080eead960ab969fdd050d8cf job0/radfield_0000.out -4b01065c6e54ed8c28d55b80d005484a job0/radfield_0001.out -2040872a4f19535421c278d93afa3959 job0/radfield_0002.out +ea8e226d96878c1e9dbf03d51d8a901a job0/radfield_0000.out +66ae75f111c660835fd74575d3f5efb1 job0/radfield_0001.out +fdeb82c6b0b35791d1f28d2b56a86259 job0/radfield_0002.out From f4b439478303c93338ad37dead5e40b6b9f7eaa2 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 16 Aug 2024 17:01:31 +0100 Subject: [PATCH 018/117] Fix type sizeof error (allocated 32b instead of 24b per transition) --- input.cc | 4 ++-- ltepop.cc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/input.cc b/input.cc index 076c04688..78a3c037e 100644 --- a/input.cc +++ b/input.cc @@ -515,8 +515,8 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons auto [_, my_rank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); - auto size = static_cast(my_rank_trans * sizeof(TransitionLine)); - int disp_unit = sizeof(TransitionLine); + auto size = static_cast(my_rank_trans * sizeof(LevelTransition)); + int disp_unit = sizeof(LevelTransition); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &alltransblock, &win_alltransblock); diff --git a/ltepop.cc b/ltepop.cc index 9e4321987..35f96c916 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -31,7 +31,8 @@ struct nneSolutionParas { auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const double T) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); - assert_always(T >= MINTEMP); + assert_testmodeonly(T >= MINTEMP); + const int lowerindex = floor(log(T / MINTEMP) / T_step_log); if (lowerindex < TABLESIZE - 1) { const int upperindex = lowerindex + 1; From d553acb63e963e2412798bb88e336282dcb1d820 Mon Sep 17 00:00:00 2001 From: jpollin98 <152508849+jpollin98@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:41:53 +0100 Subject: [PATCH 019/117] Use node-shared memory for non-thermal excitation ratecoeffs (#99) The main NT_EXCITATIONS list is now stored on node memory instead of local memory as dynamically allocating memory on each rank requires an extremely large amount of memory for 3D nebular simulations. --------- Co-authored-by: Luke Shingles --- nonthermal.cc | 247 +++++++++++++++++++++++++++++--------------------- nonthermal.h | 2 +- sn3d.cc | 2 +- 3 files changed, 147 insertions(+), 104 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 84266ce70..eda7fc34a 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -99,11 +100,15 @@ struct collionrow { double B; double C; double D; - double auger_g_accumulated; // track the statistical weight represented by the values below, so they can be updated - // with new g-weighted averaged values - double prob_num_auger[NT_MAX_AUGER_ELECTRONS + 1]; // probability of 0, 1, ..., NT_MAX_AUGER_ELECTRONS Auger - // electrons being ejected when the shell is ionised - float en_auger_ev; // the average kinetic energy released in Auger electrons after making a hole in this shell + // track the statistical weight represented by the values below, so they can be updated with new g-weighted averaged + // values + double auger_g_accumulated; + + // probability of 0, 1, ..., NT_MAX_AUGER_ELECTRONS Auger electrons being ejected when the shell is ionised + std::array prob_num_auger; + + // the average kinetic energy released in Auger electrons after making a hole in this shell + float en_auger_ev; float n_auger_elec_avg; }; @@ -130,6 +135,15 @@ struct nt_excitation_struct { int loweruptransindex; }; +// temporary storage of full excitation list for current cell before possible truncation and copy to node-shared memory +thread_local std::vector tmp_excitation_list; + +// pointer to either local or node-shared memory excitation list of all cells +nt_excitation_struct *excitations_list_all_cells{}; + +// the minimum of MAX_NT_EXCITATIONS_STORED and the number of included excitation transitions in the atomic dataset +int nt_excitations_stored = 0; + struct nt_solution_struct { double *yfunc{}; // Samples of the Spencer-Fano solution function. Multiply by energy to get non-thermal // electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + @@ -140,16 +154,16 @@ struct nt_solution_struct { float frac_excitation = 0.; // fraction of deposition energy going to excitation // these points arrays of length includedions - float *eff_ionpot{}; // these are used to calculate the non-thermal ionization rate - double *fracdep_ionization_ion = - nullptr; // the fraction of the non-thermal deposition energy going to ionizing this ion + float *eff_ionpot{}; // these are used to calculate the non-thermal ionization rate + double *fracdep_ionization_ion{}; // the fraction of the non-thermal deposition energy going to ionizing each ion - // these point to arrays of length includedions * (NT_MAX_AUGER_ELECTRONS + 1) + // these point to arrays of length includedions * (NT_MAX_AUGER_ELECTRONS + 1) float *prob_num_auger{}; // probability that one ionisation of this ion will produce n Auger electrons. // elements sum to 1.0 for a given ion float *ionenfrac_num_auger{}; // like above, but energy weighted. elements sum to 1.0 for an ion - std::vector frac_excitations_list; + int frac_excitations_list_size = 0; + nt_excitation_struct *frac_excitations_list{}; int timestep_last_solved = -1; // the quantities above were calculated for this timestep float nneperion_when_solved{NAN}; // the nne when the solver was last run @@ -157,8 +171,8 @@ struct nt_solution_struct { nt_solution_struct *nt_solution; -double *deposition_rate_density; -int *deposition_rate_density_timestep; +std::vector deposition_rate_density; +std::vector deposition_rate_density_timestep; void read_shell_configs() { assert_always(NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE); @@ -456,6 +470,27 @@ void read_collion_data() { } } +auto get_possible_nt_excitation_count() -> int { + int ntexcitationcount = 0; + for (int element = 0; element < get_nelements(); element++) { + for (int ion = 0; ion < get_nions(element); ion++) { + const int nlevels = std::min(NTEXCITATION_MAXNLEVELS_LOWER, get_nlevels(element, ion)); + for (int lower = 0; lower < nlevels; lower++) { + const int nuptrans = get_nuptrans(element, ion, lower); + for (int t = 0; t < nuptrans; t++) { + const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; + const int upper = globals::linelist[lineindex].upperlevelindex; + if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { + continue; + } + ntexcitationcount++; + } + } + } + } + return ntexcitationcount; +} + void zero_all_effionpot(const int modelgridindex) { assert_always(nt_solution[modelgridindex].prob_num_auger); assert_always(nt_solution[modelgridindex].ionenfrac_num_auger); @@ -1413,7 +1448,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo double frac_ionization_total = 0.; int excitationindex = 0; // unique index for every included excitation transition - nt_solution[modelgridindex].frac_excitations_list.resize(0); + tmp_excitation_list.resize(0); for (int element = 0; element < get_nelements(); element++) { const int Z = get_atomicnumber(element); const int nions = get_nions(element); @@ -1508,7 +1543,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // unreliable // ratecoeffperdeposition = 0.; - nt_solution[modelgridindex].frac_excitations_list.push_back({ + tmp_excitation_list.push_back({ .frac_deposition = frac_excitation_thistrans, .ratecoeffperdeposition = ratecoeffperdeposition, .lineindex = lineindex, @@ -1571,45 +1606,48 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } } - if constexpr (NT_EXCITATION_ON && (MAX_NT_EXCITATIONS_STORED > 0)) { + if (nt_excitations_stored > 0) { // sort by descending frac_deposition - std::ranges::stable_sort(nt_solution[modelgridindex].frac_excitations_list, std::ranges::greater{}, - &nt_excitation_struct::frac_deposition); + std::ranges::stable_sort(tmp_excitation_list, std::ranges::greater{}, &nt_excitation_struct::frac_deposition); // the excitation list is now sorted by frac_deposition descending const double deposition_rate_density = get_deposition_rate_density(modelgridindex); - if (nt_solution[modelgridindex].frac_excitations_list.size() > MAX_NT_EXCITATIONS_STORED) { + if (std::ssize(tmp_excitation_list) > nt_excitations_stored) { // truncate the sorted list to save memory - printout(" Truncating non-thermal excitation list from %zu to %d transitions.\n", - nt_solution[modelgridindex].frac_excitations_list.size(), MAX_NT_EXCITATIONS_STORED); - nt_solution[modelgridindex].frac_excitations_list.resize(MAX_NT_EXCITATIONS_STORED); + printout(" Truncating non-thermal excitation list from %zu to %d transitions.\n", tmp_excitation_list.size(), + nt_excitations_stored); + tmp_excitation_list.resize(nt_excitations_stored); } + std::copy(tmp_excitation_list.begin(), tmp_excitation_list.end(), + nt_solution[modelgridindex].frac_excitations_list); + + nt_solution[modelgridindex].frac_excitations_list_size = tmp_excitation_list.size(); + printout("[info] mem_usage: non-thermal excitations for cell %d at this timestep occupy %.3f MB\n", modelgridindex, - nt_solution[modelgridindex].frac_excitations_list.size() * + nt_solution[modelgridindex].frac_excitations_list_size * sizeof(nt_solution[modelgridindex].frac_excitations_list[0]) / 1024. / 1024.); const auto T_e = grid::get_Te(modelgridindex); - printout(" Top non-thermal excitation fractions (total excitations = %zu):\n", - nt_solution[modelgridindex].frac_excitations_list.size()); - const int ntransdisplayed = - std::min(50, static_cast(nt_solution[modelgridindex].frac_excitations_list.size())); + printout(" Top non-thermal excitation fractions (total excitations = %d):\n", + nt_solution[modelgridindex].frac_excitations_list_size); + const int ntransdisplayed = std::min(50, nt_solution[modelgridindex].frac_excitations_list_size); for (excitationindex = 0; excitationindex < ntransdisplayed; excitationindex++) { - const double frac_deposition = nt_solution[modelgridindex].frac_excitations_list[excitationindex].frac_deposition; + const auto &ntexc = nt_solution[modelgridindex].frac_excitations_list[excitationindex]; + const double frac_deposition = ntexc.frac_deposition; if (frac_deposition > 0.) { - const int lineindex = nt_solution[modelgridindex].frac_excitations_list[excitationindex].lineindex; - const TransitionLine *line = &globals::linelist[lineindex]; - const int element = line->elementindex; - const int ion = line->ionindex; - const int lower = line->lowerlevelindex; - const int upper = line->upperlevelindex; - const int uptransindex = nt_solution[modelgridindex].frac_excitations_list[excitationindex].loweruptransindex; + const int lineindex = ntexc.lineindex; + const TransitionLine &line = globals::linelist[lineindex]; + const int element = line.elementindex; + const int ion = line.ionindex; + const int lower = line.lowerlevelindex; + const int upper = line.upperlevelindex; + const int uptransindex = ntexc.loweruptransindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon(element, ion, lower); - const double ratecoeffperdeposition = - nt_solution[modelgridindex].frac_excitations_list[excitationindex].ratecoeffperdeposition; + const double ratecoeffperdeposition = ntexc.ratecoeffperdeposition; const double ntcollexc_ratecoeff = ratecoeffperdeposition * deposition_rate_density; const double t_mid = globals::timesteps[timestep].mid; @@ -1631,8 +1669,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::ranges::stable_sort(nt_solution[modelgridindex].frac_excitations_list, std::ranges::less{}, - &nt_excitation_struct::lineindex); + std::ranges::stable_sort(std::span(nt_solution[modelgridindex].frac_excitations_list, + nt_solution[modelgridindex].frac_excitations_list_size), + std::ranges::less{}, &nt_excitation_struct::lineindex); } // NT_EXCITATION_ON @@ -1910,8 +1949,8 @@ void init(const int my_rank, const int ndo_nonempty) { assert_always(nonthermal_initialized == false); nonthermal_initialized = true; - deposition_rate_density = static_cast(malloc(grid::get_npts_model() * sizeof(double))); - deposition_rate_density_timestep = static_cast(malloc(grid::get_npts_model() * sizeof(int))); + deposition_rate_density.resize(grid::get_npts_model()); + deposition_rate_density_timestep.resize(grid::get_npts_model()); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { deposition_rate_density[modelgridindex] = -1.; @@ -1950,6 +1989,46 @@ void init(const int my_rank, const int ndo_nonempty) { fflush(nonthermalfile); } + if (NT_EXCITATION_ON) { + nt_excitations_stored = std::min(MAX_NT_EXCITATIONS_STORED, get_possible_nt_excitation_count()); + printout("[info] mem_usage: storing %d non-thermal excitations for non-empty cells occupies %.3f MB\n", + nt_excitations_stored, + grid::get_nonempty_npts_model() * sizeof(nt_excitation_struct) * nt_excitations_stored / 1024. / 1024.); + + const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); + +#ifdef MPI_ON + + MPI_Win win_shared_excitations_list{}; + + int my_rank_cells = nonempty_npts_model / globals::node_nprocs; + + // rank_in_node 0 gets any remainder + if (globals::rank_in_node == 0) { + my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); + } + + auto size = static_cast(my_rank_cells * sizeof(nt_excitation_struct) * nt_excitations_stored); + + int disp_unit = sizeof(nt_excitation_struct); + MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &excitations_list_all_cells, + &win_shared_excitations_list); + + MPI_Win_shared_query(win_shared_excitations_list, 0, &size, &disp_unit, &excitations_list_all_cells); + + nt_solution = static_cast(calloc(grid::get_npts_model(), sizeof(nt_solution_struct))); + + printout("Finished setting up shared memory for NT Excitation\n"); + MPI_Barrier(MPI_COMM_WORLD); + +#else + + excitations_list_all_cells = static_cast( + malloc(nonempty_npts_model * sizeof(nt_excitation_struct) * nt_excitations_stored)); + +#endif + } + nt_solution = static_cast(calloc(grid::get_npts_model(), sizeof(nt_solution_struct))); size_t mem_usage_yfunc = 0; @@ -1978,6 +2057,11 @@ void init(const int my_rank, const int ndo_nonempty) { mem_usage_yfunc += SFPTS * sizeof(double); } + const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + + nt_solution[modelgridindex].frac_excitations_list = + NT_EXCITATION_ON ? &excitations_list_all_cells[nonemptymgi * nt_excitations_stored] : nullptr; + zero_all_effionpot(modelgridindex); } else { nt_solution[modelgridindex].eff_ionpot = nullptr; @@ -1987,9 +2071,10 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[modelgridindex].ionenfrac_num_auger = nullptr; nt_solution[modelgridindex].yfunc = nullptr; + nt_solution[modelgridindex].frac_excitations_list = nullptr; } - nt_solution[modelgridindex].frac_excitations_list.clear(); + nt_solution[modelgridindex].frac_excitations_list_size = 0; } if (STORE_NT_SPECTRUM) { @@ -2098,9 +2183,6 @@ __host__ __device__ auto get_deposition_rate_density(const int modelgridindex) - void close_file() { nonthermal_initialized = false; - free(deposition_rate_density); - free(deposition_rate_density_timestep); - if (!NT_ON || !NT_SOLVE_SPENCERFANO) { return; } @@ -2295,7 +2377,8 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const } // binary search, assuming the excitation list is sorted by lineindex ascending - auto ntexclist = nt_solution[modelgridindex].frac_excitations_list; + const auto ntexclist = std::span(nt_solution[modelgridindex].frac_excitations_list, + nt_solution[modelgridindex].frac_excitations_list_size); auto ntexcitation = std::ranges::lower_bound(ntexclist, lineindex, {}, &nt_excitation_struct::lineindex); if (ntexcitation == ntexclist.end() || ntexcitation->lineindex != lineindex) { return 0.; @@ -2363,7 +2446,8 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { zrand -= frac_ionization; // now zrand is between zero and frac_excitation // the selection algorithm is the same as for the ionization transitions - for (const auto &ntexcitation : nt_solution[modelgridindex].frac_excitations_list) { + for (const auto &ntexcitation : std::span(nt_solution[modelgridindex].frac_excitations_list, + nt_solution[modelgridindex].frac_excitations_list_size)) { const double frac_deposition_exc = ntexcitation.frac_deposition; if (zrand < frac_deposition_exc) { const int lineindex = ntexcitation.lineindex; @@ -2430,7 +2514,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i nt_solution[modelgridindex].nneperion_when_solved = -1.; nt_solution[modelgridindex].timestep_last_solved = -1; - nt_solution[modelgridindex].frac_excitations_list.resize(0); + nt_solution[modelgridindex].frac_excitations_list_size = 0; zero_all_effionpot(modelgridindex); return; @@ -2623,9 +2707,10 @@ void write_restart_data(FILE *gridsave_file) { } // write NT excitations - fprintf(gridsave_file, "%d\n", static_cast(nt_solution[modelgridindex].frac_excitations_list.size())); + fprintf(gridsave_file, "%d\n", nt_solution[modelgridindex].frac_excitations_list_size); - for (const auto &excitation : nt_solution[modelgridindex].frac_excitations_list) { + for (const auto &excitation : std::span(nt_solution[modelgridindex].frac_excitations_list, + nt_solution[modelgridindex].frac_excitations_list_size)) { fprintf(gridsave_file, "%la %la %d\n", excitation.frac_deposition, excitation.ratecoeffperdeposition, excitation.lineindex); } @@ -2699,8 +2784,8 @@ void read_restart_data(FILE *gridsave_file) { int frac_excitations_list_size_in = 0; assert_always(fscanf(gridsave_file, "%d\n", &frac_excitations_list_size_in) == 1); - if (static_cast(nt_solution[modelgridindex].frac_excitations_list.size()) != frac_excitations_list_size_in) { - nt_solution[modelgridindex].frac_excitations_list.resize(frac_excitations_list_size_in); + if (nt_solution[modelgridindex].frac_excitations_list_size != frac_excitations_list_size_in) { + nt_solution[modelgridindex].frac_excitations_list_size = frac_excitations_list_size_in; } for (int excitationindex = 0; excitationindex < frac_excitations_list_size_in; excitationindex++) { @@ -2721,7 +2806,7 @@ void read_restart_data(FILE *gridsave_file) { } #ifdef MPI_ON -void nt_MPI_Bcast(const int modelgridindex, const int root, const int my_rank) { +void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) { if (grid::get_numassociatedcells(modelgridindex) == 0) { return; } @@ -2751,60 +2836,18 @@ void nt_MPI_Bcast(const int modelgridindex, const int root, const int my_rank) { MPI_FLOAT, root, MPI_COMM_WORLD); // communicate NT excitations - const auto frac_excitations_list_size_old = nt_solution[modelgridindex].frac_excitations_list.size(); - auto frac_excitations_list_size_new = nt_solution[modelgridindex].frac_excitations_list.size(); - MPI_Bcast(&frac_excitations_list_size_new, 1, MPI_INT, root, MPI_COMM_WORLD); - - if (frac_excitations_list_size_new != frac_excitations_list_size_old) { - nt_solution[modelgridindex].frac_excitations_list.resize(frac_excitations_list_size_new); - } - - const auto frac_excitations_list_size = nt_solution[modelgridindex].frac_excitations_list.size(); - int buffer_size = (2 * sizeof(double) + sizeof(int)) * frac_excitations_list_size; - char *buffer = static_cast(malloc(buffer_size)); - int position = 0; - - if constexpr (TESTMODE) { - printout("Size of frac_excitations_list: %zu\n", frac_excitations_list_size); - printout("Buffer size allocated for fractional excitations is %g MB\n", buffer_size / 1024. / 1024.); - } - - MPI_Barrier(MPI_COMM_WORLD); - if (root == my_rank) { - for (size_t excitationindex = 0; excitationindex < frac_excitations_list_size; excitationindex++) { - MPI_Pack(&nt_solution[modelgridindex].frac_excitations_list[excitationindex].frac_deposition, 1, MPI_DOUBLE, - buffer, buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(&nt_solution[modelgridindex].frac_excitations_list[excitationindex].ratecoeffperdeposition, 1, - MPI_DOUBLE, buffer, buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(&nt_solution[modelgridindex].frac_excitations_list[excitationindex].lineindex, 1, MPI_INT, buffer, - buffer_size, &position, MPI_COMM_WORLD); - } + MPI_Bcast(&nt_solution[modelgridindex].frac_excitations_list_size, 1, MPI_INT, root, MPI_COMM_WORLD); + + if (globals::rank_in_node == 0) { + // communicate NT excitation list via inter-node communication + MPI_Bcast( + nt_solution[modelgridindex].frac_excitations_list, + static_cast(nt_solution[modelgridindex].frac_excitations_list_size) * sizeof(nt_excitation_struct), + MPI_BYTE, root_node_id, globals::mpi_comm_internode); } MPI_Barrier(MPI_COMM_WORLD); - MPI_Bcast(buffer, buffer_size, MPI_PACKED, root, MPI_COMM_WORLD); - - MPI_Barrier(MPI_COMM_WORLD); - - position = 0; - - for (size_t excitationindex = 0; excitationindex < frac_excitations_list_size; excitationindex++) { - MPI_Unpack(buffer, buffer_size, &position, - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].frac_deposition, 1, MPI_DOUBLE, - MPI_COMM_WORLD); - MPI_Unpack(buffer, buffer_size, &position, - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].ratecoeffperdeposition, 1, - MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack(buffer, buffer_size, &position, - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].lineindex, 1, MPI_INT, - MPI_COMM_WORLD); - } - - MPI_Barrier(MPI_COMM_WORLD); - - free(buffer); - if (STORE_NT_SPECTRUM) { assert_always(nt_solution[modelgridindex].yfunc != nullptr); MPI_Bcast(nt_solution[modelgridindex].yfunc, SFPTS, MPI_DOUBLE, root, MPI_COMM_WORLD); diff --git a/nonthermal.h b/nonthermal.h index e54bcec12..2b75341b3 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -24,7 +24,7 @@ void calculate_deposition_rate_density(int modelgridindex, int timestep, Heating void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); -void nt_MPI_Bcast(int modelgridindex, int root, int my_rank); +void nt_MPI_Bcast(int modelgridindex, int root, int root_node_id); void nt_reset_stats(); void nt_print_stats(double modelvolume, double deltat); } // namespace nonthermal diff --git a/sn3d.cc b/sn3d.cc index a055efc3f..837e2fee5 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -238,7 +238,7 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const radfield::do_MPI_Bcast(modelgridindex, root, root_node_id); - nonthermal::nt_MPI_Bcast(modelgridindex, root, my_rank); + nonthermal::nt_MPI_Bcast(modelgridindex, root, root_node_id); if (globals::total_nlte_levels > 0 && globals::rank_in_node == 0) { MPI_Bcast(grid::modelgrid[modelgridindex].nlte_pops.data(), globals::total_nlte_levels, MPI_DOUBLE, From 6a8ad2e9da39ecfcec536ef650dd37b9e4ed3e1a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 17 Aug 2024 17:59:41 +0100 Subject: [PATCH 020/117] nonthermal: Store ionstage instead of nelec --- nonthermal.cc | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index eda7fc34a..ddaf4dc2c 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -92,7 +92,7 @@ std::vector> shells_q; struct collionrow { int Z; - int nelec; + int ionstage; int n; int l; double ionpot_ev; @@ -377,7 +377,7 @@ void read_auger_data() { // now loop through shells with impact ionisation cross sections and apply Auger data that matches n, l values for (auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == (Z - ionstage + 1) && collionrow.n == n && collionrow.l == l) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage && collionrow.n == n && collionrow.l == l) { printout( "Z=%2d ionstage %2d shellnum %d n %d l %d ionpot %7.2f E_A %8.1f E_A' %8.1f epsilon %6d %5.1f " "P(n_Auger)", @@ -437,20 +437,22 @@ void read_collion_data() { for (int i = 0; i < colliondatacount; i++) { collionrow collionrow{}; - assert_always(fscanf(cifile, "%2d %2d %1d %1d %lg %lg %lg %lg %lg", &collionrow.Z, &collionrow.nelec, &collionrow.n, + int nelec = -1; + assert_always(fscanf(cifile, "%2d %2d %1d %1d %lg %lg %lg %lg %lg", &collionrow.Z, &nelec, &collionrow.n, &collionrow.l, &collionrow.ionpot_ev, &collionrow.A, &collionrow.B, &collionrow.C, &collionrow.D) == 9); + assert_always(nelec > 0); + collionrow.ionstage = collionrow.Z - nelec + 1; + const int element = get_elementindex(collionrow.Z); - const int ionstage = collionrow.Z - collionrow.nelec + 1; - if (element < 0 || ionstage < get_ionstage(element, 0) || - ionstage > get_ionstage(element, get_nions(element) - 1)) { + if (element < 0 || collionrow.ionstage < get_ionstage(element, 0) || + collionrow.ionstage > get_ionstage(element, get_nions(element) - 1)) { continue; } + + std::ranges::fill(collionrow.prob_num_auger, 0.); collionrow.prob_num_auger[0] = 1.; - for (int a = 1; a <= NT_MAX_AUGER_ELECTRONS; a++) { - collionrow.prob_num_auger[a] = 0.; - } collionrow.auger_g_accumulated = 0.; collionrow.en_auger_ev = 0.; @@ -461,6 +463,7 @@ void read_collion_data() { // printout("ci row: %2d %2d %1d %1d %lg %lg %lg %lg %lg\n", collionrow.Z, collionrow.nelec, collionrow.n, // collionrow.l, collionrow.ionpot_ev, collionrow.A, collionrow.B, collionrow.C, collionrow.D); } + colliondata.shrink_to_fit(); printout("Stored %zu of %d input shell cross sections\n", colliondata.size(), colliondatacount); fclose(cifile); @@ -474,16 +477,15 @@ auto get_possible_nt_excitation_count() -> int { int ntexcitationcount = 0; for (int element = 0; element < get_nelements(); element++) { for (int ion = 0; ion < get_nions(element); ion++) { - const int nlevels = std::min(NTEXCITATION_MAXNLEVELS_LOWER, get_nlevels(element, ion)); - for (int lower = 0; lower < nlevels; lower++) { + const int lower_nlevels = std::min(NTEXCITATION_MAXNLEVELS_LOWER, get_nlevels(element, ion)); + for (int lower = 0; lower < lower_nlevels; lower++) { const int nuptrans = get_nuptrans(element, ion, lower); for (int t = 0; t < nuptrans; t++) { const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; const int upper = globals::linelist[lineindex].upperlevelindex; - if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { - continue; + if (upper < NTEXCITATION_MAXNLEVELS_UPPER) { + ntexcitationcount++; } - ntexcitationcount++; } } } @@ -802,7 +804,7 @@ auto N_e(const int modelgridindex, const double energy) -> double // ionization terms for (const auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == Z - ionstage + 1) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double ionpot_ev = collionrow.ionpot_ev; const double J = get_J(Z, ionstage, ionpot_ev); const double lambda = std::min(SF_EMAX - energy_ev, energy_ev + ionpot_ev); @@ -1106,7 +1108,7 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme double ionpot_valence = -1; for (auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == Z - ionstage + 1) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage) { get_xs_ionization_vector(cross_section_vec, collionrow); if (assumeshellpotentialisvalence) { @@ -1175,7 +1177,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen double ionpot_valence = -1; int matching_nlsubshell_count = 0; for (auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == Z - ionstage + 1) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage) { matching_nlsubshell_count++; const double frac_ionization_shell = calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow); eta_sum += frac_ionization_shell; @@ -1473,7 +1475,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo int matching_nlsubshell_count = 0; for (auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == Z - ionstage + 1) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double frac_ionization_ion_shell = calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow); frac_ionization_ion += frac_ionization_ion_shell; @@ -1647,8 +1649,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const int uptransindex = ntexc.loweruptransindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon(element, ion, lower); - const double ratecoeffperdeposition = ntexc.ratecoeffperdeposition; - const double ntcollexc_ratecoeff = ratecoeffperdeposition * deposition_rate_density; + const double ntcollexc_ratecoeff = ntexc.ratecoeffperdeposition * deposition_rate_density; const double t_mid = globals::timesteps[timestep].mid; const double radexc_ratecoeff = rad_excitation_ratecoeff(modelgridindex, element, ion, lower, uptransindex, @@ -1779,7 +1780,7 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int { gsl_vector *const vec_xs_ionization = gsl_vector_alloc(SFPTS); for (auto &collionrow : colliondata) { - if (collionrow.Z == Z && collionrow.nelec == Z - ionstage + 1) { + if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double ionpot_ev = collionrow.ionpot_ev; const double en_auger_ev = collionrow.en_auger_ev; // const double n_auger_elec_avg = colliondata[n].n_auger_elec_avg; From e86c360bbb363294905a63a092fffd35846b593f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 18 Aug 2024 17:18:09 +0100 Subject: [PATCH 021/117] Non-thermal: Replace a * b / a with b (round-off level change) (#106) --- nonthermal.cc | 14 +++++------- .../results_md5_final.txt | 8 +++---- .../results_md5_job0.txt | 8 +++---- .../results_md5_final.txt | 22 +++++++++---------- .../results_md5_job0.txt | 20 ++++++++--------- 5 files changed, 34 insertions(+), 38 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index ddaf4dc2c..388588832 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1526,21 +1526,17 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } const double epsilon_trans = epsilon(element, ion, upper) - epsilon_lower; - const double nt_frac_excitation_perlevelpop = - epsilon_trans * calculate_nt_excitation_ratecoeff_perdeposition(modelgridindex, element, ion, lower, t, - statweight_lower, epsilon_trans); + const double ratecoeffperdeposition = calculate_nt_excitation_ratecoeff_perdeposition( + modelgridindex, element, ion, lower, t, statweight_lower, epsilon_trans); + const double nt_frac_excitation_perlevelpop = epsilon_trans * ratecoeffperdeposition; const double frac_excitation_thistrans = nnlevel * nt_frac_excitation_perlevelpop; frac_excitation_ion += frac_excitation_thistrans; if constexpr (NT_EXCITATION_ON) { + assert_always(std::isfinite(ratecoeffperdeposition)); // the atomic data set was limited for Fe V, which caused the ground multiplet to be massively // depleted, and then almost no recombination happened! - if (above_minionfraction && nt_frac_excitation_perlevelpop > 0 && (Z != 26 || ionstage != 5)) { - const double ratecoeffperdeposition = nt_frac_excitation_perlevelpop / epsilon_trans; - - assert_always(ratecoeffperdeposition >= 0); - assert_always(std::isfinite(ratecoeffperdeposition)); - + if (above_minionfraction && ratecoeffperdeposition > 0 && (Z != 26 || ionstage != 5)) { // if (get_coll_str(lineindex) < 0) // if collision strength is not defined, the rate coefficient is // unreliable // ratecoeffperdeposition = 0.; diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 75c3846d4..6b9eb8215 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -11,17 +11,17 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out c1a6cec53ad08507a3d33d26da81f5a0 packets00_0000.out -82de8a66326c3e03921a1c8a202964cd packets00_0001.out +cd7bb6d7cfe495b7406ef294bcbf8aa5 packets00_0001.out c991bc240721279875b2936204a3bfc4 packets00_0002.out 1f3dfaafc02a8cbb47a3e62ba1f5f577 packets00_0003.out 5ebe9a852e9975574a6c946396b2a493 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out 41a368446a406a721a6f9e8ba501f688 job1/estimators_0000.out d4944478ee048e90c97b36d446da524d job1/estimators_0001.out -b7425d047198d784b042fe7ccaaa76a3 job1/estimators_0002.out +5e017495cce2903b6562ee5898ae700c job1/estimators_0002.out 68bc097a9846683d70a6ea4c05409b6c job1/nlte_0000.out -d3ed010a31599ee2b89923280f964ecd job1/nlte_0001.out -87baf1e0392e88950f8eb63611b1c8f4 job1/nlte_0002.out +1f42a41c734a379c43c9831282e01a3b job1/nlte_0001.out +a503160f8b2ab0daafd1a327155c89d9 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index 1f3ffbf81..0ed2709df 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -17,13 +17,13 @@ b2550978a93cc4b3e90784b845f03e03 light_curve.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out d5be89a8d1af7fd6be5c43872e445d6f job0/estimators_0000.out c10f74a61fbd197aad25725bb48c5168 job0/estimators_0001.out -d688dd4c1320e4b17285afc409889085 job0/estimators_0002.out +4f4c606953b350605dc8b8b03a169bac job0/estimators_0002.out 784108881cb7cd2ab9f880ba22105f1c job0/nlte_0000.out -2ef5f4bd1f7f18e105c00c9c14f60372 job0/nlte_0001.out -41e8612ead2de71745aa862549c8738c job0/nlte_0002.out +8d081daafb63005388d675bb5a09bd7e job0/nlte_0001.out +cd0456b8df5b41aca5f930a26cfb6c32 job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -a246460b3f977ebc4075b332fc883a85 job0/radfield_0000.out +7e9eeae2662e50b8cdacea0e48b17a2f job0/radfield_0000.out 557988c63e95c5fd7c1afe44facdb6b0 job0/radfield_0001.out 23af1dc66920467d2dfae6f70272029f job0/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 320e4b183..3ba8339ec 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -10,21 +10,21 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out 2fbe87a317801b68d8097d3d0083fc1f light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -c9bcddf85fd37d293d1fea9f8228bc64 packets00_0000.out -9a394b36a5a54b61817beb6c0f6940ca packets00_0001.out -d596b43bdad55241ef176d6831209d9f packets00_0002.out -d7d3895079e60e383f3addadf81e0e63 packets00_0003.out +3dfe8799a8e5604d417d2660e7c3d527 packets00_0000.out +125289b175cfdc79c07f96c460d51622 packets00_0001.out +e8247a5cf14742233c9c4e00a9d6b9f2 packets00_0002.out +9b1bfec708d8a15bed0ac2526fed4b09 packets00_0003.out c794b14a31f6c47464b0bbe72c5ce0fb spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out cd82cf5f2a867ec6f1ee328533c3db31 job1/estimators_0000.out -cabb6379d0aa3af3c696b3ac76ef395b job1/estimators_0001.out -deafe1934c00b337a086488f189a9c76 job1/estimators_0002.out -60319cc607d07450d133097ffc047733 job1/nlte_0000.out -9e28edade1e73d51c3fb8c480d615961 job1/nlte_0001.out -dcc7a3c1dae628b793eb7ae1410ca39e job1/nlte_0002.out +8da02f394fbaff90ae7f5d42902dca19 job1/estimators_0001.out +85938a7cf404d6a321fc213a953a64b6 job1/estimators_0002.out +7a77628812bcc3817cf521249cce7197 job1/nlte_0000.out +6c51dd67dc33038823e674710e862faa job1/nlte_0001.out +e61ba5b8b4780b62ee05076ff45268a6 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -69d3a85085154dbc2f4bcbe1cc10d311 job1/radfield_0000.out +79737c6717a49beec528fd4d6bb7fca1 job1/radfield_0000.out 5281dd710252b0c2c08ed50355ba3987 job1/radfield_0001.out -6e9074af85aba3a62555b01052581671 job1/radfield_0002.out +14c3f5bd88492c3b863e075a305b77e5 job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index ca7335899..39ac20ea1 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -9,21 +9,21 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out a0593185f1a88664c8df5ca8db65160f light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -e1a43ad7854ba07c3039aa219120879f packets00_0000.out -6e8dc1d1c515cc44e291e725a68d2bef packets00_0001.out -4a36a1cb05e6935777d8b2b12183aca6 packets00_0002.out -0912a606740de431a0d3164cb8657f2e packets00_0003.out +0657a2cde6aa10cab3afd3f4f0793a58 packets00_0000.out +45de6bcc5f0280c42cff5a82f88edf26 packets00_0001.out +78aff0b4f5a6cc7992e0f695e34807bc packets00_0002.out +584cbfce883f9fd38f1e7f15b96612c7 packets00_0003.out 4bb17284dbfe23d42f9eaecd7c9cdb44 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out e831f0a4a820c3932f54196718e229e4 job0/estimators_0000.out 340dc15b95391780cc400bfef074f00c job0/estimators_0001.out -e8d5416218afc33407ef1029fb74d791 job0/estimators_0002.out -95bd6cac6bf694cf9ec3534741686129 job0/nlte_0000.out -5d63a6fab6ce324a98b58cc75e328edd job0/nlte_0001.out -98466294358c997c37029fee6fd96e75 job0/nlte_0002.out +c25cbbd7255fe4af2c6eb604877ca190 job0/estimators_0002.out +e5ace14c553cf3740bee1df94fde209d job0/nlte_0000.out +7c46469ea1f9675cc7a33c9004d989e5 job0/nlte_0001.out +ebc341a405730478997b4987bb76b9c1 job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -ea8e226d96878c1e9dbf03d51d8a901a job0/radfield_0000.out -66ae75f111c660835fd74575d3f5efb1 job0/radfield_0001.out +c5b81a79d8ae799c09c588b41f1e3a2f job0/radfield_0000.out +ab52b0e6955ad389c85125df8cc064f6 job0/radfield_0001.out fdeb82c6b0b35791d1f28d2b56a86259 job0/radfield_0002.out From 40264ca7b7223a175aff71f8d0dc85dbf7860e34 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 19 Aug 2024 16:23:39 +0100 Subject: [PATCH 022/117] Nonthermal: simplify and reduce memory use, clean up comments (#107) --- .clang-tidy | 1 - artisoptions_christinenonthermal.h | 4 +- artisoptions_classic.h | 4 +- artisoptions_doc.md | 18 +- artisoptions_kilonova_lte.h | 4 +- artisoptions_nltenebular.h | 4 +- artisoptions_nltewithoutnonthermal.h | 4 +- atomic.h | 169 +++---- constants.h | 17 +- decay.cc | 77 ++- exspec.cc | 6 +- exspec.h | 2 +- gammapkt.cc | 68 ++- globals.h | 88 ++-- grid.cc | 304 ++++++------ grid.h | 34 +- input.cc | 197 ++++---- kpkt.cc | 144 +++--- ltepop.cc | 87 ++-- macroatom.cc | 158 +++---- nltepop.cc | 16 +- nonthermal.cc | 440 ++++++------------ nonthermal.h | 2 +- packet.cc | 25 +- packet.h | 8 +- radfield.cc | 71 ++- ratecoeff.cc | 179 ++++--- rpkt.cc | 182 ++++---- rpkt.h | 2 +- sn3d.cc | 70 +-- spectrum_lightcurve.cc | 16 +- stats.cc | 2 +- tests/setup_classicmode_1d_3dgrid.sh | 2 +- tests/setup_classicmode_3d.sh | 2 +- tests/setup_kilonova_1d_1dgrid.sh | 2 +- tests/setup_kilonova_1d_3dgrid.sh | 2 +- tests/setup_kilonova_2d_2dgrid.sh | 2 +- ...kilonova_2d_2dgrid_barnesthermalisation.sh | 2 +- .../setup_kilonova_2d_2dgrid_expansionopac.sh | 2 +- ...up_kilonova_2d_2dgrid_xcomgammaphotoion.sh | 2 +- tests/setup_kilonova_2d_3dgrid.sh | 2 +- tests/setup_nebular_1d_3dgrid.sh | 2 +- tests/setup_nebular_1d_3dgrid_limitbfest.sh | 2 +- thermalbalance.cc | 72 ++- update_grid.cc | 90 ++-- update_packets.cc | 13 +- vectors.h | 51 +- 47 files changed, 1140 insertions(+), 1511 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 2c570b4a3..db8c0d55a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -44,7 +44,6 @@ Checks: > -readability-magic-numbers, WarningsAsErrors: > *, - -performance-enum-size, FormatStyle: file ExtraArgs: [-std=c++20] CheckOptions: diff --git a/artisoptions_christinenonthermal.h b/artisoptions_christinenonthermal.h index 4d5b917af..c648cc0db 100644 --- a/artisoptions_christinenonthermal.h +++ b/artisoptions_christinenonthermal.h @@ -9,7 +9,7 @@ constexpr int MPKTS = 10000; -constexpr int GRID_TYPE = GRID_CARTESIAN3D; +constexpr auto GRID_TYPE = GridType::CARTESIAN3D; constexpr int CUBOID_NCOORDGRID_X = 100; constexpr int CUBOID_NCOORDGRID_Y = 100; constexpr int CUBOID_NCOORDGRID_Z = 100; @@ -133,7 +133,7 @@ constexpr bool USE_CALCULATED_MEANATOMICWEIGHT = false; constexpr bool WRITE_PARTIAL_EMISSIONABSORPTIONSPEC = false; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD = TIMESTEP_SIZES_LOGARITHMIC; +constexpr auto TIMESTEP_SIZE_METHOD = TimeStepSizeMethod::LOGARITHMIC; constexpr double FIXED_TIMESTEP_WIDTH = -1.; diff --git a/artisoptions_classic.h b/artisoptions_classic.h index 1900ec104..bf6534a0d 100644 --- a/artisoptions_classic.h +++ b/artisoptions_classic.h @@ -9,7 +9,7 @@ constexpr int MPKTS = 100000; -constexpr int GRID_TYPE = GRID_CARTESIAN3D; +constexpr auto GRID_TYPE = GridType::CARTESIAN3D; constexpr int CUBOID_NCOORDGRID_X = 100; constexpr int CUBOID_NCOORDGRID_Y = 100; constexpr int CUBOID_NCOORDGRID_Z = 100; @@ -131,7 +131,7 @@ constexpr bool USE_CALCULATED_MEANATOMICWEIGHT = false; constexpr bool WRITE_PARTIAL_EMISSIONABSORPTIONSPEC = false; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD = TIMESTEP_SIZES_LOGARITHMIC; +constexpr auto TIMESTEP_SIZE_METHOD = TimeStepSizeMethod::LOGARITHMIC; constexpr double FIXED_TIMESTEP_WIDTH = -1.; diff --git a/artisoptions_doc.md b/artisoptions_doc.md index 3f02058bf..8e02ba737 100644 --- a/artisoptions_doc.md +++ b/artisoptions_doc.md @@ -2,9 +2,9 @@ // Number of energy packets per process (MPI rank). OpenMP threads share these packets constexpr int MPKTS; -constexpr int GRID_TYPE = {GRID_CARTESIAN3D, GRID_CYLINDRICAL2D, GRID_SPHERICAL1D} +constexpr auto GRID_TYPE = {GridType::CARTESIAN3D, GridType::CYLINDRICAL2D, GridType::SPHERICAL1D} -// for GRID_CARTESIAN3D, set the dimensions. This will have no effect with a 3D model.txt since they will be set to match the input +// for GridType::CARTESIAN3D, set the dimensions. This will have no effect with a 3D model.txt since they will be set to match the input constexpr int CUBOID_NCOORDGRID_X; constexpr int CUBOID_NCOORDGRID_Y; constexpr int CUBOID_NCOORDGRID_Z; @@ -53,7 +53,7 @@ constexpr bool USE_MODEL_INITIAL_ENERGY; // record counts of emissions and absorptions in each line constexpr bool RECORD_LINESTAT; -/// Rate coefficients +// Rate coefficients constexpr int TABLESIZE; constexpr double MINTEMP; constexpr double MAXTEMP; @@ -74,8 +74,8 @@ constexpr bool TRACK_ION_STATS; constexpr double MINPOP; -constexpr double NU_MIN_R; /// lower frequency boundary for UVOIR spectra and BB sampling -constexpr double NU_MAX_R; /// upper frequency boundary for UVOIR spectra and BB sampling +constexpr double NU_MIN_R; // lower frequency boundary for UVOIR spectra and BB sampling +constexpr double NU_MAX_R; // upper frequency boundary for UVOIR spectra and BB sampling // ** Start of radiation field model options ** @@ -203,14 +203,8 @@ constexpr bool INSTANT_PARTICLE_DEPOSITION; // values that would give the same number or more more fixed timesteps than the total number of timesteps in the // simulation. The times are set in days. -enum timestepsizemethods { - TIMESTEP_SIZES_LOGARITHMIC = 0, - TIMESTEP_SIZES_CONSTANT = 1, - TIMESTEP_SIZES_LOGARITHMIC_THEN_CONSTANT = 2, - TIMESTEP_SIZES_CONSTANT_THEN_LOGARITHMIC = 3, -}; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD; +constexpr enum class timestepsizemethods TIMESTEP_SIZE_METHOD; constexpr double FIXED_TIMESTEP_WIDTH; diff --git a/artisoptions_kilonova_lte.h b/artisoptions_kilonova_lte.h index 3d38dda29..27790b5b6 100644 --- a/artisoptions_kilonova_lte.h +++ b/artisoptions_kilonova_lte.h @@ -9,7 +9,7 @@ constexpr int MPKTS = 15000; -constexpr int GRID_TYPE = GRID_CARTESIAN3D; +constexpr auto GRID_TYPE = GridType::CARTESIAN3D; constexpr int CUBOID_NCOORDGRID_X = 50; constexpr int CUBOID_NCOORDGRID_Y = 50; constexpr int CUBOID_NCOORDGRID_Z = 50; @@ -130,7 +130,7 @@ constexpr bool USE_CALCULATED_MEANATOMICWEIGHT = true; constexpr bool WRITE_PARTIAL_EMISSIONABSORPTIONSPEC = false; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD = TIMESTEP_SIZES_LOGARITHMIC; +constexpr auto TIMESTEP_SIZE_METHOD = TimeStepSizeMethod::LOGARITHMIC; constexpr double FIXED_TIMESTEP_WIDTH = -1.; diff --git a/artisoptions_nltenebular.h b/artisoptions_nltenebular.h index 8194ad7db..8b055acdf 100644 --- a/artisoptions_nltenebular.h +++ b/artisoptions_nltenebular.h @@ -9,7 +9,7 @@ constexpr int MPKTS = 1000000; -constexpr int GRID_TYPE = GRID_CARTESIAN3D; +constexpr auto GRID_TYPE = GridType::CARTESIAN3D; constexpr int CUBOID_NCOORDGRID_X = 50; constexpr int CUBOID_NCOORDGRID_Y = 50; constexpr int CUBOID_NCOORDGRID_Z = 50; @@ -142,7 +142,7 @@ constexpr bool USE_CALCULATED_MEANATOMICWEIGHT = false; constexpr bool WRITE_PARTIAL_EMISSIONABSORPTIONSPEC = false; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD = TIMESTEP_SIZES_LOGARITHMIC; +constexpr auto TIMESTEP_SIZE_METHOD = TimeStepSizeMethod::LOGARITHMIC; constexpr double FIXED_TIMESTEP_WIDTH = -1.; diff --git a/artisoptions_nltewithoutnonthermal.h b/artisoptions_nltewithoutnonthermal.h index e144d015c..e48d2d86a 100644 --- a/artisoptions_nltewithoutnonthermal.h +++ b/artisoptions_nltewithoutnonthermal.h @@ -9,7 +9,7 @@ constexpr int MPKTS = 10000; -constexpr int GRID_TYPE = GRID_CARTESIAN3D; +constexpr auto GRID_TYPE = GridType::CARTESIAN3D; constexpr int CUBOID_NCOORDGRID_X = 100; constexpr int CUBOID_NCOORDGRID_Y = 100; constexpr int CUBOID_NCOORDGRID_Z = 100; @@ -134,7 +134,7 @@ constexpr bool USE_CALCULATED_MEANATOMICWEIGHT = false; constexpr bool WRITE_PARTIAL_EMISSIONABSORPTIONSPEC = false; -constexpr enum timestepsizemethods TIMESTEP_SIZE_METHOD = TIMESTEP_SIZES_LOGARITHMIC; +constexpr auto TIMESTEP_SIZE_METHOD = TimeStepSizeMethod::LOGARITHMIC; constexpr double FIXED_TIMESTEP_WIDTH = 0.1; diff --git a/atomic.h b/atomic.h index 4ee7471e8..e28c47d70 100644 --- a/atomic.h +++ b/atomic.h @@ -19,17 +19,18 @@ inline int includedions = 0; // total number of levels of any element inline int includedlevels = 0; -inline double - last_phixs_nuovernuedge; // last photoion cross section point as a factor of nu_edge = last_phixs_nuovernuedge -inline std::array phixs_file_version_exists; // first value in this array is not used but exists so the - // indexes match those of the phixsdata_filenames array +// last photoion cross section point as a factor of nu_edge = last_phixs_nuovernuedge +inline double last_phixs_nuovernuedge; + +// first value in this array is not used but exists so the indexes match those of the phixsdata_filenames array +inline std::array phixs_file_version_exists; + constexpr std::array phixsdata_filenames = {"version0ignore", "phixsdata.txt", "phixsdata_v2.txt"}; [[nodiscard]] inline auto get_nelements() -> int { return static_cast(globals::elements.size()); } -inline auto get_nnion_tot(int modelgridindex) -> double // total density of nuclei -{ +inline auto get_nnion_tot(int modelgridindex) -> double { double nntot = 0.; for (int element = 0; element < get_nelements(); element++) { nntot += grid::get_elem_numberdens(modelgridindex, element); @@ -38,53 +39,43 @@ inline auto get_nnion_tot(int modelgridindex) -> double return nntot; } -inline auto get_nions(const int element) -> int -/// Returns the number of ions associated with a specific element given by -/// its elementindex. -{ +// Return the number of ions associated with a specific element given by its elementindex. +inline auto get_nions(const int element) -> int { assert_testmodeonly(element < get_nelements()); return globals::elements[element].nions; } -inline auto get_nlevels(const int element, const int ion) -> int -/// Returns the number of levels associated with with a specific ion given -/// its elementindex and ionindex. -{ +// Return the number of levels associated with with a specific ion given its elementindex and ionindex. +inline auto get_nlevels(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].nlevels; } -[[nodiscard]] inline auto epsilon(const int element, const int ion, const int level) -> double -/// Returns the energy of (element,ion,level). -{ +// Return the energy of (element,ion,level). +[[nodiscard]] inline auto epsilon(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); return globals::elements[element].ions[ion].levels[level].epsilon; } -[[nodiscard]] inline auto get_ionstage(const int element, const int ion) -> int -/// Returns the ionisation stage of an ion specified by its elementindex and -/// ionindex. -{ +// Return the ionisation stage of an ion specified by its elementindex and ionindex. +[[nodiscard]] inline auto get_ionstage(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].ionstage; } -[[nodiscard]] inline auto get_ionisinglevels(const int element, const int ion) -> int -/// Returns the number of levels associated with an ion that -/// have energies below the ionisation threshold. -{ +// Return the number of levels associated with an ion that have energies below the ionisation threshold. +[[nodiscard]] inline auto get_ionisinglevels(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].ionisinglevels; } -inline auto get_nphixstargets(const int element, const int ion, const int level) -> int -/// Returns the number of target states for photoionization of (element,ion,level). -{ +// Returns the number of target states for photoionization of (element,ion,level). +inline auto get_nphixstargets(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(level < get_nlevels(element, ion)); const int nions = get_nions(element); @@ -95,10 +86,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return 0; } +// Return the level index of a target state for photoionization of (element,ion,level). [[nodiscard]] inline auto get_phixsupperlevel(const int element, const int ion, const int level, - const int phixstargetindex) -> int -/// Returns the level index of a target state for photoionization of (element,ion,level). -{ + const int phixstargetindex) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); @@ -108,10 +98,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return globals::elements[element].ions[ion].levels[level].phixstargets[phixstargetindex].levelindex; } +// Return the probability of a target state for photoionization of (element,ion,level). [[nodiscard]] inline auto get_phixsprobability(const int element, const int ion, const int level, - const int phixstargetindex) -> double -/// Returns the probability of a target state for photoionization of (element,ion,level). -{ + const int phixstargetindex) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); @@ -121,38 +110,32 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return globals::elements[element].ions[ion].levels[level].phixstargets[phixstargetindex].probability; } -[[nodiscard]] inline auto einstein_spontaneous_emission(const int lineindex) -> double // double einstein_spontaneous_emission(int element, int ion, int upper, int lower) -/// reads A_ul from levellist which consists of -/// (epsilon_upper; 0) | (g_upper; 0) | (A_upper,upper-1; f_upper,upper-1) | (A_uppper,upper-2; f_upper,upper-2) | ... | -/// (A_upper,1; f_upper,1) -{ +// reads A_ul from levellist which consists of +// (epsilon_upper; 0) | (g_upper; 0) | (A_upper,upper-1; f_upper,upper-1) | (A_uppper,upper-2; f_upper,upper-2) | ... | +// (A_upper,1; f_upper,1) +[[nodiscard]] inline auto einstein_spontaneous_emission(const int lineindex) -> double { return globals::linelist[lineindex].einstein_A; } -[[nodiscard]] inline auto stat_weight(const int element, const int ion, const int level) -> double -/// Returns the statistical weight of (element,ion,level). -{ +// Return the statistical weight of (element,ion,level). +[[nodiscard]] inline auto stat_weight(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); return globals::elements[element].ions[ion].levels[level].stat_weight; } -[[nodiscard]] inline auto get_maxrecombininglevel(const int element, const int ion) -> int -/// Returns the number of bf-continua associated with ion ion of element element. -{ +// Return the number of bf-continua associated with ion ion of element element. +[[nodiscard]] inline auto get_maxrecombininglevel(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].maxrecombininglevel; } +// Calculate the photoionisation cross-section at frequency nu out of the atomic data. [[nodiscard]] inline auto photoionization_crosssection_fromtable(const float *const photoion_xs, const double nu_edge, - const double nu) -> double -/// Calculates the photoionisation cross-section at frequency nu out of the atomic data. -/// Input: - edge frequency nu_edge of the desired bf-continuum -/// - nu -{ + const double nu) -> double { // if (nu < nu_edge || nu > nu_edge * 1.05) // return 0; // else @@ -169,9 +152,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) const int i = static_cast(floor((nu - nu_edge) / (globals::NPHIXSNUINCREMENT * nu_edge))); sigma_bf = photoion_xs[i]; } else { - /// use a parameterization of sigma_bf by the Kramers formula - /// which anchor point should we take ??? the cross-section at the edge or at the highest grid point ??? - /// so far the highest grid point, otherwise the cross-section is not continuous + // use a parameterization of sigma_bf by the Kramers formula + // which anchor point should we take ??? the cross-section at the edge or at the highest grid point ??? + // so far the highest grid point, otherwise the cross-section is not continuous sigma_bf = photoion_xs[globals::NPHIXSPOINTS - 1] * pow(nu_edge * (1 + globals::NPHIXSNUINCREMENT * globals::NPHIXSPOINTS) / nu, 3); } @@ -197,9 +180,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) const double factor_b = ireal - i; sigma_bf = ((1. - factor_b) * sigma_bf_a) + (factor_b * sigma_bf_b); } else { - /// use a parameterization of sigma_bf by the Kramers formula - /// which anchor point should we take ??? the cross-section at the edge or at the highest grid point ??? - /// so far the highest grid point, otherwise the cross-section is not continuous + // use a parameterization of sigma_bf by the Kramers formula + // which anchor point should we take ??? the cross-section at the edge or at the highest grid point ??? + // so far the highest grid point, otherwise the cross-section is not continuous const double nu_max_phixs = nu_edge * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table sigma_bf = photoion_xs[globals::NPHIXSPOINTS - 1] * pow(nu_max_phixs / nu, 3); } @@ -249,28 +232,25 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) inline void set_nelements(const int nelements_in) { globals::elements.resize(nelements_in); } -inline auto get_atomicnumber(const int element) -> int -/// Returns the atomic number associated with a given elementindex. -{ +// Returns the atomic number associated with a given elementindex. +inline auto get_atomicnumber(const int element) -> int { assert_testmodeonly(element >= 0); assert_testmodeonly(element < get_nelements()); return globals::elements[element].anumber; } -[[nodiscard]] inline auto is_nlte(const int element, const int ion, const int level) -> bool // Returns true if (element,ion,level) is to be treated in nlte. // (note this function returns true for the ground state, // although it is stored separately from the excited NLTE states) -{ +[[nodiscard]] inline auto is_nlte(const int element, const int ion, const int level) -> bool { return LEVEL_IS_NLTE(get_atomicnumber(element), get_ionstage(element, ion), level); // defined in artisoptions.h } -inline auto get_elementindex(const int Z) -> int -/// Returns the elementindex associated with a given atomic number. -/// If there is no element with the given atomic number in the atomic data -/// a negative value is returned to flag this event. -{ +// Return the elementindex associated with a given atomic number. +// If there is no element with the given atomic number in the atomic data, +// then return a negative value +inline auto get_elementindex(const int Z) -> int { const auto elem = std::ranges::find_if(globals::elements, [Z](const Element &element) { return element.anumber == Z; }); if (elem != globals::elements.end()) { @@ -296,22 +276,14 @@ inline void update_includedionslevels_maxnions() { } } -inline auto get_includedions() -> int -// returns the number of ions of all elements combined -{ - return includedions; -} +// return the number of ions of all elements combined +inline auto get_includedions() -> int { return includedions; } -inline auto get_includedlevels() -> int -// returns the number of ions of all elements combined -{ - return includedlevels; -} +// return the number of ions of all elements combined +inline auto get_includedlevels() -> int { return includedlevels; } -[[nodiscard]] inline auto get_max_nions() -> int { - // number greater than or equal to nions(element) for all elements - return maxnions; -} +// get a number greater than or equal to nions(element) for all elements +[[nodiscard]] inline auto get_max_nions() -> int { return maxnions; } [[nodiscard]] inline auto elem_has_nlte_levels(const int element) -> bool { return globals::elements[element].has_nlte_levels; @@ -328,18 +300,16 @@ inline auto get_includedlevels() -> int return false; } -[[nodiscard]] inline auto get_nlevels_nlte(const int element, const int ion) -> int // Returns the number of NLTE levels associated with with a specific ion given // its elementindex and ionindex. Includes the superlevel if there is one but does not include the ground state -{ +[[nodiscard]] inline auto get_nlevels_nlte(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].nlevels_nlte; } -[[nodiscard]] inline auto level_isinsuperlevel(const int element, const int ion, const int level) -> bool // ion has NLTE levels, but this one is not NLTE => is in the superlevel -{ +[[nodiscard]] inline auto level_isinsuperlevel(const int element, const int ion, const int level) -> bool { return (!is_nlte(element, ion, level) && level != 0 && (get_nlevels_nlte(element, ion) > 0)); } @@ -349,9 +319,8 @@ inline auto get_includedlevels() -> int return globals::elements[element].ions[ion].nlevels_groundterm; } -[[nodiscard]] inline auto get_uniqueionindex(const int element, const int ion) -> int // Get an index for an ionstage of an element that is unique for every ion of every element -{ +[[nodiscard]] inline auto get_uniqueionindex(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -377,9 +346,8 @@ inline auto get_includedlevels() -> int assert_always(false); // allionsindex too high to be valid } -[[nodiscard]] inline auto get_uniquelevelindex(const int element, const int ion, const int level) -> int // Get an index for level of an ionstage of an element that is unique across every ion of every element -{ +[[nodiscard]] inline auto get_uniquelevelindex(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); @@ -389,9 +357,8 @@ inline auto get_includedlevels() -> int return uniquelevelindex; } -[[nodiscard]] inline auto get_levelfromuniquelevelindex(const int alllevelsindex) -> std::tuple // inverse of get_uniquelevelindex(). get the element/ion/level from a unique level index -{ +[[nodiscard]] inline auto get_levelfromuniquelevelindex(const int alllevelsindex) -> std::tuple { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -414,36 +381,32 @@ inline auto get_includedlevels() -> int return (get_nlevels(element, ion) > get_nlevels_nlte(element, ion) + 1); } -[[nodiscard]] inline auto get_ndowntrans(const int element, const int ion, const int level) -> int // the number of downward bound-bound transitions from the specified level -{ +[[nodiscard]] inline auto get_ndowntrans(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); return globals::elements[element].ions[ion].levels[level].ndowntrans; } -[[nodiscard]] inline auto get_nuptrans(const int element, const int ion, const int level) -> int // the number of upward bound-bound transitions from the specified level -{ +[[nodiscard]] inline auto get_nuptrans(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); return globals::elements[element].ions[ion].levels[level].nuptrans; } -inline void set_ndowntrans(const int element, const int ion, const int level, const int ndowntrans) // the number of downward bound-bound transitions from the specified level -{ +inline void set_ndowntrans(const int element, const int ion, const int level, const int ndowntrans) { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); globals::elements[element].ions[ion].levels[level].ndowntrans = ndowntrans; } -inline void set_nuptrans(const int element, const int ion, const int level, const int nuptrans) // the number of upward bound-bound transitions from the specified level -{ +inline void set_nuptrans(const int element, const int ion, const int level, const int nuptrans) { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); @@ -463,19 +426,17 @@ inline void set_nuptrans(const int element, const int ion, const int level, cons return -1; } -[[nodiscard]] inline auto get_emtype_continuum(const int element, const int ion, const int level, - const int upperionlevel) -> int // Returns the emissiontype index of the continuum associated to the given level. Will be negative and ordered by // element/ion/level/phixstargetindex -{ +[[nodiscard]] inline auto get_emtype_continuum(const int element, const int ion, const int level, + const int upperionlevel) -> int { const int phixstargetindex = get_phixtargetindex(element, ion, level, upperionlevel); return globals::elements[element].ions[ion].levels[level].cont_index - phixstargetindex; } +// Returns the energy of (element,ion,level). [[nodiscard]] inline auto get_phixs_threshold(const int element, const int ion, const int level, - const int phixstargetindex) -> double -/// Returns the energy of (element,ion,level). -{ + const int phixstargetindex) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); diff --git a/constants.h b/constants.h index d515cf386..a605fca95 100644 --- a/constants.h +++ b/constants.h @@ -46,26 +46,19 @@ constexpr double OSCSTRENGTHCONVERSION = 1.3473837e+21; constexpr double H_ionpot = 13.5979996 * EV; -enum gridtypes { - GRID_SPHERICAL1D = 1, // 1D radial shells (non-uniform dr) - GRID_CYLINDRICAL2D = 2, // 2D cylindrical grid with uniform dz, drcyl - GRID_CARTESIAN3D = 3 // 3D Cartesian cubic grid with uniform dx=dy=dz +enum class GridType { + SPHERICAL1D, // 1D radial shells (non-uniform dr) + CYLINDRICAL2D, // 2D cylindrical grid with uniform dz, drcyl + CARTESIAN3D // 3D Cartesian cubic grid with uniform dx=dy=dz }; -constexpr int GRID_UNIFORM = GRID_CARTESIAN3D; // deprecated alias for GRID_CARTESIAN3D - // constant for van-Regemorter approximation. constexpr double C_0 = 5.465e-11; constexpr int MAXFILENAMELENGTH = 128; constexpr size_t GSLWSIZE = 16384; // GSL integration workspace size -enum timestepsizemethods { - TIMESTEP_SIZES_LOGARITHMIC = 0, - TIMESTEP_SIZES_CONSTANT = 1, - TIMESTEP_SIZES_LOGARITHMIC_THEN_CONSTANT = 2, - TIMESTEP_SIZES_CONSTANT_THEN_LOGARITHMIC = 3, -}; +enum class TimeStepSizeMethod { LOGARITHMIC, CONSTANT, LOGARITHMIC_THEN_CONSTANT, CONSTANT_THEN_LOGARITHMIC }; enum class ThermalisationScheme { INSTANT, DETAILED, BARNES, WOLLAEGER, GUTTMAN }; diff --git a/decay.cc b/decay.cc index 939b276a3..cd0ab6064 100644 --- a/decay.cc +++ b/decay.cc @@ -149,9 +149,8 @@ MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; return get_nuc_decaybranchprob(get_nucindex(z_parent, a_parent), decaytype); } -[[nodiscard]] auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool // check if (z_parent, a_parent) is a parent of (z, a) -{ +[[nodiscard]] auto nuc_is_parent(const int z_parent, const int a_parent, const int z, const int a) -> bool { assert_testmodeonly(nuc_exists(z_parent, a_parent)); // each radioactive nuclide is limited to one daughter nuclide return std::ranges::any_of(all_decaytypes, [=](const auto decaytype) { @@ -165,9 +164,8 @@ MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; return {nuclides[nucindex].z, nuclides[nucindex].a}; } -[[nodiscard]] auto get_nucindex_or_neg_one(const int z, const int a) -> int // get the nuclide array index from the atomic number and mass number -{ +[[nodiscard]] auto get_nucindex_or_neg_one(const int z, const int a) -> int { assert_testmodeonly(get_num_nuclides() > 0); const int num_nuclides = get_num_nuclides(); @@ -199,10 +197,9 @@ void printout_nuclidemeanlife(const int z, const int a) { } } -[[nodiscard]] auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double // decay energy in the form of kinetic energy of electrons, positrons, or alpha particles, // depending on the relevant decay type (but not including neutrinos) -{ +[[nodiscard]] auto nucdecayenergyparticle(const int nucindex, const int decaytype) -> double { assert_testmodeonly(decaytype >= 0); assert_testmodeonly(decaytype < decaytypes::DECAYTYPE_COUNT); @@ -225,9 +222,8 @@ void printout_nuclidemeanlife(const int z, const int a) { } } -[[nodiscard]] auto nucdecayenergytotal(const int z, const int a) -> double // average energy (erg) per decay in the form of gammas and particles [erg] -{ +[[nodiscard]] auto nucdecayenergytotal(const int z, const int a) -> double { const int nucindex = get_nucindex(z, a); const auto endecay_particles = std::accumulate( all_decaytypes.cbegin(), all_decaytypes.cend(), 0., [nucindex](const double ensum, const auto &decaytype) { @@ -237,10 +233,8 @@ void printout_nuclidemeanlife(const int z, const int a) { return nuclides[nucindex].endecay_gamma + endecay_particles; } -[[nodiscard]] auto nucdecayenergy(const int nucindex, const int decaytype) -> double -// contributed energy release per decay [erg] for decaytype (e.g. decaytypes::DECAYTYPE_BETAPLUS) -// (excludes neutrinos!) -{ +// contributed energy release per decay [erg] for decaytype (e.g. decaytypes::DECAYTYPE_BETAPLUS) (excludes neutrinos!) +[[nodiscard]] auto nucdecayenergy(const int nucindex, const int decaytype) -> double { const double endecay = nuclides[nucindex].endecay_gamma + nucdecayenergyparticle(nucindex, decaytype); return endecay; @@ -257,9 +251,8 @@ void printout_nuclidemeanlife(const int z, const int a) { return get_decaypathlength(decaypaths[decaypathindex]); } +// return the product of all branching factors in the decay path [[nodiscard]] auto calculate_decaypath_branchproduct(const DecayPath &decaypath) -> double { - // return the product of all branching factors in the decay path - double branchprod = 1.; const auto decaypathlength = get_decaypathlength(decaypath); for (int i = 0; i < decaypathlength; i++) { @@ -268,9 +261,8 @@ void printout_nuclidemeanlife(const int z, const int a) { return branchprod; } +// a decaypath's energy is the decay energy of the last nuclide and decaytype in the chain [[nodiscard]] auto get_decaypath_lastnucdecayenergy(const DecayPath &dpath) -> double { - // a decaypath's energy is the decay energy of the last nuclide and decaytype in the chain - const int nucindex_end = dpath.nucindex.back(); const int decaytype_end = dpath.decaytypes.back(); return nucdecayenergy(nucindex_end, decaytype_end); @@ -447,9 +439,9 @@ void find_decaypaths(const std::vector &custom_zlist, const std::vector &custom_zlist, const std::vector &custom_alist, const std::vector &standard_nuclides) { - // remove nuclides that are not a standard or custom input-specified nuclide, or connected to these by decays std::erase_if(nuclides, [&](const auto &nuc) { // keep nucleus if it is in the standard list if (std::ranges::any_of(standard_nuclides, @@ -798,9 +790,8 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode return nuclides[nucindex].a; } -[[nodiscard]] auto get_nucindex(const int z, const int a) -> int // get the nuclide array index from the atomic number and mass number -{ +[[nodiscard]] auto get_nucindex(const int z, const int a) -> int { const int nucindex = get_nucindex_or_neg_one(z, a); if (nucindex >= 0) { return nucindex; @@ -810,9 +801,8 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode return -1; } -[[nodiscard]] auto nuc_exists(const int z, const int a) -> bool // check if nuclide exists in the simulation -{ +[[nodiscard]] auto nuc_exists(const int z, const int a) -> bool { for (int nucindex = 0; nucindex < get_num_nuclides(); nucindex++) { if (nuclides[nucindex].z == z && nuclides[nucindex].a == a) { return true; @@ -821,9 +811,8 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode return false; } -[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(const int nucindex) -> double // average energy per decay in the form of gamma rays [erg] -{ +[[nodiscard]] __host__ __device__ auto nucdecayenergygamma(const int nucindex) -> double { return nuclides[nucindex].endecay_gamma; } @@ -831,15 +820,11 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode return nucdecayenergygamma(get_nucindex(z, a)); } -void set_nucdecayenergygamma(const int nucindex, const double value) // set average energy per decay in the form of gamma rays [erg] -{ - nuclides[nucindex].endecay_gamma = value; -} +void set_nucdecayenergygamma(const int nucindex, const double value) { nuclides[nucindex].endecay_gamma = value; } -auto get_nucstring_z(const std::string &strnuc) -> int // convert something like Ni56 to integer 28 -{ +auto get_nucstring_z(const std::string &strnuc) -> int { std::string elcode = strnuc; std::erase_if(elcode, &isdigit); @@ -853,9 +838,8 @@ auto get_nucstring_z(const std::string &strnuc) -> int return -1; } -auto get_nucstring_a(const std::string &strnuc) -> int // convert something like Ni56 to integer 56 -{ +auto get_nucstring_a(const std::string &strnuc) -> int { // find first digit character size_t i = 0; for (; i < strnuc.length(); i++) { @@ -872,9 +856,8 @@ auto get_nucstring_a(const std::string &strnuc) -> int return a; } +// add all nuclides and decays, and later trim any irrelevant ones (not connected to input-specified nuclei) void init_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist) { - // add all nuclides and decays, and later trim any irrelevant ones (not connected to input-specified nuclei) later - assert_always(custom_zlist.size() == custom_alist.size()); // Ni57 @@ -1019,7 +1002,7 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector printout("Number of decay paths: %d (max length %d)\n", get_num_decaypaths(), maxdecaypathlength); - /// Read in data for gamma ray lines and make a list of them in energy order. + // Read in data for gamma ray lines and make a list of them in energy order. gammapkt::init_gamma_data(); // TODO: generalise this to all included nuclides @@ -1033,10 +1016,9 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector nucdecayenergytotal(25, 52) / MEV); } -auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridindex, const double tstart) -> double // calculate the decay energy per unit mass [erg/g] released from time t_model to tstart, accounting for // the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) -{ +auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridindex, const double tstart) -> double { double tot_endecay = 0.; for (const auto &decaypath : decaypaths) { const int decaypathlength = get_decaypathlength(decaypath); @@ -1058,10 +1040,8 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridinde return tot_endecay; } -auto get_modelcell_simtime_endecay_per_mass(const int mgi) -> double -// get the density at time tmin of decay energy that will -// be released during the simulation time range [erg/cm3] -{ +// get the density at time tmin of decay energy that will be released during the simulation time range [erg/cm3] +auto get_modelcell_simtime_endecay_per_mass(const int mgi) -> double { double endecay_per_mass = 0.; for (int decaypathindex = 0; decaypathindex < get_num_decaypaths(); decaypathindex++) { endecay_per_mass += get_simtime_endecay_per_ejectamass(mgi, decaypathindex); @@ -1134,9 +1114,9 @@ void free_decaypath_energy_per_mass() { decaypath_energy_per_mass = {}; } -[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) -> double // energy release rate in form of kinetic energy of positrons, electrons, and alpha particles in [erg/s/g] -{ +[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, + const int decaytype) -> double { double dep_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1160,9 +1140,8 @@ void free_decaypath_energy_per_mass() { return dep_sum; } -[[nodiscard]] auto get_gamma_emission_rate(const int modelgridindex, const double t) -> double // energy release rate in form of gamma-rays in [erg/s/g] -{ +[[nodiscard]] auto get_gamma_emission_rate(const int modelgridindex, const double t) -> double { double eps_gamma_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1185,9 +1164,8 @@ void free_decaypath_energy_per_mass() { return eps_gamma_sum; } -[[nodiscard]] auto get_qdot_modelcell(const int modelgridindex, const double t, const int decaytype) -> double // energy release rate [erg/s/g] including everything (even neutrinos that are ignored elsewhere) -{ +[[nodiscard]] auto get_qdot_modelcell(const int modelgridindex, const double t, const int decaytype) -> double { double qdot = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1221,11 +1199,8 @@ auto get_global_etot_t0_tinf() -> double { return etot_tinf; } -void update_abundances(const int modelgridindex, const int timestep, const double t_current) -/// Updates the mass fractions of elements using the current abundances of nuclides -/// Parameters: - modelgridindex: the grid cell for which to update the abundances -/// - t_current: current time (here mid of current timestep) -{ +// Update the mass fractions of elements using the current abundances of nuclides +void update_abundances(const int modelgridindex, const int timestep, const double t_current) { printout("update_abundances for cell %d timestep %d\n", modelgridindex, timestep); for (int element = get_nelements() - 1; element >= 0; element--) { diff --git a/exspec.cc b/exspec.cc index 4c371e243..af33e3a5c 100644 --- a/exspec.cc +++ b/exspec.cc @@ -39,7 +39,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra std::vector gamma_light_curve_lum(globals::ntimesteps, 0.); std::vector gamma_light_curve_lumcmf(globals::ntimesteps, 0.); - /// Set up the spectrum grid and initialise the bins to zero. + // Set up the spectrum grid and initialise the bins to zero. init_spectra(rpkt_spectra, NU_MIN_R, NU_MAX_R, globals::do_emission_res); if constexpr (POL_ON) { @@ -208,7 +208,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) printout("Begining exspec.\n"); - /// Get input stuff + // Get input stuff printout("time before input %ld\n", std::time(nullptr)); input(globals::rank_global); printout("time after input %ld\n", std::time(nullptr)); @@ -244,7 +244,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) time_init(); - const int amax = ((grid::get_model_type() == GRID_SPHERICAL1D)) ? 0 : MABINS; + const int amax = ((grid::get_model_type() == GridType::SPHERICAL1D)) ? 0 : MABINS; // a is the escape direction angle bin for (int a = -1; a < amax; a++) { do_angle_bin(a, pkts, load_allrank_packets, rpkt_spectra, stokes_i, stokes_q, stokes_u, gamma_spectra); diff --git a/exspec.h b/exspec.h index a1405f8df..388c8f8ba 100644 --- a/exspec.h +++ b/exspec.h @@ -2,7 +2,7 @@ #ifndef EXSPEC_H #define EXSPEC_H -/// Spectrum data structure +// Spectrum data structure constexpr int MNUBINS = 1000; constexpr int NPHIBINS = 10; diff --git a/gammapkt.cc b/gammapkt.cc index e2b6f9a3f..73783b418 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -320,9 +320,8 @@ auto choose_f(const double xx, const double zrand) -> double return ftry; } +// For Thomson scattering we can get the new angle from a random number very easily. auto thomson_angle() -> double { - // For Thomson scattering we can get the new angle from a random number very easily. - const double B_coeff = (8. * rng_uniform()) - 4.; double t_coeff = sqrt((B_coeff * B_coeff) + 4); @@ -340,9 +339,8 @@ auto thomson_angle() -> double { return mu; } -[[nodiscard]] auto scatter_dir(const std::array dir_in, const double cos_theta) -> std::array -// Routine for scattering a direction through angle theta. -{ +// scattering a direction through angle theta. +[[nodiscard]] auto scatter_dir(const std::array dir_in, const double cos_theta) -> std::array { // begin with setting the direction in coordinates where original direction // is parallel to z-hat. @@ -379,9 +377,8 @@ auto thomson_angle() -> double { return dir_out; } -void compton_scatter(Packet &pkt) -// Routine to deal with physical Compton scattering event. -{ +// handle physical Compton scattering event +void compton_scatter(Packet &pkt) { // printout("Compton scattering.\n"); const double xx = H * pkt.nu_cmf / ME / CLIGHT / CLIGHT; @@ -476,9 +473,8 @@ void compton_scatter(Packet &pkt) } } +// calculate the absorption coefficient [cm^-1] for photo electric effect scattering in the observer reference frame auto get_chi_photo_electric_rf(const Packet &pkt) -> double { - // calculate the absorption coefficient [cm^-1] for photo electric effect scattering in the observer reference frame - double chi_cmf{NAN}; // Start by working out the x-section in the co-moving frame. @@ -574,9 +570,8 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { return chi_rf; } +// calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame auto sigma_pair_prod_rf(const Packet &pkt) -> double { - // calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame - const int mgi = grid::get_cell_modelgridindex(pkt.where); const double rho = grid::get_rho(mgi); @@ -637,10 +632,8 @@ auto sigma_pair_prod_rf(const Packet &pkt) -> double { return chi_rf; } -constexpr auto meanf_sigma(const double x) -> double -// Routine to compute the mean energy converted to non-thermal electrons times -// the Klein-Nishina cross section. -{ +// Routine to compute the mean energy converted to non-thermal electrons times the Klein-Nishina cross section. +constexpr auto meanf_sigma(const double x) -> double { const double f = 1 + (2 * x); const double term0 = 2 / x; @@ -654,15 +647,13 @@ constexpr auto meanf_sigma(const double x) -> double return tot; } +// Subroutine to record the heating rate in a cell due to gamma rays. +// By heating rate I mean, for now, really the rate at which the code is making +// k-packets in that cell which will then convert into r-packets. This is (going +// to be) used for the new light_curve syn-style calculation. +// The intention is that dep_estimator_gamma will contain the emissivity of r-packets +// in the co-moving frame (which is going to be isotropic). void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const int nonemptymgi) { - // Subroutine to record the heating rate in a cell due to gamma rays. - // By heating rate I mean, for now, really the rate at which the code is making - // k-packets in that cell which will then convert into r-packets. This is (going - // to be) used for the new light_curve syn-style calculation. - - // The intention is that dep_estimator_gamma will contain the emissivity of r-packets - // in the co-moving frame (which is going to be isotropic). - if (!(dist > 0)) { return; } @@ -688,15 +679,14 @@ void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const atomicadd(globals::dep_estimator_gamma[nonemptymgi], heating_cont); } +// handle physical pair production event +// +// In pair production, the original gamma makes an electron positron pair - kinetic energy equal to +// gamma ray energy - 1.022 MeV. We assume that the electron deposits any kinetic energy directly to +// the thermal pool. The positron annihilates with an electron locally making a pair of gamma rays +// at 0.511 MeV in the local cmf (isotropic). So all the thermal energy goes to the thermal pool +// immediately and the remainder goes into gamma-rays at 0.511 MeV. void pair_prod(Packet &pkt) { - // Routine to deal with pair production. - - // In pair production, the original gamma makes an electron positron pair - kinetic energy equal to - // gamma ray energy - 1.022 MeV. We assume that the electron deposits any kinetic energy directly to - // the thermal pool. The positron annihilates with an electron locally making a pair of gamma rays - // at 0.511 MeV in the local cmf (isotropic). So all the thermal energy goes to the thermal pool - // immediately and the remainder goes into gamma-rays at 0.511 MeV. - const double prob_gamma = 1.022 * MEV / (H * pkt.nu_cmf); if (prob_gamma < 0) { @@ -736,11 +726,8 @@ void pair_prod(Packet &pkt) { } } -void transport_gamma(Packet &pkt, const double t2) -// Now routine for moving a gamma packet. Idea is that we have as input -// a gamma packet with known properties at time t1 and we want to follow it -// until time t2. -{ +// move a gamma packet until time t2 +void transport_gamma(Packet &pkt, const double t2) { // Assign optical depth to next physical event. And start counter of // optical depth for this path. const double zrand = rng_uniform_pos(); @@ -753,7 +740,7 @@ void transport_gamma(Packet &pkt, const double t2) auto [sdist, snext] = grid::boundary_distance(pkt.dir, pkt.pos, pkt.prop_time, pkt.where, &pkt.last_cross); - const double maxsdist = (GRID_TYPE == GRID_CARTESIAN3D) + const double maxsdist = (GRID_TYPE == GridType::CARTESIAN3D) ? globals::rmax * pkt.prop_time / globals::tmin : 2 * globals::rmax * (pkt.prop_time + sdist / CLIGHT_PROP) / globals::tmin; if (sdist > maxsdist) { @@ -1045,11 +1032,8 @@ void init_gamma_data() { } } +// convert a pellet to a gamma ray (or kpkt if no gamma spec loaded) __host__ __device__ void pellet_gamma_decay(Packet &pkt) { - // Subroutine to convert a pellet to a gamma ray (or kpkt if no gamma spec loaded) - - // pkt is a pointer to the packet that is decaying. - // Start by getting the position of the pellet at the point of decay. Pellet // is moving with the matter. diff --git a/globals.h b/globals.h index 4e10f4f87..fbb252898 100644 --- a/globals.h +++ b/globals.h @@ -81,61 +81,61 @@ struct LevelTransition { }; struct EnergyLevel { - double epsilon{-1}; /// Excitation energy of this level relative to the neutral ground level. - LevelTransition *uptrans{}; /// Allowed upward transitions from this level - LevelTransition *downtrans{}; /// Allowed downward transitions from this level + double epsilon{-1}; // Excitation energy of this level relative to the neutral ground level. + LevelTransition *uptrans{}; // Allowed upward transitions from this level + LevelTransition *downtrans{}; // Allowed downward transitions from this level int nuptrans{0}; int ndowntrans{0}; - PhotoionTarget *phixstargets{}; /// pointer to table of target states and probabilities - float *photoion_xs{}; /// Pointer to a lookup-table providing photoionisation cross-sections for this level. - int nphixstargets{0}; /// length of phixstargets array: - float stat_weight{0.}; /// Statistical weight of this level. + PhotoionTarget *phixstargets{}; // pointer to table of target states and probabilities + float *photoion_xs{}; // Pointer to a lookup-table providing photoionisation cross-sections for this level. + int nphixstargets{0}; // length of phixstargets array: + float stat_weight{0.}; // Statistical weight of this level. - int cont_index{-1}; /// Index of the continuum associated to this level. Negative number. + int cont_index{-1}; // Index of the continuum associated to this level. Negative number. int closestgroundlevelcont{-1}; bool metastable{}; /// }; struct Ion { - EnergyLevel *levels; /// Carries information for each level: 0,1,...,nlevels-1 - int ionstage; /// Which ionisation stage: XI=0, XII=1, XIII=2, ... - int nlevels; /// Number of levels for this ionisation stage - int nlevels_nlte; /// number of nlte levels for this ion - int first_nlte; /// index into nlte_pops array of a grid cell - int ionisinglevels; /// Number of levels which have a bf-continuum - int maxrecombininglevel; /// level index of the highest level with a non-zero recombination rate + EnergyLevel *levels; // Carries information for each level: 0,1,...,nlevels-1 + int ionstage; // Which ionisation stage: XI=0, XII=1, XIII=2, ... + int nlevels; // Number of levels for this ionisation stage + int nlevels_nlte; // number of nlte levels for this ion + int first_nlte; // index into nlte_pops array of a grid cell + int ionisinglevels; // Number of levels which have a bf-continuum + int maxrecombininglevel; // level index of the highest level with a non-zero recombination rate int nlevels_groundterm; int coolingoffset; int ncoolingterms; int uniquelevelindexstart; int groundcontindex; float *Alpha_sp; - double ionpot; /// Ionisation threshold to the next ionstage + double ionpot; // Ionisation threshold to the next ionstage // int nbfcontinua; // ionsphixslist *phixslist; }; struct Element { - Ion *ions{}; /// Carries information for each ion: 0,1,...,nions-1 - int nions{0}; /// Number of ions for the current element - int anumber{-1}; /// Atomic number - // int uppermost_ion; /// Highest ionisation stage which has a decent population for a given + Ion *ions{}; // Carries information for each ion: 0,1,...,nions-1 + int nions{0}; // Number of ions for the current element + int anumber{-1}; // Atomic number + // int uppermost_ion; // Highest ionisation stage which has a decent population for a given // cell - /// Be aware that this must not be used outside of the update_grid routine - /// and their daughters. Neither it will work with OpenMP threads. - int uniqueionindexstart{-1}; /// Index of the lowest ionisation stage of this element - float initstablemeannucmass = {0.}; /// Atomic mass number in multiple of MH + // Be aware that this must not be used outside of the update_grid routine + // and their daughters. Neither it will work with OpenMP threads. + int uniqueionindexstart{-1}; // Index of the lowest ionisation stage of this element + float initstablemeannucmass = {0.}; // Atomic mass number in multiple of MH bool has_nlte_levels{false}; }; struct TransitionLine { - double nu; /// Frequency of the line transition + double nu; // Frequency of the line transition float einstein_A; - int elementindex; /// It's a transition of element (not its atomic number, - /// but the (x-1)th element included in the simulation. - int ionindex; /// The same for the elements ion - int upperlevelindex; /// And the participating upper - int lowerlevelindex; /// and lower levels + int elementindex; // It's a transition of element (not its atomic number, + // but the (x-1)th element included in the simulation. + int ionindex; // The same for the elements ion + int upperlevelindex; // And the participating upper + int lowerlevelindex; // and lower levels }; struct GSLIntegrationParas { @@ -158,23 +158,23 @@ struct chphixstargets { using CellCachePhixsTargets = chphixstargets; enum ma_action { - /// Radiative deexcitation rate from this level. + // Radiative deexcitation rate from this level. MA_ACTION_RADDEEXC = 0, - /// Collisional deexcitation rate from this level. + // Collisional deexcitation rate from this level. MA_ACTION_COLDEEXC = 1, - /// Radiative recombination from this level. + // Radiative recombination from this level. MA_ACTION_RADRECOMB = 2, - /// Collisional recombination rate from this level. + // Collisional recombination rate from this level. MA_ACTION_COLRECOMB = 3, - /// Rate for internal downward transitions to same ionisation stage. + // Rate for internal downward transitions to same ionisation stage. MA_ACTION_INTERNALDOWNSAME = 4, - /// Rate for internal upward transitions to same ionisation stage. + // Rate for internal upward transitions to same ionisation stage. MA_ACTION_INTERNALDOWNLOWER = 5, - /// Rate for internal downward transitions to lower ionisation stage. + // Rate for internal downward transitions to lower ionisation stage. MA_ACTION_INTERNALUPSAME = 6, - /// Rate for internal upward transitions to higher ionisation stage. + // Rate for internal upward transitions to higher ionisation stage. MA_ACTION_INTERNALUPHIGHER = 7, - /// Rate for internal upward transitions to higher ionisation stage due to non-thermal collisions. + // Rate for internal upward transitions to higher ionisation stage due to non-thermal collisions. MA_ACTION_INTERNALUPHIGHERNT = 8, MA_ACTION_COUNT = 9, }; @@ -189,20 +189,20 @@ struct CellCacheLevels { }; struct CellCacheIons { - CellCacheLevels *chlevels; /// Pointer to the ions levellist. + CellCacheLevels *chlevels; // Pointer to the ions levellist. }; struct CellCacheElements { - CellCacheIons *chions; /// Pointer to the elements ionlist. + CellCacheIons *chions; // Pointer to the elements ionlist. }; struct CellCache { - double *cooling_contrib{}; /// Cooling contributions by the different processes. + double *cooling_contrib{}; // Cooling contributions by the different processes. CellCacheElements *chelements{}; std::vector ch_all_levels; std::vector ch_allcont_departureratios; double chi_ff_nnionpart{-1}; - int cellnumber{-1}; /// Identifies the cell the data is valid for. + int cellnumber{-1}; // Identifies the cell the data is valid for. }; namespace globals { @@ -258,7 +258,7 @@ inline int opacity_case{}; // 0 grey, 1 for Fe-grp dependence. // MK: 3 combination of 1 & 2 depending on a rho_crit // MK: 4 non-grey treatment -/// ATOMIC DATA +// ATOMIC DATA inline int nlines{-1}; inline std::vector elements; diff --git a/grid.cc b/grid.cc index 12ad560e7..2ccf146b7 100644 --- a/grid.cc +++ b/grid.cc @@ -43,9 +43,9 @@ namespace { std::array coordlabel{'?', '?', '?'}; -std::array ncoordgrid{0}; /// propagation grid dimensions +std::array ncoordgrid{0}; // propagation grid dimensions -enum gridtypes model_type = GRID_SPHERICAL1D; +auto model_type = GridType::SPHERICAL1D; size_t npts_model = 0; // number of model grid cells size_t nonempty_npts_model = 0; // number of allocated non-empty model grid cells @@ -55,7 +55,7 @@ std::array ncoord_model{0}; // the model.txt input grid dimensions double min_den; // minimum model density -double mfegroup = 0.; /// Total mass of Fe group elements in ejecta +double mfegroup = 0.; // Total mass of Fe group elements in ejecta int first_cellindex = -1; // auto-dermine first cell index in model.txt (usually 1 or 0) @@ -70,7 +70,7 @@ std::vector mg_associated_cells; std::vector nonemptymgi_of_mgi; std::vector mgi_of_nonemptymgi; -std::span totmassradionuclide{}; /// total mass of each radionuclide in the ejecta +std::span totmassradionuclide{}; // total mass of each radionuclide in the ejecta #ifdef MPI_ON MPI_Win win_nltepops_allcells = MPI_WIN_NULL; @@ -177,22 +177,25 @@ void allocate_initradiobund() { } auto get_cell_r_inner(const int cellindex) -> double { - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { return get_cellcoordmin(cellindex, 0); } - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { const auto rcyl_inner = get_cellcoordmin(cellindex, 0); const auto z_inner = std::min(std::abs(get_cellcoordmin(cellindex, 1)), std::abs(get_cellcoordmax(cellindex, 1))); return std::sqrt(std::pow(rcyl_inner, 2) + std::pow(z_inner, 2)); } - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { const auto x_inner = std::min(std::abs(get_cellcoordmin(cellindex, 0)), std::abs(get_cellcoordmax(cellindex, 0))); const auto y_inner = std::min(std::abs(get_cellcoordmin(cellindex, 1)), std::abs(get_cellcoordmax(cellindex, 1))); const auto z_inner = std::min(std::abs(get_cellcoordmin(cellindex, 2)), std::abs(get_cellcoordmax(cellindex, 2))); return std::sqrt(std::pow(x_inner, 2) + std::pow(y_inner, 2) + std::pow(z_inner, 2)); } + + assert_always(false); + return NAN; } void set_ffegrp(const int modelgridindex, float x) { @@ -273,7 +276,7 @@ void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, } void allocate_nonemptycells_composition_cooling() -/// Initialise composition dependent cell data for the given cell +// Initialise composition dependent cell data for the given cell { const size_t npts_nonempty = get_nonempty_npts_model(); @@ -364,7 +367,7 @@ void allocate_nonemptycells_composition_cooling() std::span(&nltepops_allcells[nonemptymgi * globals::total_nlte_levels], globals::total_nlte_levels); assert_always(modelgrid[modelgridindex].nlte_pops.data() != nullptr); - /// -1 indicates that there is currently no information on the nlte populations + // -1 indicates that there is currently no information on the nlte populations std::ranges::fill(modelgrid[modelgridindex].nlte_pops, -1.); } @@ -406,17 +409,17 @@ void allocate_nonemptymodelcells() { if (FORCE_SPHERICAL_ESCAPE_SURFACE && radial_pos_mid > globals::vmax * globals::tmin) { // for 1D models, the final shell outer v should already be at vmax - assert_always(model_type != GRID_SPHERICAL1D || cell[cellindex].modelgridindex == get_npts_model()); + assert_always(model_type != GridType::SPHERICAL1D || cell[cellindex].modelgridindex == get_npts_model()); cell[cellindex].modelgridindex = get_npts_model(); } const int mgi = get_cell_modelgridindex(cellindex); - assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); + assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); mg_associated_cells[mgi] += 1; modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; - assert_always(!(get_model_type() == GRID_CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || + assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || (mgi == get_npts_model())); } @@ -583,10 +586,9 @@ void map_2dmodelto3dgrid() } } -void map_modeltogrid_direct() // mgi and cellindex are interchangeable in this mode (except for empty cells that associated with mgi == // get_npts_model()) -{ +void map_modeltogrid_direct() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const int mgi = (modelgrid[cellindex].rhoinit > 0) ? cellindex : get_npts_model(); set_cell_modelgridindex(cellindex, mgi); @@ -599,16 +601,16 @@ void abundances_read() { MPI_Barrier(MPI_COMM_WORLD); #endif printout("reading abundances.txt..."); - const bool threedimensional = (get_model_type() == GRID_CARTESIAN3D); + const bool threedimensional = (get_model_type() == GridType::CARTESIAN3D); - /// Open the abundances file + // Open the abundances file auto abundance_file = fstream_required("abundances.txt", std::ios::in); - /// and process through the grid to read in the abundances per cell - /// The abundance file should only contain information for non-empty - /// cells. Its format must be cellnumber (integer), abundance for - /// element Z=1 (float) up to abundance for element Z=30 (float) - /// i.e. in total one integer and 30 floats. + // and process through the grid to read in the abundances per cell + // The abundance file should only contain information for non-empty + // cells. Its format must be cellnumber (integer), abundance for + // element Z=1 (float) up to abundance for element Z=30 (float) + // i.e. in total one integer and 30 floats. // loop over propagation cells for 3D models, or modelgrid cells for (int mgi = 0; mgi < get_npts_model(); mgi++) { @@ -648,8 +650,8 @@ void abundances_read() { } for (int element = 0; element < get_nelements(); element++) { - /// now set the abundances (by mass) of included elements, i.e. - /// read out the abundances specified in the atomic data file + // now set the abundances (by mass) of included elements, i.e. + // read out the abundances specified in the atomic data file const int anumber = get_atomicnumber(element); const float elemabundance = abundances_in[anumber - 1] / normfactor; assert_always(elemabundance >= 0.); @@ -693,12 +695,12 @@ void parse_model_headerline(const std::string &line, std::vector &zlist, st } else if (token == "logrho") { // 1D models have log10(rho [g/cm3]) assert_always(columnindex == 2); - assert_always(get_model_type() == GRID_SPHERICAL1D); + assert_always(get_model_type() == GridType::SPHERICAL1D); } else if (token == "rho") { // 2D and 3D models have rho [g/cm3] - assert_always(get_model_type() != GRID_SPHERICAL1D); - assert_always((columnindex == 4 && get_model_type() == GRID_CARTESIAN3D) || - (columnindex == 3 && get_model_type() == GRID_CYLINDRICAL2D)); + assert_always(get_model_type() != GridType::SPHERICAL1D); + assert_always((columnindex == 4 && get_model_type() == GridType::CARTESIAN3D) || + (columnindex == 3 && get_model_type() == GridType::CYLINDRICAL2D)); continue; } else if (token.starts_with("X_") && token != "X_Fegroup") { colnames.push_back(token); @@ -794,13 +796,13 @@ auto read_model_columns(std::fstream &fmodel) -> std::tuple std::tuple> t_model_days; t_model = t_model_days * DAY; - /// Now read in vmax for the model (in cm s^-1). + // Now read in vmax for the model (in cm s^-1). assert_always(get_noncommentline(fmodel, line)); std::istringstream(line) >> globals::vmax; @@ -997,15 +997,14 @@ void read_2d_model() printout("effectively used model grid cells: %d\n", nonemptymgi); } -void read_3d_model() -/// Subroutine to read in a 3-D model. -{ +// read a 3D Cartesian model +void read_3d_model() { auto fmodel = fstream_required("model.txt", std::ios::in); std::string line; - /// 1st read the number of data points in the table of input model. - /// This MUST be the same number as the maximum number of points used in the grid - if not, abort. + // 1st read the number of data points in the table of input model. + // This MUST be the same number as the maximum number of points used in the grid - if not, abort. int npts_model_in = 0; assert_always(get_noncommentline(fmodel, line)); std::istringstream(line) >> npts_model_in; @@ -1025,13 +1024,13 @@ void read_3d_model() std::istringstream(line) >> t_model_days; t_model = t_model_days * DAY; - /// Now read in vmax for the model (in cm s^-1). + // Now read in vmax for the model (in cm s^-1). assert_always(get_noncommentline(fmodel, line)); std::istringstream(line) >> globals::vmax; const double xmax_tmodel = globals::vmax * t_model; - /// Now read in the lines of the model. + // Now read in the lines of the model. min_den = -1.; // check if expected positions match in either xyz or zyx column order @@ -1149,20 +1148,19 @@ void calc_modelinit_totmassradionuclides() { continue; } double cellvolume = 0.; - if (get_model_type() == GRID_SPHERICAL1D) { + if (get_model_type() == GridType::SPHERICAL1D) { const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; // mass_in_shell = rho_model[mgi] * (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(t_model, 3) / 3.; cellvolume = (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(globals::tmin, 3) / 3.; - } else if (get_model_type() == GRID_CYLINDRICAL2D) { + } else if (get_model_type() == GridType::CYLINDRICAL2D) { const int n_r = mgi % ncoord_model[0]; cellvolume = pow(globals::tmin / t_model, 3) * dcoord_z * PI * (pow((n_r + 1) * dcoord_rcyl, 2.) - pow(n_r * dcoord_rcyl, 2.)); - } else if (get_model_type() == GRID_CARTESIAN3D) { - /// Assumes cells are cubes here - all same volume. + } else if (get_model_type() == GridType::CARTESIAN3D) { + // Assumes cells are cubes here - all same volume. cellvolume = pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); } else { - printout("Unknown model type %d in function %s\n", get_model_type(), __func__); - std::abort(); + assert_always(false); } const double mass_in_shell = get_rho_tmin(mgi) * cellvolume; @@ -1269,19 +1267,18 @@ void read_grid_restart_data(const int timestep) { fclose(gridsave_file); } -void assign_initial_temperatures() -/// Routine for assigning temperatures to the grid cells at the start of the simulation. -{ +// Assign temperatures to the grid cells at the start of the simulation +void assign_initial_temperatures() { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif - /// For a simulation started from scratch we estimate the initial temperatures + // For a simulation started from scratch we estimate the initial temperatures - /// We assume that for early times the material is so optically thick, that - /// all the radiation is trapped in the cell it originates from. This - /// means furthermore LTE, so that both temperatures can be evaluated - /// according to the local energy density resulting from the 56Ni decay. - /// The dilution factor is W=1 in LTE. + // We assume that for early times the material is so optically thick, that + // all the radiation is trapped in the cell it originates from. This + // means furthermore LTE, so that both temperatures can be evaluated + // according to the local energy density resulting from the 56Ni decay. + // The dilution factor is W=1 in LTE. printout("Assigning initial temperatures...\n"); @@ -1390,9 +1387,8 @@ void setup_nstart_ndo() { } } -void setup_grid_cartesian_3d() -/// Routine for doing a uniform cuboidal grid. -{ +// set up a uniform cuboidal grid. +void setup_grid_cartesian_3d() { // vmax is per coordinate, but the simulation volume corners will // have a higher expansion velocity than the sides const double vmax_corner = sqrt(3 * pow(globals::vmax, 2)); @@ -1401,8 +1397,8 @@ void setup_grid_cartesian_3d() assert_always(vmax_corner < CLIGHT); } - /// Set grid size for uniform xyz grid - if (get_model_type() == GRID_CARTESIAN3D) { + // Set grid size for uniform xyz grid + if (get_model_type() == GridType::CARTESIAN3D) { // if we used in a 3D ejecta model, the propagation grid must match the input grid exactly ncoordgrid[0] = ncoord_model[0]; ncoordgrid[1] = ncoord_model[1]; @@ -1451,7 +1447,7 @@ void setup_grid_cartesian_3d() } void setup_grid_spherical1d() { - assert_always(get_model_type() == GRID_SPHERICAL1D); + assert_always(get_model_type() == GridType::SPHERICAL1D); coordlabel[0] = 'r'; coordlabel[1] = '_'; coordlabel[2] = '_'; @@ -1477,7 +1473,7 @@ void setup_grid_cylindrical_2d() { printout("corner vmax %g [cm/s] (%.2fc)\n", vmax_corner, vmax_corner / CLIGHT); assert_always(vmax_corner < CLIGHT); - assert_always(get_model_type() == GRID_CYLINDRICAL2D); + assert_always(get_model_type() == GridType::CYLINDRICAL2D); coordlabel[0] = 'r'; coordlabel[1] = 'z'; coordlabel[2] = '_'; @@ -1501,11 +1497,11 @@ void setup_grid_cylindrical_2d() { auto get_grid_type_name() -> std::string { switch (GRID_TYPE) { - case GRID_SPHERICAL1D: + case GridType::SPHERICAL1D: return "spherical"; - case GRID_CYLINDRICAL2D: + case GridType::CYLINDRICAL2D: return "cylindrical"; - case GRID_CARTESIAN3D: + case GridType::CARTESIAN3D: return "uniform cuboidal"; default: { return "unknown"; @@ -1516,9 +1512,9 @@ auto get_grid_type_name() -> std::string { auto get_poscoordpointnum(const double pos, const double time, const int axis) -> int { // pos must be position in grid coordinate system, not necessarily xyz - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { if (axis == 0) { return static_cast(pos / time / globals::vmax * ncoordgrid[axis]); } @@ -1527,7 +1523,7 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - } assert_always(false); - } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + } else if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { for (int n_r = 0; n_r < ncoordgrid[0]; n_r++) { if ((pos >= grid::get_cellcoordmin(n_r, 0)) && (pos < grid::get_cellcoordmax(n_r, 0))) { return n_r; @@ -1541,15 +1537,15 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { auto posgridcoord = std::array{}; - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { posgridcoord[0] = pos_xyz[0]; posgridcoord[1] = pos_xyz[1]; posgridcoord[2] = pos_xyz[2]; - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { posgridcoord[0] = std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)); posgridcoord[1] = pos_xyz[2]; posgridcoord[2] = 0.; - } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + } else if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { posgridcoord[0] = vec_len(pos_xyz); posgridcoord[1] = 0.; posgridcoord[2] = 0.; @@ -1715,15 +1711,15 @@ auto wid_init(const int cellindex, const int axis) -> double // for spherical grid this is the radial extent (r_outer - r_inner) // these values are at time globals::tmin { - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return 2 * globals::rmax / ncoordgrid[axis]; } - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { return (axis == 0) ? globals::rmax / ncoordgrid[axis] : 2 * globals::rmax / ncoordgrid[axis]; } - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { const int modelgridindex = get_cell_modelgridindex(cellindex); const double v_inner = modelgridindex > 0 ? vout_model[modelgridindex - 1] : 0.; return (vout_model[modelgridindex] - v_inner) * globals::tmin; @@ -1732,21 +1728,20 @@ auto wid_init(const int cellindex, const int axis) -> double assert_always(false); } -auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double // return the model cell volume (when mapped to the propagation cells) at globals::tmin // for a uniform cubic grid this is constant -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { +auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return (wid_init(modelgridindex, 0) * wid_init(modelgridindex, 1) * wid_init(modelgridindex, 2)) * get_numassociatedcells(modelgridindex); } - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { return wid_init(modelgridindex, 1) * PI * (pow(get_cellcoordmax(modelgridindex, 0), 2) - pow(get_cellcoordmin(modelgridindex, 0), 2)); } - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { return 4. / 3. * PI * (pow(get_cellcoordmax(modelgridindex, 0), 3) - pow(get_cellcoordmin(modelgridindex, 0), 3)); } @@ -1757,7 +1752,7 @@ auto get_gridcell_volume_tmin(const int cellindex) -> double // return the propagation cell volume at globals::tmin // for a spherical grid, the cell index is required (and should be equivalent to a modelgridindex) { - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return (wid_init(cellindex, 0) * wid_init(cellindex, 0) * wid_init(cellindex, 0)); } @@ -1770,16 +1765,16 @@ auto get_cellcoordmax(const int cellindex, const int axis) -> double // get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell // e.g., the minimum x position in xyz coords, or the minimum radius { - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(0, axis); } - if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { assert_testmodeonly(axis <= 1); return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); } - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { assert_testmodeonly(axis == 0); return grid::get_cellcoordmin(cellindex, axis) + grid::wid_init(cellindex, axis); } @@ -1787,18 +1782,16 @@ auto get_cellcoordmax(const int cellindex, const int axis) -> double assert_always(false); } -auto get_cellcoordmin(const int cellindex, const int axis) -> double // get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell // e.g., the minimum x position in xyz coords, or the minimum radius -{ +auto get_cellcoordmin(const int cellindex, const int axis) -> double { return cell[cellindex].pos_min[axis]; // return - coordmax[axis] + (2 * get_cellcoordpointnum(cellindex, axis) * coordmax[axis] / ncoordgrid[axis]); } -auto get_coordcellindexincrement(const int axis) -> int // how much do we change the cellindex to move along a coordinately axis (e.g., the x, y, z directions, or r // direction) -{ +auto get_coordcellindexincrement(const int axis) -> int { // assert_testmodeonly(axis < get_ngriddimensions()); switch (axis) { @@ -1821,10 +1814,9 @@ auto get_coordcellindexincrement(const int axis) -> int } } -auto get_cellcoordpointnum(const int cellindex, const int axis) -> int // convert a cell index number into an integer (x,y,z or r) coordinate index from 0 to ncoordgrid[axis] -{ - if constexpr (GRID_TYPE == GRID_CARTESIAN3D || GRID_TYPE == GRID_CYLINDRICAL2D) { +auto get_cellcoordpointnum(const int cellindex, const int axis) -> int { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D || GRID_TYPE == GridType::CYLINDRICAL2D) { switch (axis) { // 3D Cartesian: increment x first, then y, then z // 2D Cylindrical: increment r first, then z @@ -1847,7 +1839,7 @@ auto get_cellcoordpointnum(const int cellindex, const int axis) -> int } } - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { return cellindex; } @@ -1878,15 +1870,13 @@ __host__ __device__ auto get_nnetot(const int modelgridindex) -> float { __host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } -void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) // mass fraction of an element (all isotopes combined) -{ +void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) { modelgrid[modelgridindex].elem_massfracs[element] = newabundance; } -__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double // mass fraction of an element (all isotopes combined) -{ +__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double { const double elem_meanweight = grid::get_element_meanweight(modelgridindex, element); return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); } @@ -1949,9 +1939,9 @@ void set_TJ(const int modelgridindex, const float TJ) { modelgrid[modelgridindex void set_W(const int modelgridindex, const float W) { modelgrid[modelgridindex].W = W; } -auto get_model_type() -> enum gridtypes { return model_type; } +auto get_model_type() -> GridType { return model_type; } -void set_model_type(const enum gridtypes model_type_value) { model_type = model_type_value; } +void set_model_type(const GridType model_type_value) { model_type = model_type_value; } __host__ __device__ auto get_npts_model() -> int // number of model grid cells @@ -1960,16 +1950,14 @@ __host__ __device__ auto get_npts_model() -> int return npts_model; } -auto get_nonempty_npts_model() -> int // number of model grid cells -{ +auto get_nonempty_npts_model() -> int { assert_testmodeonly(nonempty_npts_model > 0); return nonempty_npts_model; } -auto get_t_model() -> double // get time at which model input densities are defined -{ +auto get_t_model() -> double { assert_testmodeonly(t_model > 0.); return t_model; } @@ -1983,16 +1971,14 @@ __host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { return mgi; } -__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int // number of propagation cells associated with each modelgrid cell -{ +__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int { assert_testmodeonly(modelgridindex <= get_npts_model()); return mg_associated_cells[modelgridindex]; } -__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int // get the index in the list of non-empty cells for a given model grid cell -{ +__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int { assert_testmodeonly(get_nonempty_npts_model() > 0); assert_testmodeonly(mgi < get_npts_model()); @@ -2004,9 +1990,8 @@ __host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int return nonemptymgi; } -__host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int // get the index in the list of non-empty cells for a given model grid cell -{ +__host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int { assert_testmodeonly(get_nonempty_npts_model() > 0); assert_testmodeonly(nonemptymgi >= 0); assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); @@ -2019,9 +2004,8 @@ __host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int // the abundances below are initial abundances at t_model +// get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index auto get_modelinitnucmassfrac(const int modelgridindex, const int nucindex) -> float { - // get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index - assert_testmodeonly(modelgrid[modelgridindex].initnucmassfrac != nullptr); return modelgrid[modelgridindex].initnucmassfrac[nucindex]; } @@ -2043,9 +2027,8 @@ auto get_element_meanweight(const int mgi, const int element) -> float return globals::elements[element].initstablemeannucmass; } -void set_element_meanweight(const int mgi, const int element, const float meanweight) -// weight is in grams -{ +// set element weight in grams +void set_element_meanweight(const int mgi, const int element, const float meanweight) { assert_always(meanweight > 0.); modelgrid[mgi].elem_meanweight[element] = meanweight; } @@ -2066,10 +2049,9 @@ auto get_initenergyq(const int modelgridindex) -> double { return modelgrid[modelgridindex].initenergyq; } -auto get_cellradialposmid(const int cellindex) -> double // get the radial distance from the origin to the centre of the cell at time tmin -{ - if (GRID_TYPE == GRID_SPHERICAL1D) { +auto get_cellradialposmid(const int cellindex) -> double { + if (GRID_TYPE == GridType::SPHERICAL1D) { // mid point radius // return get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); // volume averaged mean radius is slightly complex for radial shells @@ -2078,7 +2060,7 @@ auto get_cellradialposmid(const int cellindex) -> double return 3. / 4 * (pow(r_outer, 4.) - pow(r_inner, 4.)) / (pow(r_outer, 3) - pow(r_inner, 3.)); } - if (GRID_TYPE == GRID_CYLINDRICAL2D) { + if (GRID_TYPE == GridType::CYLINDRICAL2D) { const double rcyl_mid = get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)); const double z_mid = get_cellcoordmin(cellindex, 1) + (0.5 * wid_init(cellindex, 1)); return std::sqrt(std::pow(rcyl_mid, 2) + std::pow(z_mid, 2)); @@ -2131,7 +2113,7 @@ void calculate_kappagrey() { } } - /// Second pass through allows calculation of normalized chi_grey + // Second pass through allows calculation of normalized chi_grey double check1 = 0.; double check2 = 0.; for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { @@ -2141,7 +2123,7 @@ void calculate_kappagrey() { if (globals::opacity_case == 0) { kappa = globals::GREY_OP; } else if (globals::opacity_case == 1 || globals::opacity_case == 4) { - /// kappagrey used for initial grey approximation in case 4 + // kappagrey used for initial grey approximation in case 4 kappa = ((0.9 * get_ffegrp(mgi)) + 0.1) * globals::GREY_OP / ((0.9 * mfegroup / mtot_input) + 0.1); } else if (globals::opacity_case == 2) { const double opcase2_normal = globals::GREY_OP * rho_sum / ((0.9 * fe_sum) + (0.1 * (ngrid - empty_cells))); @@ -2217,34 +2199,25 @@ void calculate_kappagrey() { void read_ejecta_model() { switch (get_model_type()) { - case GRID_SPHERICAL1D: { + case GridType::SPHERICAL1D: { printout("Read 1D model\n"); read_1d_model(); break; } - case GRID_CYLINDRICAL2D: { + case GridType::CYLINDRICAL2D: { printout("Read 2D model\n"); read_2d_model(); break; } - case GRID_CARTESIAN3D: { + case GridType::CARTESIAN3D: { printout("Read 3D model\n"); read_3d_model(); break; } - - default: { - if constexpr (TESTMODE) { - printout("ERROR: Unknown model type %d\n", get_model_type()); - assert_testmodeonly(false); - } else { - __builtin_unreachable(); - } - } } printout("npts_model: %d\n", get_npts_model()); @@ -2340,17 +2313,16 @@ auto get_ndo_nonempty(const int rank) -> int { return ranks_ndo_nonempty[rank]; } -void grid_init(const int my_rank) -/// Initialises the propagation grid cells and associates them with modelgrid cells -{ - /// The cells will be ordered by x then y, then z. Call a routine that - /// sets up the initial positions and widths of the cells. +// Initialise the propagation grid cells and associate them with modelgrid cells +void grid_init(const int my_rank) { + // The cells will be ordered by x then y, then z. Call a routine that + // sets up the initial positions and widths of the cells. - if (GRID_TYPE == GRID_CARTESIAN3D) { + if (GRID_TYPE == GridType::CARTESIAN3D) { setup_grid_cartesian_3d(); - } else if (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if (GRID_TYPE == GridType::CYLINDRICAL2D) { setup_grid_cylindrical_2d(); - } else if (GRID_TYPE == GRID_SPHERICAL1D) { + } else if (GRID_TYPE == GridType::SPHERICAL1D) { setup_grid_spherical1d(); } else { printout("[fatal] grid_init: Error: Unknown grid type. Abort."); @@ -2364,7 +2336,7 @@ void grid_init(const int my_rank) } printout(" total propagation cells: %d\n", ngrid); - /// Now set up the density in each cell. + // Now set up the density in each cell. // Calculate the critical opacity at which opacity_case 3 switches from a // regime proportional to the density to a regime independent of the density @@ -2375,18 +2347,18 @@ void grid_init(const int my_rank) printout("grid_init: rho_crit = %g [g/cm3]\n", globals::rho_crit); if (get_model_type() == GRID_TYPE) { - if (get_model_type() == GRID_CARTESIAN3D) { + if (get_model_type() == GridType::CARTESIAN3D) { assert_always(ncoord_model[0] == ncoordgrid[0]); assert_always(ncoord_model[1] == ncoordgrid[1]); assert_always(ncoord_model[2] == ncoordgrid[2]); } map_modeltogrid_direct(); - } else if (get_model_type() == GRID_SPHERICAL1D) { - assert_always(GRID_TYPE == GRID_CARTESIAN3D); + } else if (get_model_type() == GridType::SPHERICAL1D) { + assert_always(GRID_TYPE == GridType::CARTESIAN3D); map_1dmodelto3dgrid(); - } else if (get_model_type() == GRID_CYLINDRICAL2D) { - assert_always(GRID_TYPE == GRID_CARTESIAN3D); + } else if (get_model_type() == GridType::CYLINDRICAL2D) { + assert_always(GRID_TYPE == GridType::CARTESIAN3D); map_2dmodelto3dgrid(); } else { printout("[fatal] grid_init: Error: Unknown density type. Abort."); @@ -2398,7 +2370,7 @@ void grid_init(const int my_rank) for (int n = 0; n < ngrid; n++) { const int mgi = get_cell_modelgridindex(n); if (mgi != get_npts_model()) { - fprintf(grid_file, "%d %d\n", n, mgi); /// write only non-empty cells to grid file + fprintf(grid_file, "%d %d\n", n, mgi); // write only non-empty cells to grid file } } fclose(grid_file); @@ -2413,10 +2385,10 @@ void grid_init(const int my_rank) radfield::init(my_rank, ndo_nonempty); nonthermal::init(my_rank, ndo_nonempty); - /// and assign a temperature to the cells + // and assign a temperature to the cells if (globals::simulation_continued_from_saved) { - /// For continuation of an existing simulation we read the temperatures - /// at the end of the simulation and write them to the grid. + // For continuation of an existing simulation we read the temperatures + // at the end of the simulation and write them to the grid. read_grid_restart_data(globals::timestep_initial); } else { assign_initial_temperatures(); @@ -2425,8 +2397,7 @@ void grid_init(const int my_rank) // when mapping 1D spherical or 2D cylindrical model onto cubic grid, scale up the // radioactive abundances to account for the missing masses in // the model cells that are not associated with any propagation cells - // Luke: TODO: it's probably better to adjust the density instead of the abundances - if (GRID_TYPE == GRID_CARTESIAN3D && get_model_type() == GRID_SPHERICAL1D && globals::rank_in_node == 0) { + if (GRID_TYPE == GridType::CARTESIAN3D && get_model_type() == GridType::SPHERICAL1D && globals::rank_in_node == 0) { for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { if (totmassradionuclide[nucindex] <= 0) { continue; @@ -2468,9 +2439,8 @@ auto get_totmassradionuclide(const int z, const int a) -> double { return totmassradionuclide[decay::get_nucindex(z, a)]; } -[[nodiscard]] auto get_cellindex_from_pos(const std::array pos, const double time) -> int -/// identify the cell index from an (x,y,z) position and a time. -{ +// identify the cell index from an (x,y,z) position and a time. +[[nodiscard]] auto get_cellindex_from_pos(const std::array pos, const double time) -> int { auto posgridcoords = get_gridcoords_from_xyz(pos); int cellindex = 0; for (int d = 0; d < get_ngriddimensions(); d++) { @@ -2486,12 +2456,10 @@ auto get_totmassradionuclide(const int z, const int a) -> double { return cellindex; } -[[nodiscard]] __host__ __device__ auto boundary_distance(const std::array dir, - const std::array pos, const double tstart, - const int cellindex, - enum cell_boundary *pkt_last_cross) -> std::tuple -/// Basic routine to compute distance to a cell boundary. -{ +// compute distance to a cell boundary. +[[nodiscard]] __host__ __device__ auto boundary_distance( + const std::array dir, const std::array pos, const double tstart, const int cellindex, + enum cell_boundary *pkt_last_cross) -> std::tuple { if constexpr (FORCE_SPHERICAL_ESCAPE_SURFACE) { if (get_cell_r_inner(cellindex) > globals::vmax * globals::tmin) { return {0., -99}; @@ -2512,19 +2480,19 @@ auto get_totmassradionuclide(const int z, const int a) -> double { for (int d = 0; d < ndim; d++) { cellcoordmax[d] = grid::get_cellcoordmax(cellindex, d); } - if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { // keep xyz Cartesian coordinates for (int d = 0; d < ndim; d++) { pktvelgridcoord[d] = dir[d] * CLIGHT_PROP; } - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { // xy plane radial velocity pktvelgridcoord[0] = (pos[0] * dir[0] + pos[1] * dir[1]) / pktposgridcoord[0] * CLIGHT_PROP; // second cylindrical coordinate is z pktvelgridcoord[1] = dir[2] * CLIGHT_PROP; - } else if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + } else if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { // the only coordinate is radius from the origin pktvelgridcoord[0] = dot(pos, dir) / pktposgridcoord[0] * CLIGHT_PROP; // radial velocity } else { @@ -2602,7 +2570,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { std::array{-1}; // distance to reach the cell's upper boundary on each coordinate auto d_coordminboundary = std::array{-1}; // distance to reach the cell's lower boundary on each coordinate - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { last_cross = BOUNDARY_NONE; // handle this separately by setting d_inner and d_outer negative for invalid direction const double speed = vec_len(dir) * CLIGHT_PROP; // just in case dir is not normalised @@ -2612,7 +2580,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { const double r_outer = cellcoordmax[0] * tstart / globals::tmin; d_coordmaxboundary[0] = expanding_shell_intersection(pos, dir, speed, r_outer, false, tstart); - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { // coordinate 0 is radius in x-y plane, coord 1 is z if (last_cross == COORD0_MIN || last_cross == COORD0_MAX) { last_cross = @@ -2622,7 +2590,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { std::tie(d_coordminboundary, d_coordmaxboundary) = get_coordboundary_distances_cylindrical2d( pos, dir, pktposgridcoord, pktvelgridcoord, cellindex, tstart, cellcoordmax); - } else if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + } else if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { // There are six possible boundary crossings. Each of the three // cartesian coordinates may be taken in turn. For x, the packet // trajectory is diff --git a/grid.h b/grid.h index 1c6c09fe1..12c961420 100644 --- a/grid.h +++ b/grid.h @@ -32,17 +32,17 @@ struct ModelGridCell { float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] float ffegrp = 0.; float kappagrey = 0.; - float grey_depth = 0.; /// Grey optical depth to surface of the modelgridcell - /// This is only stored to print it outside the OpenMP loop in update_grid to the - /// estimatorsfile so there is no need to communicate it via MPI so far! - int *elements_uppermost_ion{}; /// Highest ionisation stage which has a decent population for a particular - /// element in a given cell. - float *elem_massfracs{}; /// Pointer to an array which contains the time dependent - /// abundances of all included elements and all the groundlevel - - float *ion_groundlevelpops{}; /// groundlevel populations of all included ions - float *ion_partfuncts{}; /// partition functions for all included ions - std::span nlte_pops; /// Pointer to an array that contains the nlte-level populations for this cell + float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell + // This is only stored to print it outside the OpenMP loop in update_grid to the + // estimatorsfile so there is no need to communicate it via MPI so far! + int *elements_uppermost_ion{}; // Highest ionisation stage which has a decent population for a particular + // element in a given cell. + float *elem_massfracs{}; // Pointer to an array which contains the time dependent + // abundances of all included elements and all the groundlevel + + float *ion_groundlevelpops{}; // groundlevel populations of all included ions + float *ion_partfuncts{}; // partition functions for all included ions + std::span nlte_pops; // Pointer to an array that contains the nlte-level populations for this cell double totalcooling = -1; double *ion_cooling_contribs{}; uint_fast8_t thick = 0; @@ -50,11 +50,11 @@ struct ModelGridCell { constexpr auto get_ngriddimensions() -> int { switch (GRID_TYPE) { - case GRID_SPHERICAL1D: + case GridType::SPHERICAL1D: return 1; - case GRID_CYLINDRICAL2D: + case GridType::CYLINDRICAL2D: return 2; - case GRID_CARTESIAN3D: + case GridType::CARTESIAN3D: return 3; default: assert_always(false); @@ -109,8 +109,8 @@ void set_element_meanweight(int mgi, int element, float meanweight); [[nodiscard]] auto get_numassociatedcells(int modelgridindex) -> int; [[nodiscard]] auto get_modelcell_nonemptymgi(int mgi) -> int; [[nodiscard]] auto get_mgi_of_nonemptymgi(int nonemptymgi) -> int; -[[nodiscard]] auto get_model_type() -> enum gridtypes; -void set_model_type(enum gridtypes model_type_value); +[[nodiscard]] auto get_model_type() -> GridType; +void set_model_type(GridType model_type_value); [[nodiscard]] auto get_npts_model() -> int; [[nodiscard]] auto get_nonempty_npts_model() -> int; [[nodiscard]] auto get_t_model() -> double; @@ -137,7 +137,7 @@ void write_grid_restart_data(int timestep); void calculate_kappagrey(); inline void change_cell(Packet &pkt, const int snext) -/// Routine to take a packet across a boundary. +// Routine to take a packet across a boundary. { if (snext >= 0) { // Just need to update "where". diff --git a/input.cc b/input.cc index 78a3c037e..012f834d9 100644 --- a/input.cc +++ b/input.cc @@ -60,7 +60,7 @@ struct Transition { float A; float coll_str; bool forbidden; -}; /// only used temporarily during input +}; // only used temporarily during input constexpr std::array inputlinecomments = { " 0: pre_zseed: specific random number seed if > 0 or random if negative", @@ -166,10 +166,10 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } } - /// The level contributes to the ionisinglevels if its energy - /// is below the ionisation potential and the level doesn't - /// belong to the topmost ion included. - /// Rate coefficients are only available for ionising levels. + // The level contributes to the ionisinglevels if its energy + // is below the ionisation potential and the level doesn't + // belong to the topmost ion included. + // Rate coefficients are only available for ionising levels. // also need (levelenergy < ionpot && ...)? if (lowerion < get_nions(element) - 1) { for (int phixstargetindex = 0; phixstargetindex < get_nphixstargets(element, lowerion, lowerlevel); @@ -202,8 +202,8 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input double phixs = -1.; assert_always(phixsfile >> energy >> phixs); nutable[i] = nu_edge + (energy * 13.6 * EV) / H; - /// the photoionisation cross-sections in the database are given in Mbarn=1e6 * 1e-28m^2 - /// to convert to cgs units multiply by 1e-18 + // the photoionisation cross-sections in the database are given in Mbarn=1e6 * 1e-28m^2 + // to convert to cgs units multiply by 1e-18 phixstable[i] = phixs * 1e-18; } const double nu_max = nutable[nphixspoints_inputtable - 1]; @@ -234,8 +234,8 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input assert_always(phixsfile >> phixs); assert_always(phixs >= 0); - /// the photoionisation cross-sections in the database are given in Mbarn = 1e6 * 1e-28m^2 - /// to convert to cgs units multiply by 1e-18 + // the photoionisation cross-sections in the database are given in Mbarn = 1e6 * 1e-28m^2 + // to convert to cgs units multiply by 1e-18 globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs[i] = phixs * 1e-18; // fprintf(database_file,"%g %g\n", nutable[i], phixstable[i]); } @@ -303,20 +303,20 @@ void read_phixs_data(const int phixs_file_version) { bool skip_this_phixs_table = false; // printout("[debug] Z %d, upperion %d, upperlevel %d, lowerion %d, lowerlevel, // %d\n",Z,upperion,upperlevel,lowerion,lowerlevel); - /// translate readin anumber to element index + // translate readin anumber to element index const int element = get_elementindex(Z); - /// store only photoionization crosssections for elements that are part of the current model atom + // store only photoionization crosssections for elements that are part of the current model atom skip_this_phixs_table = true; // will be set to false for good data if (element >= 0 && get_nions(element) > 0) { - /// translate readin ionstages to ion indices + // translate readin ionstages to ion indices const int upperion = upperionstage - get_ionstage(element, 0); const int lowerion = lowerionstage - get_ionstage(element, 0); const int lowerlevel = lowerlevel_in - groundstate_index_in; assert_always(lowerionstage >= 0); assert_always(lowerlevel >= 0); - /// store only photoionization crosssections for ions that are part of the current model atom + // store only photoionization crosssections for ions that are part of the current model atom if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_nlevels(element, lowerion)) { read_phixs_data_table(phixsfile, nphixspoints_inputtable, element, lowerion, lowerlevel, upperion, upperlevel_in, &mem_usage_phixs); @@ -383,17 +383,17 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons globals::elements[element].ions[ion].levels[level].metastable = true; // globals::elements[element].ions[ion].levels[level].main_qn = mainqn; - /// The level contributes to the ionisinglevels if its energy - /// is below the ionization potential and the level doesn't - /// belong to the topmost ion included. - /// Rate coefficients are only available for ionising levels. + // The level contributes to the ionisinglevels if its energy + // is below the ionization potential and the level doesn't + // belong to the topmost ion included. + // Rate coefficients are only available for ionising levels. if (levelenergy < ionpot && ion < nions - 1) { globals::elements[element].ions[ion].ionisinglevels++; } - /// store the possible downward transitions from the current level in following order to memory - /// A_level,level-1; A_level,level-2; ... A_level,1 - /// entries which are not explicitly set are zero (the zero is set/initialized by calloc!) + // store the possible downward transitions from the current level in following order to memory + // A_level,level-1; A_level,level-2; ... A_level,1 + // entries which are not explicitly set are zero (the zero is set/initialized by calloc!) transitions[level].to = &transitions[0].to[transitionblockindex]; transitionblockindex += level; assert_always((transitionblockindex + level) < transitblocksize); @@ -558,8 +558,8 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons continue; } - /// Make sure that we don't allow duplicate. In that case take only the lines - /// first occurrence + // Make sure that we don't allow duplicate. In that case take only the lines + // first occurrence const int transitioncheck = transitions[level].to[(level - targetlevel) - 1]; // -99 means that the transition hasn't been seen yet @@ -610,7 +610,7 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons .forbidden = transition.forbidden}; } - /// This is not a metastable level. + // This is not a metastable level. globals::elements[element].ions[ion].levels[level].metastable = false; (*lineindex)++; @@ -712,17 +712,17 @@ void read_atomicdata_files() { printout("single_level_top_ion: %s\n", single_level_top_ion ? "true" : "false"); printout("single_ground_level: %s\n", single_ground_level ? "true" : "false"); - /// initialize atomic data structure to number of elements + // initialize atomic data structure to number of elements int nelements_in = 0; assert_always(compositiondata >> nelements_in); set_nelements(nelements_in); - /// Initialize the linelist + // Initialize the linelist std::vector temp_linelist; std::vector transitiontable; - /// temperature to determine relevant ionstages + // temperature to determine relevant ionstages int T_preset = 0; assert_always(compositiondata >> T_preset); assert_always(T_preset == 0); // no longer in use @@ -730,15 +730,15 @@ void read_atomicdata_files() { assert_always(compositiondata >> homogeneous_abundances); assert_always(homogeneous_abundances == 0); // no longer in use - /// open transition data file + // open transition data file auto ftransitiondata = fstream_required("transitiondata.txt", std::ios::in); - int lineindex = 0; /// counter to determine the total number of lines + int lineindex = 0; // counter to determine the total number of lines int uniqueionindex = 0; // index into list of all ions of all elements int uniquelevelindex = 0; // index into list of all levels of all ions of all elements int nbfcheck = 0; for (int element = 0; element < get_nelements(); element++) { - /// read information about the next element which should be stored to memory + // read information about the next element which should be stored to memory int Z = 0; int nions = 0; int lowermost_ionstage = 0; @@ -756,29 +756,29 @@ void read_atomicdata_files() { assert_always(uniformabundance >= 0); assert_always(mass_amu >= 0); - /// write this element's data to memory + // write this element's data to memory globals::elements[element].anumber = Z; globals::elements[element].nions = nions; globals::elements[element].initstablemeannucmass = mass_amu * MH; globals::elements[element].uniqueionindexstart = uniqueionindex; - /// Initialize the elements ionlist + // Initialize the elements ionlist globals::elements[element].ions = static_cast(calloc(nions, sizeof(Ion))); assert_always(globals::elements[element].ions != nullptr); - /// now read in data for all ions of the current element. before doing so initialize - /// energy scale for the current element (all level energies are stored relative to - /// the ground level of the neutral ion) + // now read in data for all ions of the current element. before doing so initialize + // energy scale for the current element (all level energies are stored relative to + // the ground level of the neutral ion) double energyoffset = 0.; double ionpot = 0.; for (int ion = 0; ion < nions; ion++) { int nlevelsmax = nlevelsmax_readin; // printout("element %d ion %d\n", element, ion); - /// calculate the current levels ground level energy + // calculate the current levels ground level energy assert_always(ionpot >= 0); energyoffset += ionpot; - /// read information for the elements next ionstage + // read information for the elements next ionstage int adata_Z_in = -1; int ionstage = -1; int nlevels = 0; @@ -830,7 +830,7 @@ void read_atomicdata_files() { nlevelsmax = nlevels; } - /// and proceed through the transitionlist till we match this ionstage (if it was not the neutral one) + // and proceed through the transitionlist till we match this ionstage (if it was not the neutral one) int transdata_Z_in = -1; int transdata_ionstage_in = -1; int tottransitions_in_file = 0; @@ -849,7 +849,7 @@ void read_atomicdata_files() { assert_always(tottransitions_in_file >= 0); // read the data for the levels and set up the list of possible transitions for each level - /// store the ions data to memory and set up the ions zeta and levellist + // store the ions data to memory and set up the ions zeta and levellist globals::elements[element].ions[ion].ionstage = ionstage; globals::elements[element].ions[ion].nlevels = nlevelsmax; globals::elements[element].ions[ion].ionisinglevels = 0; @@ -881,7 +881,7 @@ void read_atomicdata_files() { assert_always(transdata_Z_in == Z); assert_always(transdata_ionstage_in == ionstage); - /// load transition table for the CURRENT ion to temporary memory + // load transition table for the CURRENT ion to temporary memory // first levels will be collisionally // coupled to the first levels (assumed forbidden) @@ -921,7 +921,7 @@ void read_atomicdata_files() { } printout("nbfcheck %d\n", nbfcheck); - /// Save the linecounters value to the global variable containing the number of lines + // Save the linecounters value to the global variable containing the number of lines globals::nlines = lineindex; printout("nlines %d\n", globals::nlines); if (globals::rank_in_node == 0) { @@ -932,7 +932,7 @@ void read_atomicdata_files() { std::abort(); } - /// Set up the list of allowed upward transitions for each level + // Set up the list of allowed upward transitions for each level printout("total uptrans %d\n", totaluptrans); printout("total downtrans %d\n", totaldowntrans); @@ -1000,7 +1000,7 @@ void read_atomicdata_files() { printout("[info] mem_usage: linelist occupies %.3f MB (node shared memory)\n", globals::nlines * sizeof(TransitionLine) / 1024. / 1024); - /// Save sorted linelist into a file + // Save sorted linelist into a file // if (rank_global == 0) // { // FILE *linelist_file = fopen_required("linelist.dat", "w"); @@ -1131,10 +1131,10 @@ void read_atomicdata_files() { } auto search_groundphixslist(const double nu_edge, const int element_in, const int ion_in, const int level_in) -> int -/// Return the closest ground level continuum index to the given edge -/// frequency. If the given edge frequency is redder than the reddest -/// continuum return -1. -/// NB: groundphixslist must be in ascending order. +// Return the closest ground level continuum index to the given edge +// frequency. If the given edge frequency is redder than the reddest +// continuum return -1. +// NB: groundphixslist must be in ascending order. { assert_always((USE_LUT_PHOTOION || USE_LUT_BFHEATING)); @@ -1343,10 +1343,9 @@ void write_bflist_file() { } } +// set up the photoionisation transition lists +// and temporary gamma/kappa lists for each thread void setup_phixs_list() { - // set up the photoionisation transition lists - // and temporary gamma/kappa lists for each thread - printout("[info] read_atomicdata: number of bfcontinua %d\n", globals::nbfcontinua); printout("[info] read_atomicdata: number of ground-level bfcontinua %d\n", globals::nbfcontinua_ground); @@ -1516,7 +1515,7 @@ void setup_phixs_list() { void read_atomicdata() { read_atomicdata_files(); - /// INITIALISE THE ABSORPTION/EMISSION COUNTERS ARRAYS + // INITIALISE THE ABSORPTION/EMISSION COUNTERS ARRAYS if constexpr (RECORD_LINESTAT) { globals::ecounter.resize(globals::nlines); globals::acounter.resize(globals::nlines); @@ -1526,7 +1525,7 @@ void read_atomicdata() { setup_cellcache(); - /// Printout some information about the read-in model atom + // Printout some information about the read-in model atom int includedionisinglevels = 0; int includedboundboundtransitions = 0; @@ -1566,7 +1565,7 @@ void read_atomicdata() { setup_phixs_list(); - /// set-up/gather information for nlte stuff + // set-up/gather information for nlte stuff globals::total_nlte_levels = 0; int n_super_levels = 0; @@ -1617,9 +1616,8 @@ void read_atomicdata() { } // anonymous namespace -void input(int rank) -/// To govern the input. For now hardwire everything. -{ +// read input.txt, atomic data, and ejecta model +void input(int rank) { globals::n_titer = 1; globals::lte_iteration = false; @@ -1638,10 +1636,10 @@ void input(int rank) std::abort(); } - /// Read in parameters from input.txt + // Read in parameters from input.txt read_parameterfile(rank); - /// Read in parameters from vpkt.txt + // Read in parameters from vpkt.txt if (VPKT_ON) { read_parameterfile_vpkt(); } @@ -1659,9 +1657,8 @@ void input(int rank) grid::read_ejecta_model(); } -auto get_noncommentline(std::fstream &input, std::string &line) -> bool // read the next line, skipping any comment lines beginning with '#' -{ +auto get_noncommentline(std::fstream &input, std::string &line) -> bool { while (true) { const bool linefound = !(!std::getline(input, line)); // printout("LINE: >%s< linefound: %s commentonly: %s \n", line.c_str(), linefound ? "true" : "false", @@ -1675,9 +1672,8 @@ auto get_noncommentline(std::fstream &input, std::string &line) -> bool } } -void read_parameterfile(int rank) -/// Subroutine to read in input parameters from input.txt. -{ +// read input parameters from input.txt +void read_parameterfile(int rank) { auto file = fstream_required("input.txt", std::ios::in); std::string line; @@ -1704,9 +1700,9 @@ void read_parameterfile(int rank) #pragma omp parallel #endif { - /// For MPI parallelisation, the random seed is changed based on the rank of the process - /// For OpenMP parallelisation rng is a threadprivate variable and the seed changed according - /// to the thread-ID tid. + // For MPI parallelisation, the random seed is changed based on the rank of the process + // For OpenMP parallelisation rng is a threadprivate variable and the seed changed according + // to the thread-ID tid. const auto tid = get_thread_num(); auto rngseed = pre_zseed + static_cast(13 * (rank * get_max_threads() + tid)); #ifndef GPU_ON @@ -1753,11 +1749,11 @@ void read_parameterfile(int rank) int dum1 = 0; std::istringstream(line) >> dum1; if (dum1 == 1) { - grid::set_model_type(GRID_SPHERICAL1D); + grid::set_model_type(GridType::SPHERICAL1D); } else if (dum1 == 2) { - grid::set_model_type(GRID_CYLINDRICAL2D); + grid::set_model_type(GridType::CYLINDRICAL2D); } else if (dum1 == 3) { - grid::set_model_type(GRID_CARTESIAN3D); + grid::set_model_type(GridType::CARTESIAN3D); } assert_always(get_noncommentline(file, line)); // UNUSED compute the r-light curve? @@ -1793,7 +1789,7 @@ void read_parameterfile(int rank) assert_always(get_noncommentline(file, line)); std::istringstream(line) >> globals::rho_crit_para; // free parameter for calculation of rho_crit printout("input: rho_crit_para %g\n", globals::rho_crit_para); - /// he calculation of rho_crit itself depends on the time, therfore it happens in grid_init and update_grid + // he calculation of rho_crit itself depends on the time, therfore it happens in grid_init and update_grid assert_always(get_noncommentline(file, line)); int debug_packet = 0; @@ -1813,15 +1809,15 @@ void read_parameterfile(int rank) assert_always(globals::timestep_initial == 0); } - /// Wavelength (in Angstroms) at which the parameterisation of the radiation field - /// switches from the nebular approximation to LTE. + // Wavelength (in Angstroms) at which the parameterisation of the radiation field + // switches from the nebular approximation to LTE. float dum2{NAN}; assert_always(get_noncommentline(file, line)); std::istringstream(line) >> dum2; // free parameter for calculation of rho_crit globals::nu_rfcut = CLIGHT / (dum2 * 1e-8); printout("input: nu_rfcut %g\n", globals::nu_rfcut); - /// Sets the number of initial LTE timesteps for NLTE runs + // Sets the number of initial LTE timesteps for NLTE runs assert_always(get_noncommentline(file, line)); std::istringstream(line) >> globals::num_lte_timesteps; printout("input: doing the first %d timesteps in LTE\n", globals::num_lte_timesteps); @@ -1854,35 +1850,35 @@ void read_parameterfile(int rank) "LUT).\n"); } - /// Set up initial grey approximation? + // Set up initial grey approximation? assert_always(get_noncommentline(file, line)); std::istringstream(line) >> globals::cell_is_optically_thick >> globals::num_grey_timesteps; printout( "input: cells with Thomson optical depth > %g are treated in grey approximation for the first %d timesteps\n", globals::cell_is_optically_thick, globals::num_grey_timesteps); - /// Limit the number of bf-continua + // Limit the number of bf-continua assert_always(get_noncommentline(file, line)); int max_bf_continua = 0; std::istringstream(line) >> max_bf_continua; assert_always(max_bf_continua == -1); - /// for exspec: read number of MPI tasks + // for exspec: read number of MPI tasks assert_always(get_noncommentline(file, line)); std::istringstream(line) >> globals::nprocs_exspec; - /// Extract line-of-sight dependent information of last emission for spectrum_res + // Extract line-of-sight dependent information of last emission for spectrum_res assert_always(get_noncommentline(file, line)); std::istringstream(line) >> dum1; globals::do_emission_res = (dum1 != 0); - /// To reduce the work imbalance between different MPI tasks I introduced a diffusion - /// for kpkts, since it turned out that this work imbalance was largely dominated - /// by continuous collisional interactions. By introducing a diffusion time for kpkts - /// this loop is broken. The following two parameters control this approximation. - /// Parameter one (a float) gives the relative fraction of a time step which individual - /// kpkts live. Parameter two (an int) gives the number of time steps for which we - /// want to use this approximation + // To reduce the work imbalance between different MPI tasks I introduced a diffusion + // for kpkts, since it turned out that this work imbalance was largely dominated + // by continuous collisional interactions. By introducing a diffusion time for kpkts + // this loop is broken. The following two parameters control this approximation. + // Parameter one (a float) gives the relative fraction of a time step which individual + // kpkts live. Parameter two (an int) gives the number of time steps for which we + // want to use this approximation assert_always(get_noncommentline(file, line)); int n_kpktdiffusion_timesteps{0}; float kpktdiffusion_timescale{0.}; @@ -1898,7 +1894,7 @@ void read_parameterfile(int rank) } void update_parameterfile(int nts) -/// Subroutine to read in input parameters from input.txt. +// Subroutine to read in input parameters from input.txt. { assert_always(globals::rank_global == 0); if (nts >= 0) { @@ -1932,19 +1928,19 @@ void update_parameterfile(int nts) // overwrite particular lines to enable restarting from the current timestep if (nts >= 0) { if (noncomment_linenum == 2) { - /// Number of start and end time step + // Number of start and end time step snprintf(c_line, sizeof(c_line), "%d %d", nts, globals::timestep_finish); // line.assign(c_line); line.replace(line.begin(), line.end(), c_line); } else if (noncomment_linenum == 16) { - /// resume from gridsave file - snprintf(c_line, sizeof(c_line), "%d", 1); /// Force continuation + // resume from gridsave file + snprintf(c_line, sizeof(c_line), "%d", 1); // Force continuation line.assign(c_line); } } if (noncomment_linenum == 21) { - /// by default, exspec should use all available packet files + // by default, exspec should use all available packet files globals::nprocs_exspec = globals::nprocs; snprintf(c_line, sizeof(c_line), "%d", globals::nprocs_exspec); line.assign(c_line); @@ -1980,20 +1976,19 @@ void update_parameterfile(int nts) printout("done\n"); } -void time_init() -// define the time steps -{ - /// t=globals::tmin is the start of the calculation. t=globals::tmax is the end of the calculation. - /// globals::ntimesteps is the number of time steps +// initialize the time steps +void time_init() { + // t=globals::tmin is the start of the calculation. t=globals::tmax is the end of the calculation. + // globals::ntimesteps is the number of time steps globals::timesteps.resize(globals::ntimesteps + 1); for (auto &ts : globals::timesteps) { ts = TimeStep{}; } - /// Now set the individual time steps + // Now set the individual time steps switch (TIMESTEP_SIZE_METHOD) { - case TIMESTEP_SIZES_LOGARITHMIC: { + case TimeStepSizeMethod::LOGARITHMIC: { for (int n = 0; n < globals::ntimesteps; n++) { // For logarithmic steps, the logarithmic inverval will be const double dlogt = (log(globals::tmax) - log(globals::tmin)) / globals::ntimesteps; globals::timesteps[n].start = globals::tmin * exp(n * dlogt); @@ -2003,7 +1998,7 @@ void time_init() break; } - case TIMESTEP_SIZES_CONSTANT: { + case TimeStepSizeMethod::CONSTANT: { for (int n = 0; n < globals::ntimesteps; n++) { // for constant timesteps const double dt = (globals::tmax - globals::tmin) / globals::ntimesteps; @@ -2014,7 +2009,7 @@ void time_init() break; } - case TIMESTEP_SIZES_LOGARITHMIC_THEN_CONSTANT: { + case TimeStepSizeMethod::LOGARITHMIC_THEN_CONSTANT: { // First part log, second part fixed timesteps const double t_transition = TIMESTEP_TRANSITION_TIME * DAY; // transition from logarithmic to fixed timesteps const double maxtsdelta = FIXED_TIMESTEP_WIDTH * DAY; // maximum timestep width in fixed part @@ -2047,8 +2042,8 @@ void time_init() break; } - case TIMESTEP_SIZES_CONSTANT_THEN_LOGARITHMIC: { - // /// First part fixed timesteps, second part log timesteps + case TimeStepSizeMethod::CONSTANT_THEN_LOGARITHMIC: { + // // First part fixed timesteps, second part log timesteps const double t_transition = TIMESTEP_TRANSITION_TIME * DAY; // transition from fixed to logarithmic timesteps const double maxtsdelta = FIXED_TIMESTEP_WIDTH * DAY; // timestep width of fixed timesteps assert_always(t_transition > globals::tmin); @@ -2102,8 +2097,8 @@ void time_init() // } // assert_always(globals::timesteps[0].width <= maxt); // no solution is possible with these constraints! - /// and add a dummy timestep which contains the endtime - /// of the calculation + // and add a dummy timestep which contains the endtime + // of the calculation globals::timesteps[globals::ntimesteps].start = globals::tmax; globals::timesteps[globals::ntimesteps].mid = globals::tmax; globals::timesteps[globals::ntimesteps].width = 0.; diff --git a/kpkt.cc b/kpkt.cc index 6c890263b..7a40f65e2 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -27,15 +28,10 @@ namespace kpkt { namespace { -enum coolingtype { - COOLINGTYPE_FF = 0, - COOLINGTYPE_FB = 1, - COOLINGTYPE_COLLEXC = 2, - COOLINGTYPE_COLLION = 3, -}; +enum class CoolingType : std::uint8_t { FREEFREE, FREEBOUND, COLLEXC, COLLION }; struct CellCacheCoolingList { - enum coolingtype type; + CoolingType type; int level; int upperlevel; }; @@ -45,13 +41,12 @@ std::vector coolinglist; int n_kpktdiffusion_timesteps{0}; float kpktdiffusion_timescale{0.}; +// calculate the cooling contribution list of individual levels/processes for an ion +// oldcoolingsum is the sum of lower ion (of same element or all ions of lower elements) cooling contributions template auto calculate_cooling_rates_ion(const int modelgridindex, const int element, const int ion, const int indexionstart, const int cellcacheslotid, double *const C_ff, double *const C_fb, double *const C_exc, - double *const C_ionization) -> double -// calculate the cooling contribution list of individual levels/processes for an ion -// oldcoolingsum is the sum of lower ion (of same element or all ions of lower elements) cooling contributions -{ + double *const C_ionization) -> double { const auto nne = grid::get_nne(modelgridindex); const auto T_e = grid::get_Te(modelgridindex); @@ -65,7 +60,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co const int nionisinglevels = get_ionisinglevels(element, ion); const double nncurrention = get_nnion(modelgridindex, element, ion); - /// ff creation of rpkt + // ff creation of rpkt const int ioncharge = get_ionstage(element, ion) - 1; // printout("[debug] ioncharge %d, nncurrention %g, nne %g\n",ion,nncurrention,nne); if (ioncharge > 0) { @@ -75,7 +70,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co if constexpr (update_cooling_contrib_list) { globals::cellcache[cellcacheslotid].cooling_contrib[i] = C_ion; - assert_testmodeonly(coolinglist[i].type == COOLINGTYPE_FF); + assert_testmodeonly(coolinglist[i].type == CoolingType::FREEFREE); i++; } else { @@ -83,7 +78,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co } } - /// excitation to same ionization stage + // excitation to same ionization stage const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { // printout("[debug] do_kpkt: element %d, ion %d, level %d\n", element, ion, level); @@ -107,7 +102,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co if constexpr (update_cooling_contrib_list) { globals::cellcache[cellcacheslotid].cooling_contrib[i] = C_ion; - assert_testmodeonly(coolinglist[i].type == COOLINGTYPE_COLLEXC); + assert_testmodeonly(coolinglist[i].type == CoolingType::COLLEXC); i++; } @@ -134,7 +129,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co if constexpr (update_cooling_contrib_list) { globals::cellcache[cellcacheslotid].cooling_contrib[i] = C_ion; - assert_testmodeonly(coolinglist[i].type == COOLINGTYPE_COLLION); + assert_testmodeonly(coolinglist[i].type == CoolingType::COLLION); assert_testmodeonly(coolinglist[i].level == level); assert_testmodeonly(coolinglist[i].upperlevel == upper); @@ -145,8 +140,8 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co } } - /// fb creation of r-pkt - /// free bound rates are calculated from the lower ion, but associated to the higher ion + // fb creation of r-pkt + // free bound rates are calculated from the lower ion, but associated to the higher ion for (int level = 0; level < nionisinglevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { @@ -160,7 +155,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co if constexpr (update_cooling_contrib_list) { globals::cellcache[cellcacheslotid].cooling_contrib[i] = C_ion; - assert_testmodeonly(coolinglist[i].type == COOLINGTYPE_FB); + assert_testmodeonly(coolinglist[i].type == CoolingType::FREEBOUND); assert_testmodeonly(coolinglist[i].level == level); assert_testmodeonly(coolinglist[i].upperlevel == get_phixsupperlevel(element, ion, level, phixstargetindex)); @@ -188,12 +183,12 @@ void set_ncoolingterms() { int ionterms = 0; globals::elements[element].ions[ion].coolingoffset = ncoolingterms; - /// Ionised ions add one ff-cooling term + // Ionised ions add one ff-cooling term if (get_ionstage(element, ion) > 1) { ionterms++; } - /// Ionisinglevels below the closure ion add to bf and col ionisation - /// All the levels add number of col excitations + // Ionisinglevels below the closure ion add to bf and col ionisation + // All the levels add number of col excitations const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { // if (ion < nions - 1) and (level < get_ionisinglevels(element,ion)) @@ -211,10 +206,9 @@ void set_ncoolingterms() { } } -auto sample_planck_analytic(const double T) -> double // return a randomly chosen frequency according to the Planck distribution of temperature T using an analytic method. // More testing of this function is needed. -{ +auto sample_planck_analytic(const double T) -> double { const double nu_peak = 5.879e10 * T; if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { printout("[warning] sample_planck: intensity peaks outside frequency range\n"); @@ -244,9 +238,8 @@ auto sample_planck_analytic(const double T) -> double return bin_nu_lower + nuoffset; } -auto sample_planck_montecarlo(const double T) -> double // return a randomly chosen frequency according to the Planck distribution of temperature T using a Monte Carlo method -{ +auto sample_planck_montecarlo(const double T) -> double { const double nu_peak = 5.879e10 * T; if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { printout("[warning] sample_planck: intensity peaks outside frequency range\n"); @@ -264,14 +257,13 @@ auto sample_planck_montecarlo(const double T) -> double } } // anonymous namespace -void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heatingcoolingrates) // Calculate the cooling rates for a given cell and store them for each ion // optionally store components (ff, bf, collisional) in heatingcoolingrates struct -{ - double C_ff_all = 0.; /// free-free creation of rpkts - double C_fb_all = 0.; /// free-bound creation of rpkt - double C_exc_all = 0.; /// collisional excitation of macroatoms - double C_ionization_all = 0.; /// collisional ionisation of macroatoms +void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heatingcoolingrates) { + double C_ff_all = 0.; // free-free creation of rpkts + double C_fb_all = 0.; // free-bound creation of rpkt + double C_exc_all = 0.; // collisional excitation of macroatoms + double C_ionization_all = 0.; // collisional ionisation of macroatoms for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { const auto [element, ion] = get_ionfromuniqueionindex(allionindex); grid::modelgrid[modelgridindex].ion_cooling_contribs[allionindex] = calculate_cooling_rates_ion( @@ -302,13 +294,11 @@ void set_kpktdiffusion(const float kpktdiffusion_timescale_in, const int n_kpktd } void setup_coolinglist() { - /// SET UP THE COOLING LIST - ///====================================================== - /// Determine number of processes which allow kpkts to convert to something else. - /// This number is given by the collisional excitations (so far determined from the oscillator strengths - /// by the van Regemorter formula, therefore totaluptrans), the number of free-bound emissions and collisional - /// ionisations (as long as we only deal with ionisation to the ground level this means for both of these - /// \sum_{elements,ions}get_nlevels(element,ion) and free-free which is \sum_{elements} get_nions(element)-1 + // Determine number of processes which allow kpkts to convert to something else. + // This number is given by the collisional excitations (so far determined from the oscillator strengths + // by the van Regemorter formula, therefore totaluptrans), the number of free-bound emissions and collisional + // ionisations (as long as we only deal with ionisation to the ground level this means for both of these + // \sum_{elements,ions}get_nlevels(element,ion) and free-free which is \sum_{elements} get_nions(element)-1 set_ncoolingterms(); const size_t mem_usage_coolinglist = ncoolingterms * sizeof(CellCacheCoolingList); @@ -324,12 +314,12 @@ void setup_coolinglist() { const int nionisinglevels = get_ionisinglevels(element, ion); - /// ff creation of rpkt - /// ------------------- + // ff creation of rpkt + // ------------------- const int ioncharge = get_ionstage(element, ion) - 1; // printout("[debug] ioncharge %d, nncurrention %g, nne %g\n",ion,nncurrention,nne); if (ioncharge > 0) { - coolinglist[i].type = COOLINGTYPE_FF; + coolinglist[i].type = CoolingType::FREEFREE; coolinglist[i].level = -99; coolinglist[i].upperlevel = -99; i++; @@ -337,7 +327,7 @@ void setup_coolinglist() { for (int level = 0; level < nlevels_currention; level++) { if (get_nuptrans(element, ion, level) > 0) { - coolinglist[i].type = COOLINGTYPE_COLLEXC; + coolinglist[i].type = CoolingType::COLLEXC; coolinglist[i].level = level; // upper level is not valid because this is the contribution of all upper levels combined - have to // calculate individually when selecting a random process @@ -346,26 +336,26 @@ void setup_coolinglist() { } } - if (ion < (nions - 1)) /// check whether further ionisation stage available + if (ion < (nions - 1)) // check whether further ionisation stage available { for (int level = 0; level < nionisinglevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upper = get_phixsupperlevel(element, ion, level, phixstargetindex); - coolinglist[i].type = COOLINGTYPE_COLLION; + coolinglist[i].type = CoolingType::COLLION; coolinglist[i].level = level; coolinglist[i].upperlevel = upper; i++; } } - /// fb creation of r-pkt - /// free bound rates are calculated from the lower ion, but associated to the higher ion + // fb creation of r-pkt + // free bound rates are calculated from the lower ion, but associated to the higher ion for (int level = 0; level < nionisinglevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upper = get_phixsupperlevel(element, ion, level, phixstargetindex); - coolinglist[i].type = COOLINGTYPE_FB; + coolinglist[i].type = CoolingType::FREEBOUND; coolinglist[i].level = level; coolinglist[i].upperlevel = upper; i++; @@ -381,7 +371,7 @@ void setup_coolinglist() { } __host__ __device__ void do_kpkt_blackbody(Packet &pkt) -/// handle a k-packet (e.g., in a thick cell) by emitting according to the planck function +// handle a k-packet (e.g., in a thick cell) by emitting according to the planck function { const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); @@ -395,10 +385,10 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) } assert_always(std::isfinite(pkt.nu_cmf)); - /// and then emit the packet randomly in the comoving frame + // and then emit the packet randomly in the comoving frame emit_rpkt(pkt); // printout("[debug] calculate_chi_rpkt after kpkt to rpkt by ff\n"); - pkt.next_trans = -1; /// FLAG: transition history here not important, cont. process + pkt.next_trans = -1; // FLAG: transition history here not important, cont. process // if (tid == 0) k_stat_to_r_bb++; stats::increment(stats::COUNTER_K_STAT_TO_R_BB); stats::increment(stats::COUNTER_INTERACTIONS); @@ -409,14 +399,13 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) pkt.nscatterings = 0; } -__host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) -/// handle a k-packet (kinetic energy of the free electrons) -{ +// handle a k-packet (kinetic energy of the free electrons) +__host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { const double t1 = pkt.prop_time; const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); - /// don't calculate cooling rates after each cell crossings any longer - /// but only if we really get a kpkt and they hadn't been calculated already + // don't calculate cooling rates after each cell crossings any longer + // but only if we really get a kpkt and they hadn't been calculated already // printout("[debug] do_kpkt: propagate k-pkt\n"); @@ -438,7 +427,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) assert_always(grid::modelgrid[modelgridindex].totalcooling > 0.); const double rndcool_ion = rng_uniform() * grid::modelgrid[modelgridindex].totalcooling; - /// Randomly select the occuring cooling process + // Randomly select the occuring cooling process double coolingsum = 0.; int element = -1; int ion = -1; @@ -523,22 +512,22 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) const auto rndcoolingtype = coolinglist[i].type; const auto T_e = grid::get_Te(modelgridindex); - if (rndcoolingtype == COOLINGTYPE_FF) { - /// The k-packet converts directly into a r-packet by free-free-emission. - /// Need to select the r-packets frequency and a random direction in the - /// co-moving frame. + if (rndcoolingtype == CoolingType::FREEFREE) { + // The k-packet converts directly into a r-packet by free-free-emission. + // Need to select the r-packets frequency and a random direction in the + // co-moving frame. // printout("[debug] do_kpkt: k-pkt -> free-free\n"); - /// Sample the packets comoving frame frequency according to paperII 5.4.3 eq.41 + // Sample the packets comoving frame frequency according to paperII 5.4.3 eq.41 - const double zrand = rng_uniform_pos(); /// delivers zrand in ]0,1[ + const double zrand = rng_uniform_pos(); // delivers zrand in ]0,1[ pkt.nu_cmf = -KB * T_e / H * log(zrand); assert_always(std::isfinite(pkt.nu_cmf)); - /// and then emit the packet randomly in the comoving frame + // and then emit the packet randomly in the comoving frame emit_rpkt(pkt); - pkt.next_trans = -1; /// FLAG: transition history here not important, cont. process + pkt.next_trans = -1; // FLAG: transition history here not important, cont. process stats::increment(stats::COUNTER_K_STAT_TO_R_FF); pkt.last_event = LASTEVENT_KPKT_TO_RPKT_FFBB; @@ -550,16 +539,16 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) vpkt_call_estimators(pkt, TYPE_KPKT); } - } else if (rndcoolingtype == COOLINGTYPE_FB) { - /// The k-packet converts directly into a r-packet by free-bound-emission. - /// Need to select the r-packets frequency and a random direction in the - /// co-moving frame. + } else if (rndcoolingtype == CoolingType::FREEBOUND) { + // The k-packet converts directly into a r-packet by free-bound-emission. + // Need to select the r-packets frequency and a random direction in the + // co-moving frame. const int lowerion = ion; const int lowerlevel = coolinglist[i].level; const int upper = coolinglist[i].upperlevel; - /// then randomly sample the packets frequency according to the continuums - /// energy distribution + // then randomly sample the packets frequency according to the continuums + // energy distribution // Sample the packets comoving frame frequency according to paperII 4.2.2 // const double zrand = rng_uniform(); @@ -578,7 +567,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) pkt.e_cmf / H / pkt.nu_cmf); } - pkt.next_trans = -1; /// FLAG: transition history here not important, cont. process + pkt.next_trans = -1; // FLAG: transition history here not important, cont. process stats::increment(stats::COUNTER_K_STAT_TO_R_FB); pkt.last_event = LASTEVENT_KPKT_TO_RPKT_FB; pkt.emissiontype = get_emtype_continuum(element, lowerion, lowerlevel, upper); @@ -590,8 +579,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) if constexpr (VPKT_ON) { vpkt_call_estimators(pkt, TYPE_KPKT); } - } else if (rndcoolingtype == COOLINGTYPE_COLLEXC) { - /// the k-packet activates a macro-atom due to collisional excitation + } else if (rndcoolingtype == CoolingType::COLLEXC) { + // the k-packet activates a macro-atom due to collisional excitation // printout("[debug] do_kpkt: k-pkt -> collisional excitation of MA\n"); const float nne = grid::get_nne(modelgridindex); @@ -646,8 +635,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) pkt.trueemissionvelocity = -1; do_macroatom(pkt, {.element = element, .ion = ion, .level = upper, .activatingline = -99}); - } else if (rndcoolingtype == COOLINGTYPE_COLLION) { - /// the k-packet activates a macro-atom due to collisional ionisation + } else if (rndcoolingtype == CoolingType::COLLION) { + // the k-packet activates a macro-atom due to collisional ionisation // printout("[debug] do_kpkt: k-pkt -> collisional ionisation of MA\n"); const int upperion = ion + 1; @@ -667,8 +656,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) do_macroatom(pkt, {.element = element, .ion = upperion, .level = upper, .activatingline = -99}); } else if constexpr (TESTMODE) { - printout("ERROR: Unknown rndcoolingtype type %d\n", rndcoolingtype); - assert_testmodeonly(false); + assert_always(false); } else { __builtin_unreachable(); } diff --git a/ltepop.cc b/ltepop.cc index 35f96c916..340a2d8b9 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -47,8 +47,8 @@ auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const d return globals::elements[element].ions[ion].Alpha_sp[TABLESIZE - 1]; } +// use Saha equation for LTE ionization balance auto phi_lte(const int element, const int ion, const int modelgridindex) -> double { - // use Saha equation for LTE ionization balance const int uniqueionindex = get_uniqueionindex(element, ion); auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; @@ -59,10 +59,9 @@ auto phi_lte(const int element, const int ion, const int modelgridindex) -> doub return partfunct_ratio * SAHACONST * pow(T_e, -1.5) * exp(ionpot / KB / T_e); } -auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const int nonemptymgi) -> double -/// Calculates population ratio (a saha factor) of two consecutive ionisation stages -/// in nebular approximation phi_j,k* = N_j,k*/(N_j+1,k* * nne) -{ +// Calculate population ratio (a saha factor) of two consecutive ionisation stages in nebular approximation phi_j,k* = +// N_j,k*/(N_j+1,k* * nne) +auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const int nonemptymgi) -> double { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -124,12 +123,12 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, return phi; } -auto get_element_nne_contrib(const int modelgridindex, const int element) - -> double { // calculate number density of the current element (abundances are given by mass) - // Use ionization fractions to calculate the free electron contributions +// calculate the free electron contribution from an element +auto get_element_nne_contrib(const int modelgridindex, const int element) -> double { if (grid::get_elem_numberdens(modelgridindex, element) <= 0.) { return 0.; } + double nne = 0.; const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -140,10 +139,9 @@ auto get_element_nne_contrib(const int modelgridindex, const int element) return nne; } -auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double // assume a value for nne and then calculate the resulting nne // the difference between the assumed and calculated nne is returned -{ +auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double { const auto *paras = static_cast(voidparas); const int modelgridindex = paras->modelgridindex; const bool force_lte = paras->force_lte; @@ -241,8 +239,8 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co } auto calculate_partfunct(const int element, const int ion, const int modelgridindex) -> double -/// Calculates the partition function for ion=ion of element=element in -/// cell modelgridindex +// Calculates the partition function for ion=ion of element=element in +// cell modelgridindex { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); @@ -343,14 +341,13 @@ void set_calculated_nne(const int modelgridindex) { grid::set_nne(modelgridindex, std::max(MINPOP, nne)); } +// Special case of only neutral ions, set nne to some finite value so that packets are not lost in kpkts void set_groundlevelpops_neutral(const int modelgridindex) { - /// Special case of only neutral ions, set nne to some finite value that - /// packets are not lost in kpkts printout("[warning] calculate_ion_balance_nne: only neutral ions in cell modelgridindex %d\n", modelgridindex); for (int element = 0; element < get_nelements(); element++) { const auto nnelement = grid::get_elem_numberdens(modelgridindex, element); const int nions = get_nions(element); - /// Assign the species population to the neutral ion and set higher ions to MINPOP + // Assign the species population to the neutral ion and set higher ions to MINPOP for (int ion = 0; ion < nions; ion++) { const int uniqueionindex = get_uniqueionindex(element, ion); double nnion{NAN}; @@ -370,7 +367,7 @@ void set_groundlevelpops_neutral(const int modelgridindex) { } auto find_converged_nne(const int modelgridindex, double nne_hi, const bool force_lte) -> float { - /// Search solution for nne in [nne_lo,nne_hi] + // Search solution for nne in [nne_lo,nne_hi] nneSolutionParas paras = {.modelgridindex = modelgridindex, .force_lte = force_lte}; gsl_function f = {.function = &nne_solution_f, .params = ¶s}; @@ -429,11 +426,10 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc } // anonymous namespace -[[nodiscard]] auto calculate_ionfractions(const int element, const int modelgridindex, const double nne, - const bool use_phi_lte) -> std::vector // Calculate the fractions of an element's population in each ionization stage based on Saha LTE or ionisation // equilibrium -{ +[[nodiscard]] auto calculate_ionfractions(const int element, const int modelgridindex, const double nne, + const bool use_phi_lte) -> std::vector { const int uppermost_ion = grid::get_elements_uppermost_ion(modelgridindex, element); assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); @@ -469,10 +465,9 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc return ionfractions; } -auto get_groundlevelpop(const int modelgridindex, const int element, const int ion) -> double -/// Returns the given ions groundlevel population for modelgridindex which was precalculated -/// during update_grid and stored to the grid. -{ +// Return the given ions groundlevel population for modelgridindex which was precalculated +// during update_grid and stored to the grid. +auto get_groundlevelpop(const int modelgridindex, const int element, const int ion) -> double { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -487,9 +482,8 @@ auto get_groundlevelpop(const int modelgridindex, const int element, const int i return nn; } -auto calculate_levelpop_lte(const int modelgridindex, const int element, const int ion, const int level) -> double -/// Calculates occupation population of a level assuming LTE excitation -{ +// Calculate occupation population of a level assuming LTE excitation +auto calculate_levelpop_lte(const int modelgridindex, const int element, const int ion, const int level) -> double { assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -522,10 +516,9 @@ auto calculate_levelpop(const int modelgridindex, const int element, const int i return nn; } +// Calculate the population of a level from either LTE or NLTE information __host__ __device__ auto get_levelpop(const int modelgridindex, const int element, const int ion, - const int level) -> double -/// Calculates the population of a level from either LTE or NLTE information -{ + const int level) -> double { double nn = 0.; if (use_cellcache) { assert_testmodeonly(modelgridindex == globals::cellcache[cellcacheslotid].cellnumber); @@ -540,14 +533,11 @@ __host__ __device__ auto get_levelpop(const int modelgridindex, const int elemen return nn; } -void calculate_cellpartfuncts(const int modelgridindex, const int element) -/// The partition functions depend only on T_R and W. This means they don't -/// change during any iteration on T_e. Therefore their precalculation was -/// taken out of calculate_ion_balance_nne to save runtime. +// The partition functions depend only on T_R and W. This means they don't +// change during any iteration on T_e. Therefore their precalculation was +// taken out of calculate_ion_balance_nne to save runtime. // TODO: not true if LTEPOP_EXCITATION_USE_TJ is true unless LTE mode only (TJ=TR=Te) -{ - /// Precalculate partition functions for each ion in every cell - /// this saves a factor 10 in calculation time of Saha-Boltzman populations +void calculate_cellpartfuncts(const int modelgridindex, const int element) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] = @@ -555,10 +545,9 @@ void calculate_cellpartfuncts(const int modelgridindex, const int element) } } +// calculates saha factor in LTE: Phi_level,ion,element = nn_level,ion,element/(nne*nn_upper,ion+1,element) __host__ __device__ auto calculate_sahafact(const int element, const int ion, const int level, const int upperionlevel, - const double T, const double E_threshold) -> double -/// calculates saha factor in LTE: Phi_level,ion,element = nn_level,ion,element/(nne*nn_upper,ion+1,element) -{ + const double T, const double E_threshold) -> double { const double g_lower = stat_weight(element, ion, level); const double g_upper = stat_weight(element, ion + 1, upperionlevel); const double sf = SAHACONST * g_lower / g_upper * pow(T, -1.5) * exp(E_threshold / KB / T); @@ -574,24 +563,23 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co return sf; } -[[nodiscard]] __host__ __device__ auto get_nnion(const int modelgridindex, const int element, const int ion) -> double -/// Use the ground level population and partition function to get an ion population -{ +// Use the ground level population and partition function to get an ion population +[[nodiscard]] __host__ __device__ auto get_nnion(const int modelgridindex, const int element, const int ion) -> double { return get_groundlevelpop(modelgridindex, element, ion) * grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] / stat_weight(element, ion, 0); } +// If not already set by the NLTE solver, set the ground level populations from either Saha LTE or +// ionization/recombination balance (Photoionization Equilibrium) void set_groundlevelpops(const int modelgridindex, const int element, const float nne, const bool force_lte) { - /// If not already set by the NLTE solver, set the ground level populations from either Saha LTE or - /// ionization/recombination balance (Photoionization Equilibrium) const int nions = get_nions(element); if (nions <= 0) { return; } - /// calculate number density of the current element (abundances are given by mass) + // calculate number density of the current element (abundances are given by mass) const double nnelement = grid::get_elem_numberdens(modelgridindex, element); const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); @@ -601,7 +589,7 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa const int uppermost_ion = static_cast(ionfractions.size() - 1); - /// Use ion fractions to calculate the groundlevel populations + // Use ion fractions to calculate the groundlevel populations for (int ion = 0; ion < nions; ion++) { const int uniqueionindex = get_uniqueionindex(element, ion); double nnion{NAN}; @@ -626,10 +614,9 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa } } -auto calculate_ion_balance_nne(const int modelgridindex) -> void -/// Determines the electron number density for a given cell using one of -/// libgsl's root_solvers and calculates the depending level populations. -{ +// Determine the electron number density for a given cell using one of +// libgsl's root_solvers and calculates the depending level populations. +auto calculate_ion_balance_nne(const int modelgridindex) -> void { const bool force_lte = globals::lte_iteration || grid::modelgrid[modelgridindex].thick == 1; const double nne_hi = grid::get_rho(modelgridindex) / MH; diff --git a/macroatom.cc b/macroatom.cc index 158ba4c34..398fd12fa 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -45,8 +45,8 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele const auto &levelref = globals::elements[element].ions[ion].levels[level]; - /// Downward transitions within the current ionisation stage: - /// radiative/collisional deexcitation and internal downward jumps + // Downward transitions within the current ionisation stage: + // radiative/collisional deexcitation and internal downward jumps double sum_internal_down_same = 0.; double sum_raddeexc = 0.; double sum_coldeexc = 0.; @@ -80,8 +80,8 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele processrates[MA_ACTION_COLDEEXC] = sum_coldeexc; processrates[MA_ACTION_INTERNALDOWNSAME] = sum_internal_down_same; - /// Downward transitions to lower ionisation stages: - /// radiative/collisional recombination and internal downward jumps + // Downward transitions to lower ionisation stages: + // radiative/collisional recombination and internal downward jumps // checks only if there is a lower ion, doesn't make sure that Z(ion)=Z(ion-1)+1 double sum_internal_down_lower = 0.; double sum_radrecomb = 0.; @@ -107,20 +107,18 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele processrates[MA_ACTION_RADRECOMB] = sum_radrecomb; processrates[MA_ACTION_COLRECOMB] = sum_colrecomb; - /// Calculate sum for upward internal transitions - /// transitions within the current ionisation stage + // Calculate sum for upward internal transitions + // transitions within the current ionisation stage double sum_internal_up_same = 0.; const int nuptrans = get_nuptrans(element, ion, level); for (int i = 0; i < nuptrans; i++) { - const auto &uptransition = globals::elements[element].ions[ion].levels[level].uptrans[i]; - const int upper = uptransition.targetlevelindex; - const int lineindex = uptransition.lineindex; - const double epsilon_trans = epsilon(element, ion, upper) - epsilon_current; + const auto &uptrans = globals::elements[element].ions[ion].levels[level].uptrans[i]; + const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; - const double R = rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, lineindex, t_mid); + const double R = + rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, uptrans.lineindex, t_mid); const double C = col_excitation_ratecoeff(T_e, nne, element, ion, level, i, epsilon_trans, statweight); - const double NT = - nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, lineindex); + const double NT = nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, uptrans.lineindex); const double individ_internal_up_same = (R + C + NT) * epsilon_current; @@ -131,7 +129,7 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele assert_always(std::isfinite(processrates[MA_ACTION_INTERNALUPSAME])); - /// Transitions to higher ionisation stages + // Transitions to higher ionisation stages double sum_up_highernt = 0.; double sum_up_higher = 0.; const int ionisinglevels = get_ionisinglevels(element, ion); @@ -142,8 +140,6 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - // const int upper = get_phixsupperlevel(element, ion, level, phixstargetindex); - // const double epsilon_trans = epsilon(element, ion + 1, upper) - epsilon(element, ion, level); const double epsilon_trans = get_phixs_threshold(element, ion, level, phixstargetindex); const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); @@ -164,7 +160,7 @@ auto do_macroatom_internal_down_same(const int element, const int ion, const int const double *sum_internal_down_same = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_down_same; - /// Randomly select the occuring transition + // Randomly select the occuring transition const double targetval = rng_uniform() * sum_internal_down_same[ndowntrans - 1]; // first sum_internal_down_same[i] such that sum_internal_down_same[i] > targetval @@ -178,10 +174,10 @@ auto do_macroatom_internal_down_same(const int element, const int ion, const int return lower; } +// radiative deexcitation void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, const int level, const int activatingline) { - /// radiative deexcitation of MA: emitt rpkt - /// randomly select which line transitions occurs + // randomly select which line transitions occurs const int ndowntrans = get_ndowntrans(element, ion, level); const auto *sum_epstrans_rad_deexc = @@ -236,7 +232,7 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele const double epsilon_current = epsilon(element, *ion, *level); const int upperion = *ion; const int upperionlevel = *level; - /// Randomly select a continuum + // Randomly select a continuum const double targetval = rng_uniform() * rad_recomb; double rate = 0; const int nlevels = get_ionisinglevels(element, upperion - 1); @@ -260,7 +256,7 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele std::abort(); } - /// set the new state + // set the new state *ion = upperion - 1; *level = lower; @@ -274,7 +270,7 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele stats::increment(stats::COUNTER_INTERACTIONS); pkt.last_event = 2; - /// Finally emit the packet into a randomly chosen direction, update the continuum opacity and set some flags + // Finally emit the packet into a randomly chosen direction, update the continuum opacity and set some flags emit_rpkt(pkt); if constexpr (TRACK_ION_STATS) { @@ -282,7 +278,7 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele pkt.e_cmf / H / pkt.nu_cmf); } - pkt.next_trans = -1; /// continuum transition, no restrictions for further line interactions + pkt.next_trans = -1; // continuum transition, no restrictions for further line interactions pkt.emissiontype = get_emtype_continuum(element, *ion, lower, upperionlevel); pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; @@ -316,9 +312,8 @@ void do_macroatom_ionisation(const int modelgridindex, const int element, int *c } // anonymous namespace -__host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) -/// Material for handling activated macro atoms. -{ +// handle activated macro atoms +__host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) { const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); assert_testmodeonly(nonemptymgi >= 0); @@ -332,12 +327,12 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); // macroatom should not be used in thick cells - /// calculate occupation number for active MA level //////////////////////////////////// - /// general QUESTION: is it better to calculate the n_1 (later the n_ionstage and - /// U_ionstage) here where we need them or once in update_grid for each grid cell - /// not sure whether this reduces the number of calculations, as number of grid cells - /// is much larger than number of pellets (next question: connection to number of - /// photons) + // calculate occupation number for active MA level //////////////////////////////////// + // general QUESTION: is it better to calculate the n_1 (later the n_ionstage and + // U_ionstage) here where we need them or once in update_grid for each grid cell + // not sure whether this reduces the number of calculations, as number of grid cells + // is much larger than number of pellets (next question: connection to number of + // photons) const int element = pktmastate.element; int ion = pktmastate.ion; int level = pktmastate.level; @@ -356,10 +351,10 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast bool end_packet = false; while (!end_packet) { - /// Set this here to 1 to overcome problems in cells which have zero population - /// in some ionisation stage. This is possible because the dependence on the - /// originating levels population cancels out in the macroatom transition probabilities - /// which are based on detailed balance. + // Set this here to 1 to overcome problems in cells which have zero population + // in some ionisation stage. This is possible because the dependence on the + // originating levels population cancels out in the macroatom transition probabilities + // which are based on detailed balance. assert_testmodeonly(ion >= 0); assert_testmodeonly(ion < get_nions(element)); @@ -377,7 +372,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast assert_testmodeonly(globals::cellcache[cellcacheslotid].cellnumber == modelgridindex); - /// If there are no precalculated rates available then calculate them + // If there are no precalculated rates available then calculate them if (chlevel.processrates[MA_ACTION_INTERNALUPHIGHER] < 0) { calculate_macroatom_transitionrates(modelgridindex, element, ion, level, t_mid, chlevel); } @@ -437,7 +432,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast } case MA_ACTION_COLDEEXC: { - /// collisional deexcitation of macro atom => convert the packet into a k-packet + // collisional deexcitation of macro atom => convert the packet into a k-packet // printout("[debug] do_ma: collisional deexcitation\n"); stats::increment(stats::COUNTER_MA_STAT_DEACTIVATION_COLLDEEXC); @@ -463,7 +458,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast } case MA_ACTION_RADRECOMB: { - /// Radiative recombination of MA: emitt a continuum-rpkt + // Radiative recombination of MA: emitt a continuum-rpkt // printout("[debug] do_ma: radiative recombination\n"); // printout("[debug] do_ma: element %d, ion %d, level %d\n", element, ion, level); @@ -479,7 +474,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast } case MA_ACTION_COLRECOMB: { - /// collisional recombination of macro atom => convert the packet into a k-packet + // collisional recombination of macro atom => convert the packet into a k-packet // printout("[debug] do_ma: collisonal recombination\n"); stats::increment(stats::COUNTER_MA_STAT_DEACTIVATION_COLLRECOMB); stats::increment(stats::COUNTER_INTERACTIONS); @@ -503,7 +498,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment(stats::COUNTER_MA_STAT_INTERNALDOWNLOWER); - /// Randomly select the occuring transition + // Randomly select the occuring transition const double targetrate = rng_uniform() * processrates[MA_ACTION_INTERNALDOWNLOWER]; // zrand = 1. - 1e-14; double rate = 0.; @@ -522,7 +517,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast break; } } - /// and set the macroatom's new state + // and set the macroatom's new state if constexpr (TRACK_ION_STATS) { stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); @@ -555,7 +550,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // printout("[debug] do_ma: internal upward jump within current ionstage\n"); stats::increment(stats::COUNTER_INTERACTIONS); - /// randomly select the occuring transition + // randomly select the occuring transition const double *sum_internal_up_same = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_up_same; @@ -641,8 +636,6 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast } } -/// Calculation of radiative rates /////////////////////////////////////////////////////// - void macroatom_open_file(const int my_rank) { if constexpr (!LOG_MACROATOM) { return; @@ -662,12 +655,11 @@ void macroatom_close_file() { } } +// radiative deexcitation rate: paperII 3.5.2 +// multiply by upper level population to get a rate per second auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int upper, const int lower, const double epsilon_trans, const float A_ul, - const double upperstatweight, const double t_current) -> double -/// radiative deexcitation rate: paperII 3.5.2 -// multiply by upper level population to get a rate per second -{ + const double upperstatweight, const double t_current) -> double { assert_always(upper > lower); const double n_u = get_levelpop(modelgridindex, element, ion, upper); @@ -709,12 +701,11 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con return R; } +// radiative excitation rate: paperII 3.5.2 +// multiply by lower level population to get a rate per second auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const int lineindex, - const double t_current) -> double -/// radiative excitation rate: paperII 3.5.2 -// multiply by lower level population to get a rate per second -{ + const double t_current) -> double { const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].targetlevelindex; const double n_u = get_levelpop(modelgridindex, element, ion, upper); @@ -750,11 +741,10 @@ auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const return 0.; } -auto rad_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, - const int upperionlevel, const int lowerionlevel, const int modelgridindex) -> double -/// radiative recombination rate: paperII 3.5.2 +// radiative recombination rate: paperII 3.5.2 // multiply by upper level population to get a rate per second -{ +auto rad_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, + const int upperionlevel, const int lowerionlevel, const int modelgridindex) -> double { // it's probably faster to only check this condition outside this function // in a case where this wasn't checked, the function will return zero anyway // if (upperionlevel > get_maxrecombininglevel(element, upperion)) @@ -800,10 +790,9 @@ auto stim_recombination_ratecoeff(const float nne, const int element, const int return R; } -auto col_recombination_ratecoeff(const int modelgridindex, const int element, const int upperion, const int upper, - const int lower, const double epsilon_trans) -> double // multiply by upper level population to get a rate per second -{ +auto col_recombination_ratecoeff(const int modelgridindex, const int element, const int upperion, const int upper, + const int lower, const double epsilon_trans) -> double { // it's probably faster to only check this condition outside this function // in a case where this wasn't checked, the function will return zero anyway // if (upper > get_maxrecombininglevel(element, upperion)) @@ -817,8 +806,8 @@ auto col_recombination_ratecoeff(const int modelgridindex, const int element, co const double fac1 = epsilon_trans / KB / T_e; const int ionstage = get_ionstage(element, upperion); - /// Seaton approximation: Mihalas (1978), eq.5-79, p.134 - /// select gaunt factor according to ionic charge + // Seaton approximation: Mihalas (1978), eq.5-79, p.134 + // select gaunt factor according to ionic charge double g{NAN}; if (ionstage - 1 == 1) { g = 0.1; @@ -842,16 +831,15 @@ auto col_recombination_ratecoeff(const int modelgridindex, const int element, co return 0.; } -auto col_ionization_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, - const int phixstargetindex, const double epsilon_trans) -> double -/// collisional ionization rate: paperII 3.5.1 +// collisional ionization rate: paperII 3.5.1 // multiply by lower level population to get a rate per second -{ +auto col_ionization_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, + const int phixstargetindex, const double epsilon_trans) -> double { assert_testmodeonly(phixstargetindex >= 0); assert_testmodeonly(phixstargetindex < get_nphixstargets(element, ion, lower)); - /// Seaton approximation: Mihalas (1978), eq.5-79, p.134 - /// select gaunt factor according to ionic charge + // Seaton approximation: Mihalas (1978), eq.5-79, p.134 + // select gaunt factor according to ionic charge double g{NAN}; const int ionstage = get_ionstage(element, ion); if (ionstage == 1) { @@ -866,7 +854,7 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen const double sigma_bf = globals::elements[element].ions[ion].levels[lower].photoion_xs[0] * get_phixsprobability(element, ion, lower, phixstargetindex); - const double C = nne * 1.55e13 * pow(T_e, -0.5) * g * sigma_bf * exp(-fac1) / fac1; /// photoionization at the edge + const double C = nne * 1.55e13 * pow(T_e, -0.5) * g * sigma_bf * exp(-fac1) / fac1; // photoionization at the edge // printout("[debug] col_ion: nne %g, T_e %g, g %g, epsilon_trans %g, sigma_bf %g\n", // nne,T_e,g,epsilon_trans,sigma_bf); @@ -875,10 +863,9 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen return C; } -auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, const int element, - const int ion, const int upper, const LevelTransition &downtransition) -> double // multiply by upper level population to get a rate per second -{ +auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, const int element, + const int ion, const int upper, const LevelTransition &downtransition) -> double { const int lower = downtransition.targetlevelindex; const double upperstatweight = stat_weight(element, ion, upper); const double lowerstatweight = stat_weight(element, ion, lower); @@ -887,20 +874,20 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e const bool forbidden = downtransition.forbidden; if (!forbidden) // alternative: (coll_strength > -1.5) i.e. to catch -1 { - /// permitted E1 electric dipole transitions - /// collisional deexcitation: formula valid only for atoms!!!!!!!!!!! - /// Rutten script eq. 3.33. p.50 + // permitted E1 electric dipole transitions + // collisional deexcitation: formula valid only for atoms!!!!!!!!!!! + // Rutten script eq. 3.33. p.50 // f = osc_strength(element,ion,upper,lower); // C = n_u * 2.16 * pow(fac1,-1.68) * pow(T_e,-1.5) * // stat_weight(element,ion,lower)/stat_weight(element,ion,upper) * nne * f; const double trans_osc_strength = downtransition.osc_strength; const double eoverkt = epsilon_trans / (KB * T_e); - /// Van-Regemorter formula, Mihalas (1978), eq.5-75, p.133 - const double g_bar = 0.2; /// this should be read in from transitions data: it is 0.2 for transitions nl -> n'l' - /// and 0.7 for transitions nl -> nl' + // Van-Regemorter formula, Mihalas (1978), eq.5-75, p.133 + const double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> n'l' + // and 0.7 for transitions nl -> nl' // test = 0.276 * exp(fac1) * gsl_sf_expint_E1(fac1); - /// crude approximation to the already crude Van-Regemorter formula + // crude approximation to the already crude Van-Regemorter formula // double test = 0.276 * exp(fac1) * (-EULERGAMMA - log(fac1)); // double Gamma = (g_bar > test) ? g_bar : test; @@ -926,11 +913,10 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e return nne * 8.629e-6 * coll_str_thisline / upperstatweight / std::sqrt(T_e); } +// multiply by lower level population to get a rate per second auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, - const double lowerstatweight) -> double -// multiply by lower level population to get a rate per second -{ + const double lowerstatweight) -> double { // assert_testmodeonly(i < get_nuptrans(element, ion, lower)); double C = 0.; const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; @@ -942,9 +928,9 @@ auto col_excitation_ratecoeff(const float T_e, const float nne, const int elemen { const double trans_osc_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; - /// permitted E1 electric dipole transitions - /// collisional excitation: formula valid only for atoms!!!!!!!!!!! - /// Rutten script eq. 3.32. p.50 + // permitted E1 electric dipole transitions + // collisional excitation: formula valid only for atoms!!!!!!!!!!! + // Rutten script eq. 3.32. p.50 // C = n_l * 2.16 * pow(eoverkt,-1.68) * pow(T_e,-1.5) * exp(-eoverkt) * nne * // osc_strength(element,ion,upper,lower); @@ -952,7 +938,7 @@ auto col_excitation_ratecoeff(const float T_e, const float nne, const int elemen const double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> n'l' // and 0.7 for transitions nl -> nl' // test = 0.276 * exp(eoverkt) * gsl_sf_expint_E1(eoverkt); - /// crude approximation to the already crude Van-Regemorter formula + // crude approximation to the already crude Van-Regemorter formula const double exp_eoverkt = exp(eoverkt); const double test = 0.276 * exp_eoverkt * (-EULERGAMMA - std::log(eoverkt)); diff --git a/nltepop.cc b/nltepop.cc index 3afc829bc..8e841213e 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -32,10 +32,9 @@ FILE *nlte_file{}; // can save memory by using a combined rate matrix at the cost of diagnostic information constexpr bool individual_process_matricies = true; -auto get_nlte_vector_index(const int element, const int ion, const int level) -> int // this is the index for the NLTE solver that is handling all ions of a single element // This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements -{ +auto get_nlte_vector_index(const int element, const int ion, const int level) -> int { // have to convert from nlte_pops index to nlte_vector index // the difference is that nlte vectors apply to a single element and include ground states // The (+ ion) term accounts for the ground state population indicies that are not counted in the NLTE array @@ -80,12 +79,11 @@ void eliminate_nlte_matrix_rowcol(const int index, const int gs_index, gsl_matri gsl_vector_set(balance_vector, index, 0.0); } -void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector *balance_vector, - const gsl_vector * /*pop_norm_factor_vec*/) // find rows and columns that barely interaction with other levels, and effectively // removing them by zeroing their interactions and setting their departure // coeff to 1.0 -{ +void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector *balance_vector, + const gsl_vector * /*pop_norm_factor_vec*/) { const gsl_matrix rate_matrix_var = *rate_matrix; const int nlte_dimension = rate_matrix_var.size1; for (int index = 0; index < nlte_dimension; index++) { @@ -489,8 +487,7 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, assert_always(std::isfinite(C)); const double NTC = - nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, lineindex) * - s_renorm[level]; + nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, lineindex) * s_renorm[level]; const int lower_index = level_index; const int upper_index = get_nlte_vector_index(element, ion, upper); @@ -666,11 +663,10 @@ auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { return is_singular; } -auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, - gsl_vector *popvec, const gsl_vector *pop_normfactor_vec) -> bool // solve rate_matrix * x = balance_vector, // then popvec[i] = x[i] / pop_norm_factor_vec[i] -{ +auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, + gsl_vector *popvec, const gsl_vector *pop_normfactor_vec) -> bool { bool completed_solution = false; const size_t nlte_dimension = balance_vector->size; assert_always(pop_normfactor_vec->size == nlte_dimension); diff --git a/nonthermal.cc b/nonthermal.cc index 388588832..6bf676262 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -70,14 +70,6 @@ namespace { // return 0.; // } -constexpr bool STORE_NT_SPECTRUM = false; // if this is on, the non-thermal energy spectrum will be kept in memory for - // every grid cell during packet propagation, which - // can take up a lot of memory for large grid sizes - // alternatively, just the non-thermal ionization rates can be stored - // but we might want to re-enable this option to incorporate - // non-thermal excitation rates if there are - // many more transitions to store than there are NT spectrum samples - // minimum number fraction of the total population to include in SF solution constexpr double minionfraction = 1.e-8; @@ -120,56 +112,62 @@ bool nonthermal_initialized = false; gsl_vector *envec; // energy grid on which solution is sampled gsl_vector *logenvec; // log of envec gsl_vector *sourcevec; // samples of the source function (energy distribution of deposited energy) -double E_init_ev = - 0; // the energy injection rate density (and mean energy of injected electrons if source integral is one) in eV + +// Samples of the Spencer-Fano solution function for the current cell being worked on. Multiply by energy to get +// non-thermal electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + dE) y has units +// of particles / cm2 / s / eV +thread_local std::array yfunc{}; + +// the energy injection rate density (and mean energy of injected electrons if source integral is one) in eV/s/cm3 +double E_init_ev = 0; constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); // Monte Carlo result - compare to analytical expectation double nt_energy_deposited; -struct nt_excitation_struct { +struct NonThermalExcitation { double frac_deposition; // the fraction of the non-thermal deposition energy going to the excitation transition double ratecoeffperdeposition; // the excitation rate coefficient divided by the deposition rate density int lineindex; - int loweruptransindex; }; // temporary storage of full excitation list for current cell before possible truncation and copy to node-shared memory -thread_local std::vector tmp_excitation_list; +thread_local std::vector tmp_excitation_list; // pointer to either local or node-shared memory excitation list of all cells -nt_excitation_struct *excitations_list_all_cells{}; +NonThermalExcitation *excitations_list_all_cells{}; // the minimum of MAX_NT_EXCITATIONS_STORED and the number of included excitation transitions in the atomic dataset int nt_excitations_stored = 0; -struct nt_solution_struct { - double *yfunc{}; // Samples of the Spencer-Fano solution function. Multiply by energy to get non-thermal - // electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + - // dE) y has units of particles / cm2 / s / eV +struct NonThermalSolutionIon { + // these points arrays of length includedions. TODO: move to NonThermalSolutionIon + float eff_ionpot{0.}; // these are used to calculate the non-thermal ionization rate + double fracdep_ionization_ion{0.}; // the fraction of the non-thermal deposition energy going to ionizing each ion + + // probability that one ionisation of this ion will produce n Auger electrons. + // items sum to 1.0 for a given ion + std::array prob_num_auger{}; + // like prob_num_auger, but energy weighted. items sum to 1.0 for an ion + std::array ionenfrac_num_auger{}; +}; +struct NonThermalCellSolution { float frac_heating = 1.; // energy fractions should add up to 1.0 if the solution is good float frac_ionization = 0.; // fraction of deposition energy going to ionization float frac_excitation = 0.; // fraction of deposition energy going to excitation - // these points arrays of length includedions - float *eff_ionpot{}; // these are used to calculate the non-thermal ionization rate - double *fracdep_ionization_ion{}; // the fraction of the non-thermal deposition energy going to ionizing each ion - - // these point to arrays of length includedions * (NT_MAX_AUGER_ELECTRONS + 1) - float *prob_num_auger{}; // probability that one ionisation of this ion will produce n Auger electrons. - // elements sum to 1.0 for a given ion - float *ionenfrac_num_auger{}; // like above, but energy weighted. elements sum to 1.0 for an ion + NonThermalSolutionIon *allions{}; int frac_excitations_list_size = 0; - nt_excitation_struct *frac_excitations_list{}; + NonThermalExcitation *frac_excitations_list{}; int timestep_last_solved = -1; // the quantities above were calculated for this timestep float nneperion_when_solved{NAN}; // the nne when the solver was last run }; -nt_solution_struct *nt_solution; +std::vector nt_solution; std::vector deposition_rate_density; std::vector deposition_rate_density_timestep; @@ -230,7 +228,7 @@ void read_binding_energies() { assert_always(get_noncommentline(binding_energies_file, line)); std::istringstream ssline(line); int z_element = elemindex + 1; - /// new file as an atomic number column + // new file as an atomic number column if (binding_en_newformat) { ssline >> z_element; } @@ -247,16 +245,16 @@ void read_binding_energies() { } } -auto get_auger_probability(const int modelgridindex, const int element, const int ion, const int naugerelec) -> double { +auto get_auger_probability(const int modelgridindex, const int element, const int ion, const int naugerelec) { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; + return nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[naugerelec]; } -auto get_ion_auger_enfrac(const int modelgridindex, const int element, const int ion, const int naugerelec) -> double { +auto get_ion_auger_enfrac(const int modelgridindex, const int element, const int ion, const int naugerelec) { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + naugerelec]; + return nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[naugerelec]; } void check_auger_probabilities(int modelgridindex) { @@ -494,18 +492,13 @@ auto get_possible_nt_excitation_count() -> int { } void zero_all_effionpot(const int modelgridindex) { - assert_always(nt_solution[modelgridindex].prob_num_auger); - assert_always(nt_solution[modelgridindex].ionenfrac_num_auger); - for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - nt_solution[modelgridindex].eff_ionpot[uniqueionindex] = 0.; + nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = 0.; - nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)] = 1.; - nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)] = 1.; - for (int a = 1; a <= NT_MAX_AUGER_ELECTRONS; a++) { - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; - } + std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger, 0.); + std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger, 0.); + nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[0] = 1.; + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[0] = 1.; const auto [element, ion] = get_ionfromuniqueionindex(uniqueionindex); assert_always(fabs(get_auger_probability(modelgridindex, element, ion, 0) - 1.0) < 1e-3); @@ -542,20 +535,7 @@ auto get_energyindex_ev_gteq(const double energy_ev) -> int return index; } -auto get_y_sample(const int modelgridindex, const int index) -> double { - if (nt_solution[modelgridindex].yfunc != nullptr) { - if (!std::isfinite(nt_solution[modelgridindex].yfunc[index])) { - printout("get_y_sample index %d %g\n", index, nt_solution[modelgridindex].yfunc[index]); - } - return nt_solution[modelgridindex].yfunc[index]; - } - printout("non-thermal: attempted to get y function sample index %d in cell %d, but the y array pointer is null\n", - index, modelgridindex); - std::abort(); - return -1; -} - -auto get_y(const int modelgridindex, const double energy_ev) -> double { +auto get_y(const double energy_ev) -> double { if (energy_ev <= 0) { return 0.; } @@ -565,21 +545,21 @@ auto get_y(const int modelgridindex, const double energy_ev) -> double { // assert_always(index > 0); if (index < 0) { // return 0.; - assert_always(std::isfinite(get_y_sample(modelgridindex, 0))); - return get_y_sample(modelgridindex, 0); + assert_always(std::isfinite(yfunc[0])); + return yfunc[0]; } - if (index > SFPTS - 1) { + if (index >= SFPTS - 1) { return 0.; } const double enbelow = gsl_vector_get(envec, index); const double enabove = gsl_vector_get(envec, index + 1); - const double ybelow = get_y_sample(modelgridindex, index); - const double yabove = get_y_sample(modelgridindex, index + 1); + const double ybelow = yfunc[index]; + const double yabove = yfunc[index + 1]; const double x = (energy_ev - enbelow) / (enabove - enbelow); return ((1 - x) * ybelow) + (x * yabove); // or return the nearest neighbour - // return get_y_sample(modelgridindex, index); + // return yfunc[index]; } void nt_write_to_file(const int modelgridindex, const int timestep, const int iteration) { @@ -613,7 +593,7 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it for (int s = 0; s < SFPTS; s++) { fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, gsl_vector_get(envec, s), - gsl_vector_get(sourcevec, s), yscalefactor * get_y_sample(modelgridindex, s)); + gsl_vector_get(sourcevec, s), yscalefactor * yfunc[s]); } fflush(nonthermalfile); #ifdef _OPENMP @@ -797,7 +777,7 @@ auto N_e(const int modelgridindex, const double energy) -> double } const double epsilon_trans = epsilon(element, ion, upper) - epsilon_lower; const double epsilon_trans_ev = epsilon_trans / EV; - N_e_ion += (nnlevel / nnion) * get_y(modelgridindex, energy_ev + epsilon_trans_ev) * + N_e_ion += (nnlevel / nnion) * get_y(energy_ev + epsilon_trans_ev) * xs_excitation(element, ion, lower, t, epsilon_trans, statweight_lower, energy + epsilon_trans); } } @@ -817,7 +797,7 @@ auto N_e(const int modelgridindex, const double energy) -> double const double endash = gsl_vector_get(envec, i); const double delta_endash = DELTA_E; - N_e_ion += get_y(modelgridindex, energy_ev + endash) * xs_impactionization(energy_ev + endash, collionrow) * + N_e_ion += get_y(energy_ev + endash) * xs_impactionization(energy_ev + endash, collionrow) * Psecondary(energy_ev + endash, endash, ionpot_ev, J) * delta_endash; } @@ -826,7 +806,7 @@ auto N_e(const int modelgridindex, const double energy) -> double for (int i = integral2startindex; i < SFPTS; i++) { const double endash = gsl_vector_get(envec, i); const double delta_endash = DELTA_E; - N_e_ion += get_y_sample(modelgridindex, i) * xs_impactionization(endash, collionrow) * + N_e_ion += yfunc[i] * xs_impactionization(endash, collionrow) * Psecondary(endash, energy_ev + ionpot_ev, ionpot_ev, J) * delta_endash; } } @@ -856,11 +836,11 @@ auto calculate_frac_heating(const int modelgridindex) -> float const double endash = gsl_vector_get(envec, i); // first term - frac_heating_Einit += get_y_sample(modelgridindex, i) * (electron_loss_rate(endash * EV, nne) / EV) * DELTA_E; + frac_heating_Einit += yfunc[i] * (electron_loss_rate(endash * EV, nne) / EV) * DELTA_E; } // second term - frac_heating_Einit += SF_EMIN * get_y(modelgridindex, SF_EMIN) * (electron_loss_rate(SF_EMIN * EV, nne) / EV); + frac_heating_Einit += SF_EMIN * get_y(SF_EMIN) * (electron_loss_rate(SF_EMIN * EV, nne) / EV); double N_e_contrib = 0.; // third term (integral from zero to SF_EMIN) @@ -1070,7 +1050,7 @@ auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int elem // either multiply by the variable delta_e for LOG_E spacing... - gsl_vector_view const yvecview = gsl_vector_view_array(nt_solution[modelgridindex].yfunc, SFPTS); + gsl_vector_view const yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); double y_dot_crosssection_de = 0.; gsl_blas_ddot(&yvecview.vector, cross_section_vec, &y_dot_crosssection_de); @@ -1130,10 +1110,8 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme gsl_vector_free(cross_section_vec); - assert_always(nt_solution[modelgridindex].yfunc != nullptr); - double y_dot_crosssection_de = 0.; - gsl_vector_view const yvecview_thismgi = gsl_vector_view_array(nt_solution[modelgridindex].yfunc, SFPTS); + gsl_vector_view const yvecview_thismgi = gsl_vector_view_array(yfunc.data(), SFPTS); gsl_blas_ddot(&yvecview_thismgi.vector, cross_section_vec_allshells, &y_dot_crosssection_de); gsl_vector_free(cross_section_vec_allshells); @@ -1166,11 +1144,8 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen std::array eta_nauger_ionize_over_ionpot_sum{}; std::array eta_nauger_ionize_sum{}; - std::fill_n(&nt_solution[modelgridindex].prob_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)], - NT_MAX_AUGER_ELECTRONS + 1, 0.); - - std::fill_n(&nt_solution[modelgridindex].ionenfrac_num_auger[uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)], - NT_MAX_AUGER_ELECTRONS + 1, 0.); + std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger, 0.); + std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger, 0.); double eta_over_ionpot_sum = 0.; double eta_sum = 0.; @@ -1211,30 +1186,29 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen const int upperion = ion + 1 + a; if (upperion <= topion) // not too many Auger electrons to exceed the top ion of this element { - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = + nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = eta_nauger_ionize_sum[a] / eta_sum; } else { // the following ensures that multiple ionisations can't send you to an ion stage that is not in // the model. Send it to the highest ion stage instead const int a_replace = topion - ion - 1; - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a_replace] += + nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger.at(a_replace) += eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex] - .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a_replace] += + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger.at(a_replace) += eta_nauger_ionize_sum[a] / eta_sum; - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0; - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 0.; + nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = 0; + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = 0.; } } } } else { const int a = 0; - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 1.; - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a] = 1.; + nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = 1.; + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = 1.; } if (matching_nlsubshell_count > 0) { @@ -1242,7 +1216,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen if (!std::isfinite(eff_ionpot)) { eff_ionpot = 0.; } - nt_solution[modelgridindex].eff_ionpot[get_uniqueionindex(element, ion)] = eff_ionpot; + nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = eff_ionpot; } else { printout("WARNING! No matching subshells in NT impact ionisation cross section data for Z=%d ionstage %d.\n", get_atomicnumber(element), get_ionstage(element, ion)); @@ -1250,27 +1224,22 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen "-> Defaulting to work function approximation and ionisation energy is not accounted for in Spencer-Fano " "solution.\n"); - nt_solution[modelgridindex].eff_ionpot[get_uniqueionindex(element, ion)] = - 1. / get_oneoverw(element, ion, modelgridindex); + nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = 1. / get_oneoverw(element, ion, modelgridindex); } } -auto get_eff_ionpot(const int modelgridindex, const int element, const int ion) -> float // get the effective ion potential from the stored value // a value of 0. should be treated as invalid -{ - return nt_solution[modelgridindex].eff_ionpot[get_uniqueionindex(element, ion)]; +auto get_eff_ionpot(const int modelgridindex, const int element, const int ion) { + return nt_solution[modelgridindex].allions[get_uniqueionindex(element, ion)].eff_ionpot; // OR // return calculate_eff_ionpot(modelgridindex, element, ion); } -auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, const int ion) -> double // Kozma & Fransson 1992 equation 13 -{ - if (grid::get_numassociatedcells(modelgridindex) <= 0) { - printout("ERROR: nt_ionization_ratecoeff_sf called on empty cell %d\n", modelgridindex); - std::abort(); - } +// returns the rate coefficient in s^-1 +auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, const int ion) -> double { + assert_testmodeonly(grid::get_numassociatedcells(modelgridindex) > 0); const double deposition_rate_density = get_deposition_rate_density(modelgridindex); if (deposition_rate_density > 0.) { @@ -1278,16 +1247,17 @@ auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, con // alternatively, if the y vector is still in memory: // return calculate_nt_ionization_ratecoeff(modelgridindex, element, ion); } + return 0.; } -auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int element, const int ion, const int lower, - const int uptransindex, const double statweight_lower, const double epsilon_trans) -> int // vector of collisional excitation cross sections in cm^2 // epsilon_trans is in erg // returns the index of the first valid cross section point (en >= epsilon_trans) // all elements below this index are invalid and should not be used -{ +auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int element, const int ion, const int lower, + const int uptransindex, const double statweight_lower, + const double epsilon_trans) -> int { const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; if (coll_strength >= 0) { // collision strength is available, so use it @@ -1344,22 +1314,16 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele return -1; } -auto calculate_nt_excitation_ratecoeff_perdeposition(const int modelgridindex, const int element, const int ion, +// Kozma & Fransson equation 9 divided by level population and epsilon_trans +// returns the rate coefficient in s^-1 divided by deposition rate density in erg/cm^3/s +auto calculate_nt_excitation_ratecoeff_perdeposition(const gsl_vector_view yvecview, const int element, const int ion, const int lower, const int uptransindex, const double statweight_lower, - const double epsilon_trans) -> double -// Kozma & Fransson equation 9 divided by level population and epsilon_trans -{ - if (nt_solution[modelgridindex].yfunc == nullptr) { - printout("ERROR: Call to nt_excitation_ratecoeff with no y vector in memory."); - std::abort(); - } - + const double epsilon_trans) -> double { gsl_vector *xs_excitation_vec = gsl_vector_alloc(SFPTS); if (get_xs_excitation_vector(xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, epsilon_trans) >= 0) { double y_dot_crosssection = 0.; - gsl_vector_view const yvecview = gsl_vector_view_array(nt_solution[modelgridindex].yfunc, SFPTS); gsl_blas_ddot(xs_excitation_vec, &yvecview.vector, &y_dot_crosssection); gsl_vector_free(xs_excitation_vec); @@ -1372,8 +1336,8 @@ auto calculate_nt_excitation_ratecoeff_perdeposition(const int modelgridindex, c return 0.; } +// returns the energy rate [erg/cm3/s] going toward non-thermal ionisation of lowerion auto ion_ntion_energyrate(const int modelgridindex, const int element, const int lowerion) -> double { - // returns the energy rate [erg/cm3/s] going toward non-thermal ionisation of lowerion const double nnlowerion = get_nnion(modelgridindex, element, lowerion); double enrate = 0.; const auto maxupperion = nt_ionisation_maxupperion(element, lowerion); @@ -1394,8 +1358,8 @@ auto ion_ntion_energyrate(const int modelgridindex, const int element, const int return gamma_nt * enrate; } +// returns the energy rate [erg/s] going toward non-thermal ionisation in a modelgrid cell auto get_ntion_energyrate(const int modelgridindex) -> double { - // returns the energy rate [erg/s] going toward non-thermal ionisation in a modelgrid cell double ratetotal = 0.; for (int ielement = 0; ielement < get_nelements(); ielement++) { const int nions = get_nions(ielement); @@ -1441,7 +1405,19 @@ auto select_nt_ionization(const int modelgridindex) -> std::tuple { assert_always(false); } +auto get_uptransindex(const int element, const int ion, const int lower, const int upper) { + const int nuptrans = get_nuptrans(element, ion, lower); + for (int t = 0; t < nuptrans; t++) { + if (upper == globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex) { + return t; + } + } + assert_always(false); + return -1; +} + void analyse_sf_solution(const int modelgridindex, const int timestep, const bool enable_sfexcitation) { + const gsl_vector_view yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); const float nne = grid::get_nne(modelgridindex); const double nntot = get_nnion_tot(modelgridindex); const double nnetot = grid::get_nnetot(modelgridindex); @@ -1449,7 +1425,6 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo double frac_excitation_total = 0.; double frac_ionization_total = 0.; - int excitationindex = 0; // unique index for every included excitation transition tmp_excitation_list.resize(0); for (int element = 0; element < get_nelements(); element++) { const int Z = get_atomicnumber(element); @@ -1495,11 +1470,11 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // do not ionize the top ion if (ion < nions - 1) { - nt_solution[modelgridindex].fracdep_ionization_ion[uniqueionindex] = frac_ionization_ion; + nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion = frac_ionization_ion; frac_ionization_total += frac_ionization_ion; } else { - nt_solution[modelgridindex].fracdep_ionization_ion[uniqueionindex] = 0.; + nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion = 0.; } printout(" frac_ionization: %g (%d subshells)\n", frac_ionization_ion, matching_nlsubshell_count); @@ -1527,9 +1502,8 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double epsilon_trans = epsilon(element, ion, upper) - epsilon_lower; const double ratecoeffperdeposition = calculate_nt_excitation_ratecoeff_perdeposition( - modelgridindex, element, ion, lower, t, statweight_lower, epsilon_trans); - const double nt_frac_excitation_perlevelpop = epsilon_trans * ratecoeffperdeposition; - const double frac_excitation_thistrans = nnlevel * nt_frac_excitation_perlevelpop; + yvecview, element, ion, lower, t, statweight_lower, epsilon_trans); + const double frac_excitation_thistrans = nnlevel * epsilon_trans * ratecoeffperdeposition; frac_excitation_ion += frac_excitation_thistrans; if constexpr (NT_EXCITATION_ON) { @@ -1545,9 +1519,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo .frac_deposition = frac_excitation_thistrans, .ratecoeffperdeposition = ratecoeffperdeposition, .lineindex = lineindex, - .loweruptransindex = t, }); - (excitationindex)++; } } // NT_EXCITATION_ON } // for t @@ -1606,7 +1578,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo if (nt_excitations_stored > 0) { // sort by descending frac_deposition - std::ranges::stable_sort(tmp_excitation_list, std::ranges::greater{}, &nt_excitation_struct::frac_deposition); + std::ranges::stable_sort(tmp_excitation_list, std::ranges::greater{}, &NonThermalExcitation::frac_deposition); // the excitation list is now sorted by frac_deposition descending const double deposition_rate_density = get_deposition_rate_density(modelgridindex); @@ -1618,11 +1590,10 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo tmp_excitation_list.resize(nt_excitations_stored); } + nt_solution[modelgridindex].frac_excitations_list_size = tmp_excitation_list.size(); std::copy(tmp_excitation_list.begin(), tmp_excitation_list.end(), nt_solution[modelgridindex].frac_excitations_list); - nt_solution[modelgridindex].frac_excitations_list_size = tmp_excitation_list.size(); - printout("[info] mem_usage: non-thermal excitations for cell %d at this timestep occupy %.3f MB\n", modelgridindex, nt_solution[modelgridindex].frac_excitations_list_size * sizeof(nt_solution[modelgridindex].frac_excitations_list[0]) / 1024. / 1024.); @@ -1632,17 +1603,17 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo nt_solution[modelgridindex].frac_excitations_list_size); const int ntransdisplayed = std::min(50, nt_solution[modelgridindex].frac_excitations_list_size); - for (excitationindex = 0; excitationindex < ntransdisplayed; excitationindex++) { - const auto &ntexc = nt_solution[modelgridindex].frac_excitations_list[excitationindex]; - const double frac_deposition = ntexc.frac_deposition; - if (frac_deposition > 0.) { + for (int excitationindex = 0; excitationindex < ntransdisplayed; excitationindex++) { + const auto &ntexc = tmp_excitation_list[excitationindex]; + if (ntexc.frac_deposition > 0.) { const int lineindex = ntexc.lineindex; - const TransitionLine &line = globals::linelist[lineindex]; + const auto &line = globals::linelist[lineindex]; const int element = line.elementindex; const int ion = line.ionindex; const int lower = line.lowerlevelindex; const int upper = line.upperlevelindex; - const int uptransindex = ntexc.loweruptransindex; + + const auto uptransindex = get_uptransindex(element, ion, lower, upper); const double epsilon_trans = epsilon(element, ion, upper) - epsilon(element, ion, lower); const double ntcollexc_ratecoeff = ntexc.ratecoeffperdeposition * deposition_rate_density; @@ -1660,15 +1631,16 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo printout( " frac_deposition %.3e Z=%2d ionstage %d lower %4d upper %4d rad_exc %.1e coll_exc %.1e nt_exc %.1e " "nt/tot %.1e collstr %.1e lineindex %d\n", - frac_deposition, get_atomicnumber(element), get_ionstage(element, ion), lower, upper, radexc_ratecoeff, - collexc_ratecoeff, ntcollexc_ratecoeff, ntcollexc_ratecoeff / exc_ratecoeff, coll_str, lineindex); + ntexc.frac_deposition, get_atomicnumber(element), get_ionstage(element, ion), lower, upper, + radexc_ratecoeff, collexc_ratecoeff, ntcollexc_ratecoeff, ntcollexc_ratecoeff / exc_ratecoeff, coll_str, + lineindex); } } // sort the excitation list by ascending lineindex for fast lookup with a binary search std::ranges::stable_sort(std::span(nt_solution[modelgridindex].frac_excitations_list, nt_solution[modelgridindex].frac_excitations_list_size), - std::ranges::less{}, &nt_excitation_struct::lineindex); + std::ranges::less{}, &NonThermalExcitation::lineindex); } // NT_EXCITATION_ON @@ -1681,7 +1653,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double endash = gsl_vector_get(envec, i); const double delta_endash = DELTA_E; const double oneovervelocity = sqrt(9.10938e-31 / 2 / endash / 1.60218e-19) / 100; // in sec/cm - nne_nt_max += yscalefactor * get_y_sample(modelgridindex, i) * oneovervelocity * delta_endash; + nne_nt_max += yscalefactor * yfunc[i] * oneovervelocity * delta_endash; } nt_solution[modelgridindex].frac_excitation = frac_excitation_total; @@ -1706,17 +1678,6 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo nt_solution[modelgridindex].frac_heating = 1. - frac_excitation_total - frac_ionization_total; printout(" (replacing calculated frac_heating_tot with %g to make frac_sum = 1.0)\n", nt_solution[modelgridindex].frac_heating); - - // const double nnion = get_nnion(modelgridindex, element, ion); - // double ntexcit_in_a = 0.; - // for (int level = 0; level < get_nlevels(0, 1); level++) - // { - // ntexcit_in_a += nnion * nt_excitation_ratecoeff(modelgridindex, 0, 1, level, 75); - // } - // printout(" total nt excitation rate into level 75: %g\n", ntexcit_in_a); - - // compensate for lost energy by scaling the solution - // E_init_ev *= frac_sum; } void sfmatrix_add_excitation(gsl_matrix *const sfmatrix, const int modelgridindex, const int element, const int ion) { @@ -1809,8 +1770,8 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int // endash ranges from en to SF_EMAX, but skip over the zero-cross section points const int jstart = std::max(i, xsstartindex); for (int j = jstart; j < SFPTS; j++) { - // j is the matrix column index which corresponds to the piece of the integral at y(E') where E' >= E and E' = - // envec(j) + // j is the matrix column index which corresponds to the piece of the integral at y(E') where E' >= E and E' + // = envec(j) const double endash = gsl_vector_get(envec, j); // J * atan[(epsilon - ionpot_ev) / J] is the indefinite integral of 1/[1 + (epsilon - ionpot_ev)^2/ J^2] @@ -1844,7 +1805,8 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int int augerstopindex = 0; if (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { // en_auger_ev is (if LJS understands it correctly) averaged to include some probability of zero Auger - // electrons so we need a boost to get the average energy of Auger electrons given that there are one or more + // electrons so we need a boost to get the average energy of Auger electrons given that there are one or + // more const double en_boost = 1 / (1. - collionrow.prob_num_auger[0]); augerstopindex = get_energyindex_ev_gteq(en_auger_ev * en_boost); @@ -1878,7 +1840,7 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int gsl_vector_free(vec_xs_ionization); } -void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, gsl_vector *yvec) { +void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, std::array &yvec_arr) { // WARNING: this assumes sfmatrix is in upper triangular form already! const gsl_matrix *sfmatrix_LU = sfmatrix; gsl_permutation *p = gsl_permutation_calloc(SFPTS); // identity permutation @@ -1894,6 +1856,9 @@ void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, gsl_ve // printout("Solving SF matrix equation\n"); + gsl_vector_view yvecview = gsl_vector_view_array(yvec_arr.data(), SFPTS); + gsl_vector *yvec = &yvecview.vector; + // solve matrix equation: sf_matrix * y_vec = rhsvec for yvec gsl_linalg_LU_solve(sfmatrix_LU, p, rhsvec, yvec); // printout("Refining solution\n"); @@ -1940,6 +1905,7 @@ void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, gsl_ve printout("solve_sfmatrix: WARNING: y function goes negative!\n"); } } + } // anonymous namespace void init(const int my_rank, const int ndo_nonempty) { @@ -1972,7 +1938,6 @@ void init(const int my_rank, const int ndo_nonempty) { printout(" SFPTS %d\n", SFPTS); printout(" SF_EMIN %g eV\n", SF_EMIN); printout(" SF_EMAX %g eV\n", SF_EMAX); - printout(" STORE_NT_SPECTRUM %s\n", STORE_NT_SPECTRUM ? "on" : "off"); printout(" NT_USE_VALENCE_IONPOTENTIAL %s\n", NT_USE_VALENCE_IONPOTENTIAL ? "on" : "off"); printout(" NT_MAX_AUGER_ELECTRONS %d\n", NT_MAX_AUGER_ELECTRONS); printout(" SF_AUGER_CONTRIBUTION %s\n", SF_AUGER_CONTRIBUTION_ON ? "on" : "off"); @@ -1990,7 +1955,7 @@ void init(const int my_rank, const int ndo_nonempty) { nt_excitations_stored = std::min(MAX_NT_EXCITATIONS_STORED, get_possible_nt_excitation_count()); printout("[info] mem_usage: storing %d non-thermal excitations for non-empty cells occupies %.3f MB\n", nt_excitations_stored, - grid::get_nonempty_npts_model() * sizeof(nt_excitation_struct) * nt_excitations_stored / 1024. / 1024.); + grid::get_nonempty_npts_model() * sizeof(NonThermalExcitation) * nt_excitations_stored / 1024. / 1024.); const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); @@ -2005,30 +1970,26 @@ void init(const int my_rank, const int ndo_nonempty) { my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); } - auto size = static_cast(my_rank_cells * sizeof(nt_excitation_struct) * nt_excitations_stored); + auto size = static_cast(my_rank_cells * sizeof(NonThermalExcitation) * nt_excitations_stored); - int disp_unit = sizeof(nt_excitation_struct); + int disp_unit = sizeof(NonThermalExcitation); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &excitations_list_all_cells, &win_shared_excitations_list); MPI_Win_shared_query(win_shared_excitations_list, 0, &size, &disp_unit, &excitations_list_all_cells); - nt_solution = static_cast(calloc(grid::get_npts_model(), sizeof(nt_solution_struct))); - - printout("Finished setting up shared memory for NT Excitation\n"); MPI_Barrier(MPI_COMM_WORLD); #else - excitations_list_all_cells = static_cast( - malloc(nonempty_npts_model * sizeof(nt_excitation_struct) * nt_excitations_stored)); + excitations_list_all_cells = static_cast( + malloc(nonempty_npts_model * sizeof(NonThermalExcitation) * nt_excitations_stored)); #endif } - nt_solution = static_cast(calloc(grid::get_npts_model(), sizeof(nt_solution_struct))); + nt_solution.resize(grid::get_npts_model()); - size_t mem_usage_yfunc = 0; for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { // should make these negative? nt_solution[modelgridindex].frac_heating = 0.97; @@ -2039,20 +2000,8 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[modelgridindex].timestep_last_solved = -1; if (grid::get_numassociatedcells(modelgridindex) > 0) { - nt_solution[modelgridindex].eff_ionpot = static_cast(calloc(get_includedions(), sizeof(float))); - nt_solution[modelgridindex].fracdep_ionization_ion = - static_cast(calloc(get_includedions(), sizeof(double))); - - nt_solution[modelgridindex].prob_num_auger = - static_cast(calloc(get_includedions() * (NT_MAX_AUGER_ELECTRONS + 1), sizeof(float))); - nt_solution[modelgridindex].ionenfrac_num_auger = - static_cast(calloc(get_includedions() * (NT_MAX_AUGER_ELECTRONS + 1), sizeof(float))); - - if (STORE_NT_SPECTRUM) { - nt_solution[modelgridindex].yfunc = static_cast(calloc(SFPTS, sizeof(double))); - assert_always(nt_solution[modelgridindex].yfunc != nullptr); - mem_usage_yfunc += SFPTS * sizeof(double); - } + nt_solution[modelgridindex].allions = + static_cast(calloc(get_includedions(), sizeof(NonThermalSolutionIon))); const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); @@ -2061,24 +2010,14 @@ void init(const int my_rank, const int ndo_nonempty) { zero_all_effionpot(modelgridindex); } else { - nt_solution[modelgridindex].eff_ionpot = nullptr; - nt_solution[modelgridindex].fracdep_ionization_ion = nullptr; + nt_solution[modelgridindex].allions = nullptr; - nt_solution[modelgridindex].prob_num_auger = nullptr; - nt_solution[modelgridindex].ionenfrac_num_auger = nullptr; - - nt_solution[modelgridindex].yfunc = nullptr; nt_solution[modelgridindex].frac_excitations_list = nullptr; } nt_solution[modelgridindex].frac_excitations_list_size = 0; } - if (STORE_NT_SPECTRUM) { - printout("[info] mem_usage: storing non-thermal spectra for all allocated cells occupies %.3f MB\n", - mem_usage_yfunc / 1024. / 1024.); - }; - envec = gsl_vector_calloc(SFPTS); // energy grid on which solution is sampled logenvec = gsl_vector_calloc(SFPTS); sourcevec = gsl_vector_calloc(SFPTS); // energy grid on which solution is sampled @@ -2192,13 +2131,7 @@ void close_file() { gsl_vector_free(sourcevec); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { - if (STORE_NT_SPECTRUM) { - free(nt_solution[modelgridindex].yfunc); - } - free(nt_solution[modelgridindex].fracdep_ionization_ion); - free(nt_solution[modelgridindex].eff_ionpot); - free(nt_solution[modelgridindex].prob_num_auger); - free(nt_solution[modelgridindex].ionenfrac_num_auger); + free(nt_solution[modelgridindex].allions); } } colliondata.clear(); @@ -2228,36 +2161,30 @@ __host__ __device__ auto nt_ionization_upperion_probability(const int modelgridi if (numaugerelec < NT_MAX_AUGER_ELECTRONS) { if (energyweighted) { - return nt_solution[modelgridindex] - .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]; + return nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[numaugerelec]; } - return nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]; + return nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[numaugerelec]; } if (numaugerelec == NT_MAX_AUGER_ELECTRONS) { double prob_remaining = 1.; for (int a = 0; a < NT_MAX_AUGER_ELECTRONS; a++) { if (energyweighted) { - prob_remaining -= - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]; + prob_remaining -= nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]; } else { - prob_remaining -= - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]; + prob_remaining -= nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a]; } } if (energyweighted) { assert_always(fabs(prob_remaining - - nt_solution[modelgridindex] - .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]) < + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[numaugerelec]) < 0.001); } else { - if (fabs(prob_remaining - - nt_solution[modelgridindex] - .prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + numaugerelec]) >= 0.001) { + if (fabs(prob_remaining - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[numaugerelec]) >= + 0.001) { printout("Auger probabilities issue for cell %d Z=%02d ionstage %d to %d\n", modelgridindex, get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, upperion)); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - printout(" a %d prob %g\n", a, - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]); + printout(" a %d prob %g\n", a, nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a]); } std::abort(); } @@ -2344,7 +2271,7 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lowerlevel, const int uptransindex, - const double epsilon_trans, const int lineindex) -> double { + const int lineindex) -> double { if constexpr (!NT_EXCITATION_ON) { return 0.; } @@ -2356,27 +2283,12 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const return 0.; } - if (grid::get_numassociatedcells(modelgridindex) <= 0) { - printout("ERROR: nt_excitation_ratecoeff called on empty cell %d\n", modelgridindex); - std::abort(); - } - - // if the NT spectrum is stored, we can calculate any non-thermal excitation rate, even if - // it didn't make the cut to be kept in the stored excitation list - if (STORE_NT_SPECTRUM) { - const double deposition_rate_density = get_deposition_rate_density(modelgridindex); - const double statweight_lower = stat_weight(element, ion, lowerlevel); - - const double ratecoeffperdeposition = calculate_nt_excitation_ratecoeff_perdeposition( - modelgridindex, element, ion, lowerlevel, uptransindex, statweight_lower, epsilon_trans); - - return ratecoeffperdeposition * deposition_rate_density; - } + assert_testmodeonly(grid::get_numassociatedcells(modelgridindex) > 0); // binary search, assuming the excitation list is sorted by lineindex ascending const auto ntexclist = std::span(nt_solution[modelgridindex].frac_excitations_list, nt_solution[modelgridindex].frac_excitations_list_size); - auto ntexcitation = std::ranges::lower_bound(ntexclist, lineindex, {}, &nt_excitation_struct::lineindex); + const auto ntexcitation = std::ranges::lower_bound(ntexclist, lineindex, {}, &NonThermalExcitation::lineindex); if (ntexcitation == ntexclist.end() || ntexcitation->lineindex != lineindex) { return 0.; } @@ -2518,7 +2430,6 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i } const float nne = grid::get_nne(modelgridindex); // electrons per cm^3 - // const double nnetot = grid::get_nnetot(modelgridindex); const double nne_per_ion = nne / get_nnion_tot(modelgridindex); const double nne_per_ion_last = nt_solution[modelgridindex].nneperion_when_solved; const double nne_per_ion_fracdiff = fabs((nne_per_ion_last / nne_per_ion) - 1.); @@ -2601,10 +2512,10 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i const int nions = get_nions(element); bool first_included_ion_of_element = true; for (int ion = 0; ion < nions; ion++) { - const double nnion = get_nnion(modelgridindex, element, ion); // hopefully ions per cm^3? + const double nnion = get_nnion(modelgridindex, element, ion); - if (nnion < minionfraction * get_nnion_tot(modelgridindex)) // skip negligible ions - { + // skip negligible ions + if (nnion < minionfraction * get_nnion_tot(modelgridindex)) { continue; } @@ -2649,16 +2560,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // } // printout("\n"); - if (!STORE_NT_SPECTRUM) { - nt_solution[modelgridindex].yfunc = static_cast(calloc(SFPTS, sizeof(double))); - } - - gsl_vector_view yvecview = gsl_vector_view_array(nt_solution[modelgridindex].yfunc, SFPTS); - gsl_vector *yvec = &yvecview.vector; - - sfmatrix_solve(sfmatrix, rhsvec, yvec); - - // gsl_matrix_free(sfmatrix_LU); // if sfmatrix_LU is different to sfmatrix + sfmatrix_solve(sfmatrix, rhsvec, yfunc); gsl_matrix_free(sfmatrix); gsl_vector_free(rhsvec); @@ -2668,10 +2570,6 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i } analyse_sf_solution(modelgridindex, timestep, enable_sfexcitation); - - if (!STORE_NT_SPECTRUM) { - free(nt_solution[modelgridindex].yfunc); - } } void write_restart_data(FILE *gridsave_file) { @@ -2693,13 +2591,12 @@ void write_restart_data(FILE *gridsave_file) { nt_solution[modelgridindex].frac_excitation); for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - fprintf(gridsave_file, "%la ", nt_solution[modelgridindex].fracdep_ionization_ion[uniqueionindex]); - fprintf(gridsave_file, "%a ", nt_solution[modelgridindex].eff_ionpot[uniqueionindex]); + fprintf(gridsave_file, "%la ", nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion); + fprintf(gridsave_file, "%a ", nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - fprintf(gridsave_file, "%a %a ", - nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a], - nt_solution[modelgridindex].ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]); + fprintf(gridsave_file, "%a %a ", nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a], + nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]); } } @@ -2711,13 +2608,6 @@ void write_restart_data(FILE *gridsave_file) { fprintf(gridsave_file, "%la %la %d\n", excitation.frac_deposition, excitation.ratecoeffperdeposition, excitation.lineindex); } - - // write non-thermal spectrum - if (STORE_NT_SPECTRUM) { - for (int s = 0; s < SFPTS; s++) { - fprintf(gridsave_file, "%la\n", nt_solution[modelgridindex].yfunc[s]); - } - } } } } @@ -2762,16 +2652,15 @@ void read_restart_data(FILE *gridsave_file) { } for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - assert_always( - fscanf(gridsave_file, "%la ", &nt_solution[modelgridindex].fracdep_ionization_ion[uniqueionindex]) == 1); - assert_always(fscanf(gridsave_file, "%a ", &nt_solution[modelgridindex].eff_ionpot[uniqueionindex]) == 1); + assert_always(fscanf(gridsave_file, "%la ", + &nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion) == 1); + assert_always(fscanf(gridsave_file, "%a ", &nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot) == + 1); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - assert_always( - fscanf(gridsave_file, "%a %a ", - &nt_solution[modelgridindex].prob_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a], - &nt_solution[modelgridindex] - .ionenfrac_num_auger[(uniqueionindex * (NT_MAX_AUGER_ELECTRONS + 1)) + a]) == 2); + assert_always(fscanf(gridsave_file, "%a %a ", + &nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a], + &nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]) == 2); } } @@ -2791,13 +2680,6 @@ void read_restart_data(FILE *gridsave_file) { &nt_solution[modelgridindex].frac_excitations_list[excitationindex].ratecoeffperdeposition, &nt_solution[modelgridindex].frac_excitations_list[excitationindex].lineindex) == 3); } - - // read non-thermal spectrum - if (STORE_NT_SPECTRUM) { - for (int s = 0; s < SFPTS; s++) { - assert_always(fscanf(gridsave_file, "%la\n", &nt_solution[modelgridindex].yfunc[s]) == 1); - } - } } } } @@ -2824,13 +2706,8 @@ void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ MPI_Bcast(&nt_solution[modelgridindex].frac_ionization, 1, MPI_FLOAT, root, MPI_COMM_WORLD); MPI_Bcast(&nt_solution[modelgridindex].frac_excitation, 1, MPI_FLOAT, root, MPI_COMM_WORLD); - MPI_Bcast(nt_solution[modelgridindex].fracdep_ionization_ion, get_includedions(), MPI_DOUBLE, root, MPI_COMM_WORLD); - MPI_Bcast(nt_solution[modelgridindex].eff_ionpot, get_includedions(), MPI_FLOAT, root, MPI_COMM_WORLD); - - MPI_Bcast(nt_solution[modelgridindex].prob_num_auger, get_includedions() * (NT_MAX_AUGER_ELECTRONS + 1), MPI_FLOAT, - root, MPI_COMM_WORLD); - MPI_Bcast(nt_solution[modelgridindex].ionenfrac_num_auger, get_includedions() * (NT_MAX_AUGER_ELECTRONS + 1), - MPI_FLOAT, root, MPI_COMM_WORLD); + MPI_Bcast(nt_solution[modelgridindex].allions, + static_cast(get_includedions()) * sizeof(NonThermalSolutionIon), MPI_BYTE, root, MPI_COMM_WORLD); // communicate NT excitations MPI_Bcast(&nt_solution[modelgridindex].frac_excitations_list_size, 1, MPI_INT, root, MPI_COMM_WORLD); @@ -2839,19 +2716,12 @@ void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ // communicate NT excitation list via inter-node communication MPI_Bcast( nt_solution[modelgridindex].frac_excitations_list, - static_cast(nt_solution[modelgridindex].frac_excitations_list_size) * sizeof(nt_excitation_struct), + static_cast(nt_solution[modelgridindex].frac_excitations_list_size) * sizeof(NonThermalExcitation), MPI_BYTE, root_node_id, globals::mpi_comm_internode); } MPI_Barrier(MPI_COMM_WORLD); - if (STORE_NT_SPECTRUM) { - assert_always(nt_solution[modelgridindex].yfunc != nullptr); - MPI_Bcast(nt_solution[modelgridindex].yfunc, SFPTS, MPI_DOUBLE, root, MPI_COMM_WORLD); - } - - MPI_Barrier(MPI_COMM_WORLD); - check_auger_probabilities(modelgridindex); } } diff --git a/nonthermal.h b/nonthermal.h index 2b75341b3..a73c0faff 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -20,7 +20,7 @@ void calculate_deposition_rate_density(int modelgridindex, int timestep, Heating [[nodiscard]] auto get_deposition_rate_density(int modelgridindex) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; [[nodiscard]] auto nt_excitation_ratecoeff(int modelgridindex, int element, int ion, int lowerlevel, int uptransindex, - double epsilon_trans, int lineindex) -> double; + int lineindex) -> double; void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); diff --git a/packet.cc b/packet.cc index 15b780fde..6b7234a53 100644 --- a/packet.cc +++ b/packet.cc @@ -27,17 +27,16 @@ namespace { -void place_pellet(const double e0, const int cellindex, const int pktnumber, Packet &pkt) -/// This subroutine places pellet n with energy e0 in cell m -{ - /// First choose a position for the pellet. In the cell. +// Place pellet n with energy e0 in cell m +void place_pellet(const double e0, const int cellindex, const int pktnumber, Packet &pkt) { + // First choose a position for the pellet. In the cell. pkt.where = cellindex; - pkt.number = pktnumber; /// record the packets number for debugging + pkt.number = pktnumber; // record the packets number for debugging pkt.prop_time = globals::tmin; // pkt.last_cross = BOUNDARY_NONE; pkt.originated_from_particlenotgamma = false; - if constexpr (GRID_TYPE == GRID_SPHERICAL1D) { + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { const double zrand = rng_uniform(); const double r_inner = grid::get_cellcoordmin(cellindex, 0); const double r_outer = grid::get_cellcoordmax(cellindex, 0); @@ -48,7 +47,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac pkt.pos = vec_scale(get_rand_isotropic_unitvec(), radius); - } else if constexpr (GRID_TYPE == GRID_CYLINDRICAL2D) { + } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { const double zrand = rng_uniform_pos(); const double rcyl_inner = grid::get_cellcoordmin(cellindex, 0); const double rcyl_outer = grid::get_cellcoordmax(cellindex, 0); @@ -60,7 +59,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac pkt.pos[2] = grid::get_cellcoordmin(cellindex, 1) + (rng_uniform_pos() * grid::wid_init(cellindex, 1)); - } else if constexpr (GRID_TYPE == GRID_CARTESIAN3D) { + } else if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { for (int axis = 0; axis < 3; axis++) { pkt.pos[axis] = grid::get_cellcoordmin(cellindex, axis) + (rng_uniform_pos() * grid::wid_init(cellindex, axis)); } @@ -89,7 +88,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac } // anonymous namespace void packet_init(Packet *pkt) -/// Subroutine that initialises the packets if we start a new simulation. +// Subroutine that initialises the packets if we start a new simulation. { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); @@ -98,8 +97,8 @@ void packet_init(Packet *pkt) printout("INITIAL_PACKETS_ON is %s\n", (INITIAL_PACKETS_ON ? "on" : "off")); - /// The total number of pellets that we want to start with is just - /// npkts. The total energy of the pellets is given by etot. + // The total number of pellets that we want to start with is just + // npkts. The total energy of the pellets is given by etot. const double etot_tinf = decay::get_global_etot_t0_tinf(); printout("etot %g (t_0 to t_inf)\n", etot_tinf); @@ -128,7 +127,7 @@ void packet_init(Packet *pkt) assert_always(norm > 0); const double etot = norm; - /// So energy per pellet is + // So energy per pellet is const double e0 = etot / globals::npkts; printout("packet e0 (in time range) %g erg\n", e0); @@ -170,8 +169,8 @@ void packet_init(Packet *pkt) printout("total energy that will be freed during simulation time: %g erg\n", e_cmf_total); } +// write packets text file void write_packets(const char filename[], const Packet *const pkt) { - // write packets text file FILE *packets_file = fopen_required(filename, "w"); fprintf(packets_file, "#number where type_id posx posy posz dirx diry dirz last_cross tdecay e_cmf e_rf nu_cmf nu_rf " diff --git a/packet.h b/packet.h index 45ad07e14..0685c7dec 100644 --- a/packet.h +++ b/packet.h @@ -23,10 +23,10 @@ constexpr int EMTYPE_NOTSET{-9999000}; constexpr int EMTYPE_FREEFREE{-9999999}; struct MacroAtomState { - int element; /// macro atom of type element (this is an element index) - int ion; /// in ionstage ion (this is an ion index) - int level; /// and level=level (this is a level index) - int activatingline; /// Linelistindex of the activating line for bb activated MAs, -99 else. + int element; // macro atom of type element (this is an element index) + int ion; // in ionstage ion (this is an ion index) + int level; // and level=level (this is a level index) + int activatingline; // Linelistindex of the activating line for bb activated MAs, -99 else. }; enum cell_boundary : int { diff --git a/radfield.cc b/radfield.cc index 3f44e97c5..b185ecd41 100644 --- a/radfield.cc +++ b/radfield.cc @@ -58,8 +58,6 @@ MPI_Win win_radfieldbin_solutions = MPI_WIN_NULL; MPI_Win win_prev_bfrate_normed = MPI_WIN_NULL; #endif -// ** Detailed lines - Jblue_lu estimators for selected lines - struct Jb_lu_estimator { double value = 0.; int contribcount = 0; @@ -75,8 +73,6 @@ int *detailed_lineindicies; Jb_lu_estimator **prev_Jb_lu_normed{}; // value from the previous timestep Jb_lu_estimator **Jb_lu_raw{}; // unnormalised estimator for the current timestep -// ** end detailed lines - float *prev_bfrate_normed{}; // values from the previous timestep std::vector bfrate_raw; // unnormalised estimators for the current timestep @@ -121,9 +117,8 @@ constexpr auto get_bin_nu_lower(const int binindex) -> double { return nu_lower_first_initial; } +// find the left-closed bin [nu_lower, nu_upper) that nu belongs to constexpr auto select_bin(const double nu) -> int { - // find the left-closed bin [nu_lower, nu_upper) that nu belongs to - if (nu < nu_lower_first_initial) { return -2; // out of range, nu lower than lowest bin's lower boundary } @@ -171,10 +166,9 @@ void realloc_detailed_lines(const int new_size) { } } -void add_detailed_line(const int lineindex) // associate a Jb_lu estimator with a particular lineindex to be used // instead of the general radiation field model -{ +void add_detailed_line(const int lineindex) { if (detailed_linecount % BLOCKSIZEJBLUE == 0) { const int new_size = detailed_linecount + BLOCKSIZEJBLUE; realloc_detailed_lines(new_size); @@ -195,9 +189,8 @@ void add_detailed_line(const int lineindex) // printout("Added Jblue estimator for lineindex %d count %d\n", lineindex, detailed_linecount); } -auto get_bin_J(const int modelgridindex, const int binindex) -> double // get the normalised J_nu -{ +auto get_bin_J(const int modelgridindex, const int binindex) -> double { const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); assert_testmodeonly(modelgridindex < grid::get_npts_model()); @@ -215,9 +208,8 @@ auto get_bin_nuJ(const int modelgridindex, const int binindex) -> double { return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].nuJ_raw * J_normfactor[nonemptymgi]; } -auto get_bin_nu_bar(const int modelgridindex, const int binindex) -> double -// importantly, this is average beween the current and previous timestep -{ +// get / for a bin +auto get_bin_nu_bar(const int modelgridindex, const int binindex) -> double { const double nuJ_sum = get_bin_nuJ(modelgridindex, binindex); const double J_sum = get_bin_J(modelgridindex, binindex); return nuJ_sum / J_sum; @@ -355,7 +347,7 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { paras.modelgridindex = modelgridindex; paras.binindex = binindex; - /// Check whether the equation has a root in [T_min,T_max] + // Check whether the equation has a root in [T_min,T_max] double delta_nu_bar_min = delta_nu_bar(T_R_min, ¶s); double delta_nu_bar_max = delta_nu_bar(T_R_max, ¶s); @@ -367,7 +359,7 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { } if (delta_nu_bar_min * delta_nu_bar_max < 0) { - /// If there is a root in the interval, solve for T_R + // If there is a root in the interval, solve for T_R const double epsrel = 1e-4; const double epsabs = 0.; @@ -375,7 +367,7 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { gsl_function find_T_R_f = {.function = &delta_nu_bar, .params = ¶s}; - /// one dimensional gsl root solver, bracketing type + // one dimensional gsl root solver, bracketing type gsl_root_fsolver *T_R_solver = gsl_root_fsolver_alloc(gsl_root_fsolver_brent); gsl_root_fsolver_set(T_R_solver, &find_T_R_f, T_R_min, T_R_max); int status = 0; @@ -401,8 +393,8 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { gsl_root_fsolver_free(T_R_solver); } else if (delta_nu_bar_max < 0) { - /// Thermal balance equation always negative ===> T_R = T_min - /// Calculate the rates again at this T_e to print them to file + // Thermal balance equation always negative ===> T_R = T_min + // Calculate the rates again at this T_e to print them to file T_R = T_R_max; printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_max=%g\n", modelgridindex, binindex, T_R_max); @@ -475,9 +467,9 @@ auto get_bfcontindex(const int element, const int lowerion, const int lower, con } // anonymous namespace -void init(const int my_rank, const int ndo_nonempty) -// this should be called only after the atomic data is in memory -{ +void init(const int my_rank, const int ndo_nonempty) { + // this should be called only after the atomic data is in memory + const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); J_normfactor.resize(nonempty_npts_model + 1); @@ -656,8 +648,8 @@ void init(const int my_rank, const int ndo_nonempty) } } -/// Initialise estimator arrays which hold the last time steps values (used to damp out -/// fluctuations over timestep iterations if DO_TITER is defined) to -1. +// Initialise estimator arrays which hold the last time steps values (used to damp out +// fluctuations over timestep iterations if DO_TITER is defined) to -1. void initialise_prev_titer_photoionestimators() { #ifdef DO_TITER for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { @@ -681,9 +673,8 @@ void initialise_prev_titer_photoionestimators() { #endif } -auto get_Jblueindex(const int lineindex) -> int -// returns -1 if the line does not have a Jblue estimator -{ +auto get_Jblueindex(const int lineindex) -> int { + // returns -1 if the line does not have a Jblue estimator if constexpr (!DETAILED_LINE_ESTIMATORS_ON) { return -1; } @@ -823,10 +814,8 @@ void close_file() { } } -void zero_estimators() -// set up the new bins and clear the estimators in preparation -// for a timestep -{ +// set up the new bins and clear the estimators in preparation for a timestep +void zero_estimators() { std::ranges::fill(J_normfactor, -1.0); std::ranges::fill(J, 0.0); std::ranges::fill(nuJ, 0.0); @@ -899,9 +888,8 @@ __host__ __device__ void update_lineestimator(const int modelgridindex, const in } } -__host__ __device__ auto radfield(const double nu, const int modelgridindex) -> double -// returns mean intensity J_nu [ergs/s/sr/cm2/Hz] -{ +// mean intensity J_nu [ergs/s/sr/cm2/Hz] +__host__ __device__ auto radfield(const double nu, const int modelgridindex) -> double { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { if (globals::timestep >= FIRST_NLTE_RADFIELD_TIMESTEP) { const int binindex = select_bin(nu); @@ -923,10 +911,10 @@ __host__ __device__ auto radfield(const double nu, const int modelgridindex) -> return J_nu_fullspec; } +// return the integral of nu^3 / (exp(h nu / k T) - 1) from nu_lower to nu_upper +// or if times_nu is true, the integral of nu^4 / (exp(h nu / k T) - 1) from nu_lower to nu_upper auto planck_integral_analytic(const double T_R, const double nu_lower, const double nu_upper, const bool times_nu) -> double { - // return the integral of nu^3 / (exp(h nu / k T) - 1) from nu_lower to nu_upper - // or if times_nu is true, the integral of nu^4 / (exp(h nu / k T) - 1) from nu_lower to nu_upper double integral = 0.; if (times_nu) { @@ -961,10 +949,8 @@ auto planck_integral_analytic(const double T_R, const double nu_lower, const dou return integral; } -void fit_parameters(const int modelgridindex, const int timestep) -// finds the best fitting W and temperature parameters in each spectral bin -// using J and nuJ -{ +// finds the best fitting W and temperature parameters in each spectral bin using J and nuJ +void fit_parameters(const int modelgridindex, const int timestep) { set_params_fullspec(modelgridindex, timestep); const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); @@ -1104,12 +1090,12 @@ auto get_T_J_from_J(const int modelgridindex) -> double { const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); const double T_J = pow(J[nonemptymgi] * PI / STEBO, 1. / 4.); if (!std::isfinite(T_J)) { - /// keep old value of T_J + // keep old value of T_J printout("[warning] get_T_J_from_J: T_J estimator infinite in cell %d, use value of last timestep\n", modelgridindex); return grid::get_TR(modelgridindex); } - /// Make sure that T is in the allowed temperature range. + // Make sure that T is in the allowed temperature range. if (T_J > MAXTEMP) { printout("[warning] get_T_J_from_J: T_J would be %.1f > MAXTEMP. Clamping to MAXTEMP = %.0f K\n", T_J, MAXTEMP); return MAXTEMP; @@ -1198,10 +1184,9 @@ void reduce_estimators() MPI_Barrier(MPI_COMM_WORLD); } -void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) // broadcast computed radfield results including parameters // from the cells belonging to root process to all processes -{ +void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) { if (grid::get_numassociatedcells(modelgridindex) == 0) { return; } diff --git a/ratecoeff.cc b/ratecoeff.cc index 71cd356e9..d808ce35b 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -53,11 +53,11 @@ char compositionfile_hash[33]; std::array phixsfile_hash; auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool -/// Try to read in the precalculated rate coefficients from file -/// return true if successful or false otherwise +// Try to read in the precalculated rate coefficients from file +// return true if successful or false otherwise { - /// Check whether current atomic data and temperature range match - /// the precalculated rate coefficients + // Check whether current atomic data and temperature range match + // the precalculated rate coefficients char adatafile_hash_in[33] = "UNKNOWN"; if (fscanf(ratecoeff_file, "%32s\n", adatafile_hash_in) != 1) { @@ -169,14 +169,14 @@ auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool const int nions = get_nions(element) - 1; for (int ion = 0; ion < nions; ion++) { // nlevels = get_nlevels(element,ion); - const int nlevels = get_ionisinglevels(element, ion); /// number of ionising levels associated with current ion - // int nbfcont = get_ionisinglevels(element,ion); /// number of ionising levels of the current ion which + const int nlevels = get_ionisinglevels(element, ion); // number of ionising levels associated with current ion + // int nbfcont = get_ionisinglevels(element,ion); // number of ionising levels of the current ion which // are used in the simulation for (int level = 0; level < nlevels; level++) { - /// Loop over the phixs target states + // Loop over the phixs target states const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - /// Loop over the temperature grid + // Loop over the temperature grid for (int iter = 0; iter < TABLESIZE; iter++) { double in_alpha_sp{NAN}; double in_bfcooling_coeff{NAN}; @@ -244,10 +244,10 @@ void write_ratecoeff_dat() { // nlevels = get_nlevels(element,ion); const int nlevels = get_ionisinglevels(element, ion); for (int level = 0; level < nlevels; level++) { - /// Loop over the phixs targets + // Loop over the phixs targets const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - /// Loop over the temperature grid + // Loop over the temperature grid for (int iter = 0; iter < TABLESIZE; iter++) { const int bflutindex = get_bflutindex(iter, element, ion, level, phixstargetindex); @@ -262,25 +262,21 @@ void write_ratecoeff_dat() { fclose(ratecoeff_file); } -auto alpha_sp_integrand_gsl(const double nu, void *const voidparas) -> double -/// Integrand to calculate the rate coefficient for spontaneous recombination -/// using gsl integrators. -{ +// Integrand to calculate the rate coefficient for spontaneous recombination +auto alpha_sp_integrand_gsl(const double nu, void *const voidparas) -> double { const auto *const params = static_cast(voidparas); const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, params->nu_edge, nu); const double x = TWOOVERCLIGHTSQUARED * sigma_bf * pow(nu, 2) * exp(-HOVERKB * nu / params->T); - /// in formula this looks like - /// x = sigma_bf/H/nu * 2*H*pow(nu,3)/pow(CLIGHT,2) * exp(-H*nu/KB/T); + // in formula this looks like + // x = sigma_bf/H/nu * 2*H*pow(nu,3)/pow(CLIGHT,2) * exp(-H*nu/KB/T); - /// set contributions from Lyman continuum artificially to zero to overcome it's large opacity + // set contributions from Lyman continuum artificially to zero to overcome it's large opacity return x; } -auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> double -/// Integrand to calculate the rate coefficient for spontaneous recombination -/// using gsl integrators. -{ +// Integrand to calculate the rate coefficient for spontaneous recombination +auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> double { const auto *const params = static_cast(voidparas); const float T = params->T; @@ -288,17 +284,15 @@ auto alpha_sp_E_integrand_gsl(const double nu, void *const voidparas) -> double const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, nu_edge, nu); const double x = TWOOVERCLIGHTSQUARED * sigma_bf * pow(nu, 3) / nu_edge * exp(-HOVERKB * nu / T); - /// in formula this looks like - /// x = sigma_bf/H/nu * 2*H*pow(nu,3)/pow(CLIGHT,2) * exp(-H*nu/KB/T); + // in formula this looks like + // x = sigma_bf/H/nu * 2*H*pow(nu,3)/pow(CLIGHT,2) * exp(-H*nu/KB/T); - /// set contributions from Lyman continuum artificially to zero to overcome it's large opacity + // set contributions from Lyman continuum artificially to zero to overcome it's large opacity return x; } -auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> double -/// Integrand to calculate the rate coefficient for photoionization -/// using gsl integrators. Corrected for stimulated recombination. -{ +// Integrand to calculate the rate coefficient for photoionization corrected for stimulated recombination. +auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> double { const auto *const params = static_cast(voidparas); const float T = params->T; @@ -306,18 +300,17 @@ auto gammacorr_integrand_gsl(const double nu, void *const voidparas) -> double const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, nu_edge, nu); - /// Dependence on dilution factor W is linear. This allows to set it here to - /// 1. and scale to its actual value later on. - /// Assumption T_e = T_R makes n_kappa/n_i * (n_i/n_kappa)* = 1 + // Dependence on dilution factor W is linear. This allows to set it here to + // 1. and scale to its actual value later on. + // Assumption T_e = T_R makes n_kappa/n_i * (n_i/n_kappa)* = 1 return sigma_bf * ONEOVERH / nu * radfield::dbb(nu, T, 1) * (1 - exp(-HOVERKB * nu / T)); } -auto approx_bfheating_integrand_gsl(const double nu, void *const voidparas) -> double -/// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way -/// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation -/// formula. The radiation fields dependence on W is taken into account by multiplying -/// the resulting expression with the correct W later on. -{ +// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way +// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation +// formula. The radiation fields dependence on W is taken into account by multiplying +// the resulting expression with the correct W later on. +auto approx_bfheating_integrand_gsl(const double nu, void *const voidparas) -> double { const auto *const params = static_cast(voidparas); const float T = params->T; @@ -325,18 +318,17 @@ auto approx_bfheating_integrand_gsl(const double nu, void *const voidparas) -> d const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, nu_edge, nu); - /// Precalculation for T_e=T_R and W=1 + // Precalculation for T_e=T_R and W=1 const double x = sigma_bf * (1 - nu_edge / nu) * radfield::dbb(nu, T, 1) * (1 - exp(-HOVERKB * nu / T)); return x; } -auto bfcooling_integrand_gsl(const double nu, void *const voidparas) -> double -/// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way -/// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation -/// formula. The radiation fields dependence on W is taken into account by multiplying -/// the resulting expression with the correct W later on. -{ +// Integrand to precalculate the bound-free heating ratecoefficient in an approximative way +// on a temperature grid using the assumption that T_e=T_R and W=1 in the ionisation +// formula. The radiation fields dependence on W is taken into account by multiplying +// the resulting expression with the correct W later on. +auto bfcooling_integrand_gsl(const double nu, void *const voidparas) -> double { const auto *const params = static_cast(voidparas); const float T = params->T; @@ -352,7 +344,7 @@ void precalculate_rate_coefficient_integrals() { // target fractional accuracy of the integrator //=1e-5 took 8 hours with Fe I to V! const double epsrelwarning = 1e-2; // fractional error to emit a warning - /// Calculate the rate coefficients for each level of each ion of each element + // Calculate the rate coefficients for each level of each ion of each element for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element) - 1; #ifdef _OPENMP @@ -402,7 +394,7 @@ void precalculate_rate_coefficient_integrals() { .T = T_e, .photoion_xs = globals::elements[element].ions[ion].levels[level].photoion_xs}; - /// Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field + // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field double alpha_sp = 0.; status = @@ -485,10 +477,9 @@ void precalculate_rate_coefficient_integrals() { } } -void scale_level_phixs(const int element, const int ion, const int level, const double factor) // multiply the cross sections associated with a level by some factor and // also update the quantities integrated from (and proportional to) the cross sections -{ +void scale_level_phixs(const int element, const int ion, const int level, const double factor) { // if we store the data in node shared memory, then only one rank should update it if (globals::rank_in_node == 0) { for (int n = 0; n < globals::NPHIXSPOINTS; n++) { @@ -514,9 +505,8 @@ void scale_level_phixs(const int element, const int ion, const int level, const } } -void read_recombrate_file() // calibrate the recombination rates to tabulated values by scaling the photoionisation cross sections -{ +void read_recombrate_file() { use_cellcache = false; FILE *recombrate_file = fopen("recombrates.txt", "r"); if (recombrate_file == nullptr) { @@ -676,18 +666,16 @@ void precalculate_ion_alpha_sp() { } auto integrand_stimrecombination_custom_radfield(const double nu, void *const voidparas) -> double { - { - const auto *const params = static_cast(voidparas); - const int modelgridindex = params->modelgridindex; - const float T_e = params->T_e; + const auto *const params = static_cast(voidparas); + const int modelgridindex = params->modelgridindex; + const float T_e = params->T_e; - const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, params->nu_edge, nu); + const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, params->nu_edge, nu); - const double Jnu = radfield::radfield(nu, modelgridindex); + const double Jnu = radfield::radfield(nu, modelgridindex); - // TODO: MK thesis page 41, use population ratios and Te? - return ONEOVERH * sigma_bf / nu * Jnu * exp(-HOVERKB * nu / T_e); - } + // TODO: MK thesis page 41, use population ratios and Te? + return ONEOVERH * sigma_bf / nu * Jnu * exp(-HOVERKB * nu / T_e); } auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, const int level, @@ -736,8 +724,8 @@ auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, c } auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *const voidparas) -> double -/// Integrand to calculate the rate coefficient for photoionization -/// using gsl integrators. Corrected for stimulated recombination. +// Integrand to calculate the rate coefficient for photoionization +// using gsl integrators. Corrected for stimulated recombination. { const gsl_integral_paras_gammacorr *const params = static_cast(voidparas); const int modelgridindex = params->modelgridindex; @@ -820,11 +808,10 @@ auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int return gammacorr; } -auto get_nlevels_important(const int modelgridindex, const int element, const int ion, const bool assume_lte, - const float T_e) -> std::tuple // get the number of levels that make up a fraction of the ion population // of at least IONGAMMA_POPFRAC_LEVELS_INCLUDED -{ +auto get_nlevels_important(const int modelgridindex, const int element, const int ion, const bool assume_lte, + const float T_e) -> std::tuple { // get the stored ion population for comparison with the cumulative sum of level pops const double nnion_real = get_nnion(modelgridindex, element, ion); @@ -983,10 +970,9 @@ __host__ __device__ auto select_continuum_nu(int element, const int lowerion, co return nu_lower; } +// Return the rate coefficient for spontaneous recombination. __host__ __device__ auto get_spontrecombcoeff(int element, const int ion, const int level, const int phixstargetindex, - float T_e) -> double -/// Returns the rate coefficient for spontaneous recombination. -{ + float T_e) -> double { double Alpha_sp{NAN}; const int lowerindex = floor(log(T_e / MINTEMP) / T_step_log); assert_always(lowerindex >= 0); @@ -1006,12 +992,11 @@ __host__ __device__ auto get_spontrecombcoeff(int element, const int ion, const return Alpha_sp; } +// multiply by upper ion population (or ground population if per_groundmultipletpop is true) and nne to get a rate auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const int element, const int upperion, const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, const bool lower_superlevel_only, const bool per_groundmultipletpop, - const bool stimonly) -> double -// multiply by upper ion population (or ground population if per_groundmultipletpop is true) and nne to get a rate -{ + const bool stimonly) -> double { const int lowerion = upperion - 1; if (lowerion < 0) { return 0.; @@ -1107,16 +1092,15 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i return alpha; } -void ratecoefficients_init() -/// Precalculates the rate coefficients for stimulated and spontaneous -/// recombination and photoionisation on a given temperature grid using -/// libgsl integrators. -/// NB: with the nebular approximation they only depend on T_e, T_R and W. -/// W is easily factored out. For stimulated recombination we must assume -/// T_e = T_R for this precalculation. -{ +// Precalculates the rate coefficients for stimulated and spontaneous +// recombination and photoionisation on a given temperature grid using +// libgsl integrators. +// NB: with the nebular approximation they only depend on T_e, T_R and W. +// W is easily factored out. For stimulated recombination we must assume +// T_e = T_R for this precalculation. +void ratecoefficients_init() { printout("time before tabulation of rate coefficients %ld\n", std::time(nullptr)); - /// Determine the temperture grids gridsize + // Determine the temperture grids gridsize T_step_log = (log(MAXTEMP) - log(MINTEMP)) / (TABLESIZE - 1.); md5_file("adata.txt", adatafile_hash); @@ -1127,7 +1111,7 @@ void ratecoefficients_init() } } - /// Check if we need to calculate the ratecoefficients or if we were able to read them from file + // Check if we need to calculate the ratecoefficients or if we were able to read them from file bool ratecoeff_match = false; if (globals::rank_in_node == 0) { FILE *ratecoeff_file = fopen("ratecoeff.dat", "r"); @@ -1186,23 +1170,21 @@ auto interpolate_corrphotoioncoeff(const int element, const int ion, const int l auto get_corrphotoioncoeff_ana(int element, const int ion, const int level, const int phixstargetindex, const int modelgridindex) -> double -/// Returns the for stimulated emission corrected photoionisation rate coefficient. +// Returns the for stimulated emission corrected photoionisation rate coefficient. { assert_always(USE_LUT_PHOTOION); - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! + // The correction factor for stimulated emission in gammacorr is set to its + // LTE value. Because the T_e dependence of gammacorr is weak, this correction + // correction may be evaluated at T_R! const double W = grid::get_W(modelgridindex); const double T_R = grid::get_TR(modelgridindex); return W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); } +// Returns the stimulated recombination rate coefficient. multiply by upper level population and nne to get rate auto get_stimrecombcoeff(int element, const int lowerion, const int level, const int phixstargetindex, - const int modelgridindex) -> double -/// Returns the stimulated recombination rate coefficient -// multiple by upper level population and nne to get rate -{ + const int modelgridindex) -> double { double stimrecombcoeff = -1.; #if (SEPARATE_STIMRECOMB) if (use_cellcache) { @@ -1249,13 +1231,12 @@ __host__ __device__ auto get_bfcoolingcoeff(const int element, const int ion, co return bfcooling_coeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; } +// Return the photoionisation rate coefficient (corrected for stimulated emission) __host__ __device__ auto get_corrphotoioncoeff(const int element, const int ion, const int level, - const int phixstargetindex, const int modelgridindex) -> double -/// Returns the photoionisation rate coefficient (corrected for stimulated emission) -{ - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! + const int phixstargetindex, const int modelgridindex) -> double { + // The correction factor for stimulated emission in gammacorr is set to its + // LTE value. Because the T_e dependence of gammacorr is weak, this correction + // correction may be evaluated at T_R! double gammacorr = (use_cellcache) ? globals::cellcache[cellcacheslotid] .chelements[element] .chions[ion] @@ -1338,9 +1319,8 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - return true; } -auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, const int ion) -> double // ionisation rate coefficient. multiply by get_groundlevelpop to get a rate [s^-1] -{ +auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, const int ion) -> double { const int nions = get_nions(element); double Gamma = 0.; if (ion >= nions - 1) { @@ -1374,12 +1354,11 @@ auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, c return Gamma; } +// ionisation rate coefficient. multiply by the lower ion pop to get a rate. +// Currently only used for the estimator output file, not the simulation auto calculate_iongamma_per_ionpop(const int modelgridindex, const float T_e, const int element, const int lowerion, const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, - const bool force_bfest, const bool force_bfintegral) -> double -// ionisation rate coefficient. multiply by the lower ion pop to get a rate -// currently only used for the estimator output file, not the simulation -{ + const bool force_bfest, const bool force_bfintegral) -> double { assert_always(lowerion < get_nions(element) - 1); assert_always(!force_bfest || !force_bfintegral); diff --git a/rpkt.cc b/rpkt.cc index 3943eb5d7..cc1b4d860 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -54,10 +54,10 @@ MPI_Win win_expansionopacities = MPI_WIN_NULL; MPI_Win win_expansionopacity_planck_cumulative = MPI_WIN_NULL; #endif +// get the frequency change per distance travelled assuming linear change to the abort distance +// this is done is two parts to get identical results to do_rpkt_step() auto get_nu_cmf_abort(const std::array pos, const std::array dir, const double prop_time, const double nu_rf, const double abort_dist) -> double { - // get the frequency change per distance travelled assuming linear change to the abort distance - // this is done is two parts to get identical results to do_rpkt_step() const auto half_abort_dist = abort_dist / 2.; const auto abort_time = prop_time + (half_abort_dist / CLIGHT_PROP) + (half_abort_dist / CLIGHT_PROP); @@ -82,16 +82,14 @@ constexpr auto get_expopac_bin_nu_lower(const size_t binindex) -> double { return 1e8 * CLIGHT / lambda_upper; } -auto get_event(const int modelgridindex, - const Packet &pkt, // pointer to packet object - const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, MacroAtomState &mastate, +// return edist, the distance to the next physical event (continuum or bound-bound) and is_boundbound_event, a +// boolean BE AWARE THAT THIS PROCEDURE SHOULD BE ONLY CALLED FOR NON EMPTY CELLS!! +auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, + MacroAtomState &mastate, const double tau_rnd, // random optical depth until which the packet travels const double abort_dist, // maximal travel distance before packet leaves cell or time step ends const double nu_cmf_abort, const double d_nu_on_d_l, - const double doppler) -> std::tuple -// returns edist, the distance to the next physical event (continuum or bound-bound) and is_boundbound_event, a -// boolean BE AWARE THAT THIS PROCEDURE SHOULD BE ONLY CALLED FOR NON EMPTY CELLS!! -{ + const double doppler) -> std::tuple { assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); auto pos = pkt.pos; @@ -106,14 +104,14 @@ auto get_event(const int modelgridindex, double tau = 0.; // optical depth along path double dist = 0.; // position on path while (true) { - /// calculate distance to next line encounter ldist - /// first select the closest transition in frequency - /// we need its frequency nu_trans, the element/ion and the corresponding levels - /// create therefore new variables in packet, which contain next_lowerlevel, ... + // calculate distance to next line encounter ldist + // first select the closest transition in frequency + // we need its frequency nu_trans, the element/ion and the corresponding levels + // create therefore new variables in packet, which contain next_lowerlevel, ... - /// returns negative value if nu_cmf > nu_trans + // returns negative value if nu_cmf > nu_trans if (const int lineindex = closest_transition(nu_cmf, next_trans); lineindex >= 0) [[likely]] { - /// line interaction is possible (nu_cmf > nu_trans) + // line interaction is possible (nu_cmf > nu_trans) const double nu_trans = globals::linelist[lineindex].nu; @@ -177,7 +175,7 @@ auto get_event(const int modelgridindex, radfield::update_lineestimator(modelgridindex, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); } else { - /// bound-bound process occurs + // bound-bound process occurs // printout("[debug] get_event: tau_rnd - tau <= tau_cont + tau_line: bb-process occurs\n"); mastate = {.element = element, .ion = ion, .level = upper, .activatingline = lineindex}; @@ -187,19 +185,19 @@ auto get_event(const int modelgridindex, radfield::update_lineestimator(modelgridindex, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); } - /// the line and its parameters were already selected by closest_transition! + // the line and its parameters were already selected by closest_transition! // printout("[debug] get_event: edist %g, abort_dist %g, edist-abort_dist %g, endloop // %d\n",edist,abort_dist,edist-abort_dist,endloop); return {dist + ldist, next_trans, true}; } } else { - /// continuum process occurs before reaching the line + // continuum process occurs before reaching the line return {dist + ((tau_rnd - tau) / chi_cont), next_trans - 1, false}; } } else [[unlikely]] { - /// no line interaction possible - check whether continuum process occurs in cell + // no line interaction possible - check whether continuum process occurs in cell const double tau_cont = chi_cont * (abort_dist - dist); @@ -207,7 +205,7 @@ auto get_event(const int modelgridindex, // no continuum event before abort_dist return {std::numeric_limits::max(), next_trans, false}; } - /// continuum process occurs at edist + // continuum process occurs at edist return {dist + ((tau_rnd - tau) / chi_cont), globals::nlines + 1, false}; } @@ -311,9 +309,9 @@ auto get_event_expansion_opacity( } void electron_scatter_rpkt(Packet &pkt) { - /// now make the packet a r-pkt and set further flags + // now make the packet a r-pkt and set further flags pkt.type = TYPE_RPKT; - pkt.last_cross = BOUNDARY_NONE; /// allow all further cell crossings + pkt.last_cross = BOUNDARY_NONE; // allow all further cell crossings const auto vel_vec = get_velocity(pkt.pos, pkt.prop_time); @@ -445,8 +443,8 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch const double chi_ff = chi_rpkt_cont.ffheat * dopplerfactor; const double chi_bf = chi_rpkt_cont.bf * dopplerfactor; - /// continuum process happens. select due to its probabilities sigma/chi_cont, chi_ff/chi_cont, - /// chi_bf/chi_cont + // continuum process happens. select due to its probabilities sigma/chi_cont, chi_ff/chi_cont, + // chi_bf/chi_cont // printout("[debug] rpkt_event: r-pkt undergoes a continuum transition\n"); // printout("[debug] rpkt_event: zrand*chi_cont %g, sigma %g, chi_ff %g, chi_bf %g\n", zrand * chi_cont, // sigma, chi_ff, chi_bf); @@ -454,9 +452,9 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch const auto chi_rnd = rng_uniform() * chi_cont; if (chi_rnd < chi_escatter) { - /// electron scattering occurs - /// in this case the packet stays a R_PKT of same nu_cmf as before (coherent scattering) - /// but with different direction + // electron scattering occurs + // in this case the packet stays a R_PKT of same nu_cmf as before (coherent scattering) + // but with different direction // printout("[debug] rpkt_event: electron scattering\n"); stats::increment(stats::COUNTER_INTERACTIONS); pkt.nscatterings += 1; @@ -471,13 +469,13 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch // pkt.nu_cmf = 3.7474058e+14; electron_scatter_rpkt(pkt); - /// Electron scattering does not modify the last emission flag - /// but it updates the last emission position + // Electron scattering does not modify the last emission flag + // but it updates the last emission position pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; } else if (chi_rnd < chi_escatter + chi_ff) { - /// ff: transform to k-pkt + // ff: transform to k-pkt // printout("[debug] rpkt_event: free-free transition\n"); stats::increment(stats::COUNTER_K_STAT_FROM_FF); stats::increment(stats::COUNTER_INTERACTIONS); @@ -485,7 +483,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch pkt.type = TYPE_KPKT; pkt.absorptiontype = -1; } else if (chi_rnd < chi_escatter + chi_ff + chi_bf) { - /// bf: transform to k-pkt or activate macroatom corresponding to probabilities + // bf: transform to k-pkt or activate macroatom corresponding to probabilities // printout("[debug] rpkt_event: bound-free transition\n"); const auto &phixslist = *chi_rpkt_cont.phixslist; @@ -495,7 +493,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch const double chi_bf_inrest = chi_rpkt_cont.bf; assert_always(phixslist.chi_bf_sum[phixslist.allcontend - 1] == chi_bf_inrest); - /// Determine in which continuum the bf-absorption occurs + // Determine in which continuum the bf-absorption occurs const double chi_bf_rand = rng_uniform() * chi_bf_inrest; // first chi_bf_sum[i] such that chi_bf_sum[i] > chi_bf_rand @@ -517,7 +515,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch stats::increment_ion_stats_contabsorption(pkt, modelgridindex, element, ion); } - /// and decide whether we go to ionisation energy + // and decide whether we go to ionisation energy if (rng_uniform() < nu_edge / nu) { stats::increment(stats::COUNTER_MA_STAT_ACTIVATION_BF); stats::increment(stats::COUNTER_INTERACTIONS); @@ -532,9 +530,9 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch do_macroatom(pkt, {.element = element, .ion = ion + 1, .level = upper, .activatingline = -99}); } - /// or to the thermal pool + // or to the thermal pool else { - /// transform to k-pkt + // transform to k-pkt // printout("[debug] rpkt_event: bound-free: transform to k-pkt\n"); stats::increment(stats::COUNTER_K_STAT_FROM_BF); stats::increment(stats::COUNTER_INTERACTIONS); @@ -546,13 +544,8 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch } } +// handle bound-bound transition and activate macro-atom in corresponding upper-level void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const int mgi) { - /// bound-bound transition occured - /// activate macro-atom in corresponding upper-level. Actually all the information - /// about the macro atoms state has already been set by closest_transition, so - /// we need here just the activation! - // printout("[debug] rpkt_event: bound-bound activation of macroatom\n"); - // if (tid == 0) ma_stat_activation_bb++; stats::increment(stats::COUNTER_MA_STAT_ACTIVATION_BB); stats::increment(stats::COUNTER_INTERACTIONS); pkt.last_event = 1; @@ -585,12 +578,9 @@ void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const do_macroatom(pkt, pktmastate); } -void rpkt_event_thickcell(Packet &pkt) -/// Event handling for optically thick cells. Those cells are treated in a grey -/// approximation with electron scattering only. -/// The packet stays an R_PKT of same nu_cmf than before (coherent scattering) -/// but with different direction. -{ +// Handle r-packet interaction in thick cell (grey opacity). +// The packet stays an RPKT of same nu_cmf as before (coherent scattering) but with a different direction. +void rpkt_event_thickcell(Packet &pkt) { // printout("[debug] rpkt_event_thickcell: electron scattering\n"); stats::increment(stats::COUNTER_INTERACTIONS); pkt.nscatterings += 1; @@ -598,20 +588,18 @@ void rpkt_event_thickcell(Packet &pkt) stats::increment(stats::COUNTER_ESCOUNTER); emit_rpkt(pkt); - /// Electron scattering does not modify the last emission flag - /// but it updates the last emission position + // Electron scattering does not modify the last emission flag but it updates the last emission position pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; } +// Update the volume estimators J and nuJ +// This is done in another routine than move, as we sometimes move dummy +// packets which do not contribute to the radiation field. void update_estimators(const double e_cmf, const double nu_cmf, const double distance, const double doppler_nucmf_on_nurf, const int nonemptymgi, - const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const bool thickcell) -/// Update the volume estimators J and nuJ -/// This is done in another routine than move, as we sometimes move dummy -/// packets which do not contribute to the radiation field. -{ - /// Update only non-empty cells + const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const bool thickcell) { + // Update only non-empty cells assert_testmodeonly(nonemptymgi >= 0); const double distance_e_cmf = distance * e_cmf; @@ -623,7 +611,7 @@ void update_estimators(const double e_cmf, const double nu_cmf, const double dis return; } - /// ffheatingestimator does not depend on ion and element, so an array with gridsize is enough. + // ffheatingestimator does not depend on ion and element, so an array with gridsize is enough. atomicadd(globals::ffheatingestimator[nonemptymgi], distance_e_cmf * chi_rpkt_cont.ffheat); if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { @@ -648,10 +636,9 @@ void update_estimators(const double e_cmf, const double nu_cmf, const double dis } } -auto do_rpkt_step(Packet &pkt, const double t2) -> bool // Update an r-packet and return true if no mgi change (or it goes into an empty cell) and no pkttype change and not // reached end of timestep, otherwise false -{ +auto do_rpkt_step(Packet &pkt, const double t2) -> bool { const int cellindex = pkt.where; const int mgi = grid::get_cell_modelgridindex(cellindex); const int nonemptymgi = (mgi != grid::get_npts_model()) ? grid::get_modelcell_nonemptymgi(mgi) : -1; @@ -699,7 +686,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool return (pkt.type == TYPE_RPKT && (newmgi == grid::get_npts_model() || newmgi == mgi)); } - const double maxsdist = (GRID_TYPE == GRID_CARTESIAN3D) + const double maxsdist = (GRID_TYPE == GridType::CARTESIAN3D) ? globals::rmax * pkt.prop_time / globals::tmin : 2 * globals::rmax * (pkt.prop_time + sdist / CLIGHT_PROP) / globals::tmin; if (sdist > maxsdist) { @@ -743,16 +730,16 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool const double abort_dist = std::min(tdist, sdist); - /// Get distance to the next physical event (continuum or bound-bound) + // Get distance to the next physical event (continuum or bound-bound) double edist = -1; bool event_is_boundbound = true; const bool thickcell = grid::modelgrid[mgi].thick == 1; if (nonemptymgi < 0) { - /// for empty cells no physical event occurs. The packets just propagate. + // for empty cells no physical event occurs. The packets just propagate. edist = std::numeric_limits::max(); pkt.next_trans = -1; // skip over lines and search for line list position on the next non-empty cell } else if (thickcell) [[unlikely]] { - /// In the case of optically thick cells, we treat the packets in grey approximation to speed up the calculation + // In the case of optically thick cells, we treat the packets in grey approximation to speed up the calculation const double chi_grey = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -875,10 +862,9 @@ auto get_chi_ff_nnionpart(const int modelgridindex) -> double { return globals::cellcache[cellcacheslotid].chi_ff_nnionpart; } -auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> double // calculate the free-free absorption (to kpkt heating) coefficient [cm^-1] // = kappa(free-free) * nne -{ +auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> double { assert_always(nu > 0.); const auto nne = grid::get_nne(modelgridindex); @@ -890,10 +876,9 @@ auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> doubl return chi_ff; } +// get bound-free opacity template -auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phixslist *phixslist) -> double -// bound-free opacity -{ +auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phixslist *phixslist) -> double { assert_always(!USECELLHISTANDUPDATEPHIXSLIST || phixslist != nullptr); double chi_bf_sum = 0.; @@ -905,9 +890,9 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix const auto nne = grid::get_nne(modelgridindex); const auto nnetot = grid::get_nnetot(modelgridindex); - /// The phixslist is sorted by nu_edge in ascending order (longest to shortest wavelength) - /// If nu < allcont[i].nu_edge no absorption in any of the following continua - /// is possible, so set their kappas to zero + // The phixslist is sorted by nu_edge in ascending order (longest to shortest wavelength) + // If nu < allcont[i].nu_edge no absorption in any of the following continua + // is possible, so set their kappas to zero // break the list into nu >= nu_edge and the remainder (nu < nu_edge) int i = 0; @@ -943,8 +928,8 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix const int ion = globals::allcont[i].ion; const int level = globals::allcont[i].level; const auto bfestimindex = globals::allcont[i].bfestimindex; - /// The bf process happens only if the current cell contains - /// the involved atomic species + // The bf process happens only if the current cell contains + // the involved atomic species if ((DETAILED_BF_ESTIMATORS_ON && grid::get_elem_abundance(modelgridindex, element) > 0) || (!DETAILED_BF_ESTIMATORS_ON && ((get_nnion(modelgridindex, element, ion) / nnetot > 1.e-6) || (level == 0)))) @@ -1061,7 +1046,7 @@ void allocate_expansionopacities() { } __host__ __device__ auto closest_transition(const double nu_cmf, const int next_trans) -> int -/// for the propagation through non empty cells +// for the propagation through non empty cells // find the next transition lineindex redder than nu_cmf // return -1 if no transition can be reached { @@ -1069,25 +1054,25 @@ __host__ __device__ auto closest_transition(const double nu_cmf, const int next_ // packet is tagged as having no more line interactions return -1; } - /// if nu_cmf is smaller than the lowest frequency in the linelist, - /// no line interaction is possible: return negative value as a flag + // if nu_cmf is smaller than the lowest frequency in the linelist, + // no line interaction is possible: return negative value as a flag if (nu_cmf < globals::linelist[globals::nlines - 1].nu) { return -1; } if (next_trans > 0) [[likely]] { - /// if next_trans > 0 we know the next line we should interact with, independent of the packets - /// current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors + // if next_trans > 0 we know the next line we should interact with, independent of the packets + // current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors return next_trans; } if (nu_cmf >= globals::linelist[0].nu) { - /// if nu_cmf is larger than the highest frequency in the the linelist, - /// interaction with the first line occurs - no search + // if nu_cmf is larger than the highest frequency in the the linelist, + // interaction with the first line occurs - no search return 0; } - /// otherwise go through the list until nu_cmf is located between two - /// entries in the line list and get the index of the closest line - /// to lower frequencies + // otherwise go through the list until nu_cmf is located between two + // entries in the line list and get the index of the closest line + // to lower frequencies // will find the highest frequency (lowest index) line with nu_line <= nu_cmf // lower_bound matches the first element where the comparison function is false @@ -1103,9 +1088,8 @@ __host__ __device__ auto closest_transition(const double nu_cmf, const int next_ return matchindex; } -__host__ __device__ auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double -// returns a randomly chosen frequency with a distribution of Planck function times the expansion opacity -{ +// return a randomly chosen frequency with a distribution of Planck function times the expansion opacity +__host__ __device__ auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double { assert_testmodeonly(RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.); const auto *kappa_planck_bins = &expansionopacity_planck_cumulative[nonemptymgi * expopac_nbins]; @@ -1132,26 +1116,26 @@ __host__ __device__ void do_rpkt(Packet &pkt, const double t2) { } } +// make the packet an r-pkt and set further flags __host__ __device__ void emit_rpkt(Packet &pkt) { - /// now make the packet a r-pkt and set further flags pkt.type = TYPE_RPKT; - pkt.last_cross = BOUNDARY_NONE; /// allow all further cell crossings + pkt.last_cross = BOUNDARY_NONE; // allow all further cell crossings - /// Need to assign a new direction. Assume isotropic emission in the cmf + // Need to assign a new direction. Assume isotropic emission in the cmf const auto dir_cmf = get_rand_isotropic_unitvec(); - /// This direction is in the cmf - we want to convert it to the rest - /// frame - use aberation of angles. We want to convert from cmf to - /// rest so need -ve velocity. + // This direction is in the cmf - we want to convert it to the rest + // frame - use aberation of angles. We want to convert from cmf to + // rest so need -ve velocity. const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.prop_time); - /// negative time since we want the backwards transformation here + // negative time since we want the backwards transformation here pkt.dir = angle_ab(dir_cmf, vel_vec); // printout("[debug] pkt.dir in RF: %g %g %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); - /// Finally we want to put in the rest frame energy and frequency. And record - /// that it's now a r-pkt. + // Finally we want to put in the rest frame energy and frequency. And record + // that it's now a r-pkt. const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; @@ -1184,22 +1168,22 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff const auto nne = grid::get_nne(modelgridindex); double chi_escat = 0.; - /// free-free absorption + // free-free absorption const double chi_ff = calculate_chi_ffheating(modelgridindex, nu_cmf); double chi_bf = 0.; if (globals::opacity_case >= 4) { - /// First contribution: Thomson scattering on free electrons + // First contribution: Thomson scattering on free electrons chi_escat = SIGMA_T * nne; - /// Third contribution: bound-free absorption + // Third contribution: bound-free absorption chi_bf = chi_rpkt_cont.phixslist != nullptr ? calculate_chi_bf_gammacontr(modelgridindex, nu_cmf, chi_rpkt_cont.phixslist) : calculate_chi_bf_gammacontr(modelgridindex, nu_cmf, nullptr); } else { - /// in the other cases chi_grey is an mass absorption coefficient - /// therefore use the mass density + // in the other cases chi_grey is an mass absorption coefficient + // therefore use the mass density // sigma = globals::cell[pkt.where].chi_grey * globals::cell[pkt.where].rho; // sigma = SIGMA_T * nne; diff --git a/rpkt.h b/rpkt.h index 7ab646693..723d25911 100644 --- a/rpkt.h +++ b/rpkt.h @@ -45,7 +45,7 @@ void MPI_Bcast_binned_opacities(int modelgridindex, int root_node_id); // distance from packet position to redshifting into line at frequency nu_trans if (nu_cmf <= nu_trans) { - return 0; /// photon was propagated too far, make sure that we don't miss a line + return 0; // photon was propagated too far, make sure that we don't miss a line } if constexpr (USE_RELATIVISTIC_DOPPLER_SHIFT) { diff --git a/sn3d.cc b/sn3d.cc index 837e2fee5..fdb52cbaa 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -1,7 +1,7 @@ /* 2007-10-30 -- MK Non-grey treatment of UVOIR opacity as opacity_case 4 added. Still not fully commented. - Comments are marked by /// Deactivated code by // */ + Comments are marked by // Deactivated code by // */ /* 2007-01-17 -- MK Several minor modifications (some marked in the code with //MK), these include - global printout() routine (located in sn3d.c) @@ -410,7 +410,7 @@ void mpi_reduce_estimators(int nts) { MPI_Barrier(MPI_COMM_WORLD); - /// Communicate gamma and positron deposition and write to file + // Communicate gamma and positron deposition and write to file MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].cmf_lum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); globals::timesteps[nts].cmf_lum /= globals::nprocs; @@ -666,11 +666,11 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns const int nts_prev = (titer != 0 || nts == 0) ? nts : nts - 1; if ((titer > 0) || (globals::simulation_continued_from_saved && (nts == globals::timestep_initial))) { - /// Read the packets file to reset before each additional iteration on the timestep + // Read the packets file to reset before each additional iteration on the timestep read_temp_packetsfile(nts, my_rank, packets); } - /// Some counters on pkt-actions need to be reset to do statistics + // Some counters on pkt-actions need to be reset to do statistics stats::pkt_action_counters_reset(); if (nts == 0) { @@ -691,7 +691,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns const auto sys_time_start_communicate_grid = std::time(nullptr); -/// Each process has now updated its own set of cells. The results now need to be communicated between processes. +// Each process has now updated its own set of cells. The results now need to be communicated between processes. #ifdef MPI_ON mpi_communicate_grid_properties(my_rank, globals::nprocs, nstart, ndo, mpi_grid_buffer, mpi_grid_buffer_size); #endif @@ -699,9 +699,9 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns printout("timestep %d: time after grid properties have been communicated %ld (took %ld seconds)\n", nts, std::time(nullptr), std::time(nullptr) - sys_time_start_communicate_grid); - /// If this is not the 0th time step of the current job step, - /// write out a snapshot of the grid properties for further restarts - /// and update input.txt accordingly + // If this is not the 0th time step of the current job step, + // write out a snapshot of the grid properties for further restarts + // and update input.txt accordingly if (((nts - globals::timestep_initial) != 0)) { save_grid_and_packets(nts, my_rank, packets); do_this_full_loop = walltime_sufficient_to_continue(nts, nts_prev, walltimelimitseconds); @@ -717,7 +717,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns MPI_Barrier(MPI_COMM_WORLD); #endif if ((nts < globals::timestep_finish) && do_this_full_loop) { - /// Now process the packets. + // Now process the packets. update_packets(my_rank, nts, std::span{packets, static_cast(globals::npkts)}); @@ -763,9 +763,9 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns if constexpr (RECORD_LINESTAT) { if (my_rank == 0) { - /// Print net absorption/emission in lines to the linestat_file - /// Currently linestat information is only properly implemented for MPI only runs - /// For hybrid runs only data from thread 0 is recorded + // Print net absorption/emission in lines to the linestat_file + // Currently linestat information is only properly implemented for MPI only runs + // For hybrid runs only data from thread 0 is recorded for (int i = 0; i < globals::nlines; i++) { fprintf(linestat_file, "%d ", globals::ecounter[i]); } @@ -831,7 +831,7 @@ auto main(int argc, char *argv[]) -> int { #pragma omp parallel private(filename) #endif { - /// initialise the thread and rank specific output file + // initialise the thread and rank specific output file snprintf(filename, MAXFILENAMELENGTH, "output_%d-%d.txt", my_rank, get_thread_num()); output_file = std::ofstream(filename); assert_always(output_file.is_open()); @@ -921,10 +921,10 @@ auto main(int argc, char *argv[]) -> int { printout("time after input %ld\n", std::time(nullptr)); printout("timesteps %d\n", globals::ntimesteps); - /// Precalculate the rate coefficients for spontaneous and stimulated recombination - /// and for photoionisation. With the nebular approximation they only depend on T_e - /// T_R and W. W is easily factored out. For stimulated recombination we must assume - /// T_e = T_R for this precalculation. + // Precalculate the rate coefficients for spontaneous and stimulated recombination + // and for photoionisation. With the nebular approximation they only depend on T_e + // T_R and W. W is easily factored out. For stimulated recombination we must assume + // T_e = T_R for this precalculation. ratecoefficients_init(); @@ -936,7 +936,7 @@ auto main(int argc, char *argv[]) -> int { stats::init(); - /// Record the chosen syn_dir + // Record the chosen syn_dir FILE *syn_file = fopen_required("syn_dir.txt", "w"); fprintf(syn_file, "%g %g %g", globals::syn_dir[0], globals::syn_dir[1], globals::syn_dir[2]); fclose(syn_file); @@ -950,7 +950,7 @@ auto main(int argc, char *argv[]) -> int { write_timestep_file(); } - /// Initialise the grid. Set up the initial positions and sizes of the grid cells. + // Initialise the grid. Set up the initial positions and sizes of the grid cells. printout("time grid_init %ld\n", std::time(nullptr)); grid::grid_init(my_rank); @@ -961,17 +961,17 @@ auto main(int argc, char *argv[]) -> int { if (!globals::simulation_continued_from_saved) { std::remove("deposition.out"); - /// Next we want to initialise the packets. - /// Create a bunch of npkts packets - /// and write them to a binary file for later readin. + // Next we want to initialise the packets. + // Create a bunch of npkts packets + // and write them to a binary file for later readin. packet_init(packets); zero_estimators(); } - /// For the parallelisation of update_grid, the process needs to be told which cells belong to it. - /// The next loop is over all grid cells. For parallelisation, we want to split this loop between - /// processes. This is done by assigning each MPI process nblock cells. The residual n_leftover - /// cells are sent to processes 0 ... process n_leftover -1. + // For the parallelisation of update_grid, the process needs to be told which cells belong to it. + // The next loop is over all grid cells. For parallelisation, we want to split this loop between + // processes. This is done by assigning each MPI process nblock cells. The residual n_leftover + // cells are sent to processes 0 ... process n_leftover -1. const int nstart = grid::get_nstart(my_rank); const int ndo = grid::get_ndo(my_rank); const int ndo_nonempty = grid::get_ndo_nonempty(my_rank); @@ -986,9 +986,9 @@ auto main(int argc, char *argv[]) -> int { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); const size_t maxndo = grid::get_maxndo(); - /// Initialise the exchange buffer - /// The factor 4 comes from the fact that our buffer should contain elements of 4 byte - /// instead of 1 byte chars. But the MPI routines don't care about the buffers datatype + // Initialise the exchange buffer + // The factor 4 comes from the fact that our buffer should contain elements of 4 byte + // instead of 1 byte chars. But the MPI routines don't care about the buffers datatype mpi_grid_buffer_size = 4 * ((12 + 4 * get_includedions() + get_nelements()) * (maxndo) + 1); printout("reserve mpi_grid_buffer_size %zu space for MPI communication buffer\n", mpi_grid_buffer_size); mpi_grid_buffer = static_cast(malloc(mpi_grid_buffer_size * sizeof(char))); @@ -1022,7 +1022,7 @@ auto main(int argc, char *argv[]) -> int { // time_after_barrier); #endif - /// titer example: Do 3 iterations on timestep 0-6 + // titer example: Do 3 iterations on timestep 0-6 // globals::n_titer = (nts < 6) ? 3: 1; globals::n_titer = 1; @@ -1032,7 +1032,7 @@ auto main(int argc, char *argv[]) -> int { for (int titer = 0; titer < globals::n_titer; titer++) { terminate_early = do_timestep(nts, titer, my_rank, nstart, ndo, packets, walltimelimitseconds); #ifdef DO_TITER - /// No iterations over the zeroth timestep, set titer > n_titer + // No iterations over the zeroth timestep, set titer > n_titer if (nts == 0) titer = globals::n_titer + 1; #endif } @@ -1040,10 +1040,10 @@ auto main(int argc, char *argv[]) -> int { nts++; } - /// The main calculation is now over. The packets now have all stored the time, place and direction - /// at which they left the grid. Also their rest frame energies and frequencies. - /// Spectra and light curves are now extracted using exspec which is another make target of this - /// code. + // The main calculation is now over. The packets now have all stored the time, place and direction + // at which they left the grid. Also their rest frame energies and frequencies. + // Spectra and light curves are now extracted using exspec which is another make target of this + // code. #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index ee17036be..34deefe25 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -142,13 +142,13 @@ auto get_proccount() -> int auto columnindex_from_emissiontype(const int et) -> int { if (et >= 0) { - /// bb-emission + // bb-emission const int element = globals::linelist[et].elementindex; const int ion = globals::linelist[et].ionindex; return (element * get_max_nions()) + ion; } if (et == EMTYPE_FREEFREE) { - /// ff-emission + // ff-emission const int contindex = -1 - et; assert_always(contindex >= globals::nbfcontinua); // make sure the special value didn't collide with a real process @@ -157,7 +157,7 @@ auto columnindex_from_emissiontype(const int et) -> int { } if (et == EMTYPE_NOTSET) { return -1; - } /// bf-emission + } // bf-emission const int contindex = -1 - et; if (globals::nbfcontinua == 0) { // assert_always(false); // if there are no bf processes, we should not get here @@ -258,7 +258,7 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co PI / PARSEC / PARSEC / globals::nprocs_exspec * anglefactor; const int at = pkt.absorptiontype; if (at >= 0) { - /// bb-emission + // bb-emission const int element = globals::linelist[at].elementindex; const int ion = globals::linelist[at].ionindex; spectra.timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += @@ -668,7 +668,7 @@ void write_light_curve(const std::string &lc_filename, const int current_abin, char linebuffer[1024]; - /// Print out the UVOIR bolometric light curve. + // Print out the UVOIR bolometric light curve. for (int nts = 0; nts < numtimesteps; nts++) { assert_always(snprintf(linebuffer, sizeof(linebuffer), "%g %g %g", globals::timesteps[nts].mid / DAY, (light_curve_lum[nts] / LSUN), @@ -677,7 +677,7 @@ void write_light_curve(const std::string &lc_filename, const int current_abin, } if (current_abin == -1) { - /// Now print out the gamma ray deposition rate in the same file. + // Now print out the gamma ray deposition rate in the same file. for (int m = 0; m < numtimesteps; m++) { assert_always(snprintf(linebuffer, sizeof(linebuffer), "%g %g %g", globals::timesteps[m].mid / DAY, (globals::timesteps[m].gamma_dep / LSUN / globals::timesteps[m].width), @@ -693,7 +693,7 @@ void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector globals::tmin && arrive_time < globals::tmax) { const int nt = get_timestep(arrive_time); @@ -702,7 +702,7 @@ void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector double -/// Integrand to calculate the rate coefficient for bfheating using gsl integrators. +// Integrand to calculate the rate coefficient for bfheating using gsl integrators. { const auto *const params = static_cast(voidparas); @@ -113,8 +113,8 @@ auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, con for (int level = 0; level < nlevels; level++) { const double nnlevel = get_levelpop(modelgridindex, element, ion, level); const double epsilon_level = epsilon(element, ion, level); + // Collisional heating: deexcitation to same ionization stage - // ---------------------------------------------------------- const int ndowntrans = get_ndowntrans(element, ion, level); for (int i = 0; i < ndowntrans; i++) { const auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[i]; @@ -132,11 +132,10 @@ auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, con return C_deexc; } +// Calculate the heating rates for a given cell. Results are returned via the elements of the heatingrates data +// structure. void calculate_heating_rates(const int modelgridindex, const double T_e, const double nne, - HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) -/// Calculate the heating rates for a given cell. Results are returned -/// via the elements of the heatingrates data structure. -{ + HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { double C_deexc = 0.; // double C_recomb = 0.; @@ -151,16 +150,16 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d } } - /// Collisional heating: recombination to lower ionization stage (not included) - /// ------------------------------------------------------------ + // Collisional heating: recombination to lower ionization stage (not included) + // ------------------------------------------------------------ - /// Bound-free heating (renormalised analytical calculation) - /// -------------------------------------------------------- - /// We allow bound free-transitions only if there is a higher ionisation stage - /// left in the model atom to match the bound-free absorption in the rpkt routine. - /// There this condition is needed as we can only ionise to existing ionisation - /// stage even if there would be further ionisation stages in nature which - /// are not included in the model atom. + // Bound-free heating (renormalised analytical calculation) + // -------------------------------------------------------- + // We allow bound free-transitions only if there is a higher ionisation stage + // left in the model atom to match the bound-free absorption in the rpkt routine. + // There this condition is needed as we can only ionise to existing ionisation + // stage even if there would be further ionisation stages in nature which + // are not included in the model atom. for (int ion = 0; ion < nions - 1; ion++) { const int nbflevels = get_ionisinglevels(element, ion); @@ -171,7 +170,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d } } - /// Free-free heating (from estimators) + // Free-free heating (from estimators) const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); ffheating = globals::ffheatingestimator[nonemptymgi]; @@ -179,7 +178,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d if constexpr (DIRECT_COL_HEAT) { heatingcoolingrates->heating_collisional = C_deexc; } else { - /// Collisional heating (from estimators) + // Collisional heating (from estimators) heatingcoolingrates->heating_collisional = globals::colheatingestimator[nonemptymgi]; // C_deexc + C_recomb; } @@ -187,22 +186,21 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d heatingcoolingrates->heating_ff = ffheating; } -auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double -/// Thermal balance equation on which we have to iterate to get T_e -{ +// Thermal balance equation on which we have to iterate to get T_e +auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const Te_solution_paras *const params = static_cast(paras); const int modelgridindex = params->modelgridindex; const double t_current = params->t_current; auto *heatingcoolingrates = params->heatingcoolingrates; - /// Set new T_e guess for the current cell and update populations + // Set new T_e guess for the current cell and update populations // globals::cell[cellnumber].T_e = T_e; grid::set_Te(modelgridindex, T_e); calculate_ion_balance_nne(modelgridindex); const auto nne = grid::get_nne(modelgridindex); - /// Then calculate heating and cooling rates + // Then calculate heating and cooling rates kpkt::calculate_cooling_rates(modelgridindex, heatingcoolingrates); calculate_heating_rates(modelgridindex, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); @@ -210,7 +208,7 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double heatingcoolingrates->heating_dep = nonthermal::get_deposition_rate_density(modelgridindex) * heatingcoolingrates->nt_frac_heating; - /// Adiabatic cooling term + // Adiabatic cooling term const double nntot = get_nnion_tot(modelgridindex) + nne; const double p = nntot * KB * T_e; // pressure in [erg/cm^3] const double volumetmin = grid::get_modelcell_assocvolume_tmin(modelgridindex); @@ -231,9 +229,9 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, const int phixstargetindex, const double T_R, const double W) -> double { - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! + // The correction factor for stimulated emission in gammacorr is set to its + // LTE value. Because the T_e dependence of gammacorr is weak, this correction + // correction may be evaluated at T_R! assert_always(USE_LUT_BFHEATING); double bfheatingcoeff = 0.; @@ -254,10 +252,8 @@ auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, c return W * bfheatingcoeff; } +// depends only the radiation field - no dependence on T_e or populations void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs) { - // depends only the radiation field - // no dependence on T_e or populations - bfheatingcoeffs.resize(get_includedlevels()); const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); const double minelfrac = 0.01; @@ -277,9 +273,9 @@ void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatin if constexpr (!USE_LUT_BFHEATING) { bfheatingcoeff += calculate_bfheatingcoeff(element, ion, level, phixstargetindex, modelgridindex); } else { - /// The correction factor for stimulated emission in gammacorr is set to its - /// LTE value. Because the T_e dependence of gammacorr is weak, this correction - /// correction may be evaluated at T_R! + // The correction factor for stimulated emission in gammacorr is set to its + // LTE value. Because the T_e dependence of gammacorr is weak, this correction + // correction may be evaluated at T_R! const double T_R = grid::get_TR(modelgridindex); const double W = grid::get_W(modelgridindex); bfheatingcoeff += get_bfheatingcoeff_ana(element, ion, level, phixstargetindex, T_R, W); @@ -327,9 +323,9 @@ void call_T_e_finder(const int modelgridindex, const int timestep, const double } double T_e{NAN}; - /// Check whether the thermal balance equation has a root in [T_min,T_max] + // Check whether the thermal balance equation has a root in [T_min,T_max] if (thermalmin * thermalmax < 0) { - /// If it has, then solve for the root T_e + // If it has, then solve for the root T_e // one-dimensional gsl root solver, bracketing type gsl_root_fsolver *T_e_solver = gsl_root_fsolver_alloc(gsl_root_fsolver_brent); @@ -356,17 +352,17 @@ void call_T_e_finder(const int modelgridindex, const int timestep, const double gsl_root_fsolver_free(T_e_solver); } - /// Quick solver style: works if we can assume that there is either one or no - /// solution on [MINTEMP.MAXTEMP] (check that by doing a plot of heating-cooling vs. T_e) + // Quick solver style: works if we can assume that there is either one or no + // solution on [MINTEMP.MAXTEMP] (check that by doing a plot of heating-cooling vs. T_e) else if (thermalmax < 0) { - /// Thermal balance equation always negative ===> T_e = T_min + // Thermal balance equation always negative ===> T_e = T_min T_e = MINTEMP; printout( "[warning] call_T_e_finder: cooling bigger than heating at lower T_e boundary %g in modelcell %d " "(T_R=%g,W=%g). T_e forced to be MINTEMP\n", MINTEMP, modelgridindex, grid::get_TR(modelgridindex), grid::get_W(modelgridindex)); } else { - /// Thermal balance equation always negative ===> T_e = T_max + // Thermal balance equation always negative ===> T_e = T_max T_e = MAXTEMP; printout( "[warning] call_T_e_finder: heating bigger than cooling over the whole T_e range [%g,%g] in modelcell %d " diff --git a/update_grid.cc b/update_grid.cc index 4c9f6b977..b603685ca 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -716,7 +716,7 @@ void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, cons const auto sys_time_start_Te = std::time(nullptr); const int nts_for_te = (titer == 0) ? nts - 1 : nts; - /// Find T_e as solution for thermal balance + // Find T_e as solution for thermal balance call_T_e_finder(mgi, nts, globals::timesteps[nts_for_te].mid, MINTEMP, MAXTEMP, heatingcoolingrates, bfheatingcoeffs); @@ -811,20 +811,20 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d } } - /// 2012-01-11. These loops should terminate here to precalculate *ALL* corrphotoionrenorm - /// values so that the values are known when required by the call to get_corrphotoioncoeff in - /// the following loops. Otherwise get_corrphotoioncoeff tries to renormalize by the closest - /// corrphotoionrenorm in frequency space which can lead to zero contributions to the total - /// photoionsation rate! + // 2012-01-11. These loops should terminate here to precalculate *ALL* corrphotoionrenorm + // values so that the values are known when required by the call to get_corrphotoioncoeff in + // the following loops. Otherwise get_corrphotoioncoeff tries to renormalize by the closest + // corrphotoionrenorm in frequency space which can lead to zero contributions to the total + // photoionsation rate! } } if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions - 1; ion++) { - /// Reuse the gammaestimator array as temporary storage of the Gamma values during - /// the remaining part of the update_grid phase. Afterwards it is reset to record - /// the next timesteps gamma estimators. + // Reuse the gammaestimator array as temporary storage of the Gamma values during + // the remaining part of the update_grid phase. Afterwards it is reset to record + // the next timesteps gamma estimators. const int groundcontindex = globals::elements[element].ions[ion].groundcontindex; if (groundcontindex < 0) { continue; @@ -844,9 +844,9 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d } bfheatingestimator_save[ionestimindex] = globals::bfheatingestimator[ionestimindex]; #endif - /// Now convert bfheatingestimator into the bfheating renormalisation coefficient used in - /// get_bfheating in the remaining part of update_grid. Later on it's reset and new - /// contributions are added up. + // Now convert bfheatingestimator into the bfheating renormalisation coefficient used in + // get_bfheating in the remaining part of update_grid. Later on it's reset and new + // contributions are added up. const double bfheatingcoeff_ana = get_bfheatingcoeff_ana(element, ion, 0, 0, grid::get_TR(mgi), grid::get_W(mgi)); @@ -884,8 +884,8 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in const double deltat, HeatingCoolingRates *heatingcoolingrates) { const int assoc_cells = grid::get_numassociatedcells(mgi); if (assoc_cells < 1) { - /// For modelgrid cells that are not represented in the simulation grid, - /// Set grid properties to zero + // For modelgrid cells that are not represented in the simulation grid, + // Set grid properties to zero grid::set_TR(mgi, 0.); grid::set_TJ(mgi, 0.); grid::set_Te(mgi, 0.); @@ -901,10 +901,10 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in printout("update_grid_cell: working on cell %d before timestep %d titeration %d...\n", mgi, nts, titer); - /// Update current mass density of cell + // Update current mass density of cell grid::set_rho(mgi, grid::get_rho_tmin(mgi) / pow(tratmid, 3)); - /// Update elemental abundances with radioactive decays + // Update elemental abundances with radioactive decays decay::update_abundances(mgi, nts, globals::timesteps[nts].mid); nonthermal::calculate_deposition_rate_density(mgi, nts, heatingcoolingrates); @@ -935,14 +935,14 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // either by trapped energy release calculation, or reading from gridsave file if (USE_LUT_PHOTOION && !globals::simulation_continued_from_saved) { - /// Determine renormalisation factor for corrected photoionization cross-sections + // Determine renormalisation factor for corrected photoionization cross-sections std::fill_n(globals::corrphotoionrenorm + (nonemptymgi * globals::nbfcontinua_ground), globals::nbfcontinua_ground, 1.); } - /// W == 1 indicates that this modelgrid cell was treated grey in the - /// last timestep. Therefore it has no valid Gamma estimators and must - /// be treated in LTE at restart. + // W == 1 indicates that this modelgrid cell was treated grey in the + // last timestep. Therefore it has no valid Gamma estimators and must + // be treated in LTE at restart. if (grid::modelgrid[mgi].thick != 1 && grid::get_W(mgi) == 1) { printout( "force modelgrid cell %d to grey/LTE thick = 1 for update grid since existing W == 1. (will not have " @@ -963,11 +963,11 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } else { // For all other timesteps temperature corrections have to be applied - /// we have to calculate the electron density - /// and all the level populations - /// Normalise estimators and make sure that they are finite. - /// Then update T_R and W using the estimators. - /// (This could in principle also be done for empty cells) + // we have to calculate the electron density + // and all the level populations + // Normalise estimators and make sure that they are finite. + // Then update T_R and W using the estimators. + // (This could in principle also be done for empty cells) const auto sys_time_start_temperature_corrections = std::time(nullptr); @@ -1070,8 +1070,8 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in assert_always(grid::modelgrid[mgi].totalcooling >= 0.); assert_always(grid::modelgrid[mgi].ion_cooling_contribs[0] >= 0.); } else { - /// Cooling rates depend only on cell properties, precalculate total cooling - /// and ion contributions inside update grid and communicate between MPI tasks + // Cooling rates depend only on cell properties, precalculate total cooling + // and ion contributions inside update grid and communicate between MPI tasks const auto sys_time_start_calc_kpkt_rates = std::time(nullptr); printout("calculating cooling_rates for timestep %d cell %d...", nts, mgi); @@ -1101,7 +1101,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const const int ndo, const int titer, const std::time_t real_time_start) // Subroutine to update the matter quantities in the grid cells at the start // of the new timestep. -/// nts timestep +// nts timestep { const auto sys_time_start_update_grid = std::time(nullptr); printout("\n"); @@ -1111,11 +1111,11 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const // printout("[debug] update_grid: starting update for timestep %d...\n",m); const double tratmid = globals::timesteps[nts].mid / globals::tmin; - /// Calculate the critical opacity at which opacity_case 3 switches from a - /// regime proportional to the density to a regime independent of the density - /// This is done by solving for tau_sobolev == 1 - /// tau_sobolev = PI*QE*QE/(ME*C) * rho_crit_para * rho/nucmass(28, 56) * 3000e-8 * - /// globals::timesteps[m].mid; + // Calculate the critical opacity at which opacity_case 3 switches from a + // regime proportional to the density to a regime independent of the density + // This is done by solving for tau_sobolev == 1 + // tau_sobolev = PI*QE*QE/(ME*C) * rho_crit_para * rho/nucmass(28, 56) * 3000e-8 * + // globals::timesteps[m].mid; globals::rho_crit = ME * CLIGHT * decay::nucmass(28, 56) / (PI * QE * QE * globals::rho_crit_para * 3000e-8 * globals::timesteps[nts].mid); printout("update_grid: rho_crit = %g\n", globals::rho_crit); @@ -1129,7 +1129,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const cellcache_change_cell(-99); - /// Do not use values which are saved in the cellcache within update_grid + // Do not use values which are saved in the cellcache within update_grid use_cellcache = false; if constexpr (DETAILED_BF_ESTIMATORS_ON) { @@ -1140,14 +1140,14 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #pragma omp parallel #endif { -/// Updating cell information +// Updating cell information #ifdef _OPENMP #pragma omp for schedule(dynamic) #endif for (int mgi = nstart; mgi < nstart + ndo; mgi++) { - /// Check if this task should work on the current model grid cell. - /// If yes, update the cell and write out the estimators + // Check if this task should work on the current model grid cell. + // If yes, update the cell and write out the estimators HeatingCoolingRates heatingcoolingrates{}; update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, &heatingcoolingrates); @@ -1156,12 +1156,12 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #pragma omp critical(estimators_file) #endif { write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates); } - } /// end parallel for loop over all modelgrid cells + } // end parallel for loop over all modelgrid cells - } /// end OpenMP parallel section + } // end OpenMP parallel section - /// Now after all the relevant taks of update_grid have been finished activate - /// the use of the cellcache for all OpenMP tasks, in what follows (update_packets) + // Now after all the relevant taks of update_grid have been finished activate + // the use of the cellcache for all OpenMP tasks, in what follows (update_packets) use_cellcache = true; // alterative way to write out estimators. this keeps the modelgrid cells in order but @@ -1188,10 +1188,10 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const } void cellcache_change_cell(const int modelgridindex) { - /// All entries of the cellcache stack must be flagged as empty at the - /// onset of the new timestep. Also, boundary crossing? - /// Calculate the level populations for this cell, and flag the other entries - /// as empty. + // All entries of the cellcache stack must be flagged as empty at the + // onset of the new timestep. Also, boundary crossing? + // Calculate the level populations for this cell, and flag the other entries + // as empty. if (modelgridindex == globals::cellcache[cellcacheslotid].cellnumber) { return; } diff --git a/update_packets.cc b/update_packets.cc index 7cfc9d3d1..38bd6df73 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -133,11 +133,11 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { } } +// Handle inactive pellets. Need to do two things (a) check if it +// decays in this time step and if it does handle that. (b) if it doesn't decay in +// this time step then just move the packet along with the matter for the +// start of the next time step. void update_pellet(Packet &pkt, const int nts, const double t2) { - // Handle inactive pellets. Need to do two things (a) check if it - // decays in this time step and if it does handle that. (b) if it doesn't decay in - // this time step then just move the packet along with the matter for the - // start of the next time step. assert_always(pkt.prop_time < t2); const double ts = pkt.prop_time; @@ -342,9 +342,8 @@ void do_cell_packet_updates(std::span packets, const int nts, const doub } // anonymous namespace -void update_packets(const int my_rank, const int nts, std::span packets) -// Subroutine to move and update packets during the current timestep (nts) -{ +// Move and update packets during the current timestep (nts) +void update_packets(const int my_rank, const int nts, std::span packets) { // At the start, the packets have all either just been initialised or have already been // processed for one or more timesteps. Those that are pellets will just be sitting in the // matter. Those that are photons (or one sort or another) will already have a position and diff --git a/vectors.h b/vectors.h index df854cd74..7a80a776d 100644 --- a/vectors.h +++ b/vectors.h @@ -14,18 +14,16 @@ #include "packet.h" #include "sn3d.h" -template -[[nodiscard]] [[gnu::const]] constexpr auto vec_len(const std::array vec) -> double // return the the magnitude of a vector -{ +template +[[nodiscard]] [[gnu::const]] constexpr auto vec_len(const std::array vec) -> double { const double squaredlen = std::accumulate(vec.begin(), vec.end(), 0., [](auto a, auto b) { return a + b * b; }); return std::sqrt(squaredlen); } -[[nodiscard]] [[gnu::const]] constexpr auto vec_norm(const std::array vec_in) // get a normalized copy of vec_in -{ +[[nodiscard]] [[gnu::const]] constexpr auto vec_norm(const std::array vec_in) { const double magnitude = vec_len(vec_in); const auto vec_out = std::array{vec_in[0] / magnitude, vec_in[1] / magnitude, vec_in[2] / magnitude}; @@ -33,18 +31,16 @@ template return vec_out; } +// vector dot product template [[nodiscard]] [[gnu::const]] constexpr auto dot(const std::array x, - const std::array y) -> double -// vector dot product -{ + const std::array y) -> double { return std::inner_product(x.begin(), x.end(), y.begin(), 0.); } +// Get velocity vector of the flow at a position with homologous expansion. [[nodiscard]] [[gnu::pure]] constexpr auto get_velocity(std::span x, - const double t) -> std::array -// Routine for getting velocity vector of the flow at a position with homologous expansion. -{ + const double t) -> std::array { return std::array{x[0] / t, x[1] / t, x[2] / t}; } @@ -59,13 +55,12 @@ template return std::array{vec[0] * scalefactor, vec[1] * scalefactor, vec[2] * scalefactor}; } -[[nodiscard]] [[gnu::const]] constexpr auto angle_ab(const std::array dir1, - const std::array vel) -> std::array // aberation of angles in special relativity // dir1: direction unit vector in frame1 // vel: velocity of frame2 relative to frame1 // dir2: direction vector in frame2 -{ +[[nodiscard]] [[gnu::const]] constexpr auto angle_ab(const std::array dir1, + const std::array vel) -> std::array { const double vsqr = dot(vel, vel) / CLIGHTSQUARED; const double gamma_rel = 1. / std::sqrt(1 - vsqr); @@ -79,14 +74,13 @@ template return vec_norm(dir2); } -[[gnu::const]] [[nodiscard]] constexpr auto doppler_nucmf_on_nurf(const std::array dir_rf, - const std::array vel_rf) -> double // Doppler factor // arguments: // dir_rf: the rest frame direction (unit vector) of light propagation // vel_rf: velocity of the comoving frame relative to the rest frame // returns: the ratio f = nu_cmf / nu_rf -{ +[[gnu::const]] [[nodiscard]] constexpr auto doppler_nucmf_on_nurf(const std::array dir_rf, + const std::array vel_rf) -> double { assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED >= 0.); assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED < 1.); @@ -141,12 +135,10 @@ template return doppler_nucmf_on_nurf(dir_rf, get_velocity(pos_rf, prop_time)); } +// Move a packet along a straight line (specified by current dir vector). The distance moved is in the rest frame. constexpr auto move_pkt_withtime(std::span pos_rf, const std::array dir_rf, double &prop_time, const double nu_rf, double &nu_cmf, const double e_rf, double &e_cmf, - const double distance) -> double -/// Subroutine to move a packet along a straight line (specified by current -/// dir vector). The distance moved is in the rest frame. -{ + const double distance) -> double { assert_always(distance >= 0); const double nu_cmf_old = nu_cmf; @@ -156,8 +148,8 @@ constexpr auto move_pkt_withtime(std::span pos_rf, const std::array double { } [[nodiscard]] [[gnu::const]] constexpr auto get_arrive_time(const Packet &pkt) -> double -/// We know that a packet escaped at "escape_time". However, we have -/// to allow for travel time. Use the formula in Leon's paper. The extra -/// distance to be travelled beyond the reference surface is ds = r_ref (1 - mu). +// We know that a packet escaped at "escape_time". However, we have +// to allow for travel time. Use the formula in Leon's paper. The extra +// distance to be travelled beyond the reference surface is ds = r_ref (1 - mu). { return pkt.escape_time - (dot(pkt.pos, pkt.dir) / CLIGHT_PROP); } @@ -190,7 +182,7 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { const double dirmag = vec_len(dir_in); const auto dir = std::array{dir_in[0] / dirmag, dir_in[1] / dirmag, dir_in[2] / dirmag}; - /// Angle resolved case: need to work out the correct angle bin + // Angle resolved case: need to work out the correct angle bin const double costheta = dot(dir, syn_dir); const int costhetabin = static_cast((costheta + 1.0) * NPHIBINS / 2.0); assert_testmodeonly(costhetabin < NCOSTHETABINS); @@ -215,9 +207,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return na; } -[[nodiscard]] inline auto get_rand_isotropic_unitvec() -> std::array // Assuming isotropic distribution, get a random direction vector -{ +[[nodiscard]] inline auto get_rand_isotropic_unitvec() -> std::array { const double costheta = -1 + (2. * rng_uniform()); const double phi = rng_uniform() * 2 * PI; @@ -227,10 +218,10 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return std::array{sintheta * std::cos(phi), sintheta * std::sin(phi), costheta}; } +// Rotation angle from the scattering plane [[nodiscard]] [[gnu::const]] constexpr auto rot_angle(const std::array n1, const std::array n2, const std::array ref1, const std::array ref2) -> double { - // Rotation angle from the scattering plane // We need to rotate Stokes Parameters to (or from) the scattering plane from (or to) // the meridian frame such that Q=1 is in the scattering plane and along ref1 From d7a2e47b0081b7137d49968477cea83a70acb113 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 20 Aug 2024 08:58:55 +0100 Subject: [PATCH 023/117] Update nonthermal.cc --- nonthermal.cc | 91 +++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 6bf676262..c58103e23 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -114,17 +114,18 @@ gsl_vector *logenvec; // log of envec gsl_vector *sourcevec; // samples of the source function (energy distribution of deposited energy) // Samples of the Spencer-Fano solution function for the current cell being worked on. Multiply by energy to get -// non-thermal electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + dE) y has units -// of particles / cm2 / s / eV +// non-thermal electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + dE) in units of +// particles/cm2/s. y has units of particles/cm2/s/eV thread_local std::array yfunc{}; -// the energy injection rate density (and mean energy of injected electrons if source integral is one) in eV/s/cm3 +// the energy injection rate density (integral of E * S(e) dE) in eV/s/cm3 that the Spencer-Fano equation is solved for. +// This is arbitrary and and the solution will be scaled to match the actual energy deposition rate density. double E_init_ev = 0; constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); // Monte Carlo result - compare to analytical expectation -double nt_energy_deposited; +double nt_energy_deposited = 0; struct NonThermalExcitation { double frac_deposition; // the fraction of the non-thermal deposition energy going to the excitation transition @@ -535,6 +536,8 @@ auto get_energyindex_ev_gteq(const double energy_ev) -> int return index; } +// interpolate the y flux values to get the value at a given energy +// y has units of particles / cm2 / s / eV auto get_y(const double energy_ev) -> double { if (energy_ev <= 0) { return 0.; @@ -601,9 +604,9 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it #endif } -auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &colliondata) -> int // xs_vec will be set with impact ionization cross sections for E > ionpot_ev (and zeros below this energy) -{ +// returns the index of the first energy point >= ionpot_ev +auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &colliondata) -> int { const double ionpot_ev = colliondata.ionpot_ev; const int startindex = get_energyindex_ev_gteq(ionpot_ev); @@ -627,10 +630,9 @@ auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &collio return startindex; } -auto Psecondary(const double e_p, const double epsilon, const double I, const double J) -> double // distribution of secondary electron energies for primary electron with energy e_p // Opal, Peterson, & Beaty (1971) -{ +auto Psecondary(const double e_p, const double epsilon, const double I, const double J) -> double { const double e_s = epsilon - I; if (e_p <= I || e_s < 0.) { @@ -661,11 +663,10 @@ auto get_J(const int Z, const int ionstage, const double ionpot_ev) -> double { return 0.6 * ionpot_ev; } -constexpr auto xs_excitation(const int element, const int ion, const int lower, const int uptransindex, - const double epsilon_trans, const double lowerstatweight, const double energy) -> double // collisional excitation cross section in cm^2 // energies are in erg -{ +constexpr auto xs_excitation(const int element, const int ion, const int lower, const int uptransindex, + const double epsilon_trans, const double lowerstatweight, const double energy) -> double { if (energy < epsilon_trans) { return 0.; } @@ -695,18 +696,17 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, return 0.; } -constexpr auto electron_loss_rate(const double energy, const double nne) -> double // -dE / dx for fast electrons // energy is in ergs // nne is the thermal electron density [cm^-3] -// return units are erg / cm -{ +// return value has units of erg/cm +constexpr auto electron_loss_rate(const double energy, const double nne) -> double { if (energy <= 0.) { return 0; } // normally set to 1.0, but Shingles et al. (2021) boosted this to increase heating - const double boostfactor = 1.; + constexpr double boostfactor = 1.; const double omegap = sqrt(4 * PI * nne * pow(QE, 2) / ME); const double zetae = H * omegap / 2 / PI; @@ -717,12 +717,11 @@ constexpr auto electron_loss_rate(const double energy, const double nne) -> doub return boostfactor * nne * 2 * PI * pow(QE, 4) / energy * log(ME * pow(v, 3) / (EULERGAMMA * pow(QE, 2) * omegap)); } -constexpr auto xs_impactionization(const double energy_ev, const collionrow &colliondata) -> double // impact ionization cross section in cm^2 // energy and ionization_potential should be in eV // fitting forumula of Younger 1981 // called Q_i(E) in KF92 equation 7 -{ +constexpr auto xs_impactionization(const double energy_ev, const collionrow &colliondata) -> double { const double ionpot_ev = colliondata.ionpot_ev; const double u = energy_ev / ionpot_ev; @@ -737,11 +736,10 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col return 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); } -auto N_e(const int modelgridindex, const double energy) -> double // Kozma & Fransson equation 6. // Something related to a number of electrons, needed to calculate the heating fraction in equation 3 // not valid for energy > SF_EMIN -{ +auto N_e(const int modelgridindex, const double energy) -> double { const double energy_ev = energy / EV; const double tot_nion = get_nnion_tot(modelgridindex); double N_e = 0.; @@ -823,9 +821,9 @@ auto N_e(const int modelgridindex, const double energy) -> double return N_e; } -auto calculate_frac_heating(const int modelgridindex) -> float +// fraction of deposited energy that goes into heating the thermal electrons // Kozma & Fransson equation 3 -{ +auto calculate_frac_heating(const int modelgridindex) -> float { // frac_heating multiplied by E_init, which will be divided out at the end double frac_heating_Einit = 0.; @@ -864,6 +862,7 @@ auto calculate_frac_heating(const int modelgridindex) -> float return frac_heating; } +// fraction of deposited energy that goes into ionization auto get_nt_frac_ionization(const int modelgridindex) -> float { if (!NT_ON) { return 0.; @@ -883,6 +882,7 @@ auto get_nt_frac_ionization(const int modelgridindex) -> float { return frac_ionization; } +// fraction of deposited energy that goes into collisional excitation auto get_nt_frac_excitation(const int modelgridindex) -> float { if (!NT_ON || !NT_SOLVE_SPENCERFANO) { return 0.; @@ -1016,10 +1016,10 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { return total; } +// compute the work per ion pair for doing the NT ionization calculation. +// Makes use of EXTREMELY SIMPLE approximations - high energy limits only (can be used as an alternative to the +// Spencer-Fano solver) auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> double { - // Routine to compute the work per ion pair for doing the NT ionization calculation. - // Makes use of EXTREMELY SIMPLE approximations - high energy limits only - // Work in terms of 1/W since this is actually what we want. It is given by sigma/(Latom + Lelec). // We are going to start by taking all the high energy limits and ignoring Lelec, so that the // denominator is extremely simplified. Need to get the mean Z value. @@ -1028,29 +1028,24 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> for (int ielement = 0; ielement < get_nelements(); ielement++) { Zbar += grid::get_elem_abundance(modelgridindex, ielement) * get_atomicnumber(ielement); } - // printout("cell %d has Zbar of %g\n", modelgridindex, Zbar); - const double Aconst = 1.33e-14 * EV * EV; const double binding = get_mean_binding_energy(element, ion); + constexpr double Aconst = 1.33e-14 * EV * EV; const double oneoverW = Aconst * binding / Zbar / (2 * PI * pow(QE, 4)); - // printout("For element %d ion %d I got W of %g (eV)\n", element, ion, 1./oneoverW/EV); return oneoverW; } +// the fraction of deposited energy that goes into ionising electrons in a particular shell auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int element, const int ion, - const collionrow &collionrow) -> double -// the fraction of deposition energy that goes into ionising electrons in this particular shell -{ - const double nnion = get_nnion(modelgridindex, element, ion); // hopefully ions per cm^3? + const collionrow &collionrow) -> double { + const double nnion = get_nnion(modelgridindex, element, ion); const double ionpot_ev = collionrow.ionpot_ev; gsl_vector *cross_section_vec = gsl_vector_alloc(SFPTS); get_xs_ionization_vector(cross_section_vec, collionrow); - // either multiply by the variable delta_e for LOG_E spacing... - - gsl_vector_view const yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); + const gsl_vector_view yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); double y_dot_crosssection_de = 0.; gsl_blas_ddot(&yvecview.vector, cross_section_vec, &y_dot_crosssection_de); @@ -1111,7 +1106,7 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme gsl_vector_free(cross_section_vec); double y_dot_crosssection_de = 0.; - gsl_vector_view const yvecview_thismgi = gsl_vector_view_array(yfunc.data(), SFPTS); + const gsl_vector_view yvecview_thismgi = gsl_vector_view_array(yfunc.data(), SFPTS); gsl_blas_ddot(&yvecview_thismgi.vector, cross_section_vec_allshells, &y_dot_crosssection_de); gsl_vector_free(cross_section_vec_allshells); @@ -1915,10 +1910,8 @@ void init(const int my_rank, const int ndo_nonempty) { deposition_rate_density.resize(grid::get_npts_model()); deposition_rate_density_timestep.resize(grid::get_npts_model()); - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - deposition_rate_density[modelgridindex] = -1.; - deposition_rate_density_timestep[modelgridindex] = -1; - } + std::ranges::fill(deposition_rate_density, -1.); + std::ranges::fill(deposition_rate_density_timestep, -1); if (!NT_ON) { return; @@ -1957,14 +1950,13 @@ void init(const int my_rank, const int ndo_nonempty) { nt_excitations_stored, grid::get_nonempty_npts_model() * sizeof(NonThermalExcitation) * nt_excitations_stored / 1024. / 1024.); - const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); + const auto nonempty_npts_model = grid::get_nonempty_npts_model(); #ifdef MPI_ON MPI_Win win_shared_excitations_list{}; int my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder if (globals::rank_in_node == 0) { my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); @@ -2065,11 +2057,10 @@ void init(const int my_rank, const int ndo_nonempty) { printout("Finished initializing non-thermal solver\n"); } -void calculate_deposition_rate_density(const int modelgridindex, const int timestep, - HeatingCoolingRates *heatingcoolingrates) // set total non-thermal deposition rate from individual gamma/positron/electron/alpha rates. This should be called // after packet propagation is finished for this timestep and normalise_deposition_estimators() has been done -{ +void calculate_deposition_rate_density(const int modelgridindex, const int timestep, + HeatingCoolingRates *heatingcoolingrates) { const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); heatingcoolingrates->dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; @@ -2392,10 +2383,9 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { stats::increment(stats::COUNTER_NT_STAT_TO_KPKT); } -void solve_spencerfano(const int modelgridindex, const int timestep, const int iteration) // solve the Spencer-Fano equation to get the non-thermal electron flux energy distribution // based on Equation (2) of Li et al. (2012) -{ +void solve_spencerfano(const int modelgridindex, const int timestep, const int iteration) { bool skip_solution = false; if (grid::get_numassociatedcells(modelgridindex) < 1) { printout("Associated_cells < 1 in cell %d at timestep %d. Skipping Spencer-Fano solution.\n", modelgridindex, @@ -2416,6 +2406,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i } if (skip_solution) { + // Axelrod values nt_solution[modelgridindex].frac_heating = 0.97; nt_solution[modelgridindex].frac_ionization = 0.03; nt_solution[modelgridindex].frac_excitation = 0.; @@ -2429,7 +2420,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i return; } - const float nne = grid::get_nne(modelgridindex); // electrons per cm^3 + const auto nne = grid::get_nne(modelgridindex); // electrons per cm^3 const double nne_per_ion = nne / get_nnion_tot(modelgridindex); const double nne_per_ion_last = nt_solution[modelgridindex].nneperion_when_solved; const double nne_per_ion_fracdiff = fabs((nne_per_ion_last / nne_per_ion) - 1.); @@ -2732,12 +2723,6 @@ void nt_reset_stats() { nt_energy_deposited = 0.; } void nt_print_stats(const double modelvolume, const double deltat) { const double deposition_rate_density_montecarlo = nt_energy_deposited / EV / modelvolume / deltat; - // deposition rate density for all cells has not been communicated yet - could change this - // double total_deposition_rate_density = 0.; - // for (int mgi = 0; mgi < npts_model; mgi++) - // { - // total_deposition_rate_density += get_deposition_rate_density(mgi) / EV; - // } printout("nt_energy_deposited = %g [eV/s/cm^3]\n", deposition_rate_density_montecarlo); } From eb25e00db3c93cff5cd29773d2d0d3f109d85a3a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 20 Aug 2024 11:36:42 +0100 Subject: [PATCH 024/117] NLTE: reuse matrix and vector storage instead of alloc/free on each element solution (#108) --- nltepop.cc | 257 ++++++++++++++++++++++++----------------- nonthermal.cc | 16 +-- spectrum_lightcurve.cc | 2 +- spectrum_lightcurve.h | 4 +- 4 files changed, 164 insertions(+), 115 deletions(-) diff --git a/nltepop.cc b/nltepop.cc index 8e841213e..5c85a5554 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -32,6 +32,27 @@ FILE *nlte_file{}; // can save memory by using a combined rate matrix at the cost of diagnostic information constexpr bool individual_process_matricies = true; +// the backing storage for the gsl matrices +thread_local std::vector vec_rate_matrix; +thread_local std::vector vec_rate_matrix_rad_bb; +thread_local std::vector vec_rate_matrix_coll_bb; +thread_local std::vector vec_rate_matrix_ntcoll_bb; +thread_local std::vector vec_rate_matrix_rad_bf; +thread_local std::vector vec_rate_matrix_coll_bf; +thread_local std::vector vec_rate_matrix_ntcoll_bf; + +thread_local std::vector vec_rate_matrix_LU_decomp; + +// backing storage for gsl vectors +thread_local std::vector vec_balance_vector; +thread_local std::vector vec_pop_norm_factor_vec; +thread_local std::vector vec_pop_vec; +thread_local std::vector vec_x; +thread_local std::vector vec_permutation; +thread_local std::vector vec_work_vector; +thread_local std::vector vec_x_best; +thread_local std::vector vec_residual_vector; + // this is the index for the NLTE solver that is handling all ions of a single element // This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements auto get_nlte_vector_index(const int element, const int ion, const int level) -> int { @@ -127,41 +148,39 @@ auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, con if (into_level) { // find rate into selected level - gsl_vector_const_view row_view = gsl_matrix_const_row(rate_matrix, index_selected); - const gsl_vector *rates_vec = &row_view.vector; + auto row_vec = gsl_matrix_const_row(rate_matrix, index_selected).vector; // multiply incoming rate coefficients by their corresponding populations to get rates if (!only_levels_above) // add levels below { for (int index = 0; index < index_selected; index++) { - total_rate += gsl_vector_get(rates_vec, index) * gsl_vector_get(popvec, index); + total_rate += gsl_vector_get(&row_vec, index) * gsl_vector_get(popvec, index); } } if (!only_levels_below) // add levels above { for (unsigned int index = index_selected + 1; index < rate_matrix->size1; index++) { - total_rate += gsl_vector_get(rates_vec, index) * gsl_vector_get(popvec, index); + total_rate += gsl_vector_get(&row_vec, index) * gsl_vector_get(popvec, index); } } } else { // find rate out of selected level - gsl_vector_const_view col_view = gsl_matrix_const_column(rate_matrix, index_selected); - const gsl_vector *rates_vec = &col_view.vector; + auto col_vec = gsl_matrix_const_column(rate_matrix, index_selected).vector; // multiply outgoing rate coefficients by the population of the selected level to get rates if (!only_levels_above) // add levels below { for (int index = 0; index < index_selected; index++) { - total_rate += gsl_vector_get(rates_vec, index); + total_rate += gsl_vector_get(&col_vec, index); } } if (!only_levels_below) // add levels above { for (unsigned int index = index_selected + 1; index < rate_matrix->size2; index++) { - total_rate += gsl_vector_get(rates_vec, index); + total_rate += gsl_vector_get(&col_vec, index); } } @@ -428,6 +447,15 @@ auto get_element_nlte_dimension(const int element) -> int { return nlte_dimension; } +// get the maximum NLTE dimension for any of the included elements +auto get_max_nlte_dimension() { + int max_nlte_dimension = 0; + for (int element = 0; element < get_nelements(); element++) { + max_nlte_dimension = std::max(max_nlte_dimension, get_element_nlte_dimension(element)); + } + return max_nlte_dimension; +} + void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const int ion, const double t_mid, const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bb, gsl_matrix *rate_matrix_coll_bb, gsl_matrix *rate_matrix_ntcoll_bb) { @@ -673,18 +701,22 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons assert_always(rate_matrix->size1 == nlte_dimension); assert_always(rate_matrix->size2 == nlte_dimension); - gsl_vector *x = gsl_vector_alloc(nlte_dimension); // population solution vector (normalised) + vec_x.resize(vec_pop_norm_factor_vec.size()); + gsl_vector x = gsl_vector_view_array(vec_x.data(), nlte_dimension).vector; + vec_rate_matrix_LU_decomp.resize(vec_rate_matrix.size()); // make a copy of the rate matrix for the LU decomp - gsl_matrix *rate_matrix_LU_decomp = gsl_matrix_alloc(nlte_dimension, nlte_dimension); - gsl_matrix_memcpy(rate_matrix_LU_decomp, rate_matrix); + gsl_matrix rate_matrix_LU_decomp = + gsl_matrix_view_array(vec_rate_matrix_LU_decomp.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_memcpy(&rate_matrix_LU_decomp, rate_matrix); - gsl_permutation *p = gsl_permutation_alloc(nlte_dimension); + vec_permutation.resize(vec_pop_norm_factor_vec.size()); + gsl_permutation p{.size = nlte_dimension, .data = vec_permutation.data()}; int s = 0; // sign of the transformation - gsl_linalg_LU_decomp(rate_matrix_LU_decomp, p, &s); + gsl_linalg_LU_decomp(&rate_matrix_LU_decomp, &p, &s); - if (lumatrix_is_singular(rate_matrix_LU_decomp, element)) { + if (lumatrix_is_singular(&rate_matrix_LU_decomp, element)) { printout("ERROR: NLTE matrix is singular for element Z=%d!\n", get_atomicnumber(element)); // abort(); completed_solution = false; @@ -692,7 +724,7 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); // solve matrix equation: rate_matrix * x = balance_vector for x (population vector) - gsl_linalg_LU_solve(rate_matrix_LU_decomp, p, balance_vector, x); + gsl_linalg_LU_solve(&rate_matrix_LU_decomp, &p, balance_vector, &x); gsl_set_error_handler(previous_handler); @@ -700,23 +732,31 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons const double TOLERANCE = 1e-40; - gsl_vector *gsl_work_vector = gsl_vector_alloc(nlte_dimension); + vec_work_vector.resize(vec_pop_norm_factor_vec.size()); + gsl_vector gsl_work_vector = gsl_vector_view_array(vec_work_vector.data(), nlte_dimension).vector; + double error_best = -1.; - gsl_vector *x_best = gsl_vector_alloc(nlte_dimension); // population solution vector with lowest error - gsl_vector *residual_vector = gsl_vector_alloc(nlte_dimension); + + // population solution vector with lowest error + vec_x_best.resize(vec_pop_norm_factor_vec.size()); + gsl_vector x_best = gsl_vector_view_array(vec_x_best.data(), nlte_dimension).vector; + + vec_residual_vector.resize(vec_pop_norm_factor_vec.size()); + gsl_vector residual_vector = gsl_vector_view_array(vec_residual_vector.data(), nlte_dimension).vector; + int iteration = 0; for (iteration = 0; iteration < 10; iteration++) { if (iteration > 0) { - gsl_linalg_LU_refine(rate_matrix, rate_matrix_LU_decomp, p, balance_vector, x, gsl_work_vector); + gsl_linalg_LU_refine(rate_matrix, &rate_matrix_LU_decomp, &p, balance_vector, &x, &gsl_work_vector); } - gsl_vector_memcpy(residual_vector, balance_vector); - gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, x, -1.0, residual_vector); // calculate Ax - b = residual - const double error = fabs( - gsl_vector_get(residual_vector, gsl_blas_idamax(residual_vector))); // value of the largest absolute residual + gsl_vector_memcpy(&residual_vector, balance_vector); + gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, &x, -1.0, &residual_vector); // calculate Ax - b = residual + const double error = fabs(gsl_vector_get( + &residual_vector, gsl_blas_idamax(&residual_vector))); // value of the largest absolute residual if (error < error_best || error_best < 0.) { - gsl_vector_memcpy(x_best, x); + gsl_vector_memcpy(&x_best, &x); error_best = error; } // printout("Linear algebra solver iteration %d has a maximum residual of %g\n",iteration,error); @@ -734,21 +774,18 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons iteration, error_best); } - gsl_vector_memcpy(x, x_best); + gsl_vector_memcpy(&x, &x_best); } - gsl_vector_free(x_best); - gsl_vector_free(gsl_work_vector); - // get the real populations using the x vector and the normalisation factors - gsl_vector_memcpy(popvec, x); + gsl_vector_memcpy(popvec, &x); gsl_vector_mul(popvec, pop_normfactor_vec); // popvec will be used contains the real population densities for (size_t row = 0; row < nlte_dimension; row++) { double recovered_balance_vector_elem = 0.; gsl_vector_const_view row_view = gsl_matrix_const_row(rate_matrix, row); - gsl_blas_ddot(&row_view.vector, x, &recovered_balance_vector_elem); + gsl_blas_ddot(&row_view.vector, &x, &recovered_balance_vector_elem); int ion = 0; int level = 0; @@ -766,19 +803,14 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons " WARNING: NLTE solver gave negative population to index %zud (Z=%d ionstage %d level %d), pop = %g. " "Replacing with LTE pop of %g\n", row, get_atomicnumber(element), get_ionstage(element, ion), level, - gsl_vector_get(x, row) * gsl_vector_get(pop_normfactor_vec, row), gsl_vector_get(pop_normfactor_vec, row)); + gsl_vector_get(&x, row) * gsl_vector_get(pop_normfactor_vec, row), gsl_vector_get(pop_normfactor_vec, row)); gsl_vector_set(popvec, row, gsl_vector_get(pop_normfactor_vec, row)); } } - gsl_vector_free(residual_vector); completed_solution = true; } - gsl_vector_free(x); - gsl_matrix_free(rate_matrix_LU_decomp); - gsl_permutation_free(p); - return completed_solution; } } // anonymous namespace @@ -824,22 +856,48 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // printout("NLTE: the vector dimension is %d", nlte_dimension); - gsl_matrix *rate_matrix = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - gsl_matrix *rate_matrix_rad_bb{}; - gsl_matrix *rate_matrix_coll_bb{}; - gsl_matrix *rate_matrix_ntcoll_bb{}; - gsl_matrix *rate_matrix_rad_bf{}; - gsl_matrix *rate_matrix_coll_bf{}; - gsl_matrix *rate_matrix_ntcoll_bf{}; - if (individual_process_matricies) { - rate_matrix_rad_bb = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - rate_matrix_coll_bb = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - rate_matrix_ntcoll_bb = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - rate_matrix_rad_bf = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - rate_matrix_coll_bf = gsl_matrix_calloc(nlte_dimension, nlte_dimension); - rate_matrix_ntcoll_bf = gsl_matrix_calloc(nlte_dimension, nlte_dimension); + const auto max_nlte_dimension = get_max_nlte_dimension(); + + vec_rate_matrix.resize(max_nlte_dimension * max_nlte_dimension); + auto rate_matrix = gsl_matrix_view_array(vec_rate_matrix.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix, 0.); + + gsl_matrix rate_matrix_rad_bb; + gsl_matrix rate_matrix_coll_bb; + gsl_matrix rate_matrix_ntcoll_bb; + gsl_matrix rate_matrix_rad_bf; + gsl_matrix rate_matrix_coll_bf; + gsl_matrix rate_matrix_ntcoll_bf; + + if constexpr (individual_process_matricies) { + vec_rate_matrix_rad_bb.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_rad_bb = gsl_matrix_view_array(vec_rate_matrix_rad_bb.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_rad_bb, 0.); + + vec_rate_matrix_coll_bb.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_coll_bb = gsl_matrix_view_array(vec_rate_matrix_coll_bb.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_coll_bb, 0.); + + vec_rate_matrix_ntcoll_bb.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_ntcoll_bb = + gsl_matrix_view_array(vec_rate_matrix_ntcoll_bb.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_ntcoll_bb, 0.); + + vec_rate_matrix_rad_bf.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_rad_bf = gsl_matrix_view_array(vec_rate_matrix_rad_bf.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_rad_bf, 0.); + + vec_rate_matrix_coll_bf.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_coll_bf = gsl_matrix_view_array(vec_rate_matrix_coll_bf.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_coll_bf, 0.); + + vec_rate_matrix_ntcoll_bf.resize(max_nlte_dimension * max_nlte_dimension); + rate_matrix_ntcoll_bf = + gsl_matrix_view_array(vec_rate_matrix_ntcoll_bf.data(), nlte_dimension, nlte_dimension).matrix; + gsl_matrix_set_all(&rate_matrix_ntcoll_bf, 0.); } else { - // alias the single matrix accounting for all processes + // if not individual_process_matricies, alias a single matrix for all transition types + // the "gsl_matrix" structs are independent, but the data is shared rate_matrix_rad_bb = rate_matrix; rate_matrix_coll_bb = rate_matrix; rate_matrix_ntcoll_bb = rate_matrix; @@ -848,10 +906,6 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const rate_matrix_ntcoll_bf = rate_matrix; } - gsl_vector *const balance_vector = gsl_vector_calloc(nlte_dimension); - - assert_always(balance_vector != nullptr); - // printout(" Adding rates for ion stages:"); for (int ion = 0; ion < nions; ion++) { // const int ionstage = get_ionstage(element, ion); @@ -869,35 +923,39 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const s_renorm[level] = superlevel_boltzmann(modelgridindex, element, ion, level) / superlevel_partfunc[ion]; } - nltepop_matrix_add_boundbound(modelgridindex, element, ion, t_mid, s_renorm, rate_matrix_rad_bb, - rate_matrix_coll_bb, rate_matrix_ntcoll_bb); + nltepop_matrix_add_boundbound(modelgridindex, element, ion, t_mid, s_renorm, &rate_matrix_rad_bb, + &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb); if (ion < nions - 1) { // this is the slowest component - nltepop_matrix_add_ionisation(modelgridindex, element, ion, s_renorm, rate_matrix_rad_bf, rate_matrix_coll_bf); + nltepop_matrix_add_ionisation(modelgridindex, element, ion, s_renorm, &rate_matrix_rad_bf, &rate_matrix_coll_bf); if (NT_ON) { - nltepop_matrix_add_nt_ionisation(modelgridindex, element, ion, s_renorm, rate_matrix_ntcoll_bf); + nltepop_matrix_add_nt_ionisation(modelgridindex, element, ion, s_renorm, &rate_matrix_ntcoll_bf); } } } // printout("\n"); if (individual_process_matricies) { - // sum the matricies for each transition process to get a total rate matrix - gsl_matrix_add(rate_matrix, rate_matrix_rad_bb); - gsl_matrix_add(rate_matrix, rate_matrix_coll_bb); - gsl_matrix_add(rate_matrix, rate_matrix_ntcoll_bb); - gsl_matrix_add(rate_matrix, rate_matrix_rad_bf); - gsl_matrix_add(rate_matrix, rate_matrix_coll_bf); - gsl_matrix_add(rate_matrix, rate_matrix_ntcoll_bf); + // sum the matricies for each transition type to get a total rate matrix + gsl_matrix_add(&rate_matrix, &rate_matrix_rad_bb); + gsl_matrix_add(&rate_matrix, &rate_matrix_coll_bb); + gsl_matrix_add(&rate_matrix, &rate_matrix_ntcoll_bb); + gsl_matrix_add(&rate_matrix, &rate_matrix_rad_bf); + gsl_matrix_add(&rate_matrix, &rate_matrix_coll_bf); + gsl_matrix_add(&rate_matrix, &rate_matrix_ntcoll_bf); } // replace the first row of the matrix and balance vector with the normalisation // constraint on the total element population - gsl_vector_view first_row_view = gsl_matrix_row(rate_matrix, 0); + gsl_vector_view first_row_view = gsl_matrix_row(&rate_matrix, 0); gsl_vector_set_all(&first_row_view.vector, 1.0); + + vec_balance_vector.resize(max_nlte_dimension); + auto balance_vector = gsl_vector_view_array(vec_balance_vector.data(), nlte_dimension).vector; + gsl_vector_set_all(&balance_vector, 0.); // set first balance vector entry to the element population (all other entries will be zero) - gsl_vector_set(balance_vector, 0, nnelement); + gsl_vector_set(&balance_vector, 0, nnelement); if (FORCE_SAHA_ION_BALANCE(atomic_number)) { const auto ionfractions = calculate_ionfractions(element, modelgridindex, grid::get_nne(modelgridindex), true); @@ -908,21 +966,23 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const double nnion = nnelement * ionfractions[ion]; const int index_ion_ground = get_nlte_vector_index(element, ion, 0); const int index_ion_toplevel = get_nlte_vector_index(element, ion, get_nlevels(element, ion)); - gsl_vector_view ion_ground_row_view = gsl_matrix_row(rate_matrix, index_ion_ground); + gsl_vector_view ion_ground_row_view = gsl_matrix_row(&rate_matrix, index_ion_ground); gsl_vector_set_all(&ion_ground_row_view.vector, 0.); for (int index = index_ion_ground; index <= index_ion_toplevel; index++) { gsl_vector_set(&ion_ground_row_view.vector, index, 1.); } - gsl_vector_set(balance_vector, get_nlte_vector_index(element, ion, index_ion_ground), nnion); + gsl_vector_set(&balance_vector, get_nlte_vector_index(element, ion, index_ion_ground), nnion); } } // calculate the normalisation factors and apply them to the matrix // columns and balance vector elements - gsl_vector *pop_norm_factor_vec = gsl_vector_calloc(nlte_dimension); - // gsl_vector_set_all(pop_norm_factor_vec, 1.0); - nltepop_matrix_normalise(modelgridindex, element, rate_matrix, pop_norm_factor_vec); + vec_pop_norm_factor_vec.resize(max_nlte_dimension); + auto pop_norm_factor_vec = gsl_vector_view_array(vec_pop_norm_factor_vec.data(), nlte_dimension).vector; + gsl_vector_set_all(&pop_norm_factor_vec, 1.0); + + nltepop_matrix_normalise(modelgridindex, element, &rate_matrix, &pop_norm_factor_vec); // printout("Rate matrix | balance vector:\n"); // for (int row = 0; row < nlte_dimension; row++) @@ -944,10 +1004,13 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // their interactions and setting their normalised populations (probably departure coeff) to 1.0 // filter_nlte_matrix(element, rate_matrix, balance_vector, pop_norm_factor_vec); - gsl_vector *popvec = gsl_vector_alloc(nlte_dimension); // the true population densities + // the true population densities + + vec_pop_vec.resize(max_nlte_dimension); + auto popvec = gsl_vector_view_array(vec_pop_vec.data(), nlte_dimension).vector; const bool matrix_solve_success = - nltepop_matrix_solve(element, rate_matrix, balance_vector, popvec, pop_norm_factor_vec); + nltepop_matrix_solve(element, &rate_matrix, &balance_vector, &popvec, &pop_norm_factor_vec); if (!matrix_solve_success) { printout( @@ -958,8 +1021,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } else { // check calculated NLTE populations are valid for (int index = 0; index < nlte_dimension; index++) { - assert_always(std::isfinite(gsl_vector_get(popvec, index))); - assert_always(gsl_vector_get(popvec, index) >= 0.); + assert_always(std::isfinite(gsl_vector_get(&popvec, index))); + assert_always(gsl_vector_get(&popvec, index) >= 0.); } for (int ion = 0; ion < nions; ion++) { @@ -979,7 +1042,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const for (int level = 1; level <= nlevels_nlte; level++) { const int index = get_nlte_vector_index(element, ion, level); grid::modelgrid[modelgridindex].nlte_pops[nlte_start + level - 1] = - gsl_vector_get(popvec, index) / grid::get_rho(modelgridindex); + gsl_vector_get(&popvec, index) / grid::get_rho(modelgridindex); // solution_ion_pop += gsl_vector_get(popvec, index); } @@ -988,18 +1051,18 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const { const int index_sl = get_nlte_vector_index(element, ion, nlevels_nlte + 1); grid::modelgrid[modelgridindex].nlte_pops[nlte_start + nlevels_nlte] = - (gsl_vector_get(popvec, index_sl) / grid::modelgrid[modelgridindex].rho / superlevel_partfunc[ion]); + (gsl_vector_get(&popvec, index_sl) / grid::modelgrid[modelgridindex].rho / superlevel_partfunc[ion]); } // store the ground level population grid::modelgrid[modelgridindex].ion_groundlevelpops[get_uniqueionindex(element, ion)] = - gsl_vector_get(popvec, index_gs); + gsl_vector_get(&popvec, index_gs); // solution_ion_pop += gsl_vector_get(popvec, index_gs); calculate_cellpartfuncts(modelgridindex, element); } - const double elem_pop_matrix = gsl_blas_dasum(popvec); + const double elem_pop_matrix = gsl_blas_dasum(&popvec); const double elem_pop_error_percent = fabs((nnelement / elem_pop_matrix) - 1) * 100; if (elem_pop_error_percent > 1.0) { printout( @@ -1012,9 +1075,9 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const if (individual_process_matricies && (timestep % 5 == 0) && (nlte_iter == 0)) // output NLTE stats every nth timestep for the first NLTE iteration only { - print_element_rates_summary(element, modelgridindex, timestep, nlte_iter, popvec, rate_matrix_rad_bb, - rate_matrix_coll_bb, rate_matrix_ntcoll_bb, rate_matrix_rad_bf, rate_matrix_coll_bf, - rate_matrix_ntcoll_bf); + print_element_rates_summary(element, modelgridindex, timestep, nlte_iter, &popvec, &rate_matrix_rad_bb, + &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb, &rate_matrix_rad_bf, + &rate_matrix_coll_bf, &rate_matrix_ntcoll_bf); } const bool print_detailed_level_stats = false; @@ -1029,34 +1092,20 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const int ion = ionstage - get_ionstage(element, 0); for (int level = 0; level < get_nlevels_nlte(element, ion); level++) { - print_level_rates(modelgridindex, timestep, element, ion, level, popvec, rate_matrix_rad_bb, - rate_matrix_coll_bb, rate_matrix_ntcoll_bb, rate_matrix_rad_bf, rate_matrix_coll_bf, - rate_matrix_ntcoll_bf); + print_level_rates(modelgridindex, timestep, element, ion, level, &popvec, &rate_matrix_rad_bb, + &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb, &rate_matrix_rad_bf, &rate_matrix_coll_bf, + &rate_matrix_ntcoll_bf); } if (ion_has_superlevel(element, ion)) { const int slindex = get_nlevels_nlte(element, ion) + 1; - print_level_rates(modelgridindex, timestep, element, ion, slindex, popvec, rate_matrix_rad_bb, - rate_matrix_coll_bb, rate_matrix_ntcoll_bb, rate_matrix_rad_bf, rate_matrix_coll_bf, - rate_matrix_ntcoll_bf); + print_level_rates(modelgridindex, timestep, element, ion, slindex, &popvec, &rate_matrix_rad_bb, + &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb, &rate_matrix_rad_bf, &rate_matrix_coll_bf, + &rate_matrix_ntcoll_bf); } } } - if (individual_process_matricies) { - gsl_matrix_free(rate_matrix_rad_bb); - gsl_matrix_free(rate_matrix_coll_bb); - gsl_matrix_free(rate_matrix_ntcoll_bb); - gsl_matrix_free(rate_matrix_rad_bf); - gsl_matrix_free(rate_matrix_coll_bf); - gsl_matrix_free(rate_matrix_ntcoll_bf); - } - - gsl_vector_free(popvec); - - gsl_matrix_free(rate_matrix); - gsl_vector_free(balance_vector); - gsl_vector_free(pop_norm_factor_vec); const int duration_nltesolver = std::time(nullptr) - sys_time_start_nltesolver; if (duration_nltesolver > 2) { printout("NLTE population solver call for Z=%d took %d seconds\n", get_atomicnumber(element), duration_nltesolver); diff --git a/nonthermal.cc b/nonthermal.cc index c58103e23..af6e32722 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1106,8 +1106,8 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme gsl_vector_free(cross_section_vec); double y_dot_crosssection_de = 0.; - const gsl_vector_view yvecview_thismgi = gsl_vector_view_array(yfunc.data(), SFPTS); - gsl_blas_ddot(&yvecview_thismgi.vector, cross_section_vec_allshells, &y_dot_crosssection_de); + const auto gsl_yvec = gsl_vector_view_array(yfunc.data(), SFPTS).vector; + gsl_blas_ddot(&gsl_yvec, cross_section_vec_allshells, &y_dot_crosssection_de); gsl_vector_free(cross_section_vec_allshells); y_dot_crosssection_de *= DELTA_E; @@ -1315,18 +1315,18 @@ auto calculate_nt_excitation_ratecoeff_perdeposition(const gsl_vector_view yvecv const int lower, const int uptransindex, const double statweight_lower, const double epsilon_trans) -> double { - gsl_vector *xs_excitation_vec = gsl_vector_alloc(SFPTS); - if (get_xs_excitation_vector(xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, epsilon_trans) >= - 0) { + thread_local static std::array xs_excitation_vec{}; + + gsl_vector gsl_xs_excitation_vec = gsl_vector_view_array(xs_excitation_vec.data(), SFPTS).vector; + if (get_xs_excitation_vector(&gsl_xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, + epsilon_trans) >= 0) { double y_dot_crosssection = 0.; - gsl_blas_ddot(xs_excitation_vec, &yvecview.vector, &y_dot_crosssection); - gsl_vector_free(xs_excitation_vec); + gsl_blas_ddot(&gsl_xs_excitation_vec, &yvecview.vector, &y_dot_crosssection); y_dot_crosssection *= DELTA_E; return y_dot_crosssection / E_init_ev / EV; } - gsl_vector_free(xs_excitation_vec); return 0.; } diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 34deefe25..3f069bb11 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -525,7 +525,7 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co std::ranges::fill(spectra.fluxalltimesteps, 0.0); mem_usage += globals::ntimesteps * sizeof(Spectra); - mem_usage += globals::ntimesteps * sizeof(TimeStepstepspec); + mem_usage += globals::ntimesteps * sizeof(TimeStepSpecrum); mem_usage += globals::ntimesteps * MNUBINS * sizeof(double); for (int nts = 0; nts < globals::ntimesteps; nts++) { diff --git a/spectrum_lightcurve.h b/spectrum_lightcurve.h index ee2789855..f753c987d 100644 --- a/spectrum_lightcurve.h +++ b/spectrum_lightcurve.h @@ -7,7 +7,7 @@ #include "packet.h" -struct TimeStepstepspec { +struct TimeStepSpecrum { double *flux{}; double *absorption{}; double *emission{}; @@ -23,7 +23,7 @@ struct Spectra { std::vector absorptionalltimesteps; std::vector emissionalltimesteps; std::vector trueemissionalltimesteps; - std::vector timesteps; + std::vector timesteps; bool do_emission_res = false; }; From 547e85155a9df01972f1695eae6f948210ea5d91 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 23 Aug 2024 08:43:20 +0100 Subject: [PATCH 025/117] Non-thermal: Reduce heap allocations during update_grid (#109) --- decay.cc | 2 +- gammapkt.cc | 8 +- grid.cc | 10 +- grid.h | 2 +- input.cc | 5 +- ltepop.cc | 8 +- macroatom.cc | 102 +++++----- nltepop.cc | 128 ++++++------- nonthermal.cc | 506 +++++++++++++++++++++++--------------------------- rpkt.cc | 22 +-- sn3d.h | 21 ++- vectors.h | 36 ++-- vpkt.cc | 88 ++++----- 13 files changed, 427 insertions(+), 511 deletions(-) diff --git a/decay.cc b/decay.cc index cd0ab6064..208baf220 100644 --- a/decay.cc +++ b/decay.cc @@ -897,7 +897,7 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector nuclides.push_back({.z = 25, .a = 52, .meanlife = 0.0211395 * DAY}); nuclides.back().branchprobs[DECAYTYPE_ELECTRONCAPTURE] = 1.; - auto standard_nuclides = nuclides; + const auto standard_nuclides = nuclides; // any nuclides in the custom list that are not in the standard list need beta and alpha decay data diff --git a/gammapkt.cc b/gammapkt.cc index 73783b418..f9138603e 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -368,9 +368,9 @@ auto thomson_angle() -> double { const double r32 = dir_in[1] * norm2; const double r33 = dir_in[2] * norm2; - std::array dir_out{(r11 * xprime) + (r21 * yprime) + (r31 * zprime), - (r12 * xprime) + (r22 * yprime) + (r32 * zprime), - (r13 * xprime) + (r23 * yprime) + (r33 * zprime)}; + const auto dir_out = std::array{(r11 * xprime) + (r21 * yprime) + (r31 * zprime), + (r12 * xprime) + (r22 * yprime) + (r32 * zprime), + (r13 * xprime) + (r23 * yprime) + (r33 * zprime)}; assert_testmodeonly(std::fabs(vec_len(dir_out) - 1.) < 1e-10); @@ -971,7 +971,7 @@ void guttman_thermalisation(Packet &pkt) { // step 1: draw a random direction Packet pkt_copy = pkt; // phi rotation: around z-axis - const std::array random_dir = get_rand_isotropic_unitvec(); + const auto random_dir = get_rand_isotropic_unitvec(); pkt_copy.dir = random_dir; // fix new direction // step 2: move packet into the calculated direction and integrate the density diff --git a/grid.cc b/grid.cc index 2ccf146b7..5e5b87cee 100644 --- a/grid.cc +++ b/grid.cc @@ -2566,10 +2566,12 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // globals::tmin/tstart)-grid::get_cellcoordmin(cellindex, 2), cellcoordmax[2] - (initpos[2] * // globals::tmin/tstart)); printout("dir [%g, %g, %g]\n", dir[0],dir[1],dir[2]); - auto d_coordmaxboundary = - std::array{-1}; // distance to reach the cell's upper boundary on each coordinate - auto d_coordminboundary = - std::array{-1}; // distance to reach the cell's lower boundary on each coordinate + // distance to reach the cell's upper boundary on each coordinate + auto d_coordmaxboundary = std::array{-1}; + + // distance to reach the cell's lower boundary on each coordinate + auto d_coordminboundary = std::array{-1}; + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { last_cross = BOUNDARY_NONE; // handle this separately by setting d_inner and d_outer negative for invalid direction const double speed = vec_len(dir) * CLIGHT_PROP; // just in case dir is not normalised diff --git a/grid.h b/grid.h index 12c961420..3a27f51c8 100644 --- a/grid.h +++ b/grid.h @@ -48,7 +48,7 @@ struct ModelGridCell { uint_fast8_t thick = 0; }; -constexpr auto get_ngriddimensions() -> int { +consteval auto get_ngriddimensions() -> int { switch (GRID_TYPE) { case GridType::SPHERICAL1D: return 1; diff --git a/input.cc b/input.cc index 012f834d9..6d958a0f9 100644 --- a/input.cc +++ b/input.cc @@ -513,7 +513,7 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons MPI_Barrier(MPI_COMM_WORLD); MPI_Win win_alltransblock = MPI_WIN_NULL; - auto [_, my_rank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); + const auto [_, my_rank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); auto size = static_cast(my_rank_trans * sizeof(LevelTransition)); int disp_unit = sizeof(LevelTransition); @@ -1982,9 +1982,6 @@ void time_init() { // globals::ntimesteps is the number of time steps globals::timesteps.resize(globals::ntimesteps + 1); - for (auto &ts : globals::timesteps) { - ts = TimeStep{}; - } // Now set the individual time steps switch (TIMESTEP_SIZE_METHOD) { diff --git a/ltepop.cc b/ltepop.cc index 340a2d8b9..add83bc6a 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -50,8 +50,8 @@ auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const d // use Saha equation for LTE ionization balance auto phi_lte(const int element, const int ion, const int modelgridindex) -> double { const int uniqueionindex = get_uniqueionindex(element, ion); - auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; - auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; + const auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; + const auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; const auto T_e = grid::get_Te(modelgridindex); const double ionpot = epsilon(element, ion + 1, 0) - epsilon(element, ion, 0); @@ -72,8 +72,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, assert_testmodeonly(!elem_has_nlte_levels(element)); // don't use this function if the NLTE solver is active const int uniqueionindex = get_uniqueionindex(element, ion); - auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; - auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; + const auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; const auto T_e = grid::get_Te(modelgridindex); @@ -107,6 +106,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, // Y_nt should generally be higher than the Gamma term for nebular epoch if (!std::isfinite(phi) || phi == 0.) { + const auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; printout( "[fatal] phi: phi %g exceeds numerically possible range for element %d, ion %d, T_e %g ... remove higher or " "lower ionisation stages\n", diff --git a/macroatom.cc b/macroatom.cc index 398fd12fa..715da5c15 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -225,21 +225,22 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, pkt.nscatterings = 0; } -void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int element, int *const ion, int *const level, - const double rad_recomb) { +// get the level index of the lower ionisation stage after a randomly selected radiative recombination and update +// counters +[[nodiscard]] auto do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int element, const int upperion, + const int upperionlevel, const double rad_recomb) -> int { const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); - const double epsilon_current = epsilon(element, *ion, *level); - const int upperion = *ion; - const int upperionlevel = *level; + const double epsilon_current = epsilon(element, upperion, upperionlevel); // Randomly select a continuum const double targetval = rng_uniform() * rad_recomb; double rate = 0; const int nlevels = get_ionisinglevels(element, upperion - 1); - int lower = 0; - for (lower = 0; lower < nlevels; lower++) { - const double epsilon_trans = epsilon_current - epsilon(element, upperion - 1, lower); - const double R = rad_recombination_ratecoeff(T_e, nne, element, upperion, upperionlevel, lower, modelgridindex); + int lowerionlevel = 0; + for (lowerionlevel = 0; lowerionlevel < nlevels; lowerionlevel++) { + const double epsilon_trans = epsilon_current - epsilon(element, upperion - 1, lowerionlevel); + const double R = + rad_recombination_ratecoeff(T_e, nne, element, upperion, upperionlevel, lowerionlevel, modelgridindex); rate += R * epsilon_trans; @@ -252,20 +253,16 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele "%s: From Z=%d ionstage %d level %d, could not select lower level to recombine to. targetval %g * rad_recomb " "%g >= " "rate %g", - __func__, get_atomicnumber(element), get_ionstage(element, *ion), *level, targetval, rad_recomb, rate); + __func__, get_atomicnumber(element), get_ionstage(element, upperion), upperionlevel, targetval, rad_recomb, + rate); std::abort(); } // set the new state - *ion = upperion - 1; - *level = lower; + const int lowerion = upperion - 1; - pkt.nu_cmf = select_continuum_nu(element, upperion - 1, lower, upperionlevel, T_e); + pkt.nu_cmf = select_continuum_nu(element, upperion - 1, lowerionlevel, upperionlevel, T_e); - if (!std::isfinite(pkt.nu_cmf)) { - printout("[fatal] rad recombination of MA: selected frequency not finite ... abort\n"); - std::abort(); - } stats::increment(stats::COUNTER_MA_STAT_DEACTIVATION_FB); stats::increment(stats::COUNTER_INTERACTIONS); pkt.last_event = 2; @@ -279,31 +276,32 @@ void do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int ele } pkt.next_trans = -1; // continuum transition, no restrictions for further line interactions - pkt.emissiontype = get_emtype_continuum(element, *ion, lower, upperionlevel); + pkt.emissiontype = get_emtype_continuum(element, lowerion, lowerionlevel, upperionlevel); pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; pkt.nscatterings = 0; + return lowerionlevel; } -void do_macroatom_ionisation(const int modelgridindex, const int element, int *const ion, int *const level, - const double epsilon_current, const double internal_up_higher) { +// get the level index of the upper ionisation stage after randomly-selected photoionisation or thermal collisional +// ionisation and update counters +[[nodiscard]] auto do_macroatom_ionisation(const int modelgridindex, const int element, const int ion, const int level, + const double epsilon_current, const double internal_up_higher) -> int { const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); // Randomly select the occuring transition const double targetrate = rng_uniform() * internal_up_higher; double rate = 0.; - const int nphixstargets = get_nphixstargets(element, *ion, *level); + const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - const double epsilon_trans = get_phixs_threshold(element, *ion, *level, phixstargetindex); - const double R = get_corrphotoioncoeff(element, *ion, *level, phixstargetindex, modelgridindex); - const double C = col_ionization_ratecoeff(T_e, nne, element, *ion, *level, phixstargetindex, epsilon_trans); + const double epsilon_trans = get_phixs_threshold(element, ion, level, phixstargetindex); + const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); + const double C = col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); rate += (R + C) * epsilon_current; if (rate > targetrate) { // set the macroatom's new state - *level = get_phixsupperlevel(element, *ion, *level, phixstargetindex); - *ion += 1; - return; + return get_phixsupperlevel(element, ion, level, phixstargetindex); } } @@ -468,7 +466,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); } - do_macroatom_radrecomb(pkt, modelgridindex, element, &ion, &level, processrates[MA_ACTION_RADRECOMB]); + level = do_macroatom_radrecomb(pkt, modelgridindex, element, ion, level, processrates[MA_ACTION_RADRECOMB]); + ion -= 1; end_packet = true; break; } @@ -578,8 +577,9 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); } - do_macroatom_ionisation(modelgridindex, element, &ion, &level, epsilon_current, - processrates[MA_ACTION_INTERNALUPHIGHER]); + level = do_macroatom_ionisation(modelgridindex, element, ion, level, epsilon_current, + processrates[MA_ACTION_INTERNALUPHIGHER]); + ion += 1; if constexpr (TRACK_ION_STATS) { stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); @@ -884,8 +884,8 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e const double eoverkt = epsilon_trans / (KB * T_e); // Van-Regemorter formula, Mihalas (1978), eq.5-75, p.133 - const double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> n'l' - // and 0.7 for transitions nl -> nl' + constexpr double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> + // n'l' and 0.7 for transitions nl -> nl' // test = 0.276 * exp(fac1) * gsl_sf_expint_E1(fac1); // crude approximation to the already crude Van-Regemorter formula @@ -918,14 +918,13 @@ auto col_excitation_ratecoeff(const float T_e, const float nne, const int elemen const int uptransindex, const double epsilon_trans, const double lowerstatweight) -> double { // assert_testmodeonly(i < get_nuptrans(element, ion, lower)); - double C = 0.; const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; const double eoverkt = epsilon_trans / (KB * T_e); if (coll_strength < 0) { const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; - if (!forbidden) // alternative: (coll_strength > -1.5) i.e. to catch -1 - { + if (!forbidden) { + // alternative condition: (coll_strength > -1.5) i.e. to catch -1 const double trans_osc_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; // permitted E1 electric dipole transitions @@ -935,28 +934,27 @@ auto col_excitation_ratecoeff(const float T_e, const float nne, const int elemen // osc_strength(element,ion,upper,lower); // Van-Regemorter formula, Mihalas (1978), eq.5-75, p.133 - const double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> n'l' - // and 0.7 for transitions nl -> nl' - // test = 0.276 * exp(eoverkt) * gsl_sf_expint_E1(eoverkt); + constexpr double g_bar = 0.2; // this should be read in from transitions data: it is 0.2 for transitions nl -> + // n'l' and 0.7 for transitions nl -> nl' + // test = 0.276 * std::exp(eoverkt) * gsl_sf_expint_E1(eoverkt); // crude approximation to the already crude Van-Regemorter formula - const double exp_eoverkt = exp(eoverkt); + const double exp_eoverkt = std::exp(eoverkt); const double test = 0.276 * exp_eoverkt * (-EULERGAMMA - std::log(eoverkt)); const double Gamma = g_bar > test ? g_bar : test; - C = C_0 * nne * std::sqrt(T_e) * 14.51039491 * trans_osc_strength * pow(H_ionpot / epsilon_trans, 2) * eoverkt / - exp_eoverkt * Gamma; - } else // alterative: (coll_strength > -3.5) to catch -2 or -3 - { - // forbidden transitions: magnetic dipole, electric quadropole... - // Axelrod's approximation (thesis 1980) - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].targetlevelindex; - const double upperstatweight = stat_weight(element, ion, upper); - C = nne * 8.629e-6 * 0.01 * std::exp(-eoverkt) * upperstatweight / std::sqrt(T_e); + return C_0 * nne * std::sqrt(T_e) * 14.51039491 * trans_osc_strength * pow(H_ionpot / epsilon_trans, 2) * + eoverkt / exp_eoverkt * Gamma; } - } else { - // from Osterbrock and Ferland, p51 - C = nne * 8.629e-6 * coll_strength * std::exp(-eoverkt) / lowerstatweight / std::sqrt(T_e); + + // alterative condition: (coll_strength > -3.5) to catch -2 or -3 + + // forbidden transitions: magnetic dipole, electric quadropole... + // Axelrod's approximation (thesis 1980) + const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].targetlevelindex; + const double upperstatweight = stat_weight(element, ion, upper); + return nne * 8.629e-6 * 0.01 * std::exp(-eoverkt) * upperstatweight / std::sqrt(T_e); } - return C; + // from Osterbrock and Ferland, p51 + return nne * 8.629e-6 * coll_strength * std::exp(-eoverkt) / lowerstatweight / std::sqrt(T_e); } diff --git a/nltepop.cc b/nltepop.cc index 5c85a5554..37ee5f601 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "artisoptions.h" @@ -32,27 +33,6 @@ FILE *nlte_file{}; // can save memory by using a combined rate matrix at the cost of diagnostic information constexpr bool individual_process_matricies = true; -// the backing storage for the gsl matrices -thread_local std::vector vec_rate_matrix; -thread_local std::vector vec_rate_matrix_rad_bb; -thread_local std::vector vec_rate_matrix_coll_bb; -thread_local std::vector vec_rate_matrix_ntcoll_bb; -thread_local std::vector vec_rate_matrix_rad_bf; -thread_local std::vector vec_rate_matrix_coll_bf; -thread_local std::vector vec_rate_matrix_ntcoll_bf; - -thread_local std::vector vec_rate_matrix_LU_decomp; - -// backing storage for gsl vectors -thread_local std::vector vec_balance_vector; -thread_local std::vector vec_pop_norm_factor_vec; -thread_local std::vector vec_pop_vec; -thread_local std::vector vec_x; -thread_local std::vector vec_permutation; -thread_local std::vector vec_work_vector; -thread_local std::vector vec_x_best; -thread_local std::vector vec_residual_vector; - // this is the index for the NLTE solver that is handling all ions of a single element // This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements auto get_nlte_vector_index(const int element, const int ion, const int level) -> int { @@ -68,17 +48,17 @@ auto get_nlte_vector_index(const int element, const int ion, const int level) -> return level_index; } -void get_ion_level_of_nlte_vector_index(const int index, const int element, int *const ion, int *const level) { +[[nodiscard]] auto get_ion_level_of_nlte_vector_index(const int index, const int element) -> std::tuple { // this could easily be optimized if need be for (int dion = 0; dion < get_nions(element); dion++) { for (int dlevel = 0; dlevel < get_nlevels(element, dion); dlevel++) { if (get_nlte_vector_index(element, dion, dlevel) == index) { - *ion = dion; - *level = dlevel; - return; + return {dion, dlevel}; } } } + assert_always(false); + return {-1, -1}; } void eliminate_nlte_matrix_rowcol(const int index, const int gs_index, gsl_matrix *rate_matrix, @@ -119,9 +99,7 @@ void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector * const double element_value = fabs(gsl_matrix_get(rate_matrix, row, index)); col_max = std::max(element_value, col_max); } - int ion = -1; - int level = -1; - get_ion_level_of_nlte_vector_index(index, element, &ion, &level); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(index, element); // printout("index%4d (ionstage%2d level%4d) row_max %.1e col_max %.1e ", // index,get_ionstage(element,ion),level,row_max,col_max); @@ -141,8 +119,9 @@ void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector * } } -auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, const gsl_vector *popvec, - const bool into_level, const bool only_levels_below, const bool only_levels_above) -> double { +[[nodiscard]] auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, const gsl_vector *popvec, + const bool into_level, const bool only_levels_below, + const bool only_levels_above) -> double { double total_rate = 0.; assert_always(!only_levels_below || !only_levels_above); @@ -358,9 +337,7 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e if (index == selected_index) { continue; } - int ion = -1; - int level = -1; - get_ion_level_of_nlte_vector_index(index, element, &ion, &level); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(index, element); const int ionstage = get_ionstage(element, ion); // in means populating the selected level, out means depopulating the selected level const double pop = gsl_vector_get(popvec, index); @@ -430,7 +407,7 @@ auto get_element_superlevelpartfuncs(const int modelgridindex, const int element return superlevel_partfuncs; } -auto get_element_nlte_dimension(const int element) -> int { +[[nodiscard]] auto get_element_nlte_dimension(const int element) -> int { int nlte_dimension = 0; const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -448,7 +425,7 @@ auto get_element_nlte_dimension(const int element) -> int { } // get the maximum NLTE dimension for any of the included elements -auto get_max_nlte_dimension() { +[[nodiscard]] auto get_max_nlte_dimension() { int max_nlte_dimension = 0; for (int element = 0; element < get_nelements(); element++) { max_nlte_dimension = std::max(max_nlte_dimension, get_element_nlte_dimension(element)); @@ -632,9 +609,7 @@ void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_m // TODO: consider replacing normalisation by LTE populations with // GSL's gsl_linalg_balance_matrix(gsl_matrix * A, gsl_vector * D) function instead for (size_t column = 0; column < nlte_dimension; column++) { - int ion = -1; - int level = -1; - get_ion_level_of_nlte_vector_index(column, element, &ion, &level); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(column, element); gsl_vector_set(pop_norm_factor_vec, column, calculate_levelpop_lte(modelgridindex, element, ion, level)); @@ -667,16 +642,13 @@ void set_element_pops_lte(const int modelgridindex, const int element) { set_groundlevelpops(modelgridindex, element, grid::get_nne(modelgridindex), true); } -auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { +[[nodiscard]] auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { size_t const n = LU->size1; - bool is_singular = false; for (size_t i = 0; i < n; i++) { const double u = gsl_matrix_get(LU, i, i); if (u == 0) { - int ion = -1; - int level = -1; - get_ion_level_of_nlte_vector_index(i, element, &ion, &level); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(i, element); if (is_nlte(element, ion, level)) { printout("NLTE disconnected level: Z=%d ionstage %d level %d\n", get_atomicnumber(element), get_ionstage(element, ion), level); @@ -684,33 +656,38 @@ auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { printout("NLTE disconnected superlevel: Z=%d ionstage %d\n", get_atomicnumber(element), get_ionstage(element, ion)); } - is_singular = true; + return true; } } - return is_singular; + return false; } // solve rate_matrix * x = balance_vector, // then popvec[i] = x[i] / pop_norm_factor_vec[i] auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, - gsl_vector *popvec, const gsl_vector *pop_normfactor_vec) -> bool { + gsl_vector *popvec, const gsl_vector *pop_normfactor_vec, + const int max_nlte_dimension) -> bool { bool completed_solution = false; const size_t nlte_dimension = balance_vector->size; assert_always(pop_normfactor_vec->size == nlte_dimension); assert_always(rate_matrix->size1 == nlte_dimension); assert_always(rate_matrix->size2 == nlte_dimension); - vec_x.resize(vec_pop_norm_factor_vec.size()); + // backing storage for gsl vectors + THREADLOCALONHOST std::vector vec_x; + vec_x.resize(max_nlte_dimension); gsl_vector x = gsl_vector_view_array(vec_x.data(), nlte_dimension).vector; - vec_rate_matrix_LU_decomp.resize(vec_rate_matrix.size()); + THREADLOCALONHOST std::vector vec_rate_matrix_LU_decomp; + vec_rate_matrix_LU_decomp.resize(max_nlte_dimension * max_nlte_dimension); // make a copy of the rate matrix for the LU decomp gsl_matrix rate_matrix_LU_decomp = gsl_matrix_view_array(vec_rate_matrix_LU_decomp.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_memcpy(&rate_matrix_LU_decomp, rate_matrix); - vec_permutation.resize(vec_pop_norm_factor_vec.size()); + THREADLOCALONHOST std::vector vec_permutation; + vec_permutation.resize(max_nlte_dimension); gsl_permutation p{.size = nlte_dimension, .data = vec_permutation.data()}; int s = 0; // sign of the transformation @@ -731,18 +708,20 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons // gsl_linalg_HH_solve (&m.matrix, &b.vector, x); const double TOLERANCE = 1e-40; - - vec_work_vector.resize(vec_pop_norm_factor_vec.size()); - gsl_vector gsl_work_vector = gsl_vector_view_array(vec_work_vector.data(), nlte_dimension).vector; + THREADLOCALONHOST std::vector vec_work; + vec_work.resize(max_nlte_dimension); + gsl_vector gsl_work_vector = gsl_vector_view_array(vec_work.data(), nlte_dimension).vector; double error_best = -1.; // population solution vector with lowest error - vec_x_best.resize(vec_pop_norm_factor_vec.size()); - gsl_vector x_best = gsl_vector_view_array(vec_x_best.data(), nlte_dimension).vector; + THREADLOCALONHOST std::vector vec_x_best; + vec_x_best.resize(max_nlte_dimension); + gsl_vector gsl_x_best = gsl_vector_view_array(vec_x_best.data(), nlte_dimension).vector; - vec_residual_vector.resize(vec_pop_norm_factor_vec.size()); - gsl_vector residual_vector = gsl_vector_view_array(vec_residual_vector.data(), nlte_dimension).vector; + THREADLOCALONHOST std::vector vec_residual; + vec_residual.resize(max_nlte_dimension); + gsl_vector gsl_vec_residual = gsl_vector_view_array(vec_residual.data(), nlte_dimension).vector; int iteration = 0; for (iteration = 0; iteration < 10; iteration++) { @@ -750,13 +729,13 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons gsl_linalg_LU_refine(rate_matrix, &rate_matrix_LU_decomp, &p, balance_vector, &x, &gsl_work_vector); } - gsl_vector_memcpy(&residual_vector, balance_vector); - gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, &x, -1.0, &residual_vector); // calculate Ax - b = residual + gsl_vector_memcpy(&gsl_vec_residual, balance_vector); + gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, &x, -1.0, &gsl_vec_residual); // calculate Ax - b = residual const double error = fabs(gsl_vector_get( - &residual_vector, gsl_blas_idamax(&residual_vector))); // value of the largest absolute residual + &gsl_vec_residual, gsl_blas_idamax(&gsl_vec_residual))); // value of the largest absolute residual if (error < error_best || error_best < 0.) { - gsl_vector_memcpy(&x_best, &x); + gsl_vector_memcpy(&gsl_x_best, &x); error_best = error; } // printout("Linear algebra solver iteration %d has a maximum residual of %g\n",iteration,error); @@ -774,7 +753,7 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons iteration, error_best); } - gsl_vector_memcpy(&x, &x_best); + gsl_vector_memcpy(&x, &gsl_x_best); } // get the real populations using the x vector and the normalisation factors @@ -787,9 +766,7 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons gsl_vector_const_view row_view = gsl_matrix_const_row(rate_matrix, row); gsl_blas_ddot(&row_view.vector, &x, &recovered_balance_vector_elem); - int ion = 0; - int level = 0; - get_ion_level_of_nlte_vector_index(row, element, &ion, &level); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(row, element); // printout("index %4d (ionstage %d level%4d): residual %+.2e recovered balance: %+.2e normed pop %.2e pop %.2e // departure ratio %.4f\n", @@ -858,6 +835,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const auto max_nlte_dimension = get_max_nlte_dimension(); + THREADLOCALONHOST std::vector vec_rate_matrix; vec_rate_matrix.resize(max_nlte_dimension * max_nlte_dimension); auto rate_matrix = gsl_matrix_view_array(vec_rate_matrix.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix, 0.); @@ -869,6 +847,12 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const gsl_matrix rate_matrix_coll_bf; gsl_matrix rate_matrix_ntcoll_bf; + THREADLOCALONHOST std::vector vec_rate_matrix_rad_bb; + THREADLOCALONHOST std::vector vec_rate_matrix_coll_bb; + THREADLOCALONHOST std::vector vec_rate_matrix_ntcoll_bb; + THREADLOCALONHOST std::vector vec_rate_matrix_rad_bf; + THREADLOCALONHOST std::vector vec_rate_matrix_coll_bf; + THREADLOCALONHOST std::vector vec_rate_matrix_ntcoll_bf; if constexpr (individual_process_matricies) { vec_rate_matrix_rad_bb.resize(max_nlte_dimension * max_nlte_dimension); rate_matrix_rad_bb = gsl_matrix_view_array(vec_rate_matrix_rad_bb.data(), nlte_dimension, nlte_dimension).matrix; @@ -912,12 +896,10 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // printout(" %d", ionstage); const int nlevels = get_nlevels(element, ion); - const int nlevels_nlte = get_nlevels_nlte(element, ion); + const int nlevels_nlte = get_nlevels_nlte(element, ion); // does not count the ground state! auto s_renorm = std::vector(nlevels); - for (int level = 0; level <= nlevels_nlte; level++) { - s_renorm[level] = 1.; - } + std::fill_n(s_renorm.begin(), nlevels_nlte + 1, 1.); for (int level = (nlevels_nlte + 1); level < nlevels; level++) { s_renorm[level] = superlevel_boltzmann(modelgridindex, element, ion, level) / superlevel_partfunc[ion]; @@ -951,6 +933,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const gsl_vector_view first_row_view = gsl_matrix_row(&rate_matrix, 0); gsl_vector_set_all(&first_row_view.vector, 1.0); + THREADLOCALONHOST std::vector vec_balance_vector; vec_balance_vector.resize(max_nlte_dimension); auto balance_vector = gsl_vector_view_array(vec_balance_vector.data(), nlte_dimension).vector; gsl_vector_set_all(&balance_vector, 0.); @@ -978,6 +961,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // calculate the normalisation factors and apply them to the matrix // columns and balance vector elements + THREADLOCALONHOST std::vector vec_pop_norm_factor_vec; vec_pop_norm_factor_vec.resize(max_nlte_dimension); auto pop_norm_factor_vec = gsl_vector_view_array(vec_pop_norm_factor_vec.data(), nlte_dimension).vector; gsl_vector_set_all(&pop_norm_factor_vec, 1.0); @@ -1005,12 +989,12 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // filter_nlte_matrix(element, rate_matrix, balance_vector, pop_norm_factor_vec); // the true population densities - - vec_pop_vec.resize(max_nlte_dimension); - auto popvec = gsl_vector_view_array(vec_pop_vec.data(), nlte_dimension).vector; + THREADLOCALONHOST std::vector vec_pop; + vec_pop.resize(max_nlte_dimension); + auto popvec = gsl_vector_view_array(vec_pop.data(), nlte_dimension).vector; const bool matrix_solve_success = - nltepop_matrix_solve(element, &rate_matrix, &balance_vector, &popvec, &pop_norm_factor_vec); + nltepop_matrix_solve(element, &rate_matrix, &balance_vector, &popvec, &pop_norm_factor_vec, max_nlte_dimension); if (!matrix_solve_success) { printout( diff --git a/nonthermal.cc b/nonthermal.cc index af6e32722..29e953f6c 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -109,20 +109,55 @@ std::vector colliondata; FILE *nonthermalfile{}; bool nonthermal_initialized = false; -gsl_vector *envec; // energy grid on which solution is sampled -gsl_vector *logenvec; // log of envec -gsl_vector *sourcevec; // samples of the source function (energy distribution of deposited energy) +constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); + +// energy grid on which solution is sampled +constexpr auto engrid(int index) -> double { return SF_EMIN + (index * DELTA_E); } + +const auto logengrid = []() { + std::vector logengrid(SFPTS); + for (int i = 0; i < SFPTS; i++) { + logengrid[i] = std::log(engrid(i)); + } + return logengrid; +}(); + +// samples of the source function (energy distribution of deposited energy) +constexpr auto sourcevec(const int index) { + assert_testmodeonly(index >= 0 && index < SFPTS); + + // spread the source over some energy width + constexpr int source_spread_pts = static_cast(SFPTS * 0.03333) + 1; + constexpr double source_spread_en = source_spread_pts * DELTA_E; + constexpr int sourcestartindex = SFPTS - source_spread_pts; -// Samples of the Spencer-Fano solution function for the current cell being worked on. Multiply by energy to get -// non-thermal electron number flux. y(E) * dE is the flux of electrons with energy in the range (E, E + dE) in units of -// particles/cm2/s. y has units of particles/cm2/s/eV -thread_local std::array yfunc{}; + return (index < sourcestartindex) ? 0. : 1. / source_spread_en; + + // or put all of the source into one point at SF_EMAX + // return (index < SFPTS - 1) ? 0. : 1. / DELTA_E; + // so that E_init_ev = SF_EMAX; +}; // the energy injection rate density (integral of E * S(e) dE) in eV/s/cm3 that the Spencer-Fano equation is solved for. // This is arbitrary and and the solution will be scaled to match the actual energy deposition rate density. -double E_init_ev = 0; +constexpr double E_init_ev = []() { + double integral = 0.; + for (int s = 0; s < SFPTS; s++) { + integral += sourcevec(s) * DELTA_E * engrid(s); + } + return integral; +}(); -constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); +// rhs is the constant term (not dependent on y func) in each equation +constexpr auto rhsvec = []() { + std::array rhsvec{}; + double source_integral_to_SF_EMAX = 0.; + for (int i = SFPTS - 1; i >= 0; i--) { + rhsvec[i] = source_integral_to_SF_EMAX * DELTA_E; + source_integral_to_SF_EMAX += sourcevec(i); + } + return rhsvec; +}(); // Monte Carlo result - compare to analytical expectation double nt_energy_deposited = 0; @@ -133,9 +168,6 @@ struct NonThermalExcitation { int lineindex; }; -// temporary storage of full excitation list for current cell before possible truncation and copy to node-shared memory -thread_local std::vector tmp_excitation_list; - // pointer to either local or node-shared memory excitation list of all cells NonThermalExcitation *excitations_list_all_cells{}; @@ -473,6 +505,8 @@ void read_collion_data() { } auto get_possible_nt_excitation_count() -> int { + // count the number of excitation transitions that pass the MAXNLEVELS_LOWER and MAXNLEVELS_UPPER conditions + // this count might be higher than the number of stored ratecoeffs due to the MAX_NT_EXCITATIONS_STORED limit int ntexcitationcount = 0; for (int element = 0; element < get_nelements(); element++) { for (int ion = 0; ion < get_nions(element); ion++) { @@ -511,7 +545,7 @@ void zero_all_effionpot(const int modelgridindex) { auto get_energyindex_ev_lteq(const double energy_ev) -> int // finds the highest energy point <= energy_ev { - const int index = floor((energy_ev - SF_EMIN) / DELTA_E); + const int index = std::floor((energy_ev - SF_EMIN) / DELTA_E); if (index < 0) { return 0; @@ -525,7 +559,7 @@ auto get_energyindex_ev_lteq(const double energy_ev) -> int auto get_energyindex_ev_gteq(const double energy_ev) -> int // finds the highest energy point <= energy_ev { - const int index = ceil((energy_ev - SF_EMIN) / DELTA_E); + const int index = std::ceil((energy_ev - SF_EMIN) / DELTA_E); if (index < 0) { return 0; @@ -538,7 +572,7 @@ auto get_energyindex_ev_gteq(const double energy_ev) -> int // interpolate the y flux values to get the value at a given energy // y has units of particles / cm2 / s / eV -auto get_y(const double energy_ev) -> double { +auto get_y(const std::array &yfunc, const double energy_ev) -> double { if (energy_ev <= 0) { return 0.; } @@ -554,8 +588,8 @@ auto get_y(const double energy_ev) -> double { if (index >= SFPTS - 1) { return 0.; } - const double enbelow = gsl_vector_get(envec, index); - const double enabove = gsl_vector_get(envec, index + 1); + const double enbelow = engrid(index); + const double enabove = engrid(index + 1); const double ybelow = yfunc[index]; const double yabove = yfunc[index + 1]; const double x = (energy_ev - enbelow) / (enabove - enbelow); @@ -565,7 +599,8 @@ auto get_y(const double energy_ev) -> double { // return yfunc[index]; } -void nt_write_to_file(const int modelgridindex, const int timestep, const int iteration) { +void nt_write_to_file(const int modelgridindex, const int timestep, const int iteration, + const std::array &yfunc) { #ifdef _OPENMP #pragma omp critical(nonthermal_out_file) { @@ -595,8 +630,8 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it #endif for (int s = 0; s < SFPTS; s++) { - fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, gsl_vector_get(envec, s), - gsl_vector_get(sourcevec, s), yscalefactor * yfunc[s]); + fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, engrid(s), sourcevec(s), + yscalefactor * yfunc[s]); } fflush(nonthermalfile); #ifdef _OPENMP @@ -606,14 +641,11 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it // xs_vec will be set with impact ionization cross sections for E > ionpot_ev (and zeros below this energy) // returns the index of the first energy point >= ionpot_ev -auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &colliondata) -> int { +auto get_xs_ionization_vector(std::array &xs_vec, const collionrow &colliondata) -> int { const double ionpot_ev = colliondata.ionpot_ev; const int startindex = get_energyindex_ev_gteq(ionpot_ev); - // en points for which en < ionpot - for (int i = 0; i < startindex; i++) { - gsl_vector_set(xs_vec, i, 0.); - } + std::fill_n(xs_vec.begin(), startindex, 0.); const double A = colliondata.A; const double B = colliondata.B; @@ -621,10 +653,10 @@ auto get_xs_ionization_vector(gsl_vector *const xs_vec, const collionrow &collio const double D = colliondata.D; for (int i = startindex; i < SFPTS; i++) { - const double u = gsl_vector_get(envec, i) / ionpot_ev; + const double u = engrid(i) / ionpot_ev; const double xs_ioniz = 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); - gsl_vector_set(xs_vec, i, xs_ioniz); + xs_vec[i] = xs_ioniz; } return startindex; @@ -684,12 +716,12 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, // permitted E1 electric dipole transitions const double U = energy / epsilon_trans; - // const double g_bar = 0.2; - const double A = 0.28; - const double B = 0.15; + // constexpr double g_bar = 0.2; + constexpr double A = 0.28; + constexpr double B = 0.15; const double g_bar = (A * log(U)) + B; - const double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) + constexpr double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) // Eq 4 of Mewe 1972, possibly from Seaton 1962? return prefactor * A_naught_squared * pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength * g_bar / U; } @@ -708,12 +740,12 @@ constexpr auto electron_loss_rate(const double energy, const double nne) -> doub // normally set to 1.0, but Shingles et al. (2021) boosted this to increase heating constexpr double boostfactor = 1.; - const double omegap = sqrt(4 * PI * nne * pow(QE, 2) / ME); + const double omegap = std::sqrt(4 * PI * nne * pow(QE, 2) / ME); const double zetae = H * omegap / 2 / PI; if (energy > 14 * EV) { return boostfactor * nne * 2 * PI * pow(QE, 4) / energy * log(2 * energy / zetae); } - const double v = sqrt(2 * energy / ME); + const double v = std::sqrt(2 * energy / ME); return boostfactor * nne * 2 * PI * pow(QE, 4) / energy * log(ME * pow(v, 3) / (EULERGAMMA * pow(QE, 2) * omegap)); } @@ -739,7 +771,7 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col // Kozma & Fransson equation 6. // Something related to a number of electrons, needed to calculate the heating fraction in equation 3 // not valid for energy > SF_EMIN -auto N_e(const int modelgridindex, const double energy) -> double { +auto N_e(const int modelgridindex, const double energy, const std::array &yfunc) -> double { const double energy_ev = energy / EV; const double tot_nion = get_nnion_tot(modelgridindex); double N_e = 0.; @@ -775,7 +807,7 @@ auto N_e(const int modelgridindex, const double energy) -> double { } const double epsilon_trans = epsilon(element, ion, upper) - epsilon_lower; const double epsilon_trans_ev = epsilon_trans / EV; - N_e_ion += (nnlevel / nnion) * get_y(energy_ev + epsilon_trans_ev) * + N_e_ion += (nnlevel / nnion) * get_y(yfunc, energy_ev + epsilon_trans_ev) * xs_excitation(element, ion, lower, t, epsilon_trans, statweight_lower, energy + epsilon_trans); } } @@ -792,20 +824,18 @@ auto N_e(const int modelgridindex, const double energy) -> double { // integral from ionpot up to lambda for (int i = integral1startindex; i <= integral1stopindex; i++) { - const double endash = gsl_vector_get(envec, i); - const double delta_endash = DELTA_E; + const double endash = engrid(i); - N_e_ion += get_y(energy_ev + endash) * xs_impactionization(energy_ev + endash, collionrow) * - Psecondary(energy_ev + endash, endash, ionpot_ev, J) * delta_endash; + N_e_ion += get_y(yfunc, energy_ev + endash) * xs_impactionization(energy_ev + endash, collionrow) * + Psecondary(energy_ev + endash, endash, ionpot_ev, J) * DELTA_E; } // integral from 2E + I up to E_max const int integral2startindex = get_energyindex_ev_lteq((2 * energy_ev) + ionpot_ev); for (int i = integral2startindex; i < SFPTS; i++) { - const double endash = gsl_vector_get(envec, i); - const double delta_endash = DELTA_E; + const double endash = engrid(i); N_e_ion += yfunc[i] * xs_impactionization(endash, collionrow) * - Psecondary(endash, energy_ev + ionpot_ev, ionpot_ev, J) * delta_endash; + Psecondary(endash, energy_ev + ionpot_ev, ionpot_ev, J) * DELTA_E; } } } @@ -815,7 +845,7 @@ auto N_e(const int modelgridindex, const double energy) -> double { } // source term, should be zero at the low end anyway - N_e += gsl_vector_get(sourcevec, get_energyindex_ev_lteq(energy_ev)); + N_e += sourcevec(get_energyindex_ev_lteq(energy_ev)); assert_always(std::isfinite(N_e)); return N_e; @@ -823,7 +853,7 @@ auto N_e(const int modelgridindex, const double energy) -> double { // fraction of deposited energy that goes into heating the thermal electrons // Kozma & Fransson equation 3 -auto calculate_frac_heating(const int modelgridindex) -> float { +auto calculate_frac_heating(const int modelgridindex, const std::array &yfunc) -> float { // frac_heating multiplied by E_init, which will be divided out at the end double frac_heating_Einit = 0.; @@ -831,23 +861,23 @@ auto calculate_frac_heating(const int modelgridindex) -> float { // const float nnetot = grid::get_nnetot(modelgridindex); for (int i = 0; i < SFPTS; i++) { - const double endash = gsl_vector_get(envec, i); + const double endash = engrid(i); // first term frac_heating_Einit += yfunc[i] * (electron_loss_rate(endash * EV, nne) / EV) * DELTA_E; } // second term - frac_heating_Einit += SF_EMIN * get_y(SF_EMIN) * (electron_loss_rate(SF_EMIN * EV, nne) / EV); + frac_heating_Einit += SF_EMIN * get_y(yfunc, SF_EMIN) * (electron_loss_rate(SF_EMIN * EV, nne) / EV); double N_e_contrib = 0.; // third term (integral from zero to SF_EMIN) - const int nsteps = static_cast(ceil(SF_EMIN / DELTA_E) * 10); + const int nsteps = static_cast(std::ceil(SF_EMIN / DELTA_E) * 10); assert_always(nsteps > 0); const double delta_endash = SF_EMIN / nsteps; for (int j = 0; j < nsteps; j++) { const double endash = SF_EMIN * j / nsteps; - N_e_contrib += N_e(modelgridindex, endash * EV) * endash * delta_endash; + N_e_contrib += N_e(modelgridindex, endash * EV, yfunc) * endash * delta_endash; } frac_heating_Einit += N_e_contrib; printout(" heating N_e contrib (en < EMIN) %g nsteps %d\n", N_e_contrib / E_init_ev, nsteps); @@ -908,66 +938,51 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { } const int num_shells = electron_binding[get_atomicnumber(element) - 1].size(); - auto q = std::array < int, NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE ? 0 : 10 > {0}; + auto q = std::array{0}; if (!NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { - if (q[0] < 2) // K 1s - { - q[0]++; - } else if (q[1] < 2) // L1 2s - { - q[1]++; - } else if (q[2] < 2) // L2 2p[1/2] - { - q[2]++; - } else if (q[3] < 4) // L3 2p[3/2] - { - q[3]++; - } else if (q[4] < 2) // M1 3s - { - q[4]++; - } else if (q[5] < 2) // M2 3p[1/2] - { - q[5]++; - } else if (q[6] < 4) // M3 3p[3/2] - { - q[6]++; + if (q[0] < 2) { + q[0]++; // K 1s + } else if (q[1] < 2) { + q[1]++; // L1 2s + } else if (q[2] < 2) { + q[2]++; // L2 2p[1/2] + } else if (q[3] < 4) { + q[3]++; // L3 2p[3/2] + } else if (q[4] < 2) { + q[4]++; // M1 3s + } else if (q[5] < 2) { + q[5]++; // M2 3p[1/2] + } else if (q[6] < 4) { + q[6]++; // M3 3p[3/2] } else if (ioncharge == 0) { - if (q[9] < 2) // N1 4s - { - q[9]++; - } else if (q[7] < 4) // M4 3d[3/2] - { - q[7]++; - } else if (q[8] < 6) // M5 3d[5/2] - { - q[8]++; + if (q[9] < 2) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] } else { printout("Going beyond the 4s shell in NT calculation. Abort!\n"); std::abort(); } } else if (ioncharge == 1) { - if (q[9] < 1) // N1 4s - { - q[9]++; - } else if (q[7] < 4) // M4 3d[3/2] - { - q[7]++; - } else if (q[8] < 6) // M5 3d[5/2] - { - q[8]++; + if (q[9] < 1) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] } else { printout("Going beyond the 4s shell in NT calculation. Abort!\n"); std::abort(); } } else if (ioncharge > 1) { - if (q[7] < 4) // M4 3d[3/2] - { - q[7]++; - } else if (q[8] < 6) // M5 3d[5/2] - { - q[8]++; + if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] } else { printout("Going beyond the 4s shell in NT calculation. Abort!\n"); std::abort(); @@ -1009,8 +1024,6 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { } } total += electronsinshell / std::max(ionpot, enbinding); - - // printout("total %g\n", total); } return total; @@ -1038,21 +1051,15 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> // the fraction of deposited energy that goes into ionising electrons in a particular shell auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int element, const int ion, - const collionrow &collionrow) -> double { + const collionrow &collionrow, + const std::array &yfunc) -> double { const double nnion = get_nnion(modelgridindex, element, ion); const double ionpot_ev = collionrow.ionpot_ev; - gsl_vector *cross_section_vec = gsl_vector_alloc(SFPTS); + std::array cross_section_vec{}; get_xs_ionization_vector(cross_section_vec, collionrow); - const gsl_vector_view yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); - - double y_dot_crosssection_de = 0.; - gsl_blas_ddot(&yvecview.vector, cross_section_vec, &y_dot_crosssection_de); - gsl_vector_free(cross_section_vec); - - // or multiply the scalar result by the constant DELTA_E - y_dot_crosssection_de *= DELTA_E; + const double y_dot_crosssection_de = cblas_ddot(SFPTS, yfunc.data(), 1, cross_section_vec.data(), 1) * DELTA_E; return nnion * ionpot_ev * y_dot_crosssection_de / E_init_ev; } @@ -1068,15 +1075,18 @@ auto nt_ionization_ratecoeff_wfapprox(const int modelgridindex, const int elemen } auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion, - const bool assumeshellpotentialisvalence) -> double + const bool assumeshellpotentialisvalence, + const std::array &yfunc) -> double // Integrate the ionization cross section over the electron degradation function to get the ionization rate coefficient // i.e. multiply this by ion population to get a rate of ionizations per second // Do not call during packet propagation, as the y vector may not be in memory! // IMPORTANT: we are dividing by the shell potential, not the valence potential here! // To change this set assumeshellpotentialisvalence to true { - gsl_vector *cross_section_vec = gsl_vector_alloc(SFPTS); - gsl_vector *cross_section_vec_allshells = gsl_vector_calloc(SFPTS); + std::array cross_section_vec{}; + auto gsl_cross_section_vec = gsl_vector_view_array(cross_section_vec.data(), SFPTS).vector; + std::array cross_section_vec_allshells{}; + auto gsl_cross_section_vec_allshells = gsl_vector_view_array(cross_section_vec_allshells.data(), SFPTS).vector; const int Z = get_atomicnumber(element); const int ionstage = get_ionstage(element, ion); @@ -1096,29 +1106,23 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme assert_always(ionpot_shell >= ionpot_valence); // boost the ionization rate by assuming shell vacancy energy is used to eject valence electrons - gsl_vector_scale(cross_section_vec, ionpot_shell / ionpot_valence); + gsl_vector_scale(&gsl_cross_section_vec, ionpot_shell / ionpot_valence); } - gsl_vector_add(cross_section_vec_allshells, cross_section_vec); + gsl_vector_add(&gsl_cross_section_vec_allshells, &gsl_cross_section_vec); } } - gsl_vector_free(cross_section_vec); - - double y_dot_crosssection_de = 0.; - const auto gsl_yvec = gsl_vector_view_array(yfunc.data(), SFPTS).vector; - gsl_blas_ddot(&gsl_yvec, cross_section_vec_allshells, &y_dot_crosssection_de); - gsl_vector_free(cross_section_vec_allshells); - - y_dot_crosssection_de *= DELTA_E; + const double y_xs_de = cblas_ddot(SFPTS, yfunc.data(), 1, cross_section_vec_allshells.data(), 1) * DELTA_E; const double deposition_rate_density_ev = get_deposition_rate_density(modelgridindex) / EV; const double yscalefactor = deposition_rate_density_ev / E_init_ev; - return yscalefactor * y_dot_crosssection_de; + return yscalefactor * y_xs_de; } -void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int element, const int ion) +void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int element, const int ion, + const std::array &yfunc) // Kozma & Fransson 1992 equation 12, except modified to be a sum over all shells of an ion // the result is in ergs { @@ -1149,7 +1153,8 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen for (auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { matching_nlsubshell_count++; - const double frac_ionization_shell = calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow); + const double frac_ionization_shell = + calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); eta_sum += frac_ionization_shell; const double ionpot_shell = collionrow.ionpot_ev * EV; @@ -1250,8 +1255,8 @@ auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, con // epsilon_trans is in erg // returns the index of the first valid cross section point (en >= epsilon_trans) // all elements below this index are invalid and should not be used -auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int element, const int ion, const int lower, - const int uptransindex, const double statweight_lower, +auto get_xs_excitation_vector(std::array &xs_excitation_vec, const int element, const int ion, + const int lower, const int uptransindex, const double statweight_lower, const double epsilon_trans) -> int { const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; if (coll_strength >= 0) { @@ -1261,13 +1266,11 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele const int en_startindex = get_energyindex_ev_gteq(epsilon_trans / EV); - for (int j = 0; j < en_startindex; j++) { - gsl_vector_set(xs_excitation_vec, j, 0.); - } + std::fill_n(xs_excitation_vec.begin(), en_startindex, 0.); for (int j = en_startindex; j < SFPTS; j++) { - const double energy = gsl_vector_get(envec, j) * EV; - gsl_vector_set(xs_excitation_vec, j, constantfactor * pow(energy, -2)); + const double energy = engrid(j) * EV; + xs_excitation_vec[j] = constantfactor * pow(energy, -2); } return en_startindex; } @@ -1277,11 +1280,11 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; // permitted E1 electric dipole transitions - // const double g_bar = 0.2; - const double A = 0.28; - const double B = 0.15; + // constexpr double g_bar = 0.2; + constexpr double A = 0.28; + constexpr double B = 0.15; - const double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) + constexpr double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) const double epsilon_trans_ev = epsilon_trans / EV; // Eq 4 of Mewe 1972, possibly from Seaton 1962? @@ -1290,18 +1293,16 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele const int en_startindex = get_energyindex_ev_gteq(epsilon_trans_ev); - for (int j = 0; j < en_startindex; j++) { - gsl_vector_set(xs_excitation_vec, j, 0.); - } + std::fill_n(xs_excitation_vec.begin(), en_startindex, 0.); // U = en / epsilon // g_bar = A * log(U) + b - // xs[j] = constantfactor * g_bar / envec[j] - + // xs[j] = constantfactor * g_bar / engrid(j) + const double logepsilon = std::log(epsilon_trans_ev); for (int j = en_startindex; j < SFPTS; j++) { - const double logU = gsl_vector_get(logenvec, j) - log(epsilon_trans_ev); + const double logU = logengrid[j] - logepsilon; const double g_bar = (A * logU) + B; - gsl_vector_set(xs_excitation_vec, j, constantfactor * g_bar / gsl_vector_get(envec, j)); + xs_excitation_vec[j] = constantfactor * g_bar / engrid(j); } return en_startindex; @@ -1311,21 +1312,17 @@ auto get_xs_excitation_vector(gsl_vector *const xs_excitation_vec, const int ele // Kozma & Fransson equation 9 divided by level population and epsilon_trans // returns the rate coefficient in s^-1 divided by deposition rate density in erg/cm^3/s -auto calculate_nt_excitation_ratecoeff_perdeposition(const gsl_vector_view yvecview, const int element, const int ion, - const int lower, const int uptransindex, +auto calculate_nt_excitation_ratecoeff_perdeposition(const std::array &yvec, const int element, + const int ion, const int lower, const int uptransindex, const double statweight_lower, const double epsilon_trans) -> double { - thread_local static std::array xs_excitation_vec{}; + std::array xs_excitation_vec{}; - gsl_vector gsl_xs_excitation_vec = gsl_vector_view_array(xs_excitation_vec.data(), SFPTS).vector; - if (get_xs_excitation_vector(&gsl_xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, - epsilon_trans) >= 0) { - double y_dot_crosssection = 0.; - gsl_blas_ddot(&gsl_xs_excitation_vec, &yvecview.vector, &y_dot_crosssection); + if (get_xs_excitation_vector(xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, epsilon_trans) >= + 0) { + const double y_xs_de = cblas_ddot(SFPTS, xs_excitation_vec.data(), 1, yvec.data(), 1) * DELTA_E; - y_dot_crosssection *= DELTA_E; - - return y_dot_crosssection / E_init_ev / EV; + return y_xs_de / E_init_ev / EV; } return 0.; @@ -1411,8 +1408,8 @@ auto get_uptransindex(const int element, const int ion, const int lower, const i return -1; } -void analyse_sf_solution(const int modelgridindex, const int timestep, const bool enable_sfexcitation) { - const gsl_vector_view yvecview = gsl_vector_view_array(yfunc.data(), SFPTS); +void analyse_sf_solution(const int modelgridindex, const int timestep, const bool enable_sfexcitation, + const std::array &yfunc) { const float nne = grid::get_nne(modelgridindex); const double nntot = get_nnion_tot(modelgridindex); const double nnetot = grid::get_nnetot(modelgridindex); @@ -1420,7 +1417,11 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo double frac_excitation_total = 0.; double frac_ionization_total = 0.; - tmp_excitation_list.resize(0); + // temporary storage of the full excitation list for current cell before possible truncation and copying to + // node-shared memory + THREADLOCALONHOST std::vector tmp_excitation_list; + tmp_excitation_list.clear(); + for (int element = 0; element < get_nelements(); element++) { const int Z = get_atomicnumber(element); const int nions = get_nions(element); @@ -1441,13 +1442,13 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // printout(" nnion: %g\n", nnion); printout(" nnion/nntot: %g\n", nnion / nntot); - calculate_eff_ionpot_auger_rates(modelgridindex, element, ion); + calculate_eff_ionpot_auger_rates(modelgridindex, element, ion, yfunc); int matching_nlsubshell_count = 0; for (auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double frac_ionization_ion_shell = - calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow); + calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); frac_ionization_ion += frac_ionization_ion_shell; matching_nlsubshell_count++; printout(" shell n %d, l %d, I %5.1f eV: frac_ionization %10.4e", collionrow.n, collionrow.l, @@ -1497,7 +1498,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double epsilon_trans = epsilon(element, ion, upper) - epsilon_lower; const double ratecoeffperdeposition = calculate_nt_excitation_ratecoeff_perdeposition( - yvecview, element, ion, lower, t, statweight_lower, epsilon_trans); + yfunc, element, ion, lower, t, statweight_lower, epsilon_trans); const double frac_excitation_thistrans = nnlevel * epsilon_trans * ratecoeffperdeposition; frac_excitation_ion += frac_excitation_thistrans; @@ -1533,10 +1534,10 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo printout(" workfn approx Gamma: %9.3e\n", nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion)); printout(" SF integral Gamma: %9.3e\n", - calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, false)); + calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, false, yfunc)); printout(" SF integral(I=Iv) Gamma: %9.3e (if always use valence potential)\n", - calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, true)); + calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, true, yfunc)); printout(" ARTIS using Gamma: %9.3e\n", nt_ionization_ratecoeff(modelgridindex, element, ion)); @@ -1645,9 +1646,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo double nne_nt_max = 0.; for (int i = 0; i < SFPTS; i++) { - const double endash = gsl_vector_get(envec, i); + const double endash = engrid(i); const double delta_endash = DELTA_E; - const double oneovervelocity = sqrt(9.10938e-31 / 2 / endash / 1.60218e-19) / 100; // in sec/cm + const double oneovervelocity = std::sqrt(9.10938e-31 / 2 / endash / 1.60218e-19) / 100; // in sec/cm nne_nt_max += yscalefactor * yfunc[i] * oneovervelocity * delta_endash; } @@ -1662,7 +1663,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo printout(" nne_nt/nne < %9.3e\n", nne_nt_max / nne); // store the solution properties now while the NT spectrum is in memory (in case we free before packet prop) - nt_solution[modelgridindex].frac_heating = calculate_frac_heating(modelgridindex); + nt_solution[modelgridindex].frac_heating = calculate_frac_heating(modelgridindex, yfunc); printout(" frac_heating_tot: %g\n", nt_solution[modelgridindex].frac_heating); printout(" frac_excitation_tot: %g\n", frac_excitation_total); @@ -1675,9 +1676,10 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo nt_solution[modelgridindex].frac_heating); } -void sfmatrix_add_excitation(gsl_matrix *const sfmatrix, const int modelgridindex, const int element, const int ion) { +void sfmatrix_add_excitation(std::vector &sfmatrix, const int modelgridindex, const int element, + const int ion) { // excitation terms - gsl_vector *vec_xs_excitation_deltae = gsl_vector_alloc(SFPTS); + std::array vec_xs_excitation_deltae{}; const int nlevels_all = get_nlevels(element, ion); const int nlevels = (nlevels_all > NTEXCITATION_MAXNLEVELS_LOWER) ? NTEXCITATION_MAXNLEVELS_LOWER : nlevels_all; @@ -1702,35 +1704,34 @@ void sfmatrix_add_excitation(gsl_matrix *const sfmatrix, const int modelgridinde const int xsstartindex = get_xs_excitation_vector(vec_xs_excitation_deltae, element, ion, lower, t, statweight_lower, epsilon_trans); if (xsstartindex >= 0) { - gsl_blas_dscal(DELTA_E, vec_xs_excitation_deltae); + cblas_dscal(SFPTS, DELTA_E, vec_xs_excitation_deltae.data(), 1); for (int i = 0; i < SFPTS; i++) { - const double en = gsl_vector_get(envec, i); + const double en = engrid(i); const int stopindex = get_energyindex_ev_lteq(en + epsilon_trans_ev); const int startindex = i > xsstartindex ? i : xsstartindex; for (int j = startindex; j < stopindex; j++) { - *gsl_matrix_ptr(sfmatrix, i, j) += nnlevel * gsl_vector_get(vec_xs_excitation_deltae, j); + sfmatrix[(i * SFPTS) + j] += nnlevel * vec_xs_excitation_deltae[j]; } // do the last bit separately because we're not using the full delta_e interval const double delta_en = DELTA_E; - const double delta_en_actual = (en + epsilon_trans_ev - gsl_vector_get(envec, stopindex)); + const double delta_en_actual = (en + epsilon_trans_ev - engrid(stopindex)); - *gsl_matrix_ptr(sfmatrix, i, stopindex) += - nnlevel * gsl_vector_get(vec_xs_excitation_deltae, stopindex) * delta_en_actual / delta_en; + sfmatrix[(i * SFPTS) + stopindex] += + nnlevel * vec_xs_excitation_deltae[stopindex] * delta_en_actual / delta_en; } } } } - gsl_vector_free(vec_xs_excitation_deltae); } -void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int ionstage, const double nnion) +void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const int ionstage, const double nnion) // add the ionization terms to the Spencer-Fano matrix { - gsl_vector *const vec_xs_ionization = gsl_vector_alloc(SFPTS); + std::array vec_xs_ionization{}; for (auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double ionpot_ev = collionrow.ionpot_ev; @@ -1752,22 +1753,22 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int std::array int_eps_upper = {0}; std::array prefactors = {0}; for (int j = xsstartindex; j < SFPTS; j++) { - const double endash = gsl_vector_get(envec, j); + const double endash = engrid(j); const double epsilon_upper = std::min((endash + ionpot_ev) / 2, endash); int_eps_upper[j] = atan((epsilon_upper - ionpot_ev) / J); - prefactors[j] = gsl_vector_get(vec_xs_ionization, j) * nnion / atan((endash - ionpot_ev) / 2 / J); + prefactors[j] = vec_xs_ionization[j] * nnion / atan((endash - ionpot_ev) / 2 / J); } for (int i = 0; i < SFPTS; i++) { // i is the matrix row index, which corresponds to an energy E at which we are solve from y(E) - const double en = gsl_vector_get(envec, i); + const double en = engrid(i); // endash ranges from en to SF_EMAX, but skip over the zero-cross section points const int jstart = std::max(i, xsstartindex); for (int j = jstart; j < SFPTS; j++) { // j is the matrix column index which corresponds to the piece of the integral at y(E') where E' >= E and E' - // = envec(j) - const double endash = gsl_vector_get(envec, j); + // = engrid(j) + const double endash = engrid(j); // J * atan[(epsilon - ionpot_ev) / J] is the indefinite integral of 1/[1 + (epsilon - ionpot_ev)^2/ J^2] // in Kozma & Fransson 1992 equation 4 @@ -1776,7 +1777,7 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int std::max(endash - en, ionpot_ev); // and epsilon_upper = (endash + ionpot_ev) / 2; const double int_eps_lower = atan((epsilon_lower - ionpot_ev) / J); if (int_eps_lower <= int_eps_upper[j]) { - *gsl_matrix_ptr(sfmatrix, i, j) += prefactors[j] * (int_eps_upper[j] - int_eps_lower) * DELTA_E; + sfmatrix[(i * SFPTS) + j] += prefactors[j] * (int_eps_upper[j] - int_eps_lower) * DELTA_E; } } @@ -1790,7 +1791,7 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int // epsilon_lower = en + ionpot_ev; // epsilon_upper = (endash + ionpot_ev) / 2; if (int_eps_lower2 <= int_eps_upper[j]) { - *gsl_matrix_ptr(sfmatrix, i, j) -= prefactors[j] * (int_eps_upper[j] - int_eps_lower2) * DELTA_E; + sfmatrix[(i * SFPTS) + j] -= prefactors[j] * (int_eps_upper[j] - int_eps_lower2) * DELTA_E; } } } @@ -1810,74 +1811,87 @@ void sfmatrix_add_ionization(gsl_matrix *const sfmatrix, const int Z, const int } for (int i = 0; i < augerstopindex; i++) { - const double en = gsl_vector_get(envec, i); + const double en = engrid(i); const int jstart = i > xsstartindex ? i : xsstartindex; for (int j = jstart; j < SFPTS; j++) { - const double xs = gsl_vector_get(vec_xs_ionization, j); + const double xs = vec_xs_ionization[j]; if (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { const double en_boost = 1 / (1. - collionrow.prob_num_auger[0]); for (int a = 1; a <= NT_MAX_AUGER_ELECTRONS; a++) { if (en < (en_auger_ev * en_boost / a)) { - *gsl_matrix_ptr(sfmatrix, i, j) -= nnion * xs * collionrow.prob_num_auger[a] * a; + sfmatrix[(i * SFPTS) + j] -= nnion * xs * collionrow.prob_num_auger[a] * a; } } } else { assert_always(en < en_auger_ev); // printout("SFAuger E %g < en_auger_ev %g so subtracting %g from element with value %g\n", en, // en_auger_ev, nnion * xs, ij_contribution); - *gsl_matrix_ptr(sfmatrix, i, j) -= nnion * xs; // * n_auger_elec_avg; // * en_auger_ev??? + sfmatrix[(i * SFPTS) + j] -= nnion * xs; // * n_auger_elec_avg; // * en_auger_ev??? } } } } } } - gsl_vector_free(vec_xs_ionization); } -void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, std::array &yvec_arr) { - // WARNING: this assumes sfmatrix is in upper triangular form already! - const gsl_matrix *sfmatrix_LU = sfmatrix; - gsl_permutation *p = gsl_permutation_calloc(SFPTS); // identity permutation +// solve the Spencer-Fano matrix equation and return the y vector (samples of the Spencer-Fano solution function). +// Multiply y by energy interval [eV] to get non-thermal electron number flux. y(E) * dE is the flux of electrons with +// energy in the range (E, E + dE) in units of particles/cm2/s. y has units of particles/cm2/s/eV +auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array { + std::array vec_permutation{}; + gsl_permutation p{.size = SFPTS, .data = vec_permutation.data()}; + gsl_permutation_init(&p); + + const auto gsl_sfmatrix = gsl_matrix_const_view_array(sfmatrix.data(), SFPTS, SFPTS).matrix; + + // sfmatrix must be in upper triangular form + const auto &gsl_sfmatrix_LU = gsl_sfmatrix; // if the matrix is not upper triangular, then do a decomposition // printout("Doing LU decomposition of SF matrix\n"); // make a copy of the matrix for the LU decomp - // gsl_matrix *sfmatrix_LU = gsl_matrix_alloc(SFPTS, SFPTS); - // gsl_matrix_memcpy(sfmatrix_LU, sfmatrix); - // int s; //sign of the transformation - // gsl_permutation *p = gsl_permutation_alloc(SFPTS); - // gsl_linalg_LU_decomp(sfmatrix_LU, p, &s); + // std::array sfmatrix_LU{}; + // auto gsl_sfmatrix_LU = gsl_matrix_view_array(sfmatrix_LU.data(), SFPTS, SFPTS).matrix; + // gsl_matrix_memcpy(&gsl_sfmatrix_LU, &gsl_sfmatrix); + // int s{}; // sign of the transformation + // gsl_linalg_LU_decomp(&gsl_sfmatrix_LU, &p, &s); // printout("Solving SF matrix equation\n"); - gsl_vector_view yvecview = gsl_vector_view_array(yvec_arr.data(), SFPTS); - gsl_vector *yvec = &yvecview.vector; + std::array yvec_arr{}; + auto gsl_yvec = gsl_vector_view_array(yvec_arr.data(), SFPTS).vector; + + const auto gsl_rhsvec = gsl_vector_const_view_array(rhsvec.data(), SFPTS).vector; // solve matrix equation: sf_matrix * y_vec = rhsvec for yvec - gsl_linalg_LU_solve(sfmatrix_LU, p, rhsvec, yvec); + gsl_linalg_LU_solve(&gsl_sfmatrix_LU, &p, &gsl_rhsvec, &gsl_yvec); // printout("Refining solution\n"); double error_best = -1.; - gsl_vector *yvec_best = gsl_vector_alloc(SFPTS); // solution vector with lowest error - gsl_vector *gsl_work_vector = gsl_vector_calloc(SFPTS); - gsl_vector *residual_vector = gsl_vector_alloc(SFPTS); + std::array yvec_best{}; + auto gsl_yvec_best = gsl_vector_view_array(yvec_best.data(), SFPTS).vector; + std::array work_vector{}; + auto gsl_work_vector = gsl_vector_view_array(work_vector.data(), SFPTS).vector; + std::array residual_vector{}; + auto gsl_residual_vector = gsl_vector_view_array(residual_vector.data(), SFPTS).vector; + int iteration = 0; for (iteration = 0; iteration < 10; iteration++) { if (iteration > 0) { - gsl_linalg_LU_refine(sfmatrix, sfmatrix_LU, p, rhsvec, yvec, - gsl_work_vector); // first argument must be original matrix + gsl_linalg_LU_refine(&gsl_sfmatrix, &gsl_sfmatrix_LU, &p, &gsl_rhsvec, &gsl_yvec, + &gsl_work_vector); // first argument must be original matrix } // calculate Ax - b = residual - gsl_vector_memcpy(residual_vector, rhsvec); - gsl_blas_dgemv(CblasNoTrans, 1.0, sfmatrix, yvec, -1.0, residual_vector); + gsl_vector_memcpy(&gsl_residual_vector, &gsl_rhsvec); + gsl_blas_dgemv(CblasNoTrans, 1.0, &gsl_sfmatrix, &gsl_yvec, -1.0, &gsl_residual_vector); // value of the largest absolute residual - const double error = fabs(gsl_vector_get(residual_vector, gsl_blas_idamax(residual_vector))); + const double error = fabs(gsl_vector_get(&gsl_residual_vector, gsl_blas_idamax(&gsl_residual_vector))); if (error < error_best || error_best < 0.) { - gsl_vector_memcpy(yvec_best, yvec); + gsl_vector_memcpy(&gsl_yvec_best, &gsl_yvec); error_best = error; } // printout("Linear algebra solver iteration %d has a maximum residual of %g\n",iteration,error); @@ -1887,18 +1901,13 @@ void sfmatrix_solve(const gsl_matrix *sfmatrix, const gsl_vector *rhsvec, std::a printout(" SF solver LU_refine: After %d iterations, best solution vector has a max residual of %g (WARNING)\n", iteration, error_best); } - gsl_vector_memcpy(yvec, yvec_best); + gsl_vector_memcpy(&gsl_yvec, &gsl_yvec_best); } - gsl_vector_free(yvec_best); - gsl_vector_free(gsl_work_vector); - gsl_vector_free(residual_vector); - - // gsl_matrix_free(sfmatrix_LU); // if this matrix is different to sfmatrix then free it - gsl_permutation_free(p); - if (gsl_vector_isnonneg(yvec) == 0) { + if (gsl_vector_isnonneg(&gsl_yvec) == 0) { printout("solve_sfmatrix: WARNING: y function goes negative!\n"); } + return yvec_arr; } } // anonymous namespace @@ -2010,45 +2019,12 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[modelgridindex].frac_excitations_list_size = 0; } - envec = gsl_vector_calloc(SFPTS); // energy grid on which solution is sampled - logenvec = gsl_vector_calloc(SFPTS); - sourcevec = gsl_vector_calloc(SFPTS); // energy grid on which solution is sampled - - // const int source_spread_pts = ceil(SFPTS / 20); - const int source_spread_pts = ceil(SFPTS * 0.03333); // KF92 OXYGEN TEST - const double source_spread_en = source_spread_pts * DELTA_E; - const int sourcelowerindex = SFPTS - source_spread_pts; - + double sourceintegral = 0.; // integral of S(e) dE for (int s = 0; s < SFPTS; s++) { - const double energy_ev = SF_EMIN + (s * DELTA_E); - - gsl_vector_set(envec, s, energy_ev); - gsl_vector_set(logenvec, s, log(energy_ev)); - - // spread the source over some energy width - if (s < sourcelowerindex) { - gsl_vector_set(sourcevec, s, 0.); - } else { - gsl_vector_set(sourcevec, s, 1. / source_spread_en); - } + sourceintegral += sourcevec(s) * DELTA_E; } - // integrate the source vector to find the assumed injection rate - gsl_vector *integralvec = gsl_vector_alloc(SFPTS); - gsl_vector_memcpy(integralvec, sourcevec); - gsl_vector_scale(integralvec, DELTA_E); - const double sourceintegral = gsl_blas_dasum(integralvec); // integral of S(e) dE - - gsl_vector_mul(integralvec, envec); - E_init_ev = gsl_blas_dasum(integralvec); // integral of E * S(e) dE - gsl_vector_free(integralvec); - - // or put all of the source into one point at SF_EMAX - // gsl_vector_set_zero(sourcevec); - // gsl_vector_set(sourcevec, SFPTS - 1, 1 / DELTA_E); - // E_init_ev = SF_EMAX; - - printout("E_init: %14.7e eV\n", E_init_ev); + printout("E_init: %14.7e eV/s/cm3\n", E_init_ev); printout("source function integral: %14.7e\n", sourceintegral); read_collion_data(); @@ -2118,8 +2094,6 @@ void close_file() { fclose(nonthermalfile); nonthermalfile = nullptr; } - gsl_vector_free(envec); - gsl_vector_free(sourcevec); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { free(nt_solution[modelgridindex].allions); @@ -2476,26 +2450,13 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // timesteps.\n"); // } - gsl_matrix *const sfmatrix = gsl_matrix_calloc(SFPTS, SFPTS); - gsl_vector *const rhsvec = gsl_vector_calloc(SFPTS); // constant term (not dependent on y func) in each equation + THREADLOCALONHOST std::vector sfmatrix(SFPTS * SFPTS); + std::ranges::fill(sfmatrix, 0.); // loss terms and source terms for (int i = 0; i < SFPTS; i++) { - const double en = gsl_vector_get(envec, i); - - *gsl_matrix_ptr(sfmatrix, i, i) += electron_loss_rate(en * EV, nne) / EV; - - double source_integral_to_SF_EMAX{NAN}; - if (i < SFPTS - 1) { - gsl_vector_const_view source_e_to_SF_EMAX = gsl_vector_const_subvector(sourcevec, i + 1, SFPTS - i - 1); - source_integral_to_SF_EMAX = gsl_blas_dasum(&source_e_to_SF_EMAX.vector) * DELTA_E; - } else { - source_integral_to_SF_EMAX = 0; - } - - gsl_vector_set(rhsvec, i, source_integral_to_SF_EMAX); + sfmatrix[(i * SFPTS) + i] += electron_loss_rate(engrid(i) * EV, nne) / EV; } - // gsl_vector_set_all(rhsvec, 1.); // alternative if all electrons are injected at SF_EMAX if (enable_sfexcitation || enable_sfionization) { for (int element = 0; element < get_nelements(); element++) { @@ -2551,16 +2512,13 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // } // printout("\n"); - sfmatrix_solve(sfmatrix, rhsvec, yfunc); - - gsl_matrix_free(sfmatrix); - gsl_vector_free(rhsvec); + const auto yfunc = sfmatrix_solve(sfmatrix); if (timestep % 10 == 0) { - nt_write_to_file(modelgridindex, timestep, iteration); + nt_write_to_file(modelgridindex, timestep, iteration, yfunc); } - analyse_sf_solution(modelgridindex, timestep, enable_sfexcitation); + analyse_sf_solution(modelgridindex, timestep, enable_sfexcitation, yfunc); } void write_restart_data(FILE *gridsave_file) { diff --git a/rpkt.cc b/rpkt.cc index cc1b4d860..ef6f4299c 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -30,12 +30,6 @@ #include "vectors.h" #include "vpkt.h" -#ifdef GPU_ON -#define THREADLOCALONHOST -#else -#define THREADLOCALONHOST thread_local static -#endif - namespace { constexpr float expopac_lambdamin = 534.5; @@ -93,9 +87,9 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); auto pos = pkt.pos; - auto nu_rf = pkt.nu_rf; + const auto nu_rf = pkt.nu_rf; auto nu_cmf = pkt.nu_cmf; - auto e_rf = pkt.e_rf; + const auto e_rf = pkt.e_rf; auto e_cmf = pkt.e_cmf; auto prop_time = pkt.prop_time; int next_trans = pkt.next_trans; @@ -221,9 +215,9 @@ auto get_event_expansion_opacity( MacroAtomState &mastate, const double tau_rnd, const double nu_cmf_abort, const double d_nu_on_d_l, const double doppler) -> std::tuple { auto pos = pkt.pos; - auto nu_rf = pkt.nu_rf; + const auto nu_rf = pkt.nu_rf; auto nu_cmf = pkt.nu_cmf; - auto e_rf = pkt.e_rf; + const auto e_rf = pkt.e_rf; auto e_cmf = pkt.e_cmf; auto prop_time = pkt.prop_time; @@ -382,13 +376,13 @@ void electron_scatter_rpkt(Packet &pkt) { // Need to rotate Stokes Parameters in the scattering plane - auto [ref1_olddir, ref2_olddir] = meridian(old_dir_cmf); + const auto [ref1_olddir, ref2_olddir] = meridian(old_dir_cmf); // This is the i1 angle of Bulla+2015, obtained by computing the angle between the // reference axes ref1 and ref2 in the meridian frame and the corresponding axes // ref1_sc and ref2_sc in the scattering plane. It is the supplementary angle of the // scatt angle phisc chosen in the rejection technique above (phisc+i1=180 or phisc+i1=540) - const double i1 = rot_angle(old_dir_cmf, new_dir_cmf, ref1_olddir, ref2_olddir); + const double i1 = get_rot_angle(old_dir_cmf, new_dir_cmf, ref1_olddir, ref2_olddir); const double cos2i1 = cos(2 * i1); const double sin2i1 = sin(2 * i1); @@ -405,12 +399,12 @@ void electron_scatter_rpkt(Packet &pkt) { // Need to rotate Stokes Parameters out of the scattering plane to the meridian frame (Clockwise rotation of PI-i2) - auto [ref1, ref2] = meridian(new_dir_cmf); + const auto [ref1, ref2] = meridian(new_dir_cmf); // This is the i2 angle of Bulla+2015, obtained from the angle THETA between the // reference axes ref1_sc and ref2_sc in the scattering plane and ref1 and ref2 in the // meridian frame. NB: we need to add PI to transform THETA to i2 - const double i2 = PI + rot_angle(new_dir_cmf, old_dir_cmf, ref1, ref2); + const double i2 = PI + get_rot_angle(new_dir_cmf, old_dir_cmf, ref1, ref2); const double cos2i2 = cos(2 * i2); const double sin2i2 = sin(2 * i2); diff --git a/sn3d.h b/sn3d.h index 256bcb7c2..867a9ed80 100644 --- a/sn3d.h +++ b/sn3d.h @@ -16,9 +16,18 @@ #include #include +#include +#include +#include #include +#include +#include +#include #include #include +#ifndef GPU_ON +#include +#endif #include #include @@ -46,14 +55,10 @@ #include #endif -#include -#include -#include -#include -#include -#include -#ifndef GPU_ON -#include +#ifdef __NVCOMPILER_CUDA_ARCH__ +#define THREADLOCALONHOST +#else +#define THREADLOCALONHOST thread_local static #endif #include "constants.h" diff --git a/vectors.h b/vectors.h index 7a80a776d..5486046b4 100644 --- a/vectors.h +++ b/vectors.h @@ -25,7 +25,7 @@ template // get a normalized copy of vec_in [[nodiscard]] [[gnu::const]] constexpr auto vec_norm(const std::array vec_in) { const double magnitude = vec_len(vec_in); - const auto vec_out = std::array{vec_in[0] / magnitude, vec_in[1] / magnitude, vec_in[2] / magnitude}; + const std::array vec_out{vec_in[0] / magnitude, vec_in[1] / magnitude, vec_in[2] / magnitude}; assert_testmodeonly(fabs(vec_len(vec_out) - 1.) < 1.e-10); return vec_out; @@ -35,6 +35,7 @@ template template [[nodiscard]] [[gnu::const]] constexpr auto dot(const std::array x, const std::array y) -> double { + // if len(x) < len(y), the extra elements of y are ignored return std::inner_product(x.begin(), x.end(), y.begin(), 0.); } @@ -68,8 +69,8 @@ template const double fact1 = gamma_rel * (1 - (ndotv / CLIGHT)); const double fact2 = (gamma_rel - (gamma_rel * gamma_rel * ndotv / (gamma_rel + 1) / CLIGHT)) / CLIGHT; - std::array dir2{(dir1[0] - (vel[0] * fact2)) / fact1, (dir1[1] - (vel[1] * fact2)) / fact1, - (dir1[2] - (vel[2] * fact2)) / fact1}; + const auto dir2 = std::array{(dir1[0] - (vel[0] * fact2)) / fact1, (dir1[1] - (vel[1] * fact2)) / fact1, + (dir1[2] - (vel[2] * fact2)) / fact1}; return vec_norm(dir2); } @@ -119,9 +120,9 @@ template assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED < 1.); const double ndotv_on_c = dot(dir_rf, vel_rf) / CLIGHT; - double dopplerfactorsq = USE_RELATIVISTIC_DOPPLER_SHIFT - ? std::pow(1. - ndotv_on_c, 2) / (1 - (dot(vel_rf, vel_rf) / CLIGHTSQUARED)) - : (1. - 2 * ndotv_on_c); + const double dopplerfactorsq = USE_RELATIVISTIC_DOPPLER_SHIFT + ? std::pow(1. - ndotv_on_c, 2) / (1 - (dot(vel_rf, vel_rf) / CLIGHTSQUARED)) + : (1. - 2 * ndotv_on_c); assert_testmodeonly(std::isfinite(dopplerfactorsq)); assert_testmodeonly(dopplerfactorsq > 0); @@ -129,14 +130,14 @@ template return dopplerfactorsq; } -[[gnu::pure]] [[nodiscard]] constexpr auto doppler_packet_nucmf_on_nurf(std::span pos_rf, +[[gnu::pure]] [[nodiscard]] constexpr auto doppler_packet_nucmf_on_nurf(const std::span pos_rf, const std::array dir_rf, const double prop_time) -> double { return doppler_nucmf_on_nurf(dir_rf, get_velocity(pos_rf, prop_time)); } // Move a packet along a straight line (specified by current dir vector). The distance moved is in the rest frame. -constexpr auto move_pkt_withtime(std::span pos_rf, const std::array dir_rf, double &prop_time, +constexpr auto move_pkt_withtime(std::array &pos_rf, const std::array dir_rf, double &prop_time, const double nu_rf, double &nu_cmf, const double e_rf, double &e_cmf, const double distance) -> double { assert_always(distance >= 0); @@ -219,9 +220,10 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { } // Rotation angle from the scattering plane -[[nodiscard]] [[gnu::const]] constexpr auto rot_angle(const std::array n1, const std::array n2, - const std::array ref1, - const std::array ref2) -> double { +[[nodiscard]] [[gnu::const]] constexpr auto get_rot_angle(const std::array n1, + const std::array n2, + const std::array ref1, + const std::array ref2) -> double { // We need to rotate Stokes Parameters to (or from) the scattering plane from (or to) // the meridian frame such that Q=1 is in the scattering plane and along ref1 @@ -275,10 +277,10 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { const double gamma_rel = 1. / (sqrt(1 - vsqr)); - const std::array e_par{dot(e_rf, beta) * beta[0] / (vsqr), dot(e_rf, beta) * beta[1] / (vsqr), - dot(e_rf, beta) * beta[2] / (vsqr)}; + const auto e_par = std::array{dot(e_rf, beta) * beta[0] / (vsqr), dot(e_rf, beta) * beta[1] / (vsqr), + dot(e_rf, beta) * beta[2] / (vsqr)}; - const std::array e_perp{e_rf[0] - e_par[0], e_rf[1] - e_par[1], e_rf[2] - e_par[2]}; + const auto e_perp = std::array{e_rf[0] - e_par[0], e_rf[1] - e_par[1], e_rf[2] - e_par[2]}; const auto b_rf = cross_prod(n_rf, e_rf); @@ -292,9 +294,9 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { // const double v_cr_e[3] = {beta[1] * e_rf[2] - beta[2] * e_rf[1], beta[2] * e_rf[0] - beta[0] * e_rf[2], // beta[0] * e_rf[1] - beta[1] * e_rf[0]}; - auto e_cmf = std::array{e_par[0] + gamma_rel * (e_perp[0] + v_cr_b[0]), - e_par[1] + gamma_rel * (e_perp[1] + v_cr_b[1]), - e_par[2] + gamma_rel * (e_perp[2] + v_cr_b[2])}; + const auto e_cmf = std::array{e_par[0] + gamma_rel * (e_perp[0] + v_cr_b[0]), + e_par[1] + gamma_rel * (e_perp[1] + v_cr_b[1]), + e_par[2] + gamma_rel * (e_perp[2] + v_cr_b[2])}; return vec_norm(e_cmf); } diff --git a/vpkt.cc b/vpkt.cc index 17a881d50..0f32febe1 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -31,25 +31,25 @@ struct StokesParams { }; struct VSpecPol { - StokesParams flux[VMNUBINS]; + std::array flux; float lower_time{NAN}; float delta_t{NAN}; }; std::vector> vspecpol{}; -float lower_freq_vspec[VMNUBINS]; -float delta_freq_vspec[VMNUBINS]; +std::array lower_freq_vspec; +std::array delta_freq_vspec; // --------- INPUT PARAMETERS ----------- -int Nobs; // Number of observer directions -int Nspectra; // Number of virtual packet spectra per observer direction (total + elements switched off) +int Nobs = 0; // Number of observer directions +int Nspectra = 0; // Number of virtual packet spectra per observer direction (total + elements switched off) std::vector nz_obs_vpkt; std::vector phiobs; double VSPEC_TIMEMIN_input; double VSPEC_TIMEMAX_input; -int Nrange; // Number of wavelength ranges +int Nrange = 0; // Number of wavelength ranges std::vector VSPEC_NUMIN_input; std::vector VSPEC_NUMAX_input; @@ -65,15 +65,13 @@ std::ofstream vpkt_contrib_file; // --------- VPacket GRID ----------- -struct vgrid { - std::vector> flux; +struct VGrid { + std::vector> flux; double yvel{NAN}; double zvel{NAN}; }; -vgrid vgrid_i[VGRID_NY][VGRID_NZ]; -vgrid vgrid_q[VGRID_NY][VGRID_NZ]; -vgrid vgrid_u[VGRID_NY][VGRID_NZ]; +std::array, VGRID_NY> vgrid; int Nrange_grid; double tmin_grid; @@ -82,8 +80,8 @@ std::vector nu_grid_min; std::vector nu_grid_max; bool vgrid_on; -double dlogt_vspec{NAN}; -double dlognu_vspec{NAN}; +const double dlogt_vspec = (std::log(VSPEC_TIMEMAX) - std::log(VSPEC_TIMEMIN)) / VMTBINS; +const double dlognu_vspec = (std::log(VSPEC_NUMAX) - std::log(VSPEC_NUMIN)) / VMNUBINS; // Virtual packet is killed when tau reaches tau_max_vpkt for ALL the different setups // E.g. imagine that a packet in the first setup (all elements included) reaches tau = tau_max_vpkt @@ -155,9 +153,9 @@ void add_to_vpkt_grid(const Packet &vpkt, const std::array vel, const // Add contribution if (vpkt.nu_rf > nu_grid_min[wlbin] && vpkt.nu_rf < nu_grid_max[wlbin]) { - atomicadd(vgrid_i[ny][nz].flux[wlbin][obsdirindex], vpkt.stokes[0] * vpkt.e_rf); - atomicadd(vgrid_q[ny][nz].flux[wlbin][obsdirindex], vpkt.stokes[1] * vpkt.e_rf); - atomicadd(vgrid_u[ny][nz].flux[wlbin][obsdirindex], vpkt.stokes[2] * vpkt.e_rf); + atomicadd(vgrid[ny][nz].flux[wlbin][obsdirindex].i, vpkt.stokes[0] * vpkt.e_rf); + atomicadd(vgrid[ny][nz].flux[wlbin][obsdirindex].q, vpkt.stokes[1] * vpkt.e_rf); + atomicadd(vgrid[ny][nz].flux[wlbin][obsdirindex].u, vpkt.stokes[2] * vpkt.e_rf); } } @@ -195,18 +193,18 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar if (type_before_rpkt == TYPE_RPKT) { // Transform Stokes Parameters from the RF to the CMF - auto old_dir_cmf = frame_transform(pkt.dir, &Qi, &Ui, vel_vec); + const auto old_dir_cmf = frame_transform(pkt.dir, &Qi, &Ui, vel_vec); // Need to rotate Stokes Parameters in the scattering plane - auto obs_cmf = angle_ab(vpkt.dir, vel_vec); + const auto obs_cmf = angle_ab(vpkt.dir, vel_vec); - auto [ref1_old, ref2_old] = meridian(old_dir_cmf); + const auto [ref1_old, ref2_old] = meridian(old_dir_cmf); // This is the i1 angle of Bulla+2015, obtained by computing the angle between the // reference axes ref1 and ref2 in the meridian frame and the corresponding axes // ref1_sc and ref2_sc in the scattering plane. - const double i1 = rot_angle(old_dir_cmf, obs_cmf, ref1_old, ref2_old); + const double i1 = get_rot_angle(old_dir_cmf, obs_cmf, ref1_old, ref2_old); const double cos2i1 = cos(2 * i1); const double sin2i1 = sin(2 * i1); @@ -229,12 +227,12 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar // Need to rotate Stokes Parameters out of the scattering plane to the meridian frame - auto [ref1, ref2] = meridian(obs_cmf); + const auto [ref1, ref2] = meridian(obs_cmf); // This is the i2 angle of Bulla+2015, obtained from the angle THETA between the // reference axes ref1_sc and ref2_sc in the scattering plane and ref1 and ref2 in the // meridian frame. NB: we need to add PI to transform THETA to i2 - const double i2 = PI + rot_angle(obs_cmf, old_dir_cmf, ref1, ref2); + const double i2 = PI + get_rot_angle(obs_cmf, old_dir_cmf, ref1, ref2); const double cos2i2 = cos(2 * i2); const double sin2i2 = sin(2 * i2); @@ -243,7 +241,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar // Transform Stokes Parameters from the CMF to the RF - const std::array vel_rev{-vel_vec[0], -vel_vec[1], -vel_vec[2]}; + const auto vel_rev = std::array{-vel_vec[0], -vel_vec[1], -vel_vec[2]}; frame_transform(obs_cmf, &Q, &U, vel_rev); @@ -434,9 +432,6 @@ void init_vspecpol() { vspecpol[p].resize(indexmax); } - dlogt_vspec = (log(VSPEC_TIMEMAX) - log(VSPEC_TIMEMIN)) / VMTBINS; - dlognu_vspec = (log(VSPEC_NUMAX) - log(VSPEC_NUMIN)) / VMNUBINS; - for (int m = 0; m < VMNUBINS; m++) { lower_freq_vspec[m] = exp(log(VSPEC_NUMIN) + (m * (dlognu_vspec))); delta_freq_vspec[m] = exp(log(VSPEC_NUMIN) + ((m + 1) * (dlognu_vspec))) - lower_freq_vspec[m]; @@ -553,22 +548,13 @@ void init_vpkt_grid() { const double yvel = globals::vmax - ((n + 0.5) * ybin); const double zvel = globals::vmax - ((m + 0.5) * zbin); - vgrid_i[n][m].yvel = yvel; - vgrid_i[n][m].zvel = zvel; - - vgrid_q[n][m].yvel = yvel; - vgrid_q[n][m].zvel = zvel; + vgrid[n][m].yvel = yvel; + vgrid[n][m].zvel = zvel; - vgrid_u[n][m].yvel = yvel; - vgrid_u[n][m].zvel = zvel; + vgrid[n][m].flux.resize(Nrange_grid, {}); - vgrid_i[n][m].flux.resize(Nrange_grid, {}); - vgrid_q[n][m].flux.resize(Nrange_grid, {}); - vgrid_u[n][m].flux.resize(Nrange_grid, {}); for (int wlbin = 0; wlbin < Nrange_grid; wlbin++) { - vgrid_i[n][m].flux[wlbin].resize(Nobs, 0.); - vgrid_q[n][m].flux[wlbin].resize(Nobs, 0.); - vgrid_u[n][m].flux[wlbin].resize(Nobs, 0.); + vgrid[n][m].flux[wlbin].resize(Nobs, {0., 0., 0.}); } } } @@ -579,14 +565,9 @@ void write_vpkt_grid(FILE *vpkt_grid_file) { for (int wlbin = 0; wlbin < Nrange_grid; wlbin++) { for (int n = 0; n < VGRID_NY; n++) { for (int m = 0; m < VGRID_NZ; m++) { - fprintf(vpkt_grid_file, "%g ", vgrid_i[n][m].yvel); - fprintf(vpkt_grid_file, "%g ", vgrid_i[n][m].zvel); - - fprintf(vpkt_grid_file, "%g ", vgrid_i[n][m].flux[wlbin][obsdirindex]); - fprintf(vpkt_grid_file, "%g ", vgrid_q[n][m].flux[wlbin][obsdirindex]); - fprintf(vpkt_grid_file, "%g ", vgrid_u[n][m].flux[wlbin][obsdirindex]); - - fprintf(vpkt_grid_file, "\n"); + fprintf(vpkt_grid_file, "%g %g %g %g %g \n", vgrid[n][m].yvel, vgrid[n][m].zvel, + vgrid[n][m].flux[wlbin][obsdirindex].i, vgrid[n][m].flux[wlbin][obsdirindex].q, + vgrid[n][m].flux[wlbin][obsdirindex].u); } } } @@ -607,14 +588,9 @@ void read_vpkt_grid(const int my_rank, const int nts) { for (int wlbin = 0; wlbin < Nrange_grid; wlbin++) { for (int n = 0; n < VGRID_NY; n++) { for (int m = 0; m < VGRID_NZ; m++) { - assert_always(fscanf(vpkt_grid_file, "%lg ", &vgrid_i[n][m].yvel) == 1); - assert_always(fscanf(vpkt_grid_file, "%lg ", &vgrid_i[n][m].zvel) == 1); - - assert_always(fscanf(vpkt_grid_file, "%lg ", &vgrid_i[n][m].flux[wlbin][obsdirindex]) == 1); - assert_always(fscanf(vpkt_grid_file, "%lg ", &vgrid_q[n][m].flux[wlbin][obsdirindex]) == 1); - assert_always(fscanf(vpkt_grid_file, "%lg ", &vgrid_u[n][m].flux[wlbin][obsdirindex]) == 1); - - assert_always(fscanf(vpkt_grid_file, "\n") == 0); + assert_always(fscanf(vpkt_grid_file, "%lg %lg %lg %lg %lg \n", &vgrid[n][m].yvel, &vgrid[n][m].zvel, + &vgrid[n][m].flux[wlbin][obsdirindex].i, &vgrid[n][m].flux[wlbin][obsdirindex].q, + &vgrid[n][m].flux[wlbin][obsdirindex].u) == 5); } } } @@ -949,7 +925,7 @@ auto vpkt_call_estimators(Packet &pkt, const enum packet_type type_before_rpkt) for (int obsdirindex = 0; obsdirindex < Nobs; obsdirindex++) { // loop over different observer directions - const std::array obsdir{ + const auto obsdir = std::array{ sqrt(1 - (nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex])) * cos(phiobs[obsdirindex]), sqrt(1 - (nz_obs_vpkt[obsdirindex] * nz_obs_vpkt[obsdirindex])) * sin(phiobs[obsdirindex]), nz_obs_vpkt[obsdirindex]}; From f48021dc5d586c2733853a31800222176cce7799 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 24 Aug 2024 17:46:09 +0100 Subject: [PATCH 026/117] Shrink upper-triangular Spencer-Fano matrix during construction and avoid linelist lookups while looping through excitations (#110) Gives about a 6% speedup for nebular test model on Apple M1. --- atomic.h | 16 ++-- macroatom.cc | 1 - nltepop.cc | 6 +- nonthermal.cc | 181 +++++++++++++++++++++++++---------------- radfield.cc | 2 +- rpkt.cc | 2 +- spectrum_lightcurve.cc | 4 +- 7 files changed, 123 insertions(+), 89 deletions(-) diff --git a/atomic.h b/atomic.h index e28c47d70..2c369edc6 100644 --- a/atomic.h +++ b/atomic.h @@ -110,14 +110,6 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return globals::elements[element].ions[ion].levels[level].phixstargets[phixstargetindex].probability; } -// double einstein_spontaneous_emission(int element, int ion, int upper, int lower) -// reads A_ul from levellist which consists of -// (epsilon_upper; 0) | (g_upper; 0) | (A_upper,upper-1; f_upper,upper-1) | (A_uppper,upper-2; f_upper,upper-2) | ... | -// (A_upper,1; f_upper,1) -[[nodiscard]] inline auto einstein_spontaneous_emission(const int lineindex) -> double { - return globals::linelist[lineindex].einstein_A; -} - // Return the statistical weight of (element,ion,level). [[nodiscard]] inline auto stat_weight(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); @@ -219,7 +211,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) const double n_l = get_levelpop(modelgridindex, element, ion, lower); const double nu_trans = (epsilon(element, ion, upper) - epsilon(element, ion, lower)) / H; - const double A_ul = einstein_spontaneous_emission(lineindex); + const double A_ul = globals::linelist[lineindex].einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; @@ -421,8 +413,10 @@ inline void set_nuptrans(const int element, const int ion, const int level, cons return phixstargetindex; } } - printout("Could not find phixstargetindex\n"); - std::abort(); + assert_testmodeonly(false); + if constexpr (!TESTMODE) { + __builtin_unreachable(); + } return -1; } diff --git a/macroatom.cc b/macroatom.cc index 715da5c15..a3cbc92ea 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -671,7 +671,6 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con { const double nu_trans = epsilon_trans / H; - // const double A_ul = einstein_spontaneous_emission(lineindex); const double B_ul = CLIGHTSQUAREDOVERTWOH / std::pow(nu_trans, 3) * A_ul; const double B_lu = upperstatweight / stat_weight(element, ion, lower) * B_ul; diff --git a/nltepop.cc b/nltepop.cc index 37ee5f601..16df9b0a1 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -474,10 +474,10 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, // excitation const int nuptrans = get_nuptrans(element, ion, level); + const auto &leveluptrans = globals::elements[element].ions[ion].levels[level].uptrans; for (int i = 0; i < nuptrans; i++) { - const int lineindex = globals::elements[element].ions[ion].levels[level].uptrans[i].lineindex; - const TransitionLine *line = &globals::linelist[lineindex]; - const int upper = line->upperlevelindex; + const int lineindex = leveluptrans[i].lineindex; + const int upper = leveluptrans[i].targetlevelindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon_level; const double R = diff --git a/nonthermal.cc b/nonthermal.cc index 29e953f6c..9c12ac62e 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -205,6 +205,39 @@ std::vector nt_solution; std::vector deposition_rate_density; std::vector deposition_rate_density_timestep; +constexpr auto uppertriangular(const int i, const int j) -> int { + assert_testmodeonly(i >= 0); + assert_testmodeonly(i < SFPTS); + // sometimes you might want to get an offset for a row using j = 0 < i, so that j can be added to it. + // assert_testmodeonly(j >= i); + assert_testmodeonly(j < SFPTS); + return (SFPTS * i) - (i * (i + 1) / 2) + j; +} + +constexpr void compactify_triangular_matrix(std::vector &matrix) { + for (int i = 1; i < SFPTS; i++) { + const int rowoffset = uppertriangular(i, 0); + for (int j = 0; j < i; j++) { + assert_always(matrix[(i * SFPTS) + j] == 0.); + } + for (int j = i; j < SFPTS; j++) { + matrix[rowoffset + j] = matrix[(i * SFPTS) + j]; + } + } +} + +constexpr void decompactify_triangular_matrix(std::vector &matrix) { + for (int i = SFPTS - 1; i > 0; i--) { + const int rowoffset = uppertriangular(i, 0); + for (int j = SFPTS - 1; j >= i; j--) { + matrix[(i * SFPTS) + j] = matrix[rowoffset + j]; + } + for (int j = i - 1; j >= 0; j--) { + matrix[(i * SFPTS) + j] = 0.; + } + } +} + void read_shell_configs() { assert_always(NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE); auto shells_file = fstream_required("electron_shell_occupancy.txt", std::ios::in); @@ -514,8 +547,7 @@ auto get_possible_nt_excitation_count() -> int { for (int lower = 0; lower < lower_nlevels; lower++) { const int nuptrans = get_nuptrans(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; - const int upper = globals::linelist[lineindex].upperlevelindex; + const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; if (upper < NTEXCITATION_MAXNLEVELS_UPPER) { ntexcitationcount++; } @@ -542,7 +574,7 @@ void zero_all_effionpot(const int modelgridindex) { check_auger_probabilities(modelgridindex); } -auto get_energyindex_ev_lteq(const double energy_ev) -> int +[[nodiscard]] constexpr auto get_energyindex_ev_lteq(const double energy_ev) -> int // finds the highest energy point <= energy_ev { const int index = std::floor((energy_ev - SF_EMIN) / DELTA_E); @@ -556,7 +588,7 @@ auto get_energyindex_ev_lteq(const double energy_ev) -> int return index; } -auto get_energyindex_ev_gteq(const double energy_ev) -> int +[[nodiscard]] constexpr auto get_energyindex_ev_gteq(const double energy_ev) -> int // finds the highest energy point <= energy_ev { const int index = std::ceil((energy_ev - SF_EMIN) / DELTA_E); @@ -572,7 +604,7 @@ auto get_energyindex_ev_gteq(const double energy_ev) -> int // interpolate the y flux values to get the value at a given energy // y has units of particles / cm2 / s / eV -auto get_y(const std::array &yfunc, const double energy_ev) -> double { +[[nodiscard]] constexpr auto get_y(const std::array &yfunc, const double energy_ev) -> double { if (energy_ev <= 0) { return 0.; } @@ -654,8 +686,9 @@ auto get_xs_ionization_vector(std::array &xs_vec, const collionro for (int i = startindex; i < SFPTS; i++) { const double u = engrid(i) / ionpot_ev; - const double xs_ioniz = - 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); + const double xs_ioniz = 1e-14 * + (A * (1 - 1 / u) + B * std::pow((1 - (1 / u)), 2) + C * std::log(u) + D * std::log(u) / u) / + (u * std::pow(ionpot_ev, 2)); xs_vec[i] = xs_ioniz; } @@ -664,20 +697,21 @@ auto get_xs_ionization_vector(std::array &xs_vec, const collionro // distribution of secondary electron energies for primary electron with energy e_p // Opal, Peterson, & Beaty (1971) -auto Psecondary(const double e_p, const double epsilon, const double I, const double J) -> double { +[[nodiscard]] constexpr auto Psecondary(const double e_p, const double epsilon, const double I, + const double J) -> double { const double e_s = epsilon - I; if (e_p <= I || e_s < 0.) { return 0.; } - assert_always(J > 0); - assert_always(e_p >= I); - assert_always(e_s >= 0); - assert_always(std::isfinite(atan((e_p - I) / 2 / J))); - return 1 / (J * atan((e_p - I) / 2 / J) * (1 + pow(e_s / J, 2))); + assert_testmodeonly(J > 0); + assert_testmodeonly(e_p >= I); + assert_testmodeonly(e_s >= 0); + assert_testmodeonly(std::isfinite(std::atan((e_p - I) / 2 / J))); + return 1 / (J * std::atan((e_p - I) / 2 / J) * (1 + std::pow(e_s / J, 2))); } -auto get_J(const int Z, const int ionstage, const double ionpot_ev) -> double { +[[nodiscard]] constexpr auto get_J(const int Z, const int ionstage, const double ionpot_ev) -> double { // returns an energy in eV // values from Opal et al. 1971 as applied by Kozma & Fransson 1992 if (ionstage == 1) { @@ -707,7 +741,7 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, if (coll_strength >= 0) { // collision strength is available, so use it // Li et al. 2012 equation 11 - return pow(H_ionpot / energy, 2) / lowerstatweight * coll_strength * PI * A_naught_squared; + return std::pow(H_ionpot / energy, 2) / lowerstatweight * coll_strength * PI * A_naught_squared; } const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; if (!forbidden) { @@ -719,11 +753,11 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, // constexpr double g_bar = 0.2; constexpr double A = 0.28; constexpr double B = 0.15; - const double g_bar = (A * log(U)) + B; + const double g_bar = (A * std::log(U)) + B; constexpr double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) // Eq 4 of Mewe 1972, possibly from Seaton 1962? - return prefactor * A_naught_squared * pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength * g_bar / U; + return prefactor * A_naught_squared * std::pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength * g_bar / U; } return 0.; } @@ -740,13 +774,14 @@ constexpr auto electron_loss_rate(const double energy, const double nne) -> doub // normally set to 1.0, but Shingles et al. (2021) boosted this to increase heating constexpr double boostfactor = 1.; - const double omegap = std::sqrt(4 * PI * nne * pow(QE, 2) / ME); + const double omegap = std::sqrt(4 * PI * nne * std::pow(QE, 2) / ME); const double zetae = H * omegap / 2 / PI; if (energy > 14 * EV) { - return boostfactor * nne * 2 * PI * pow(QE, 4) / energy * log(2 * energy / zetae); + return boostfactor * nne * 2 * PI * std::pow(QE, 4) / energy * std::log(2 * energy / zetae); } const double v = std::sqrt(2 * energy / ME); - return boostfactor * nne * 2 * PI * pow(QE, 4) / energy * log(ME * pow(v, 3) / (EULERGAMMA * pow(QE, 2) * omegap)); + return boostfactor * nne * 2 * PI * std::pow(QE, 4) / energy * + std::log(ME * std::pow(v, 3) / (EULERGAMMA * std::pow(QE, 2) * omegap)); } // impact ionization cross section in cm^2 @@ -765,7 +800,8 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col const double C = colliondata.C; const double D = colliondata.D; - return 1e-14 * (A * (1 - 1 / u) + B * pow((1 - (1 / u)), 2) + C * log(u) + D * log(u) / u) / (u * pow(ionpot_ev, 2)); + return 1e-14 * (A * (1 - 1 / u) + B * std::pow((1 - (1 / u)), 2) + C * std::log(u) + D * std::log(u) / u) / + (u * std::pow(ionpot_ev, 2)); } // Kozma & Fransson equation 6. @@ -800,8 +836,7 @@ auto N_e(const int modelgridindex, const double energy, const std::array= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -1044,7 +1079,7 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> const double binding = get_mean_binding_energy(element, ion); constexpr double Aconst = 1.33e-14 * EV * EV; - const double oneoverW = Aconst * binding / Zbar / (2 * PI * pow(QE, 4)); + const double oneoverW = Aconst * binding / Zbar / (2 * PI * std::pow(QE, 4)); return oneoverW; } @@ -1255,14 +1290,15 @@ auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, con // epsilon_trans is in erg // returns the index of the first valid cross section point (en >= epsilon_trans) // all elements below this index are invalid and should not be used -auto get_xs_excitation_vector(std::array &xs_excitation_vec, const int element, const int ion, - const int lower, const int uptransindex, const double statweight_lower, - const double epsilon_trans) -> int { +auto get_xs_excitation_vector(const int element, const int ion, const int lower, const int uptransindex, + const double statweight_lower, + const double epsilon_trans) -> std::tuple, int> { + std::array xs_excitation_vec{}; const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; if (coll_strength >= 0) { // collision strength is available, so use it // Li et al. 2012 equation 11 - const double constantfactor = pow(H_ionpot, 2) / statweight_lower * coll_strength * PI * A_naught_squared; + const double constantfactor = std::pow(H_ionpot, 2) / statweight_lower * coll_strength * PI * A_naught_squared; const int en_startindex = get_energyindex_ev_gteq(epsilon_trans / EV); @@ -1270,9 +1306,9 @@ auto get_xs_excitation_vector(std::array &xs_excitation_vec, cons for (int j = en_startindex; j < SFPTS; j++) { const double energy = engrid(j) * EV; - xs_excitation_vec[j] = constantfactor * pow(energy, -2); + xs_excitation_vec[j] = constantfactor * std::pow(energy, -2); } - return en_startindex; + return {xs_excitation_vec, en_startindex}; } const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; if (!forbidden) { @@ -1289,14 +1325,14 @@ auto get_xs_excitation_vector(std::array &xs_excitation_vec, cons // Eq 4 of Mewe 1972, possibly from Seaton 1962? const double constantfactor = - epsilon_trans_ev * prefactor * A_naught_squared * pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength; + epsilon_trans_ev * prefactor * A_naught_squared * std::pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength; const int en_startindex = get_energyindex_ev_gteq(epsilon_trans_ev); std::fill_n(xs_excitation_vec.begin(), en_startindex, 0.); // U = en / epsilon - // g_bar = A * log(U) + b + // g_bar = A * std::log(U) + b // xs[j] = constantfactor * g_bar / engrid(j) const double logepsilon = std::log(epsilon_trans_ev); for (int j = en_startindex; j < SFPTS; j++) { @@ -1305,9 +1341,10 @@ auto get_xs_excitation_vector(std::array &xs_excitation_vec, cons xs_excitation_vec[j] = constantfactor * g_bar / engrid(j); } - return en_startindex; - } // gsl_vector_set_zero(xs_excitation_vec); - return -1; + return {xs_excitation_vec, en_startindex}; + } + + return {xs_excitation_vec, -1}; } // Kozma & Fransson equation 9 divided by level population and epsilon_trans @@ -1316,11 +1353,13 @@ auto calculate_nt_excitation_ratecoeff_perdeposition(const std::array double { - std::array xs_excitation_vec{}; + const auto [xs_excitation_vec, xsstartindex] = + get_xs_excitation_vector(element, ion, lower, uptransindex, statweight_lower, epsilon_trans); - if (get_xs_excitation_vector(xs_excitation_vec, element, ion, lower, uptransindex, statweight_lower, epsilon_trans) >= - 0) { - const double y_xs_de = cblas_ddot(SFPTS, xs_excitation_vec.data(), 1, yvec.data(), 1) * DELTA_E; + if (xsstartindex >= 0) { + const double y_xs_de = + cblas_ddot(SFPTS - xsstartindex, xs_excitation_vec.data() + xsstartindex, 1, yvec.data() + xsstartindex, 1) * + DELTA_E; return y_xs_de / E_init_ev / EV; } @@ -1490,8 +1529,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double epsilon_lower = epsilon(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; - const int upper = globals::linelist[lineindex].upperlevelindex; + const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -1510,6 +1548,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // if (get_coll_str(lineindex) < 0) // if collision strength is not defined, the rate coefficient is // unreliable // ratecoeffperdeposition = 0.; + const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; tmp_excitation_list.push_back({ .frac_deposition = frac_excitation_thistrans, @@ -1676,10 +1715,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo nt_solution[modelgridindex].frac_heating); } -void sfmatrix_add_excitation(std::vector &sfmatrix, const int modelgridindex, const int element, +void sfmatrix_add_excitation(std::vector &sfmatrixuppertri, const int modelgridindex, const int element, const int ion) { // excitation terms - std::array vec_xs_excitation_deltae{}; const int nlevels_all = get_nlevels(element, ion); const int nlevels = (nlevels_all > NTEXCITATION_MAXNLEVELS_LOWER) ? NTEXCITATION_MAXNLEVELS_LOWER : nlevels_all; @@ -1690,8 +1728,7 @@ void sfmatrix_add_excitation(std::vector &sfmatrix, const int modelgridi const double epsilon_lower = epsilon(element, ion, lower); const int nuptrans = get_nuptrans(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; - const int upper = globals::linelist[lineindex].upperlevelindex; + const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -1701,34 +1738,32 @@ void sfmatrix_add_excitation(std::vector &sfmatrix, const int modelgridi continue; } - const int xsstartindex = - get_xs_excitation_vector(vec_xs_excitation_deltae, element, ion, lower, t, statweight_lower, epsilon_trans); + auto [vec_xs_excitation_deltae, xsstartindex] = + get_xs_excitation_vector(element, ion, lower, t, statweight_lower, epsilon_trans); if (xsstartindex >= 0) { - cblas_dscal(SFPTS, DELTA_E, vec_xs_excitation_deltae.data(), 1); + cblas_dscal(SFPTS - xsstartindex, DELTA_E, vec_xs_excitation_deltae.data() + xsstartindex, 1); for (int i = 0; i < SFPTS; i++) { + const int rowoffset = uppertriangular(i, 0); const double en = engrid(i); const int stopindex = get_energyindex_ev_lteq(en + epsilon_trans_ev); - const int startindex = i > xsstartindex ? i : xsstartindex; + const int startindex = std::max(i, xsstartindex); for (int j = startindex; j < stopindex; j++) { - sfmatrix[(i * SFPTS) + j] += nnlevel * vec_xs_excitation_deltae[j]; + sfmatrixuppertri[rowoffset + j] += nnlevel * vec_xs_excitation_deltae[j]; } // do the last bit separately because we're not using the full delta_e interval - const double delta_en = DELTA_E; - const double delta_en_actual = (en + epsilon_trans_ev - engrid(stopindex)); - - sfmatrix[(i * SFPTS) + stopindex] += - nnlevel * vec_xs_excitation_deltae[stopindex] * delta_en_actual / delta_en; + sfmatrixuppertri[rowoffset + stopindex] += + nnlevel * vec_xs_excitation_deltae[stopindex] * delta_en_actual / DELTA_E; } } } } } -void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const int ionstage, const double nnion) +void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, const int ionstage, const double nnion) // add the ionization terms to the Spencer-Fano matrix { std::array vec_xs_ionization{}; @@ -1749,19 +1784,21 @@ void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const i // from becoming unphysical. This insight came from reading the // CMFGEN Fortran source code (Li, Dessart, Hillier 2012, doi:10.1111/j.1365-2966.2012.21198.x) // I had neglected this, so the limits of integration were incorrect. The fix didn't massively affect - // ionisation rates or spectra, but it was a source of error that led to energy fractions not adding up to 100% + // ionisation rates or spectra, but it was a source of error that led to energy fractions not adding up to + // 100% std::array int_eps_upper = {0}; std::array prefactors = {0}; for (int j = xsstartindex; j < SFPTS; j++) { const double endash = engrid(j); const double epsilon_upper = std::min((endash + ionpot_ev) / 2, endash); - int_eps_upper[j] = atan((epsilon_upper - ionpot_ev) / J); - prefactors[j] = vec_xs_ionization[j] * nnion / atan((endash - ionpot_ev) / 2 / J); + int_eps_upper[j] = std::atan((epsilon_upper - ionpot_ev) / J); + prefactors[j] = vec_xs_ionization[j] * nnion / std::atan((endash - ionpot_ev) / 2 / J); } for (int i = 0; i < SFPTS; i++) { // i is the matrix row index, which corresponds to an energy E at which we are solve from y(E) const double en = engrid(i); + const int rowoffset = uppertriangular(i, 0); // endash ranges from en to SF_EMAX, but skip over the zero-cross section points const int jstart = std::max(i, xsstartindex); @@ -1775,14 +1812,14 @@ void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const i const double epsilon_lower = std::max(endash - en, ionpot_ev); // and epsilon_upper = (endash + ionpot_ev) / 2; - const double int_eps_lower = atan((epsilon_lower - ionpot_ev) / J); + const double int_eps_lower = std::atan((epsilon_lower - ionpot_ev) / J); if (int_eps_lower <= int_eps_upper[j]) { - sfmatrix[(i * SFPTS) + j] += prefactors[j] * (int_eps_upper[j] - int_eps_lower) * DELTA_E; + sfmatrixuppertri[rowoffset + j] += prefactors[j] * (int_eps_upper[j] - int_eps_lower) * DELTA_E; } } - // below is atan((epsilon_lower - ionpot_ev) / J) where epsilon_lower = en + ionpot_ev; - const double int_eps_lower2 = atan(en / J); + // below is std::atan((epsilon_lower - ionpot_ev) / J) where epsilon_lower = en + ionpot_ev; + const double int_eps_lower2 = std::atan(en / J); // endash ranges from 2 * en + ionpot_ev to SF_EMAX if (2 * en + ionpot_ev <= SF_EMAX) { @@ -1791,7 +1828,7 @@ void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const i // epsilon_lower = en + ionpot_ev; // epsilon_upper = (endash + ionpot_ev) / 2; if (int_eps_lower2 <= int_eps_upper[j]) { - sfmatrix[(i * SFPTS) + j] -= prefactors[j] * (int_eps_upper[j] - int_eps_lower2) * DELTA_E; + sfmatrixuppertri[rowoffset + j] -= prefactors[j] * (int_eps_upper[j] - int_eps_lower2) * DELTA_E; } } } @@ -1799,7 +1836,7 @@ void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const i if constexpr (SF_AUGER_CONTRIBUTION_ON) { int augerstopindex = 0; - if (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { + if constexpr (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { // en_auger_ev is (if LJS understands it correctly) averaged to include some probability of zero Auger // electrons so we need a boost to get the average energy of Auger electrons given that there are one or // more @@ -1811,22 +1848,23 @@ void sfmatrix_add_ionization(std::vector &sfmatrix, const int Z, const i } for (int i = 0; i < augerstopindex; i++) { + const int rowoffset = uppertriangular(i, 0); const double en = engrid(i); const int jstart = i > xsstartindex ? i : xsstartindex; for (int j = jstart; j < SFPTS; j++) { const double xs = vec_xs_ionization[j]; - if (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { + if constexpr (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { const double en_boost = 1 / (1. - collionrow.prob_num_auger[0]); for (int a = 1; a <= NT_MAX_AUGER_ELECTRONS; a++) { if (en < (en_auger_ev * en_boost / a)) { - sfmatrix[(i * SFPTS) + j] -= nnion * xs * collionrow.prob_num_auger[a] * a; + sfmatrixuppertri[rowoffset + j] -= nnion * xs * collionrow.prob_num_auger[a] * a; } } } else { assert_always(en < en_auger_ev); // printout("SFAuger E %g < en_auger_ev %g so subtracting %g from element with value %g\n", en, // en_auger_ev, nnion * xs, ij_contribution); - sfmatrix[(i * SFPTS) + j] -= nnion * xs; // * n_auger_elec_avg; // * en_auger_ev??? + sfmatrixuppertri[rowoffset + j] -= nnion * xs; // * n_auger_elec_avg; // * en_auger_ev??? } } } @@ -2450,12 +2488,14 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // timesteps.\n"); // } + // sfmatrix will be a compacted upper triangular matrix during construction and then expanded into a full matrix (with + // lots of zeros) just before the solver is called THREADLOCALONHOST std::vector sfmatrix(SFPTS * SFPTS); - std::ranges::fill(sfmatrix, 0.); + std::fill_n(sfmatrix.begin(), SFPTS * (SFPTS + 1) / 2, 0.); // loss terms and source terms for (int i = 0; i < SFPTS; i++) { - sfmatrix[(i * SFPTS) + i] += electron_loss_rate(engrid(i) * EV, nne) / EV; + sfmatrix[uppertriangular(i, i)] += electron_loss_rate(engrid(i) * EV, nne) / EV; } if (enable_sfexcitation || enable_sfionization) { @@ -2512,6 +2552,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // } // printout("\n"); + decompactify_triangular_matrix(sfmatrix); const auto yfunc = sfmatrix_solve(sfmatrix); if (timestep % 10 == 0) { diff --git a/radfield.cc b/radfield.cc index b185ecd41..240845642 100644 --- a/radfield.cc +++ b/radfield.cc @@ -506,7 +506,7 @@ void init(const int my_rank, const int ndo_nonempty) { // const int upperlevel = linelist[i].upperlevelindex; // const int ion = linelist[i].ionindex; // const int ionstage = get_ionstage(element, ion); - const double A_ul = einstein_spontaneous_emission(i); + const double A_ul = globals::linelist[i].einstein_A; bool addline = false; // if (ionstage == 1 && lowerlevel == 6 && upperlevel == 55) diff --git a/rpkt.cc b/rpkt.cc index ef6f4299c..a764d83b9 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -131,7 +131,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum const int ion = globals::linelist[lineindex].ionindex; const int upper = globals::linelist[lineindex].upperlevelindex; const int lower = globals::linelist[lineindex].lowerlevelindex; - const double A_ul = einstein_spontaneous_emission(lineindex); + const double A_ul = globals::linelist[lineindex].einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 3f069bb11..e34bb7e3e 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -109,7 +109,7 @@ void printout_tracemission_stats() { const double statweight_lower = stat_weight(element, ion, lower); const double nu_trans = (epsilon(element, ion, upper) - epsilon(element, ion, lower)) / H; - const double A_ul = einstein_spontaneous_emission(lineindex); + const double A_ul = globals::linelist[lineindex].einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; const double B_lu = statweight_target / statweight_lower * B_ul; @@ -122,7 +122,7 @@ void printout_tracemission_stats() { printout("%7.2e (%5.1f%%) %4d %9d %5d %5d %8.1f %8.2e %4d %7.1f %7.1f %7.1e %7.1e\n", encontrib, 100 * encontrib / totalenergy, get_atomicnumber(element), get_ionstage(element, ion), globals::linelist[lineindex].upperlevelindex, globals::linelist[lineindex].lowerlevelindex, - downtrans->coll_str, einstein_spontaneous_emission(lineindex), downtrans->forbidden, linelambda, v_rad, + downtrans->coll_str, globals::linelist[lineindex].einstein_A, downtrans->forbidden, linelambda, v_rad, B_lu, B_ul); } else { break; From d5316f4e4fd739af2f6a464c4c2fd7ae23596041 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 25 Aug 2024 08:52:17 +0100 Subject: [PATCH 027/117] Use stable_sort only for reproducible CI mode (#111) Gives an 18% speedup for nebular test calculation on Apple M1. --- .github/workflows/ci.yml | 2 +- Makefile | 11 ++++++++++- decay.cc | 2 +- gammapkt.cc | 2 +- input.cc | 14 +++++++++----- nonthermal.cc | 9 +++++---- radfield.cc | 2 +- sn3d.h | 6 ++++++ spectrum_lightcurve.cc | 8 ++++---- update_packets.cc | 2 +- 10 files changed, 39 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2df61896..a10ba0385 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: - name: Compile run: | - make TESTMODE=${{ matrix.testmode }} MPI=ON MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec + make REPRODUCIBLE=ON TESTMODE=${{ matrix.testmode }} MPI=ON MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec cp sn3d tests/${{ matrix.testname }}_testrun/ cp exspec tests/${{ matrix.testname }}_testrun/ diff --git a/Makefile b/Makefile index f945b1811..9acb91a9d 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,16 @@ ifeq ($(TESTMODE),ON) else ifeq ($(TESTMODE),OFF) else ifeq ($(TESTMODE),) else - $(error bad value for testmode option. Should be ON or OFF) + $(error bad value for TESTMODE option. Should be ON or OFF) +endif + +ifeq ($(REPRODUCIBLE),ON) + CXXFLAGS += -DREPRODUCIBLE=true + BUILD_DIR := $(BUILD_DIR)_reproducible +else ifeq ($(REPRODUCIBLE),OFF) +else ifeq ($(REPRODUCIBLE),) +else + $(error bad value for REPRODUCIBLE option. Should be ON or OFF) endif diff --git a/decay.cc b/decay.cc index 208baf220..84d21792a 100644 --- a/decay.cc +++ b/decay.cc @@ -393,7 +393,7 @@ void find_decaypaths(const std::vector &custom_zlist, const std::vector(allnuc_gamma_line_list.size()) == total_lines); - std::ranges::stable_sort(allnuc_gamma_line_list, [](const NucGammaLine &g1, const NucGammaLine &g2) { + std::ranges::SORT_OR_STABLE_SORT(allnuc_gamma_line_list, [](const NucGammaLine &g1, const NucGammaLine &g2) { // true if d1 < d2 if (g1.energy < g2.energy) { return true; diff --git a/input.cc b/input.cc index 6d958a0f9..16b4e1dad 100644 --- a/input.cc +++ b/input.cc @@ -942,8 +942,8 @@ void read_atomicdata_files() { if (globals::rank_in_node == 0) { // sort the lineline in descending frequency - std::stable_sort(EXEC_PAR_UNSEQ temp_linelist.begin(), temp_linelist.end(), - [](const auto &a, const auto &b) { return a.nu > b.nu; }); + std::SORT_OR_STABLE_SORT(EXEC_PAR_UNSEQ temp_linelist.begin(), temp_linelist.end(), + [](const auto &a, const auto &b) { return a.nu > b.nu; }); for (int i = 0; i < globals::nlines - 1; i++) { const double nu = temp_linelist[i].nu; @@ -1371,7 +1371,7 @@ void setup_phixs_list() { } } assert_always(groundcontindex == globals::nbfcontinua_ground); - std::ranges::stable_sort(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); + std::ranges::SORT_OR_STABLE_SORT(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); } auto *nonconstallcont = @@ -1433,8 +1433,8 @@ void setup_phixs_list() { globals::bfestimcount = 0; if (globals::nbfcontinua > 0) { // indicies above were temporary only. continum index should be to the sorted list - std::ranges::stable_sort(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, - &FullPhotoionTransition::nu_edge); + std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, + &FullPhotoionTransition::nu_edge); globals::bfestim_nu_edge.clear(); for (int i = 0; i < globals::nbfcontinua; i++) { @@ -1694,6 +1694,10 @@ void read_parameterfile(int rank) { MPI_Bcast(&pre_zseed, 1, MPI_INT64_T, 0, MPI_COMM_WORLD); #endif printout("randomly-generated random number seed is %" PRId64 "\n", pre_zseed); +#if defined REPRODUCIBLE && REPRODUCIBLE + printout("ERROR: reproducible mode is on, so random number seed is required.\n"); + std::abort(); +#endif } #if defined(_OPENMP) && !defined(GPU_ON) diff --git a/nonthermal.cc b/nonthermal.cc index 9c12ac62e..b5102ce36 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1613,7 +1613,8 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo if (nt_excitations_stored > 0) { // sort by descending frac_deposition - std::ranges::stable_sort(tmp_excitation_list, std::ranges::greater{}, &NonThermalExcitation::frac_deposition); + std::ranges::SORT_OR_STABLE_SORT(tmp_excitation_list, std::ranges::greater{}, + &NonThermalExcitation::frac_deposition); // the excitation list is now sorted by frac_deposition descending const double deposition_rate_density = get_deposition_rate_density(modelgridindex); @@ -1673,9 +1674,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::ranges::stable_sort(std::span(nt_solution[modelgridindex].frac_excitations_list, - nt_solution[modelgridindex].frac_excitations_list_size), - std::ranges::less{}, &NonThermalExcitation::lineindex); + std::ranges::SORT_OR_STABLE_SORT(std::span(nt_solution[modelgridindex].frac_excitations_list, + nt_solution[modelgridindex].frac_excitations_list_size), + std::ranges::less{}, &NonThermalExcitation::lineindex); } // NT_EXCITATION_ON diff --git a/radfield.cc b/radfield.cc index 240845642..c0c4eec14 100644 --- a/radfield.cc +++ b/radfield.cc @@ -537,7 +537,7 @@ void init(const int my_rank, const int ndo_nonempty) { // these are probably sorted anyway because the previous loop goes in ascending // lineindex. But this sorting step is quick and makes sure that the // binary searching later will work correctly - std::stable_sort(detailed_lineindicies, detailed_lineindicies + detailed_linecount); + std::SORT_OR_STABLE_SORT(detailed_lineindicies, detailed_lineindicies + detailed_linecount); } printout("There are %d lines with detailed Jblue_lu estimators.\n", detailed_linecount); diff --git a/sn3d.h b/sn3d.h index 867a9ed80..e30cbfa9d 100644 --- a/sn3d.h +++ b/sn3d.h @@ -148,6 +148,12 @@ inline void print_line_start() { #define assert_testmodeonly(e) (void)0 #endif +#if defined REPRODUCIBLE && REPRODUCIBLE +#define SORT_OR_STABLE_SORT stable_sort +#else +#define SORT_OR_STABLE_SORT sort +#endif + template inline void atomicadd(T &var, const T &val) { #ifdef _OPENMP diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index e34bb7e3e..41d7ac871 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -53,8 +53,8 @@ void printout_tracemission_stats() { // mode is 0 for emission and 1 for absorption for (int mode = 0; mode < 2; mode++) { if (mode == 0) { - std::ranges::stable_sort(traceemissionabsorption, - [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); + std::ranges::SORT_OR_STABLE_SORT(traceemissionabsorption, + [](const auto &a, const auto &b) { return a.energyemitted > b.energyemitted; }); printout("lambda [%5.1f, %5.1f] nu %g %g\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_nulower, traceemissabs_nuupper); @@ -62,8 +62,8 @@ void printout_tracemission_stats() { traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceemission_totalenergy); } else { - std::ranges::stable_sort(traceemissionabsorption, std::ranges::greater{}, - &emissionabsorptioncontrib::energyabsorbed); + std::ranges::SORT_OR_STABLE_SORT(traceemissionabsorption, std::ranges::greater{}, + &emissionabsorptioncontrib::energyabsorbed); printout("Top line absorption contributions in the range lambda [%5.1f, %5.1f] time [%5.1fd, %5.1fd] (%g erg)\n", traceemissabs_lambdamin, traceemissabs_lambdamax, traceemissabs_timemin / DAY, traceemissabs_timemax / DAY, traceabsorption_totalenergy); diff --git a/update_packets.cc b/update_packets.cc index 38bd6df73..75ba8d29e 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -361,7 +361,7 @@ void update_packets(const int my_rank, const int nts, std::span packets) // printout("sorting packets..."); - std::ranges::stable_sort(packets, std_compare_packets_bymodelgriddensity); + std::ranges::SORT_OR_STABLE_SORT(packets, std_compare_packets_bymodelgriddensity); // printout("took %lds\n", std::time(nullptr) - sys_time_start_pass); From a184cfd83869581fa6ac60b507119f2a8ac6c9ce Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 26 Aug 2024 18:44:04 +0100 Subject: [PATCH 028/117] Enable more clang-tidy checks --- .clang-tidy | 2 -- atomic.h | 4 ++-- md5.cc | 2 +- nonthermal.cc | 3 ++- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index db8c0d55a..fb08c158a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -26,12 +26,10 @@ Checks: > -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-pro-bounds-pointer-arithmetic, - -cppcoreguidelines-pro-type-cstyle-cast, -cppcoreguidelines-pro-type-vararg, -fuchsia-*, -google-objc*, -google-readability-todo, - -google-runtime-int, -hicpp-vararg, -hicpp-no-array-decay, -hicpp-no-malloc, diff --git a/atomic.h b/atomic.h index 2c369edc6..3dcb210d3 100644 --- a/atomic.h +++ b/atomic.h @@ -141,7 +141,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) if (nu == nu_edge) { sigma_bf = photoion_xs[0]; } else if (nu <= nu_edge * (1 + globals::NPHIXSNUINCREMENT * globals::NPHIXSPOINTS)) { - const int i = static_cast(floor((nu - nu_edge) / (globals::NPHIXSNUINCREMENT * nu_edge))); + const int i = static_cast((nu - nu_edge) / (globals::NPHIXSNUINCREMENT * nu_edge)); sigma_bf = photoion_xs[i]; } else { // use a parameterization of sigma_bf by the Kramers formula @@ -154,7 +154,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) } const double ireal = (nu / nu_edge - 1.0) / globals::NPHIXSNUINCREMENT; - const int i = floor(ireal); + const int i = static_cast(ireal); if (i < 0) { sigma_bf = 0.; diff --git a/md5.cc b/md5.cc index d2a98e432..9cb147368 100644 --- a/md5.cc +++ b/md5.cc @@ -222,7 +222,7 @@ void md5_file(const char filename[], char hashout[(2 * MD5_BLOCK_SIZE) + 1]) { BYTE buffer[1024]; - long numbytes = -1; + size_t numbytes = -1; while (numbytes != 0 && feof(infile) == 0) { numbytes = fread(buffer, sizeof(char), 1024, infile); assert_always(ferror(infile) == 0); diff --git a/nonthermal.cc b/nonthermal.cc index b5102ce36..16d5914ec 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -642,7 +643,7 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it std::abort(); } - static long nonthermalfile_offset_iteration_zero = 0; + static int64_t nonthermalfile_offset_iteration_zero = 0; #ifdef _OPENMP #pragma omp threadprivate(nonthermalfile_offset_iteration_zero) #endif From 6d5f6f11757cbfc2e8196c2737eed3e70941e3ec Mon Sep 17 00:00:00 2001 From: Fionntan Callan <56071719+fionntancallan@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:32:15 +0100 Subject: [PATCH 029/117] Fix phixs classic readin (#113) phixs_file_version global variable was not being set, so read_phixs_data_table was reading the classic phixsdata.txt file in the wrong format, leading to noticeable differences in the synthetic observables. This PR removes the phixs_file_version global variable and passes the phixs file version through function arguments instead. --- input.cc | 5 +- .../results_md5_final.txt | 54 +- .../results_md5_job0.txt | 46 +- .../results_md5_final.txt | 1044 ++++++++--------- .../results_md5_job0.txt | 30 +- 5 files changed, 589 insertions(+), 590 deletions(-) diff --git a/input.cc b/input.cc index 16b4e1dad..2f2dd8eb4 100644 --- a/input.cc +++ b/input.cc @@ -47,7 +47,6 @@ namespace { const int groundstate_index_in = 1; // starting level index in the input files -int phixs_file_version = -1; float *allphixsblock{}; struct Transitions { @@ -95,7 +94,7 @@ CellCachePhixsTargets *chphixstargetsblock{}; void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_inputtable, const int element, const int lowerion, const int lowerlevel, const int upperion, int upperlevel_in, - size_t *mem_usage_phixs) { + size_t *mem_usage_phixs, const int phixs_file_version) { if (upperlevel_in >= 0) // file gives photoionisation to a single target state only { int upperlevel = upperlevel_in - groundstate_index_in; @@ -319,7 +318,7 @@ void read_phixs_data(const int phixs_file_version) { // store only photoionization crosssections for ions that are part of the current model atom if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_nlevels(element, lowerion)) { read_phixs_data_table(phixsfile, nphixspoints_inputtable, element, lowerion, lowerlevel, upperion, - upperlevel_in, &mem_usage_phixs); + upperlevel_in, &mem_usage_phixs, phixs_file_version); skip_this_phixs_table = false; } diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index dd3c98e43..34c42bbf9 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,37 +1,37 @@ -86c15760e6772606c0b6874da878e1e5 absorption.out -c8ddb735d68c616eb2284d027db3e77e absorptionpol.out +91de44973f7efdb2bbb67e9ebe78f2bf absorption.out +790e8eb2156e27b9bcf4fe4ec9db7c52 absorptionpol.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -484a3c7d31147c4cf9b37394f27a7e70 deposition.out -93925a0e93c735d05487d798305608ee emission.out -0aaef5e1b4a7f4bcf6177abde91d5709 emissionpol.out -0f739c9ccab71703c5314bccb0b185f1 emissiontrue.out -89b0510bce0562daad2a528748c6d805 gamma_light_curve.out -c0058c8e94c7d1da7ed18b37885fec93 gamma_spec.out +ebb29b17b5d4e5cf6d06b0ef9d8a8df2 deposition.out +ad213adf8e24a171b42f872c59a5dae0 emission.out +e8865c8b8fb79aeef5de4dfbaa176e58 emissionpol.out +91e674fadcf5a1f38e36a23aaed77cb3 emissiontrue.out +c22a1fe1065a07ad719688fee38d9b3b gamma_light_curve.out +66aa1260a8d46c287b3158e99799b4cf gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -cc7ba3712502f6d95db04b0b52432984 light_curve.out +19b4c6db4900c2e74d507c960cf55ef5 light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -10b3352ead14d4e3525e53e95d4242a3 packets00_0000.out -0d08c76357f5f25c02d47e437b4d9268 packets00_0001.out -8c23e2386f8b16dc3a7c311ea29fa91e packets00_0002.out -b5656513abdc54af9f1c851f8e487cd7 packets00_0003.out -b9a122c8a62ac1bd277d23ff9a4e37dc spec.out -5d61a2b5f77895eece5f0f1c04b97dc2 specpol.out +4382e5c02bd5534ba1bffb13eae880c6 packets00_0000.out +79baa7f0db446f2dc0b03434b466075d packets00_0001.out +1eb2657af29e3573eea7f03758a1ac0e packets00_0002.out +b7a810f6843879ea211c64057d0e2e93 packets00_0003.out +47dc8003341536751d4a5fc1042053b7 spec.out +1c34b924847577d008b968827d6f36cc specpol.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -0664f016179c072e9becf4ef5786e96e vpackets_0000.out -6c5e252d38f74c76d3ed069984ad35c5 vpackets_0001.out -20ddf629166031d0b79243ba5e8c7e1f vpackets_0002.out -9183110274310703c813f3ea07d70805 vpackets_0003.out +38c0fc1f2aeaa64e46b411e637097d27 vpackets_0000.out +074ad43f9a262b688d49fe1a037f7296 vpackets_0001.out +6e56402b2745c26899907d1fecb51b3a vpackets_0002.out +886d6db822af59198983bc30a4f0493b vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -b81eca147913a935a0e1b7d471314361 vspecpol_0000.out -0a5920d2f978204df5da1d643c423d50 vspecpol_0001.out -fcccf78f512bcce165decaccbdb2c174 vspecpol_0002.out -235a52ec7939631f31eaf726cd0b0af5 vspecpol_0003.out -d4ce4ca914355420ed982d84e7f25c3b job1/estimators_0000.out -ed3c84271c5684682f00bd4e96873449 job1/estimators_0001.out -17de43d8517c1a714acecd0f539adcca job1/estimators_0002.out -a2ca1cec547d64f2c194ff93f7b1a805 job1/estimators_0003.out +3c910fc4c70dbec8bc6a3298ab24e256 vspecpol_0000.out +447a6fa50e85aee2b2107017b2834407 vspecpol_0001.out +6e2819c669a6f777818ea7d53ad9c45c vspecpol_0002.out +95cc343aacd91999d9608237e2b15e65 vspecpol_0003.out +225e09eb035710ab91de7c07303196ee job1/estimators_0000.out +90185995d5079abbafc4984db90709d7 job1/estimators_0001.out +3b37d3290a9781cd095c6af2d19c9c31 job1/estimators_0002.out +e949621dfbcd945f99c65dde68d4cd11 job1/estimators_0003.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index 968fa54e7..cb1e739c0 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,33 +1,33 @@ -0c2e65eb3c5b56407d45dff187e98bde absorption.out +8c114a35dad58a87b8cd8e3a7b776e80 absorption.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -4f658e7623c91bb335b3ec06cf7de303 deposition.out -1ca797b23c4f5c973e8e7c5875b64bdd emission.out -0d09a535f08fcd6c45ddf0912ed2876c emissiontrue.out -d77b71c32e2090e56f3e0f28ef8748f4 gamma_light_curve.out +f5c5f8bf0f84d2483cef3ce24bb46f75 deposition.out +ccd6033593f1d4f0e47d9aac7a0e3042 emission.out +1139784b02a652a635e211b934c2cfec emissiontrue.out +457efd00d79f5dd32d4649122b9e4b73 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -e2d213f1c6d32dcf1b35b6c25768de28 light_curve.out +b8e0cefe62b6395ee5282537db59a69d light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -c073309a92f8ce66d1b1d469d7025bd6 packets00_0000.out -e3bcc3def8fea786199721c307c076a9 packets00_0001.out -42869c0f5e97c0859a9cb86a83200f71 packets00_0002.out -ca84fe5225fad046a16056e3f0fbeee0 packets00_0003.out -ba123935942e38faef2713594ec6d0b5 spec.out +029652c38ebe0a14ecfba46b76af0f28 packets00_0000.out +4c45d523f09576fe1035fa89ed0548b2 packets00_0001.out +381e796cd7d9192661584ea60e6c28dd packets00_0002.out +d6d5190184299f680e41638d67c4977c packets00_0003.out +89adfd1461b00ddbab825fc9abca2b13 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -557de1f52f7c660e7296948360a0f34a vpackets_0000.out -93f0858030a4d7ce117ada41ea7ad5a6 vpackets_0001.out -8dd1db3d29517a743a9503047b02a4fe vpackets_0002.out -1246e178307a445f5215f438b7b6bd57 vpackets_0003.out +b80b994ca74daf4696751030d26a220f vpackets_0000.out +9fc86726f401c7758a0b0c2441ed6fa3 vpackets_0001.out +d89452752b6175590dd104fe095c6259 vpackets_0002.out +22e6218e5c400595ebd035f1b166a2f1 vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -d16768502c1b6d9dbcc3d89839d7e2d0 vspecpol_0000.out -a356af5f230c93556bf3cd24d64b7e35 vspecpol_0001.out -b2f9b21799bb15233dfe8ecf2fd59275 vspecpol_0002.out -b0149ecbfe2907867e7d5681b5564109 vspecpol_0003.out -1f28eae4d04a9a61b2f65754324fbe15 job0/estimators_0000.out -5ccfdb4112c294fc2aae7a6bafe1313a job0/estimators_0001.out -aa511b10e2052f7b49e268e202dea1fa job0/estimators_0002.out -d269004b3029f571d164ff1b80be7207 job0/estimators_0003.out +819d3b1ded1e2eb9cce2565c711ba51a vspecpol_0000.out +58f69311579e40139fa7d5f609ef0f8c vspecpol_0001.out +3bec72b5f06389cab1d8259f43ad5dd3 vspecpol_0002.out +d5c9b7d3e0194c1921bcded25308d118 vspecpol_0003.out +41b24af878ddf58986b5ba1e5a104f6a job0/estimators_0000.out +6f5dbce4d8957c98b02559bfe17fa739 job0/estimators_0001.out +7df27f7428d33eb7bc1045e9e8a24a71 job0/estimators_0002.out +700ae0652cb45e12884124bc89acfb80 job0/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_final.txt b/tests/classicmode_3d_inputfiles/results_md5_final.txt index b2b482322..eaef465a3 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_final.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_final.txt @@ -1,528 +1,528 @@ -ada85fd6f9450892265513ae0a8a2c0e absorption.out -da41b933064a0a0ca8bee5e224d971a7 absorption_res_00.out -08f4b5cd06e697281c2e9feb93a0b28b absorption_res_01.out -dbf08c6c5c1456cf9a226b7d24fb033e absorption_res_02.out -48b0790c403a250b99fb90721ea6f077 absorption_res_03.out -15ba7a09800cee51d5c7cf934da469fe absorption_res_04.out -6364ff2f2e28eaa0b5da5c875753aa4a absorption_res_05.out -65852173ab4ab213d1489483994c1ef1 absorption_res_06.out -20a63e5034fbbc45d00e74483dc9e877 absorption_res_07.out -502f69b2ac15a21d37502e492255ada8 absorption_res_08.out -14a2305334b874a6674f946ae2b62ff8 absorption_res_09.out -ac6d1bec94d8266240bd41f3540c9cba absorption_res_10.out -e633e2f7827e81fe83ee34d5e9538b0c absorption_res_11.out -a295da99ededd2186c9b4ff1f27775b0 absorption_res_12.out -81500bf63c349e50c8ad61b62d4bf87c absorption_res_13.out -505502297a1ca398006a4c343de8b8d8 absorption_res_14.out -6d429eb9198154390737755ab20bccca absorption_res_15.out -781699684e4ff6897ee92419d9a81ec4 absorption_res_16.out -6e7bd7925d71cb3cfcbea65832c79b00 absorption_res_17.out -2ebd6084a203a8c23fd89435d11ecf7c absorption_res_18.out -3f0d17412b759ff3963d46991007f574 absorption_res_19.out -172492423e595be5b2f11ff10bedd72c absorption_res_20.out -b1492aacdf77e7401b75f9a86f4a726d absorption_res_21.out -e0f032278182cc8d164bfcc5bf4d7a67 absorption_res_22.out -a9921e063318ff4db1f35b58488054bc absorption_res_23.out -9a0e206d3b108b49e89b37eee05d3093 absorption_res_24.out -8ec8cd12340cf5f1d487be983a7f6100 absorption_res_25.out -01a71e315f94961cdca2bf7896d97df9 absorption_res_26.out -da7cdc2d9f029d84972746e50ef5239a absorption_res_27.out -8af1553830653e78665c4da303ffac13 absorption_res_28.out -5f276542db0d144023a8ed4770ee87fd absorption_res_29.out -b3f3a7bfbcc9898fadef4fa73d9c8055 absorption_res_30.out -d3d35deee95c3f0b29f248f25ee0dee3 absorption_res_31.out -14cf3707918a6f0966584d2bdd9b884d absorption_res_32.out -51f53c395153b980e01f63e6fb5ec2bb absorption_res_33.out -0cd98920862479bb33ec426270b242ba absorption_res_34.out -5d0917546f290dbea6b4bc3c5b393e2c absorption_res_35.out -ddab98b40eb32cdec6e805afd70db0de absorption_res_36.out -ab08be2df205eea4377a7af640b22b29 absorption_res_37.out -0a43c9f26cedef357649be41be35f31c absorption_res_38.out -c3d3d277cd95d9eb7c033e9c2ac06ba2 absorption_res_39.out -edc67bcca545cd39bfef50b145908406 absorption_res_40.out -53e636362d0d227bb8d8469e0a00fff5 absorption_res_41.out -eefa7e3902474a21527709965c5154d9 absorption_res_42.out -2ca3310ba407337af5f5a89e3db2a63e absorption_res_43.out -252017c16cf993f2a1ec0f7b096e2a76 absorption_res_44.out -cfe6541f444e2165f08a2c93f72a4aab absorption_res_45.out -6a7446c45565dad3a62b0eeab4306889 absorption_res_46.out -5215643d68ae76f9ebbb6d15e35deccb absorption_res_47.out -43f547bfc21639849af94a2ed5b4e443 absorption_res_48.out -8c36b5e3a57312b1be78e434bb634d05 absorption_res_49.out -369c3142befc40517f2e64877ddddb75 absorption_res_50.out -2b739f4725f3407f004f9abea6288cc7 absorption_res_51.out -0c3167b892b8d92b051e7efe05309a0f absorption_res_52.out -e3a7b2f2dfe53e59c4ba1f0519db7a97 absorption_res_53.out -caf6cc72c34d447b71748e60be244f5d absorption_res_54.out -8aaf92ec3b504f2f029e26ac30b36ba1 absorption_res_55.out -3f2bc3b5534ebb89199ed7586a88d0cb absorption_res_56.out -676c5c19dc8f75df446daa776f438d94 absorption_res_57.out -0f22f2eb1146a04f131b5db6d09b4166 absorption_res_58.out -bd33791adcb2055e348437bafb86a6d2 absorption_res_59.out -6f155709b56b7db0c5a7102b4fa25c11 absorption_res_60.out -42e320a6f57830d924a7c3542725d60b absorption_res_61.out -2ea73859a73ce88eb9a2df7827298f0b absorption_res_62.out -9e07cf1a42c659a6f1edc1801fb8d06a absorption_res_63.out -79e3fb5c99ff4ac18ba13624a56a6de2 absorption_res_64.out -17d642a17b363647550c59dda642ae30 absorption_res_65.out -a98c37195acc6b913f88da99c9dc8688 absorption_res_66.out -1b8f0d54bb3b0d1e79c7a2abb0c49f7f absorption_res_67.out -2a3423b7f1915d701faef049ffb97f6b absorption_res_68.out -449832bbb821468967e018e36a921d96 absorption_res_69.out -00c6ee8da8b80e575bc7539c7bc38e99 absorption_res_70.out -9ffc8c820543340213b53873549389af absorption_res_71.out -dec8a20bdb55b9fb465de008750b79d5 absorption_res_72.out -33721dd49d0f70d9b1fddaa8d61e4851 absorption_res_73.out -aef316011fed9702967fd0f3ee5d1bd9 absorption_res_74.out -65ce3a6924d11c380398013198d3dccc absorption_res_75.out -76a03fc3757222081a2e1858b0466893 absorption_res_76.out -382aaa914ea543dbccd799939dd87c30 absorption_res_77.out -5e680b63c41653aab28839e66dad90ff absorption_res_78.out -9f3543eb69d96184e05e20bd461b3605 absorption_res_79.out -20f1da8a6d2cc39ee089d82b30a89dd6 absorption_res_80.out -048b05a3c4dd45c9ae313c028cf9c615 absorption_res_81.out -c004411dc1f91858eb490ae92c5925b3 absorption_res_82.out -f2c12bb9e053143d3ed0a4a84eba2487 absorption_res_83.out -4893537f5337d3e4e0ba1942b799832c absorption_res_84.out -f279450d6ecacb822c2bde201e2412ec absorption_res_85.out -fb92d2fde0aadd45c3045c05c5320302 absorption_res_86.out -fbb30caf8435ed82a6a0790e3e90e721 absorption_res_87.out -925b39172b372c398d591f1c35495e14 absorption_res_88.out -16ab34c8ad37a89d84da47313029e07f absorption_res_89.out -1deb8d66b4280751b98921696b46ecd3 absorption_res_90.out -2f2be02033b281c47d8d4bfac5b6decb absorption_res_91.out -d981dedffcb6cdbbf91c7872ab9e1f0d absorption_res_92.out -22663b284fa6ac358921d8e7dc7e7921 absorption_res_93.out -77f08a733b22bc8e6417408f2b59a3c5 absorption_res_94.out -632a9b2fe3b559ffac3ca64e0d034a9a absorption_res_95.out -84658b0f586da5810206c19e96c39b1b absorption_res_96.out -5bc2d907740854c44c27b8ff38061d36 absorption_res_97.out -8e96873f8811ba6a7a73a8697d73df67 absorption_res_98.out -40714984580071f311637bff2524fbee absorption_res_99.out -a71f943c96688131d0130a84bc7c2882 absorptionpol.out -7855c3010744913c478fc1b8008b6af2 absorptionpol_res_00.out -17e56bd16facc1e8fc264d5fd5d40052 absorptionpol_res_01.out -43e5d6a054689d043e5a44c37bd91d93 absorptionpol_res_02.out -2bb165a412f67da261071042474aea29 absorptionpol_res_03.out -29aa6c50cd6d3ffe2341ae5e48ffbda3 absorptionpol_res_04.out -7e5292d6d2eefb4f1dd5db7e3ed358b8 absorptionpol_res_05.out -378bbbacd5e2b046aa9e0454992447b6 absorptionpol_res_06.out -0f64e3074c68967f47750916f54ab98c absorptionpol_res_07.out -acea9ee28df7975b1092fc4872714c09 absorptionpol_res_08.out -2a4f54cd06700082d7be84992c5ab511 absorptionpol_res_09.out -b53bb58107eabfe155c43270b3eb6a57 absorptionpol_res_10.out -a469fe0754e79db2f2fbb84f3ad7f1b1 absorptionpol_res_11.out -a385ca18241d8a7f07ac1d0e3f3d8224 absorptionpol_res_12.out -6bea3049e7fdb3b795479ebe6140bedc absorptionpol_res_13.out -189543baec2886f4b0b1a8ef8136f132 absorptionpol_res_14.out -f6bce9746b186cb296d399a4a496a755 absorptionpol_res_15.out -56ce3adb54bab69c92385b127db33106 absorptionpol_res_16.out -02d10fc368545466ff0b32843d89c7bf absorptionpol_res_17.out -bbeadac11cf366571f5bd3b8ec06a941 absorptionpol_res_18.out -cd5277c9777ae336f1c8522b236d57d4 absorptionpol_res_19.out -35db23dc01e6f61a99ffa825e6665b61 absorptionpol_res_20.out -66be93ca1abebde2636426b23e6119f3 absorptionpol_res_21.out -b4a5f31cde2af4458eabb2e526a75e1f absorptionpol_res_22.out -63cd49ee461fd2f7b5e16234f4f7cbbe absorptionpol_res_23.out -e61275d8804612876786a82ed904c36d absorptionpol_res_24.out -fb42f8ca5d5fb0688ace46f2f17aceaf absorptionpol_res_25.out -acf6d376a442ce9de6a4f441f4c344b3 absorptionpol_res_26.out -5c624ae555cd40e3b58fa044267e3c44 absorptionpol_res_27.out -bb019a1397e8feba9852c4d8dcf4ca62 absorptionpol_res_28.out -86a3c4397672499889db9df53e07e485 absorptionpol_res_29.out -06a918137c7ba3fe3046d92b5ddcfe70 absorptionpol_res_30.out -4150421ce77628253f4babf8e8e617ad absorptionpol_res_31.out -da60fe529699cad062c085370f07f871 absorptionpol_res_32.out -d1fd56634f84a679a401022e4f84538f absorptionpol_res_33.out -a9d9f998716b1c2aa3bd7ad96ff03027 absorptionpol_res_34.out -758a99b81e0ba2a933370de9699ed787 absorptionpol_res_35.out -38ba8fb3f74bf8808304da037dde71cc absorptionpol_res_36.out -c07e8c39c7b6828046f6610644ff4c26 absorptionpol_res_37.out -1b72a5da702a1ec8babf738adf6c8765 absorptionpol_res_38.out -b0d5a826be9b181592d828909dff9b0c absorptionpol_res_39.out -646d9dfd9524bdf8b15c5b4058327b00 absorptionpol_res_40.out -621d798a8997a61b56c0565fe5f48f83 absorptionpol_res_41.out -0058e0475ff651db2855369b1b849b92 absorptionpol_res_42.out -64c0ccb0d918670e12dc6dbdbd171713 absorptionpol_res_43.out -b274a06a1e827d5c647b181fdf18945b absorptionpol_res_44.out -8cd15e741d86cccbd286c3585624e232 absorptionpol_res_45.out -9cd15e2d59b7da5049a6f1a3f876918a absorptionpol_res_46.out -0e8a0aa02730775be6ffab5faa6ec040 absorptionpol_res_47.out -02bd12e91a6994cb6a686793a52c7186 absorptionpol_res_48.out -cacf6ade7929c77ec979c3eee6d311c6 absorptionpol_res_49.out -a0dc5427dde9c241f613870e4dafceff absorptionpol_res_50.out -18078849b07e9103c946056a4c8dc203 absorptionpol_res_51.out -3b0740263e680ef71501291134353374 absorptionpol_res_52.out -b797a614ae06a585416d21d929234e57 absorptionpol_res_53.out -78ed956bbc900752f1943b7b88e0bcb5 absorptionpol_res_54.out -5e5fb793a0e450f50863c9cda3094e62 absorptionpol_res_55.out -339872ae791e9baf75a77857c2b1075c absorptionpol_res_56.out -79ad8a47b933f4718462fec5e28c9243 absorptionpol_res_57.out -c5d80c69564c78125d15c776b82c1c9e absorptionpol_res_58.out -cdb0b2c9050c0f066281f976703012b1 absorptionpol_res_59.out -c17e4ddf6e67fc52cb4ee870185faf9d absorptionpol_res_60.out -b0ca0f5dcf3addcb8755fc18978a6a85 absorptionpol_res_61.out -08585d8c8aa34ba8cc0cc564908de806 absorptionpol_res_62.out -6c7fefe75c11020f8c9fc6abce791e9e absorptionpol_res_63.out -99e3b8bcb2722ee61b840f085e6c3f3b absorptionpol_res_64.out -a679e5b247e86419989688c56d923a66 absorptionpol_res_65.out -8866dcb157757ec2d2918ef49b4b4287 absorptionpol_res_66.out -c930972f1e0e5a6384a3159f6af900d4 absorptionpol_res_67.out -7094155804228b8d3538e0b18a6d3fe1 absorptionpol_res_68.out -2eedec117a8f46d2091655277d6f5254 absorptionpol_res_69.out -798ecca9162b3be0b59c71eff0f558b7 absorptionpol_res_70.out -b3c2d6e1e960f6b15d7436a71494527b absorptionpol_res_71.out -200513df817d22dfe07315a1bf61cff2 absorptionpol_res_72.out -630fb946c68d0ff26066c6b3905c6519 absorptionpol_res_73.out -76af8175ccf141657122ea9c9a7a0ecc absorptionpol_res_74.out -5d0d3137d87e122ce19d954c1f0725cd absorptionpol_res_75.out -811f2a8f38c795816c24dc6d62e3cbb8 absorptionpol_res_76.out -5304d53ce3202ce141337524933f6a61 absorptionpol_res_77.out -440cd4b7a3fbf2843f409fb9d0c67be7 absorptionpol_res_78.out -4dbd3dae97664c0722aae2ac39edd3c1 absorptionpol_res_79.out -e31ba3ffc25daca831077c86862ccda9 absorptionpol_res_80.out -94ae83530131739a8680c57c56db4d3d absorptionpol_res_81.out -36d7d2ca15914553c2a56c6f30017be2 absorptionpol_res_82.out -679a52cb5e159de66addf865b7a2a259 absorptionpol_res_83.out -cdd39a45584c8953ab19d701ec7ba29e absorptionpol_res_84.out -fd6ace493efd6b66b3be9e352cd0308a absorptionpol_res_85.out -2774b0afd4e542fd7c81263b9c77e276 absorptionpol_res_86.out -88c71452c548890d15e67b23d41e5558 absorptionpol_res_87.out -2d99f0ba6a124eff4917e0bf3d84e9eb absorptionpol_res_88.out -7f2da82e265886979cac607719ffd814 absorptionpol_res_89.out -c8672a449664021c78dbb509164e2074 absorptionpol_res_90.out -31313f94c0ecda21d835ca615c7c9b8e absorptionpol_res_91.out -69a3cfa4bf102651c211c2ff3f71e941 absorptionpol_res_92.out -fb1cd38c659a7c3a2de2215c9e754bda absorptionpol_res_93.out -0a5704cccb24a400f23ef517daf23b1c absorptionpol_res_94.out -87653adb9ff9efce090f30534e368453 absorptionpol_res_95.out -3320d2903d16c7181bcf7d1216123334 absorptionpol_res_96.out -d188390ec3c67621947b89e6252fadaa absorptionpol_res_97.out -9238e578f88c37f07d0fc593f4ff4f83 absorptionpol_res_98.out -a8d123ce46646fc962a7589d432a307f absorptionpol_res_99.out +c8f55c45187bd587a2b219df6d4e39e8 absorption.out +b96cfe6c0a89ee789dc91a9cb9a3c7dc absorption_res_00.out +44729ac5a2e00b963601ea87ae4384da absorption_res_01.out +fda94fba71208323892be8db90b63ed9 absorption_res_02.out +8feb2e5f214fa243faacac2080ac439b absorption_res_03.out +b05428b06db9018d23b2129949c8b31c absorption_res_04.out +08575fb0f257acfd83d8fe5c896ac907 absorption_res_05.out +a4199c6fc47a0f5ad1388173afa35321 absorption_res_06.out +4debb080f5e3e3018cdfb944480e609e absorption_res_07.out +d51beb96fe78896c6a3cc2183766c1b5 absorption_res_08.out +fad6353af8f669604617336c3a5b9751 absorption_res_09.out +a38c8bf0d06a8dfd157511d797009fda absorption_res_10.out +919441e99d2708512e8d7addf94e9ed2 absorption_res_11.out +1722982ecbb44231098ab9035571cbbd absorption_res_12.out +3f3c8792567a9a1cf639153d2928fc7f absorption_res_13.out +1ea77e298944f161a3d387ccf07210d4 absorption_res_14.out +9db7b5b07c72081e3d467f2b55cd81f6 absorption_res_15.out +67b481077c1b2122a9807a0448941584 absorption_res_16.out +ccd7afa7aad0460263db76c449415c7e absorption_res_17.out +9a04167435b2a2a2dc474c4ee7899dcc absorption_res_18.out +64c8aa15fc330906e7416b1f0dc9ac69 absorption_res_19.out +0f07cbbf0b2e5609efe2c1b5cba6b61d absorption_res_20.out +f89648db5591e94fef298ba6f68e537b absorption_res_21.out +ac05368f14fe195cecc919fa14c9f172 absorption_res_22.out +c572d756de9a9a18d578b42e5c5b7877 absorption_res_23.out +68c5dca8da5b1472a1ec2bbb7dbfaa72 absorption_res_24.out +26f8b83d5aadc4f168a24a5a62606302 absorption_res_25.out +68ef995b0d279e45f212118c967d8555 absorption_res_26.out +2a695b9524255995c72e2956ab05650b absorption_res_27.out +fdf1b6b5d494ccd304a21cea6cfe705f absorption_res_28.out +c8ae92626daef28f946024862edfbfda absorption_res_29.out +423878e5248f6b82c2dcf7fb81251967 absorption_res_30.out +fed0e05d0eb616695488e508422cac3d absorption_res_31.out +1c947b9862c8fa11e36b5f3de2df806d absorption_res_32.out +c92540270ac59ccc9d77ac1138e41241 absorption_res_33.out +863e7733172b4517848e856db4834ef8 absorption_res_34.out +dce17ac76ece8471410deef3089c7af4 absorption_res_35.out +6ca15ecf15baa6814d0dd82277bb86d7 absorption_res_36.out +5a484adafd55df2c1256bcdcf13d752e absorption_res_37.out +2e19d6ae38e4f8dfea0694f6dd092f16 absorption_res_38.out +f4af3eb5e3ca745a3a3e5b26c7411a69 absorption_res_39.out +e906acabb9f1f817f62029962290721f absorption_res_40.out +55fbd94901ae551e732c91999949c0ef absorption_res_41.out +63f441f2640f6c8466ae023a8521a3b1 absorption_res_42.out +dcb82f1f3bcf769ea59906249b64bd42 absorption_res_43.out +b402960223dbd4f541da2346a6d2f618 absorption_res_44.out +dbd8a66ccc66750f476f09f38337f8c3 absorption_res_45.out +4eee701643200bab073b5583f8ea62a9 absorption_res_46.out +37a8006fc89b2c802055d174cac700fd absorption_res_47.out +0ea0895147238eb5e80eede51764f185 absorption_res_48.out +088e197acc89d545e2414e12e6b053c0 absorption_res_49.out +8d97adcf23756771d155449f1aff95fe absorption_res_50.out +03c7d42ef06b37c8cde2cb5c176d4448 absorption_res_51.out +a5945b8c5eacb2f4f0c4b7c9bb979fbd absorption_res_52.out +903850a85d48fcf6c039206a30d82da0 absorption_res_53.out +c7aed95facf4be0f27fc8e16ab230ddf absorption_res_54.out +75ee158fd6debae30633e77abb21c297 absorption_res_55.out +e807796b762a5556a368285ca51bf8f1 absorption_res_56.out +699a0df6bc0d55db751fad2d6ecac940 absorption_res_57.out +c673cc68e08b2022cb3b2adb3f7a28fa absorption_res_58.out +e8c9c6f120e3bc4bee222068d6ae3ad1 absorption_res_59.out +1a02686b23a1de51dfff41e9d3e55bbd absorption_res_60.out +cf55920b38a356d0494567f4a5b9e8a4 absorption_res_61.out +e2aeb456e1c76e7dc03b2cc58d5366f6 absorption_res_62.out +e27d24de4296579ba9ea9059f2195529 absorption_res_63.out +fc5bc4583b4344f53c21a6af80bd7905 absorption_res_64.out +4bf05d06d2b46ecc828f9ae9c670174c absorption_res_65.out +47537e3e77c441a9a5d7c51336ba8c8d absorption_res_66.out +ad770061ecb838134e9e53e52acaa880 absorption_res_67.out +978ab11af566f7a1581e2a59dfffacb4 absorption_res_68.out +63dad8e3ff238b8570016e9528743d4e absorption_res_69.out +85c631afe5861349c722ef3f34feef29 absorption_res_70.out +d099aa191ec2a4b0c9ef1f3daa2f9409 absorption_res_71.out +454fa33ff2389f752ca0e8369f73381c absorption_res_72.out +26ccbb770d206099a1aa4b1e124e973b absorption_res_73.out +040694ad6c226f81c7879ac4f9ee54ed absorption_res_74.out +0736968ebbc19b8f2ff0b76e30abd81c absorption_res_75.out +a6397717a6e3cdd270b28709b2dcf03e absorption_res_76.out +fb9ed4554ed37ac4536fe25c70e28e48 absorption_res_77.out +f2797274e31b8b88f4477d05277fe246 absorption_res_78.out +80f1fe9a9daef72fe02e96377aa1d3a0 absorption_res_79.out +89faaa974b7525001bd5b49805abc151 absorption_res_80.out +e16284735d698808243644b9c0a1ca74 absorption_res_81.out +cec73fe16e732e2f1d62f2c0ad46e45a absorption_res_82.out +710214f9df362eb59682bab4216f647f absorption_res_83.out +d16159b39d5278c7cb622c78bb154f1b absorption_res_84.out +c60913e6ad2d68a2ac985940e007a7a6 absorption_res_85.out +9d98ecb949541ed99df0f666cb9d0e62 absorption_res_86.out +70f9a9068542016b4bd2736509725994 absorption_res_87.out +a79c5cd6767d41adbeb1da8ad8e5f928 absorption_res_88.out +1fab560fa863c34037a86868a8ff09a2 absorption_res_89.out +c7006319e56c040a296dedd4f992807b absorption_res_90.out +90d7a4f5bcb9a4104043d56f097b4a53 absorption_res_91.out +9067896b0b232cc5f726e0cf07e159a1 absorption_res_92.out +7aad48dc9ee2783617a7c38e2d392191 absorption_res_93.out +1d7a30e456fb9268a52b1b531786dfe2 absorption_res_94.out +b250dde0bd01b2e0e1ec60a55e563cd1 absorption_res_95.out +39c802aa3abe657d26bf22beadfa6c6a absorption_res_96.out +53d8b35328b153da736d96cecff874ee absorption_res_97.out +4ea7842389229e7a8efbeaac68d7a398 absorption_res_98.out +c3526581cd573c7e9968bb092cdfadeb absorption_res_99.out +13b00d80c6ed0ac378e4a84867f211d6 absorptionpol.out +6e11318e9bce8cce4af411a3b2512275 absorptionpol_res_00.out +587a3417c0629d3c4008dcbb99fb3ea9 absorptionpol_res_01.out +2a0ca3c0dcd25cfa6f61f0ef6c5f0d92 absorptionpol_res_02.out +bb2089380c0d45f3b647614982ec3fd0 absorptionpol_res_03.out +034dfa4b8f27bda20cf264983eb54653 absorptionpol_res_04.out +e5d6df85d9c06f6bd8ae447aad552bb4 absorptionpol_res_05.out +e4dbc5f271750de6e352127313c973a6 absorptionpol_res_06.out +e38c6b0846bf893d959e1eafea3a634d absorptionpol_res_07.out +daa708476bfe6c6c2b72391c999ec300 absorptionpol_res_08.out +7a57be83703e9584dce31b12772390a4 absorptionpol_res_09.out +24a62513fca30c0f829ed8fc30e974be absorptionpol_res_10.out +e0c5036901bdcaae7476b8e9a136abaf absorptionpol_res_11.out +535dfeb31bc5d66b3d70df94dc81f169 absorptionpol_res_12.out +fa0e8c0bed26ef27e36dd5f9d226f633 absorptionpol_res_13.out +b716b5b657ff782a1216bdfb1d85e1ce absorptionpol_res_14.out +332ee8a398fbff84d3bbd4bfcacd2249 absorptionpol_res_15.out +efd243f3d4c1a14ec2e76170019b384d absorptionpol_res_16.out +49e8aefb41c0b9ae3726ceacc6ba45dc absorptionpol_res_17.out +5900682ee5b5ef3fea095642c75c2d40 absorptionpol_res_18.out +50748da0b3bf5a2bcf07c804aedccb87 absorptionpol_res_19.out +1eb0bac155c81a9182426a77c46e1a67 absorptionpol_res_20.out +c6c6f2e980851668bcd9a2468f44af52 absorptionpol_res_21.out +a196328bf1d703acdb905eae041e385a absorptionpol_res_22.out +c0bbda4dfab4b7f08f10bfae2dad5bb1 absorptionpol_res_23.out +8079a2528c597b1a8cce262a47cf1ec1 absorptionpol_res_24.out +fdef77726043aceca62d108d668623a2 absorptionpol_res_25.out +0ec80f9529817452c2a26c52a59609e8 absorptionpol_res_26.out +dc7326f5a2f63193bc9e34a99c998c3c absorptionpol_res_27.out +b077a9ae3abe3dfbd6bd6ffeddb07f78 absorptionpol_res_28.out +a65e9b80c641df657626919d767f8e64 absorptionpol_res_29.out +db649464063edc880c0032f6e354655a absorptionpol_res_30.out +5c1bdf847db96293b6ab75a8f2417a54 absorptionpol_res_31.out +417db45f80d942dab1228dd9ef05500d absorptionpol_res_32.out +16789b01756663962dced4f7b37cb0a0 absorptionpol_res_33.out +121c6e908ff24483272f07428ed1e4e1 absorptionpol_res_34.out +8b042fbadbf525f705748125f276e819 absorptionpol_res_35.out +ee14be1ae8146ef88b137d99e2399f7f absorptionpol_res_36.out +5c49e82347fc93dd9e2237369d6bca9a absorptionpol_res_37.out +df29c2aa498d5bd24d9e46badb2a513d absorptionpol_res_38.out +58cb335847cc8a7f2c22a03dc53626d7 absorptionpol_res_39.out +344affafa3ecd954dae66f7f2e80a34b absorptionpol_res_40.out +4668fa759e2abb706355b4b6e034f139 absorptionpol_res_41.out +89c8e9ab860b3938b8fdb4f4ed28c260 absorptionpol_res_42.out +145e5608e26e70b789331377e53060a9 absorptionpol_res_43.out +5e64d9c9f7cc4fe0f478c750e91d4e46 absorptionpol_res_44.out +793adf1b38d379c51eeda715c6a718ed absorptionpol_res_45.out +c92730349c7b0980edd29e1cb987af74 absorptionpol_res_46.out +aac97347f193d83771d9ffdc41986fff absorptionpol_res_47.out +56e0f4c6b36327cf9b1e0960dc787b12 absorptionpol_res_48.out +000f676b8e7df90c5a0621cb0096cc23 absorptionpol_res_49.out +9379b64d625a15c3343528f061c8108e absorptionpol_res_50.out +bdf8aeda6a8fda22180ecafb9c92e06b absorptionpol_res_51.out +2afc5ed89e9168f839097fd1ab904230 absorptionpol_res_52.out +a447f92961d94650e22acfbd87185387 absorptionpol_res_53.out +c3004f7e5ed2cb33ff4fc3cf8ce5e0eb absorptionpol_res_54.out +45e8663948933a379e4091d30081de18 absorptionpol_res_55.out +52e054a26730cc1fdd81773ebd2034a0 absorptionpol_res_56.out +5f4874be0ca94a7b0a9ac353765a2507 absorptionpol_res_57.out +aa48a21719e45a20d559b8a9c09fad96 absorptionpol_res_58.out +cca17b0d5e6e8d09868be2ad368c3af6 absorptionpol_res_59.out +25a9a4dc2857d852d0552ce3133d4b76 absorptionpol_res_60.out +ab91375a990e92acc5d950d6aa37b8e0 absorptionpol_res_61.out +3de4464b8b28acdf83a40622e4ea2763 absorptionpol_res_62.out +e29980232c7fae50d2285101fcdda421 absorptionpol_res_63.out +36e689b4fab116e6a92a5c6fae9657c9 absorptionpol_res_64.out +df3ed07fe22ff184bcd7fd322d50e806 absorptionpol_res_65.out +9b17b6d4d2cb0bcd9693bfc82c8f8d5a absorptionpol_res_66.out +79b27db0c27841288595f0f33d821f97 absorptionpol_res_67.out +3ba102c2a1f9bd4d742927b9b1ee23e8 absorptionpol_res_68.out +2631711c6a79a97cfd2ab1b77c6754ef absorptionpol_res_69.out +a9f961cb588ff56ace12706f4ce38473 absorptionpol_res_70.out +3aba6b20c6fbebb730400d8b233c3553 absorptionpol_res_71.out +3c3a9099ae93138cdae0b199aeb532e1 absorptionpol_res_72.out +2a74c8ee4af3de3350d6e79c8a5632d3 absorptionpol_res_73.out +be427ac9734a90323d0c3fdd273687c5 absorptionpol_res_74.out +0b8d6996a07f3bd3f9d616b4a781efad absorptionpol_res_75.out +8c87c0b3b5020a5befd2baee1c2f808c absorptionpol_res_76.out +19f1e08b6311bcec73a136a4a0dc42f0 absorptionpol_res_77.out +a46eaee51163e196e4218b6edcf41c3e absorptionpol_res_78.out +a4501a1a0e1ea985f90e2defd7ca1657 absorptionpol_res_79.out +d925104dcf6d32400f69d8cd1c4152e8 absorptionpol_res_80.out +128919d9faeef1a0a541d700d8365314 absorptionpol_res_81.out +aeb9a7453b6a952da29b88dc415f885b absorptionpol_res_82.out +1b799b622c0b6c586d14021ceb32a977 absorptionpol_res_83.out +80cdffda4e903943fefef3230a3e5153 absorptionpol_res_84.out +d8a1fbd45375d824d1c40ca3397659b8 absorptionpol_res_85.out +7bd2d4e4f0677187747875819077d412 absorptionpol_res_86.out +1326cf949144079e2da701c7864dd707 absorptionpol_res_87.out +cacf124d3f90b5f1ee28c808b51a70d7 absorptionpol_res_88.out +1cccb972fb52f33c3ce2d4ecda0efa0f absorptionpol_res_89.out +713731765755351550e7e8fcb8d7ecaa absorptionpol_res_90.out +45db16c024ac6773e4f608c1d51531a1 absorptionpol_res_91.out +de14218423d545fd95ddaad9c8c82153 absorptionpol_res_92.out +ef0b3204f33e73100d45b46c8249c097 absorptionpol_res_93.out +f783cd96ce41a4caaeb1932ea6330c37 absorptionpol_res_94.out +5ace93383f778eb66be1422f05f5bce5 absorptionpol_res_95.out +9d53fbd1b6bdd0b2b2b31401ff4190f3 absorptionpol_res_96.out +dc9b3cc97fb6e4a4903d0fdf48af101d absorptionpol_res_97.out +61e40b881783579b14da91dcdc6819cb absorptionpol_res_98.out +bd9eacb135a5238e8ae8729e98b4ce6d absorptionpol_res_99.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -e530204f33b7968990d8f45041cc9d47 deposition.out -5a399fb3c54f7ab61519709a24da7f29 emission.out -d6c1f8e9df983928979acfe4c24db36c emission_res_00.out -30b82c590e02d6224f9279da36a41287 emission_res_01.out -c6ca913f13bf5d5e3f5e854b0661cd99 emission_res_02.out -cb128e883bd22e4a5549f429aaadb918 emission_res_03.out -66a5663bedfcff6befd36fb949ab5115 emission_res_04.out -c3627206f409456ccdfefa93bad15329 emission_res_05.out -a4b4d60a05a5c347a6ec7a105f5877b2 emission_res_06.out -9c5d9d768be3775e4dfd35a8c207d095 emission_res_07.out -986895acb8539eda6c4116f74668015b emission_res_08.out -568faad0358b9e64e0311876e8a7e576 emission_res_09.out -83c70fac07f5225b73ff24ff60c19a7c emission_res_10.out -855c9ed82fb344e6f4529586f12c4cd6 emission_res_11.out -70850ddef161ab8041b1228eeeac901c emission_res_12.out -26bb682f00a5109b695e731fe87786f7 emission_res_13.out -a78c71bd2aa5e547f92d166aaf41b90a emission_res_14.out -9b9422653caab7ba3ad5528960bbf5d5 emission_res_15.out -00e99894520bbeb8e0c1b69cfbbdb019 emission_res_16.out -64597cbe54d7e276f914f089192fabbb emission_res_17.out -d030bb80b9bc4937780127c580745a50 emission_res_18.out -4fee83796ac60b7d2221f01105e01e1d emission_res_19.out -14f4a911e8f189a17a90836954d8ecae emission_res_20.out -5b1bdd9427ee9dcb63a05a688b16d4c0 emission_res_21.out -4c4e8758f9a24d1835c1e0eab4cf9065 emission_res_22.out -b0cda59a6bd3d3e3c87568ce6c6a5279 emission_res_23.out -15868460f72ea34c34977031c9d4c1b9 emission_res_24.out -879e0383a97aea284de7d714f277990e emission_res_25.out -93bd56a37bae2724c45fa47b79df5561 emission_res_26.out -ed07636809cbec0f0a7a8fa78f9ffae3 emission_res_27.out -f86ef98b8b95f73c32e9fb57551bd86a emission_res_28.out -7e436e0a5d8dff8f880273987240138c emission_res_29.out -922342865809afbbc79618b1bf891042 emission_res_30.out -8de01f27acf7f310d21c2d37ea678e4d emission_res_31.out -31ecd03506e6686980528c4f990e6faf emission_res_32.out -4da933c77838f899e9724709032081c2 emission_res_33.out -aed2306c177d37705820810c81c3d11d emission_res_34.out -e90aceca6f82afb5908e64873f60151b emission_res_35.out -06f4210b954f3bf1024ea81f824b0e8a emission_res_36.out -2b2a495c941cfc1b6d91392bd77d31a4 emission_res_37.out -e39a917dbbcdfac9648fd31620156b81 emission_res_38.out -92824f76d017903f51fd180f953d85a9 emission_res_39.out -1c96ed5cd3bceb5d0df55328f73634a9 emission_res_40.out -06f2983fb56acf267117e71b5e0f66b6 emission_res_41.out -3b8115dc7e58fa21a109452c09e56a4e emission_res_42.out -441814a73d52835a4463cb88394961a1 emission_res_43.out -5405b804d0c54f708299b228339a5042 emission_res_44.out -d33b262fe43da96c19b8666d85177a82 emission_res_45.out -66037b3f2ec5bbeb15e73adfbb956c10 emission_res_46.out -834743ee81e93fd1ed05cc05c503db09 emission_res_47.out -c9626bc9d72a87c92d14fca368092d29 emission_res_48.out -cc1e1f203056f91b993e4fe320440718 emission_res_49.out -b709e3643030d5dc24d583b73ab580c0 emission_res_50.out -f8f1b7609afbfd1163236eb4aef96643 emission_res_51.out -ab27319fe65e7e58958a7e54e04aeac5 emission_res_52.out -95a07675ea422dc0dd70f1e533893f35 emission_res_53.out -49c6e65f84ebef81a31a590346bb5560 emission_res_54.out -6322a393ab5770a302a376148c6184d5 emission_res_55.out -8ab324801dcba31c0cb64422476ee963 emission_res_56.out -7e8f7e68b388499cddef733abf30284e emission_res_57.out -8876216c7b19ade1cf05903acb8820fa emission_res_58.out -edd79a426be787df6ed29a681fe1a08d emission_res_59.out -bf65ff2e3c51b48e229d5adcfd839600 emission_res_60.out -96479c3807df4b1f84f52f563d70ced2 emission_res_61.out -e61ad78bf499bb182d59dddd39ca0d93 emission_res_62.out -72d812d4a7337ead22bc827a77e4a3a3 emission_res_63.out -4f94c37eb1a080abb89543b240088115 emission_res_64.out -a22be0413df847e54c6abae452a84cb7 emission_res_65.out -4c60d084ec7e1b4ae8d405e26eea7910 emission_res_66.out -6ef6e83000d4e475428fe0b22708b75c emission_res_67.out -c27c315f3a0f8e4411118a9444044e34 emission_res_68.out -1ac42f7aa33a7f4e97d2cf14f153d962 emission_res_69.out -0626d14f867847ec59871e9a181e68e8 emission_res_70.out -8c444826a8288658086e3bcfacefa564 emission_res_71.out -367b887adec2cbd35a50b2954099a6fb emission_res_72.out -c2c8c2b482efeec66e460fccb48c5e14 emission_res_73.out -65d4edd1075cf81eaadc64de7c18870e emission_res_74.out -77a1af6bd2a30c76f45a83bf98d70074 emission_res_75.out -2e8772740b06b174715373ba5afe03cb emission_res_76.out -f30bd1d506f4ca9de4a484c0ce6e0d80 emission_res_77.out -fa291be4912517be0b03f41819617c0a emission_res_78.out -6e0d081beb36f3ee6fcbf0c8cf442b06 emission_res_79.out -45c8743a8daa7d70074a3008feb4f8dc emission_res_80.out -d44872ffa92a01c46ebcce0b50dd6510 emission_res_81.out -1bd061b75d261aa10db7933f1cc0551a emission_res_82.out -164fe0836684634d6b18fe1da932c927 emission_res_83.out -43d2f90c2d87bf62e158cb31f1d80449 emission_res_84.out -9cfe95a6f65b6e30b9ec64886bb2d056 emission_res_85.out -6056a3de70e5c6ec66fdccc11a404ee5 emission_res_86.out -e9fa7beb1acb16eb0db6572850976e1a emission_res_87.out -de7e9340fa5aed9009dc03c26c9aab6c emission_res_88.out -2db8883fe9d066deb152bf8f3af1543f emission_res_89.out -05935ba1456e74b13a004f0060b7a472 emission_res_90.out -931dd7d962982317d9eeba7f6872c29f emission_res_91.out -45c85a78188be75b7b7ad2fadf46956c emission_res_92.out -db246ebcebb8030a74de8ad2c523daee emission_res_93.out -0999b944328f5ddc685237735bdd4f22 emission_res_94.out -e1e7b71a5a1a008f632785fa0b2312dc emission_res_95.out -2c9cf708452dc7bf76102243e43207c1 emission_res_96.out -e363fac8ee22843d6e4c64b65f7ff8a4 emission_res_97.out -914c395cd135d64d7b23ae0ef948aa0f emission_res_98.out -4b94b9b8f301a136a0e2ef3e5297331b emission_res_99.out -5c02b066d7619ac531d6d34ca56f2d1f emissionpol.out -d2e4e3326c6b3a96ad612a28a8f74845 emissionpol_res_00.out -74474b71d2db51b946f551698da6b0e7 emissionpol_res_01.out -4044b6e6b7380f0a8c6418655a2a187e emissionpol_res_02.out -d285d72a96f18247b1b34372292bb528 emissionpol_res_03.out -1c153c6aecf49c7144ae543c9ea57df3 emissionpol_res_04.out -78f9f692f163e38de2dc5889882d77f3 emissionpol_res_05.out -85cac259ff916ca53f3885ce70d18baf emissionpol_res_06.out -ceea522985c6916550903f112a019a71 emissionpol_res_07.out -67c3bf92326bf7e768dce89d15aabd8d emissionpol_res_08.out -a93b1131623f140ef3cb65716688047e emissionpol_res_09.out -7d430caea2578a12a815741bdca2e49e emissionpol_res_10.out -296c19b46395089adbfb3750ec072e85 emissionpol_res_11.out -f2178f86ba3ae5413140e40834b5536a emissionpol_res_12.out -6493571c7012cdc59ed373c761ada329 emissionpol_res_13.out -4996318249ca7cad4244ab1347ffd540 emissionpol_res_14.out -b0cd3e4f53d2eee41fc911e311803581 emissionpol_res_15.out -0f680c2dea673d2a06f621a215471d78 emissionpol_res_16.out -60d80c82473bb22496f575bcb6548907 emissionpol_res_17.out -19fbb0431b7951c00211acb527b4ef86 emissionpol_res_18.out -a8e9c886ba78ea8fdb50be8b91e9e3e6 emissionpol_res_19.out -c319bff0a1095cecf5957e2421a4ed6b emissionpol_res_20.out -0647130bee43b15340971494676d8896 emissionpol_res_21.out -97de905b8eb90cda1a0f2fe9e10d9e6e emissionpol_res_22.out -28dad708ae5a0f95a971cf6bc814baec emissionpol_res_23.out -5cf8631202907db2df53e827ab7860e0 emissionpol_res_24.out -0f3ed29a53b1014a75a5a94ffb7751c9 emissionpol_res_25.out -15f364a59a86f7c83c7e01ce30716cae emissionpol_res_26.out -22cbe31443810a10d95156f89646710b emissionpol_res_27.out -78d69f8eaf62febc7b7038bc03833bed emissionpol_res_28.out -62aa60c3fc96fa78c62942d0d41713ba emissionpol_res_29.out -3db430871b1d5ec2886a53c99db8e8af emissionpol_res_30.out -89d854c930017d1c93bd139b31d1b041 emissionpol_res_31.out -747b24f70b4fd769771243581fa1a9b1 emissionpol_res_32.out -ad978aec3d17324a8d39c935a3b87595 emissionpol_res_33.out -b4d807dbc01007f2a5342da182257a43 emissionpol_res_34.out -0d5216142f0d9b5a0438c4352c5f12df emissionpol_res_35.out -06f76e84a34bc6dc2074d9ab42e7bd85 emissionpol_res_36.out -8715ede9663ff9f370cc93f23c9dd467 emissionpol_res_37.out -4573bc9666100969f7c97281a068118d emissionpol_res_38.out -b8f76bb26d58f21b45ec4a8c4e85a4aa emissionpol_res_39.out -2ff85c71fa29f08c6d7a88e184dd665d emissionpol_res_40.out -b2dd0b5a7925fcb5cef96b5e22f30f3b emissionpol_res_41.out -4f9076d6960254b3bedd077ceadaead7 emissionpol_res_42.out -47a26ad66436417010546454b98b0cdd emissionpol_res_43.out -93a5fef79756d22f7a447ee9b4df591f emissionpol_res_44.out -8d7c3a5ee0b828deed31fc47afc6c0d2 emissionpol_res_45.out -706ba63b1b4ed53c5ebe19bb2f69c1de emissionpol_res_46.out -c6642492a4abd69f8929c0f29655cccd emissionpol_res_47.out -5a6973e0939fc76f1e05e192f390378f emissionpol_res_48.out -1deb7bf3eec4c25a3ab1e9b1a85f1ec7 emissionpol_res_49.out -7ce0c873ce32f9ebaa311ca4794d4cc8 emissionpol_res_50.out -c1b9eead8370584bdb54c0bc13b8256e emissionpol_res_51.out -fe7e91fb64177d02cc6ef4c3230e7b6c emissionpol_res_52.out -793becc11e9ad0f0daa8de5fd24c2223 emissionpol_res_53.out -594da9f4527390dd7461514b64edf829 emissionpol_res_54.out -7783732974078d65aa98e4af56454a91 emissionpol_res_55.out -a857ad6ed02308da2792a1c88438cbff emissionpol_res_56.out -900b8f0164ccd658f48d2a5e0fd26338 emissionpol_res_57.out -9a878eea746e6fc520d975e9ad6979ca emissionpol_res_58.out -7a9eeaabd6874efcf83124f23f157894 emissionpol_res_59.out -545a40ea47a144251e2d601e57bc3fe3 emissionpol_res_60.out -11e9403c566cf88f843d745bc89abd92 emissionpol_res_61.out -67bcecda4577d16cfb86dc1404b8cf63 emissionpol_res_62.out -7dbb9bee053f3bc5fd3b6256ba60cdb6 emissionpol_res_63.out -a52cdbc66f0fb267641c4691a188d0d4 emissionpol_res_64.out -89648b0e2337fb88f2d649b25541c063 emissionpol_res_65.out -20878fe945c8615e22cc150ea45896f6 emissionpol_res_66.out -4336b3f9f9e6d2feda1c37f396ff303f emissionpol_res_67.out -dc6ab3fcc1859b69626bfc61283fa048 emissionpol_res_68.out -71482e40bc57df8edfc855d3cad53398 emissionpol_res_69.out -e12a9e7027c5328a9b0487400234b9a8 emissionpol_res_70.out -8b034d8afbd7f6e3839bc2570f18ef4d emissionpol_res_71.out -3fde41dc868a6458eeed29b535b596c1 emissionpol_res_72.out -1174467c837c6c8ffcdb9c76970b65e4 emissionpol_res_73.out -f9718b58940339539e2df746492a0a23 emissionpol_res_74.out -5f47acf327c6eb60526adb1c2bc2f5eb emissionpol_res_75.out -fbd1b46b8ecc852d610ae014d8776c27 emissionpol_res_76.out -f7bc2c8bedefa457d1806afdac37aec9 emissionpol_res_77.out -a29a6d478fec57fa3188d3c4bc7761e9 emissionpol_res_78.out -5eec68f7c1954a42a0cdb24904470660 emissionpol_res_79.out -226e459b3d316851e959012554256951 emissionpol_res_80.out -91d026b17870e73bc40b6806fbc07a37 emissionpol_res_81.out -240d825efa2f277676b3d464f5854477 emissionpol_res_82.out -764cc31d6634a3fb8d29812f0b65fab6 emissionpol_res_83.out -079f5a6f27d9cfb90d6d9099276e63ff emissionpol_res_84.out -ae3d5e359d615083969ed6fc72aa3d71 emissionpol_res_85.out -708753abb7b7089f8263ca1e8cd0a481 emissionpol_res_86.out -e92f73c9479db51cf38efb5b169a95c5 emissionpol_res_87.out -25f578c6ce60cc99764e32f1e98b74e4 emissionpol_res_88.out -5cdee734e32026dbcbb93331fd3d5449 emissionpol_res_89.out -920263c867e880f349f772a803eed247 emissionpol_res_90.out -020c0fa315bc1ce46c8172caf5d2c977 emissionpol_res_91.out -2d2e54664f847baf882816954bc33e8a emissionpol_res_92.out -7f35517d52d7877b3bf03ec30f84ce1f emissionpol_res_93.out -ea72ffecaaff6187ec916e6c72d4af32 emissionpol_res_94.out -eb9a06d129991d2ff35e8049818dbe9e emissionpol_res_95.out -ffb1aa29f7d1281257a6ef34758c5490 emissionpol_res_96.out -e557aa8587797dc331bd0f8e626b474c emissionpol_res_97.out -88294e9c2f3912347bc3fd2d7ed1ca4a emissionpol_res_98.out -8b8d93838d6afff3a6eab640d55c47f9 emissionpol_res_99.out -bda5e8fe0059ceb043103109aaaf03b9 emissiontrue.out -10015d457488d87352656b65d9948e5b emissiontrue_res_00.out -3518d3bd20c91b126ce6d8fe66e6cfaf emissiontrue_res_01.out -4878c78bf3f9a58599fffc4e934fd30e emissiontrue_res_02.out -a12eb06cd714798a34f8e028a356d319 emissiontrue_res_03.out -9b0c81db6c94aae12baff2192069cf45 emissiontrue_res_04.out -33482141c2d1f09a1800f14a5ef37750 emissiontrue_res_05.out -5bc7ba213c0b0256ca89e74da65f18c0 emissiontrue_res_06.out -40258e6a8c5d5f29834d1dc3bb66b655 emissiontrue_res_07.out -899e90f705080573f8d7fe174c19f06e emissiontrue_res_08.out -258e9ea55b73a622a05d7f6b437b2b01 emissiontrue_res_09.out -718895f942cffda3ac13d32948c9129b emissiontrue_res_10.out -eb980982d85d7a72e5c188a21a8e29d5 emissiontrue_res_11.out -a4b0c8484380433d0ac5192dc2a000df emissiontrue_res_12.out -09195f081bceb71dcf1f04b71aab99db emissiontrue_res_13.out -00210f885a7b6c48d6856cd24a674fbb emissiontrue_res_14.out -ace6cc74a8fc82bd47d49da41b611f65 emissiontrue_res_15.out -cbdc404f432c33333597c05fa8ee5148 emissiontrue_res_16.out -4c42a48ede46da1f2bb6857512171377 emissiontrue_res_17.out -0ae7b841bf8450b9f685264fa4d0c450 emissiontrue_res_18.out -5dbcf73079561394914d8b486e477484 emissiontrue_res_19.out -e81314d5f5636e4a5dd37c4249fbe42f emissiontrue_res_20.out -d6b721d4e009e70d4cc465e518fce244 emissiontrue_res_21.out -ecdcfc1d3055b139303fb9d0b4a3c2a9 emissiontrue_res_22.out -2a9769639902c664def96258275e1a7e emissiontrue_res_23.out -82a5b639e06cd6e4c65dfd398c10bf8a emissiontrue_res_24.out -3dc10f1ecb1ca0d73debed57a0a6d1da emissiontrue_res_25.out -d19c5e4c4d85402466117a0482675cae emissiontrue_res_26.out -566ba991ec8bfd73284d4c54eae60ca2 emissiontrue_res_27.out -5efdf60174eb6f700e4143c65c525f09 emissiontrue_res_28.out -03098cbfde976a824567bd75a43c5205 emissiontrue_res_29.out -a2be8d4a9f88e74a94e15d4e2b2d2937 emissiontrue_res_30.out -fc9f3247dfa33251cd623fe7c485efe7 emissiontrue_res_31.out -f5228a5ebbf816bc6ed24df3437de43d emissiontrue_res_32.out -ea24b3101199e856243fd617b29d0bfc emissiontrue_res_33.out -f43e3cb09d7f40785549f78217f759e0 emissiontrue_res_34.out -579d6ca8c3c6c2fa2177bf37f808e0b5 emissiontrue_res_35.out -c7d6d3145fefef3be751ab993c1eb632 emissiontrue_res_36.out -fb3f20af1596ca5f7cc3f29e8c711d3f emissiontrue_res_37.out -10823952aa67d66c81ff7a46a0fdde8b emissiontrue_res_38.out -0a44152178a545d671066767735b6e8e emissiontrue_res_39.out -b43edf7f057a58a851554a7dd181e64f emissiontrue_res_40.out -2b772be76db2e3ba8462f346a23b7504 emissiontrue_res_41.out -44b743e0e459e265facb46125fee4d84 emissiontrue_res_42.out -470d7ef6aa5dab5d9f27a7d563b138cf emissiontrue_res_43.out -3b6c551207a22b9b351d2a612fb3cd67 emissiontrue_res_44.out -3cda0b7dcabb4161f9c0ae94278dc8f9 emissiontrue_res_45.out -64e6edddffcb1507bfe1a927350af7ce emissiontrue_res_46.out -0a2975d0ec3c004a94087461732d4cde emissiontrue_res_47.out -179222c09007d9d0c27354849ca3b83a emissiontrue_res_48.out -669cd44fd9e37f4ba79ec4c1d8115f9e emissiontrue_res_49.out -3c88bafc953c49374984466f37935052 emissiontrue_res_50.out -a60403b91390d4469b5ead7884247b26 emissiontrue_res_51.out -74fb43be64d60378991a208ed6a4daf7 emissiontrue_res_52.out -06b3a898579a882c48c38703e2920d16 emissiontrue_res_53.out -472731d6ab60db7fbc57b09c951b64eb emissiontrue_res_54.out -effdd7040df803098b275a3b75243483 emissiontrue_res_55.out -708abe0321f202ee87171d6c1814526b emissiontrue_res_56.out -ecb267c84fef84e8eaab956b552671e6 emissiontrue_res_57.out -69ec063cee3b4e03d0a052806a118e53 emissiontrue_res_58.out -47348c9342bd8e400bf0ae49bd695583 emissiontrue_res_59.out -f6da2a42f8b41d33066d18de5309675a emissiontrue_res_60.out -ce37fa01aa02ac4bb58b557a510f5afc emissiontrue_res_61.out -44bfd0d91b6ce896c79d51742d672e19 emissiontrue_res_62.out -5f3ac663f60bd42da7ed7d9a2c5d9036 emissiontrue_res_63.out -9601631774f1c523a57bec286a53c6d4 emissiontrue_res_64.out -04d70ee686fac6c7ce614cbbaa7c600f emissiontrue_res_65.out -92f9b7d428130e1d9f3349c2f003b5de emissiontrue_res_66.out -5380d7422c2bb87e416436b9007b9784 emissiontrue_res_67.out -1a8a565d8b96fbe5be3d09e8c1b4bbde emissiontrue_res_68.out -587dc1ad2ef40163ed3c5b13aea1beb8 emissiontrue_res_69.out -69acea024096385b518bdbe57f744541 emissiontrue_res_70.out -4bed1413fcbf4e73feae57be1d52c0dc emissiontrue_res_71.out -bc2a9604690da007711d40cc8f3a7aec emissiontrue_res_72.out -8a616fa846b62d06f6201d91754c4f05 emissiontrue_res_73.out -2c1bbc51d0b9816eb3a02c35b76748f2 emissiontrue_res_74.out -28f455e6732f2f88daa2ca3afd6bcca6 emissiontrue_res_75.out -1cf52e925d7d7461ee0d51ac42cc73a9 emissiontrue_res_76.out -5e9c340ec6bc1fc5cd08f137ee837ecf emissiontrue_res_77.out -a8159143805a8a5433e5677e12403d2b emissiontrue_res_78.out -acec97d8f51c79a33a8fb72fc3b8c9dd emissiontrue_res_79.out -27126fca44eec2d78b89382e3d2ddbd2 emissiontrue_res_80.out -da47b7c8ee0556807720f0c2675a4232 emissiontrue_res_81.out -cdaf9344bcb9cd94c8386083467d23ea emissiontrue_res_82.out -8a726970ca90316eb89ef41fb358a02e emissiontrue_res_83.out -e80f626fc160e672e81cfd10b1ee8f59 emissiontrue_res_84.out -87be626ca782f53ca20fc2b7cad516f2 emissiontrue_res_85.out -dc645b33748e4f7cc3a0c24e36de5dd6 emissiontrue_res_86.out -45ad3c555adf24e82409371f4c9c620c emissiontrue_res_87.out -f2bb5a8bddfd6095d7b25f19bd0cfe25 emissiontrue_res_88.out -12120d50b7576d829a56249b3f3063d4 emissiontrue_res_89.out -2d987202b1af2a68b2245db9cdd975d0 emissiontrue_res_90.out -255116ee8a84196bc10603a1fdb4149f emissiontrue_res_91.out -fe9b17b020486f7c010450ac594950c9 emissiontrue_res_92.out -bc604b5ae563dca2727c9a2e8950be0f emissiontrue_res_93.out -0b983ec787e72602e109363e5761b230 emissiontrue_res_94.out -b09e8e63a1d35464ff5f3c7d18ca8f0d emissiontrue_res_95.out -5b45bfeeb891780a5a7354dfdcd2517d emissiontrue_res_96.out -4c21660abb605b1bd2fb5c4da8b636d8 emissiontrue_res_97.out -4e4160afba57e1d618e9d48dade344ad emissiontrue_res_98.out -26d829e122364cdfd37925a6b5c445dc emissiontrue_res_99.out -d5dcb365f4d8bc8fadc8aa7052918411 gamma_light_curve.out -adaf870be36864429d59a4bffc28358b gamma_spec.out +b10b1e323d660848ec6e580f61578b81 deposition.out +dcd6a51d0967dd808a25298c21ed731e emission.out +9212aecc608c1cf663ca415c99782e05 emission_res_00.out +261b857256c58b502c766b01be7b1092 emission_res_01.out +ab33dd83a6b0d9ada73722c6f955793c emission_res_02.out +6a9c38ccfa1678e8ea478b8fdf2f41ee emission_res_03.out +d32f37a18254dd5a38d1139c75e7a259 emission_res_04.out +b2acc3260f2be91405335290d7869ca1 emission_res_05.out +88b842b4b35cf48be679d2be24739808 emission_res_06.out +61aa45d452fa656d3cf3a4163ef9e863 emission_res_07.out +59cf0ba14dc41444da0d344c4676b0da emission_res_08.out +892a9babd440bbb657fdc6e4049009f4 emission_res_09.out +aef0a3ca75c6a882dc2e9fc31bfdf37d emission_res_10.out +4ef22dc722172ed5df04075e1c8a4d5c emission_res_11.out +3e6d05f4e795b1ae453f28d318928ab8 emission_res_12.out +e0ba8ea1f169f6c7763839bca9c6da2c emission_res_13.out +08ebac0be1e4fce5e012b61a4f53fd0c emission_res_14.out +2e81e238faa71f2a8b38c770b15470a0 emission_res_15.out +778af3051be7d6dc71e58b72945a6809 emission_res_16.out +5a59a21f5d17fe23838796ebf06e98f0 emission_res_17.out +5252f80f62417a63b0dda757b3a885df emission_res_18.out +dd114416fc0651ad48fd437a2c6a5b49 emission_res_19.out +c7325e989bb7f5ab4dc67ac1f10ebc53 emission_res_20.out +182cfd439b6bec4e33eb7ac3a47459be emission_res_21.out +10fbd01a2ae2925cb8dfc151f324ffd2 emission_res_22.out +8e835dd1fe4496039d14edd9ea6e4257 emission_res_23.out +b468fb66ff3e6bb2f54b4c64f6f987da emission_res_24.out +057126c42953596ffe73b664b8924850 emission_res_25.out +c4bd8fde3e0fa56f37840e3141e91420 emission_res_26.out +bb5e8380427316bf1cb1c14f3834efc6 emission_res_27.out +40d854dd10e87c7c21f951b1225b53c3 emission_res_28.out +1796d24d490d6c2252a69f8caed43735 emission_res_29.out +c4911a3a0291fcc4d3e06fc141711d4f emission_res_30.out +ef4d885a894e50f100d9f62d4d289528 emission_res_31.out +b05868c7e5515536e7ddd758152e730b emission_res_32.out +abe4adcade59226e3ad3a0d77ebadfd0 emission_res_33.out +113dc9ce774b4deb720d3baa6f70d851 emission_res_34.out +4f47ac52b56596652931737d7d15afd9 emission_res_35.out +8c10f04f1b0bf532d90003cbc640b469 emission_res_36.out +d94e56bbc0175ff68b7c576acfa6656f emission_res_37.out +16a5029a4dffa673a04fbcabffcb35a8 emission_res_38.out +63d1dcc0f352b479af5971c778125634 emission_res_39.out +cb010614cc490efae8b2ac30c8dbc6c7 emission_res_40.out +60f3a85f630949c9269410945cbbabd8 emission_res_41.out +5637dc059d7732ac99a81153edbfd2a2 emission_res_42.out +d81bea01c778c8e837e56d14d9e1849e emission_res_43.out +6727a305006f36437388cf257916d489 emission_res_44.out +124c2373edb9d4afb78c9b464da3e357 emission_res_45.out +aa17b5c3aa41100d3b9409efc44477e3 emission_res_46.out +73a216d4e930147f732eeddbb9a47616 emission_res_47.out +2dd300a4423b7894a11eead301b5d83f emission_res_48.out +b65572be6e4874d274159e57cef8a29f emission_res_49.out +efad285e8fd1ce63d222c6b056a46107 emission_res_50.out +1d56d75e0278d360b6aae9bd10972909 emission_res_51.out +8820a2fe2f011a311fddbf541a6c3b3d emission_res_52.out +80ab45558f8102ae6b74033c507a12af emission_res_53.out +f42b44fb63e1a542fe4ca20bf12acdb5 emission_res_54.out +841fd36689439b2e572684fbb092f92e emission_res_55.out +7742f26d2854e66392ac33a7789648b5 emission_res_56.out +a1131444c84f05ef04800213b458eb88 emission_res_57.out +13f4e3447f04e566f3da1e5c7fa6f56f emission_res_58.out +6165749df7017ec7e06807627b5aa556 emission_res_59.out +10b00290e8a53010750301afdb6d401d emission_res_60.out +6446766dfe73bca53ebbad3638d87d52 emission_res_61.out +67d3c1966ed9733965e881eacda6dafa emission_res_62.out +a56724032326e29b789389184a817100 emission_res_63.out +52df6926d77b28453bde119b1bdd5943 emission_res_64.out +3812b569b6241e5ee9bd8e2400ad3ff4 emission_res_65.out +1759126b9c93f508af1df9b943f471ed emission_res_66.out +84367cb9211e9d96a5b9873b357784b7 emission_res_67.out +161422a10738d73f0c07db6e830a75cc emission_res_68.out +32408f2d1ff64bd809ed4cf8eb963a65 emission_res_69.out +88b96e29cc469f67ee413f78c58a9a76 emission_res_70.out +f1f5ceda16c13a7ad071b1a634fa6bda emission_res_71.out +2ebcbccb9cef4cc84e71b7b22fbb7c13 emission_res_72.out +e210bdeff1c2fd35ea586699a4b95b1f emission_res_73.out +60d905085c75cb075b8bbc1d3ea67f26 emission_res_74.out +bbe4fd31b177a71ff9bf37fac21db957 emission_res_75.out +01cf996c514249249c936b7e4e20d735 emission_res_76.out +dd41d72d463db7a7b2b4408c05f937ff emission_res_77.out +bb3e37f1ea1a95923e06fe8c2eba1314 emission_res_78.out +57bc44e63f1bb8169cc9ffd274e6fede emission_res_79.out +78197a01c91d579334b4278a4f315586 emission_res_80.out +7a6a52a19d1534bd6a165017b6df4754 emission_res_81.out +412900de1a7b427ffaa99fac3fa2d754 emission_res_82.out +4de9aa27b70a15339a4f2a7a4623ed27 emission_res_83.out +f0096d5b29fca98507a17e32f75335fa emission_res_84.out +10871f114a263b434c7d08b383cb4b39 emission_res_85.out +705c720f5267f2bb205d223e62bdc3ce emission_res_86.out +abce184bbae7b990c6d97c6af79fd020 emission_res_87.out +30490514022e46cc49cc847ff84e9b7e emission_res_88.out +e567f99186f6eacf39c8782af9c6fe18 emission_res_89.out +f868fdf18018b77f31c93622bacb330f emission_res_90.out +020d912923426bb5944c4644d93e7292 emission_res_91.out +4f7b9b76e3fe2c36da6e145c58df2901 emission_res_92.out +6c81e2aa36e6ad4799e1806657551522 emission_res_93.out +37a839a6682a71868432d33e0f1f8581 emission_res_94.out +9e419d403c1a05b6def446def6fa0909 emission_res_95.out +0a9d65743830da89412cc86d05dc6490 emission_res_96.out +fd844bb2e6b95c002ae65aed405eb1e8 emission_res_97.out +49eb472d04dbcac4dc69b4ae661b0c70 emission_res_98.out +b0926bc958959c571ef6f6f30d270e76 emission_res_99.out +a2191722c08a6a8311dcc9a12ae745fc emissionpol.out +7969940ddde659830705498f123a84dc emissionpol_res_00.out +7b8f54229b7e1854dc7c698b468e4889 emissionpol_res_01.out +1b52561114eae7dc388296a328faba76 emissionpol_res_02.out +c95fb997374e1d67f14853930c4102ff emissionpol_res_03.out +5dc2a196e032c7a3f9ee8d737b4bbc9d emissionpol_res_04.out +b95d2155f560c9ca27fad4f0cefe8f9f emissionpol_res_05.out +5161628803d5bd45b1518ef9aa1d2bb6 emissionpol_res_06.out +a7d622c4bbb17c510d704897b144c6a6 emissionpol_res_07.out +93ae6787d54508a4d44321809be03891 emissionpol_res_08.out +62dccfa23e34046660907d2628b1e7b3 emissionpol_res_09.out +2264144f1acd54c68d3d1dcbf49d4e18 emissionpol_res_10.out +8902f019f57e39f2189254bc9b9d4f10 emissionpol_res_11.out +0c7069fd7a3b7889afd8f9894b048996 emissionpol_res_12.out +9e37a4899d28a96bbf21f2c3366ce4a0 emissionpol_res_13.out +9e79a711011553a3e46555392ddbbc5c emissionpol_res_14.out +ef0108af2057a7adaf1a8be29538659b emissionpol_res_15.out +8ca5992fbfa2c823aa2ccda912b72df3 emissionpol_res_16.out +de1fece89ee332e038e254a1a6e3433b emissionpol_res_17.out +7e93331248ec3dfcdf5c88b0a2cc1b7b emissionpol_res_18.out +ceabeb0b6facbca5577cd9f79226e235 emissionpol_res_19.out +38454c80eaf31ddf2c4fc83b776d04f2 emissionpol_res_20.out +168a7695d758fe2fcd63a91d8f46d443 emissionpol_res_21.out +af299e15c6eabf1ecf9850b085286932 emissionpol_res_22.out +36da6201a86b04daac46af80931fd9e1 emissionpol_res_23.out +f464a6433bd5c33204ef89cfedb0fafd emissionpol_res_24.out +ed276a85e00fbaf371d170a86f3d3cc2 emissionpol_res_25.out +e38b7928f0f47f79ac62fe456e500adf emissionpol_res_26.out +f82dc5290239499f5a0d9c24fbcdde7e emissionpol_res_27.out +61b887b4fd701b1926330ebac5483084 emissionpol_res_28.out +ff6988fede2ce8b6e07d171144bf8835 emissionpol_res_29.out +b0d0cf4eb99719548daeb903be7735de emissionpol_res_30.out +4ea99e9da70e420fe8bd1fac44030bd8 emissionpol_res_31.out +050fc1f1b0860f72786635d44f5d18dc emissionpol_res_32.out +183be76357de185a804dccda1f3386ac emissionpol_res_33.out +4c5ee8c34c50a95295a28bd556ad4a95 emissionpol_res_34.out +5163bfcf9d7d23bc26b0afff8170e053 emissionpol_res_35.out +98f71b3b2ef2e88aadf9531f0bac1236 emissionpol_res_36.out +9c0bb6962eb536cb812a8c107dc5a889 emissionpol_res_37.out +a0213e729f9fe1d3d780cc6684ceba3a emissionpol_res_38.out +76b25545af36f2801d1ffd72f4852ec6 emissionpol_res_39.out +c3714efeed25c944ef31e227e843c192 emissionpol_res_40.out +37209c33085af840c1eb2fce0b095084 emissionpol_res_41.out +5fecf392c9eb51df78d4187433513431 emissionpol_res_42.out +7bc0ba8e58e9d7bbbe4bfbd635bd0e29 emissionpol_res_43.out +479bece3c15023e4955705d758f3059d emissionpol_res_44.out +9c2a9c2fa6c1c30a39550303f8803bc1 emissionpol_res_45.out +ba88e0b0fcc7a541b0abbd60a93c08c5 emissionpol_res_46.out +a8ae3256c9b46616462c1cd55d0f07d3 emissionpol_res_47.out +04854280da47c7013c5a1c9295476935 emissionpol_res_48.out +1ba542bee6f2dd90858c5517bccc9ea7 emissionpol_res_49.out +fd4701beff8d6691d4217f355264af87 emissionpol_res_50.out +a3e8ca5574683953ec448d732ebb9315 emissionpol_res_51.out +f53f8a29eee12192af4b0d7a726b0f5d emissionpol_res_52.out +00138ee3dc25d7ea123fc2884627d037 emissionpol_res_53.out +aeb7cee1f261223c2e492e3bd9145fe6 emissionpol_res_54.out +b20e5fa7c58ef58731935710b3145cce emissionpol_res_55.out +bb85cce0743942ed72327d71f4450260 emissionpol_res_56.out +3b247fbfacba1450e4ba3317373d9d40 emissionpol_res_57.out +38170f62725abca3897712da16251838 emissionpol_res_58.out +5161c16fcb420593b64937f1cb020c16 emissionpol_res_59.out +ad3af3f9efd9b495b7dcdbcacd591b5c emissionpol_res_60.out +30382968ba79990a9126f857050287c4 emissionpol_res_61.out +d1d584e0f5750c9d956b3b6ed8f6ed9f emissionpol_res_62.out +6cd4c41011eec7fb57e5e4548e07097a emissionpol_res_63.out +586da856c5e992bf00e4dd86ae049af8 emissionpol_res_64.out +634b4f990dd47dfb5ba148152d922c74 emissionpol_res_65.out +5c83f654a2eab4b6f5ef3f2a08b6bee5 emissionpol_res_66.out +10034e36439ba01d8aab82ed1f102590 emissionpol_res_67.out +2a36909f2918164616e31d84199bee55 emissionpol_res_68.out +fa6892651b4b7cf3c9111435b8456bfb emissionpol_res_69.out +bcf56c8df883f19143f75f53531beeb1 emissionpol_res_70.out +f7277a0882452111af6170a9cc7c810e emissionpol_res_71.out +6bba372fc204ae547ddb681fafa1f930 emissionpol_res_72.out +0f3cd6d1df39db1301f7639d785ef987 emissionpol_res_73.out +51b0d1e8ebe8d7afae8a33d1a8b62a22 emissionpol_res_74.out +19b47c19fe69238ece51637f04384f7b emissionpol_res_75.out +d14c6ca4e5a1c62906b9c0aba16fc5ac emissionpol_res_76.out +12a81a31b1964e17ed2d5877f7cfcf98 emissionpol_res_77.out +78b9fc0386056d3ad2a6f1c189dceeef emissionpol_res_78.out +13780df88917d29048de54d0eeb3f830 emissionpol_res_79.out +40ead4dad160792ec288666badcab6c6 emissionpol_res_80.out +5305a49e4a26f5ac0117367637ac807e emissionpol_res_81.out +49dc6d32ccda5df68c9ba349ed39451b emissionpol_res_82.out +1c4da729c7e17a2c444d51d53f69fbd6 emissionpol_res_83.out +f8902d63f2e042480ead62a327320255 emissionpol_res_84.out +e76ab7e5200a20f3cf3c6dff0a86bb96 emissionpol_res_85.out +f965953531de31fdc6c1904a97145fad emissionpol_res_86.out +3d27067a9df755e2b29779cbcfaf458b emissionpol_res_87.out +3a2fecbd3fe11b2965b7a1b33e4d06fc emissionpol_res_88.out +4250d97416046d38633b56cd6e2ed08a emissionpol_res_89.out +86e54b2f6375b040aa2d64d767a2e24b emissionpol_res_90.out +c9a2c71973c02e82b5cd5f39c9eee158 emissionpol_res_91.out +2f56ba073be98b6286f2a668b4d18ea5 emissionpol_res_92.out +3ccdef1f75acfb3c629a34773ae490ca emissionpol_res_93.out +a6268706641b24a18936fb358fe489a5 emissionpol_res_94.out +0bbdb0360989fb25803a59b1a9606f00 emissionpol_res_95.out +93a928d97b56db601838a191022b0608 emissionpol_res_96.out +1231228c72e92d5fa2375dbc3cd0e027 emissionpol_res_97.out +1684b6288abbe27fed960b1536de24cc emissionpol_res_98.out +d2f9a72fd39493cfa43316d9e13b63ca emissionpol_res_99.out +44841a3b4a43fa1f6f7db783c4a1a5dd emissiontrue.out +9f4ff52050cfeef83a39c29a0ce7624f emissiontrue_res_00.out +9435ad78c6cc6b8a96a17c4e0f882677 emissiontrue_res_01.out +3a8a224c03588f312e50a07f4f712a4e emissiontrue_res_02.out +96cafa12fdcd58ff219e641ec4c5cfab emissiontrue_res_03.out +6372796b9c483b45d56c1639a5c8bc35 emissiontrue_res_04.out +ab5c62b807db18be5a83fbfabbe10430 emissiontrue_res_05.out +f4d74ceccdd78820f347e1338157ce10 emissiontrue_res_06.out +d9925c3d4832c8f64af647462ffd9d7c emissiontrue_res_07.out +fae8d1ec247ca00c63c8b19c1c3a7807 emissiontrue_res_08.out +cae76cce1c534e81572b74676d31a76e emissiontrue_res_09.out +e1124e3cc5a1324457b6f2bb87fc6e24 emissiontrue_res_10.out +727c16ae3413d5537c8e7f87dfa86dc3 emissiontrue_res_11.out +12cb0e7762e95e223a728e73d74fd855 emissiontrue_res_12.out +5fa1be8d449ffe4f00a35f5b50f411a0 emissiontrue_res_13.out +ec6b525d7f63b84ff36614f6a78c7fe5 emissiontrue_res_14.out +b5c732e5c01fb9f66598132fb9327a09 emissiontrue_res_15.out +197b8c1f8e92b724e095cac5dbcc3e33 emissiontrue_res_16.out +9c595d7a5a59d45bc20a022d7b008586 emissiontrue_res_17.out +663dd783e2f76206da8a0fa8d585506e emissiontrue_res_18.out +f12a4bd34b016ae08b375b7e22ed2fa0 emissiontrue_res_19.out +6208654f9450317216f3b89146d18f49 emissiontrue_res_20.out +b95f93fa8abcda4dc312c755ed08464c emissiontrue_res_21.out +3cedd44d1c18a4b93bdf0ad72bb303c9 emissiontrue_res_22.out +ac8838dde33766c43aa111bd7b63030c emissiontrue_res_23.out +a0cd199b82ae722ad7082433b57b1fb4 emissiontrue_res_24.out +dc9476bedcf72dfbbb16df8fb68e1ee5 emissiontrue_res_25.out +d4ab3626272d5d661d87283592fbf12f emissiontrue_res_26.out +2ea50cb0215339fcad96c39d1be3abee emissiontrue_res_27.out +dd8b8d2c8c040406f346c394d97f595d emissiontrue_res_28.out +ba12e5550c5477572713481e7afdefcf emissiontrue_res_29.out +2319fe5301a70c78dd93100c0cb44128 emissiontrue_res_30.out +489e088b890b32fcee7cfc7cb998e9f8 emissiontrue_res_31.out +41d2c67337fc208c989734f8533cea3e emissiontrue_res_32.out +de8b7d59d809fd54deb0c50d0c4ddf9a emissiontrue_res_33.out +55d3d9f1d1e446c3bd218e0167c4b3ac emissiontrue_res_34.out +58f055c88b2312cd16e9bc7a18844b9b emissiontrue_res_35.out +ee29ae8dc051a790cde00a0c7b6e8417 emissiontrue_res_36.out +d6d0afa8419389c8a6b1903ab3877635 emissiontrue_res_37.out +c393e052db6dc0c9948d2a9f31802fc6 emissiontrue_res_38.out +40e7c2402fdd40d6259e075563d0a177 emissiontrue_res_39.out +ac6187bebad50119f01569ada1f60e6b emissiontrue_res_40.out +5c4c885526a906e613d216a2e4ef20a2 emissiontrue_res_41.out +4d583655c47f97b525ceddba4518de4c emissiontrue_res_42.out +918fc416655b3d05329d671d155a2470 emissiontrue_res_43.out +fb9f506f2c3cb010e006ee04fd2c1bb5 emissiontrue_res_44.out +579c815c651a654b0fbb29656e38b29a emissiontrue_res_45.out +8f058e58d96e5124dcc5f0b301e938e9 emissiontrue_res_46.out +757e7e3dc8a872e592faf27921c27845 emissiontrue_res_47.out +19533d597a16eb99664b6ede42a71f5e emissiontrue_res_48.out +ce808c8200207b470eb07ba8dd0606ba emissiontrue_res_49.out +f335e5cdcf7c1323719936c97297bb9e emissiontrue_res_50.out +ab056bb8de90a5cb98898a9e0eb8baab emissiontrue_res_51.out +5b5a63097d4274114407c70b5941bb23 emissiontrue_res_52.out +1dbcdb34c6e65e41a02cbbbd75c96716 emissiontrue_res_53.out +eb0b4150073c729fe47d06e7149d7aaf emissiontrue_res_54.out +ae47530e95aa8e4f673c62d4912ab70c emissiontrue_res_55.out +dca9c6261a5f4df523c6848df22aa8dd emissiontrue_res_56.out +e5182a16afd314e4d80f2a70ba945961 emissiontrue_res_57.out +d4dff38009a0e592a4b84b85efceb678 emissiontrue_res_58.out +b0ec35b55ad51f550e89cc7c48593614 emissiontrue_res_59.out +04b0b284b731ffc7992021941f479645 emissiontrue_res_60.out +d13b1613dc59189fc1933795048a0aa7 emissiontrue_res_61.out +f565782778559cf742fe15cadb0ae44f emissiontrue_res_62.out +ed406b9b29bf8bb856c046173180b08e emissiontrue_res_63.out +946da755c895077eaa5f9f610b1fa365 emissiontrue_res_64.out +3028738235c769a2858f0a73b5d78ff5 emissiontrue_res_65.out +ee1ba3e794c600002b0d177455c784c1 emissiontrue_res_66.out +1ce1f9abeef8ee2242482c85ef96ab74 emissiontrue_res_67.out +bce7ea141b0c68f643c748d4d9efe2b7 emissiontrue_res_68.out +4803fe5dcc454252b728b607299527f2 emissiontrue_res_69.out +39c69d0705adaeda9ce4149d97cbdaac emissiontrue_res_70.out +372e865db6a8152c0f35ceab9d8bda92 emissiontrue_res_71.out +29fa1ef13e4fcdbca68ac689393b707f emissiontrue_res_72.out +7a78cf8d847f4fef030bf0178df7a9a3 emissiontrue_res_73.out +e2f613ada76ac6bf308ad9458431b595 emissiontrue_res_74.out +775fa6a7154eb666f5cf02e15f729cb6 emissiontrue_res_75.out +c24d5f8cbf34e0b576ce9f359fbaf82f emissiontrue_res_76.out +5b0a3c80e69585efd90b237e2ea2d357 emissiontrue_res_77.out +50abe1d6460f985bae1de973669e360c emissiontrue_res_78.out +31898d7a83601400641c1072edaf7fcd emissiontrue_res_79.out +d1d9663a0cc237193db7dbde1aed8443 emissiontrue_res_80.out +6efd772fac14359b6a69341b9d3e6c06 emissiontrue_res_81.out +a70939bb3ec5582da7929f4bdea289d9 emissiontrue_res_82.out +e3f4e6c1c76d2cd7979969f469ea1764 emissiontrue_res_83.out +0c55a9379c1555fb8a07bf41bf747024 emissiontrue_res_84.out +5c12f5a48b9991f9c08000ab0b480e73 emissiontrue_res_85.out +9069c4b88d3053c8b25f024c85d6f3b3 emissiontrue_res_86.out +a081e3cad59c87574e5c8eb9d059f0f9 emissiontrue_res_87.out +6ff29c35f84b15306ac5d6a9af5bdf13 emissiontrue_res_88.out +6037c8d89487a31aa9925bc2369ee37d emissiontrue_res_89.out +07e6cd793d7435c30e77319975f9edcb emissiontrue_res_90.out +db00bb02c9969a09c545d2eedcbec7e0 emissiontrue_res_91.out +498f900d56128e2560e322e42b15badd emissiontrue_res_92.out +1c16ae876894728bd4a8397ee5c6d09b emissiontrue_res_93.out +526760b5db92de082a963ca61e41d8d8 emissiontrue_res_94.out +b1ab5d45cdc378e3170e14cb29c28b12 emissiontrue_res_95.out +0c6eb415ce266eb7bf3588f46b50a494 emissiontrue_res_96.out +87afef1a20c62fec24363bd249ee873c emissiontrue_res_97.out +9eb058fc0bab6725a8cc8506f6e6ab80 emissiontrue_res_98.out +a2a662a168d14f346657ad13a9a5f2a7 emissiontrue_res_99.out +a5ff3eed46cd6845137969bc685e4837 gamma_light_curve.out +304d5b3d966245f818518265806f7fb1 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out e08bbb965fac36412810b8769a13ab9d grid.out -48e3911cfdfb1cd01de3e209941e4340 light_curve.out -433c08f5cf1c37d36af7981b57f41961 light_curve_res.out +b55e935340c11d93c28cf583701f0c89 light_curve.out +c8a8b908bcdbf00c2d57592c03e23dd3 light_curve_res.out c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -333d6dac1469f5c12ed18166ad510091 packets00_0000.out -11d05abcd28bb29b9746c41ec7ff0bf5 packets00_0001.out -43bfc8f9890c6bf376bed6ac29b16692 packets00_0002.out -fb28ce31c9e18d2cfc19893b50ae39dd packets00_0003.out -e5b85d37c6e4f132501b9307c3badccb spec.out -7adeeb59b305cc5ac524f5ff36dc2adc spec_res.out -60a61f3785c25696148120f55b346fd1 specpol.out -cac2d26160630a03e404124358209697 specpol_res.out +d4bd9d264f25c09fff92bf56870c262d packets00_0000.out +96713f8399f5fdb12b1e05b8b936d2f6 packets00_0001.out +5360849c3c59fd884cfbfb7013a4da10 packets00_0002.out +a112392101bd80542cb30df0c9650e35 packets00_0003.out +8c7c79fbc346b83861ae26c8386177a1 spec.out +d675f9c16c776141b7fc58067b682021 spec_res.out +c137d2b84f03c7dd06718fef347dbd15 specpol.out +8f8371dd520ae4c5da0824a25cfb9d09 specpol_res.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -be0d877dba38047748d2e08828e724e4 job1/estimators_0000.out -6568d3f123c47bc076dab17a98dbd45a job1/estimators_0001.out -c512d08767e7bf97dded2d2d3f67e264 job1/estimators_0002.out -ba5f21b2b35fe8b1afb8605b1b8d7cba job1/estimators_0003.out +8de6a955562c97529495d1cf9b277c8c job1/estimators_0000.out +110d292a123e92f2b6892d95e1d4e52f job1/estimators_0001.out +8ab388e33f6bc9d8415561911e7879b3 job1/estimators_0002.out +1b3946b4723bce914e7c70f5c5b2db29 job1/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_job0.txt b/tests/classicmode_3d_inputfiles/results_md5_job0.txt index 8e70cd689..907e3f249 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -22584520a4d8df15bb83d78638fa2779 absorption.out +3f28685ffbcf32c2cf427bd784967d72 absorption.out 9cbb3a257dd95b6b3dd92d1d7d913e6c bflist.out -5aef6a0b0a65a324be1fa964e0243e98 deposition.out -28def04b3442a9e047b10d65516d9491 emission.out -661cfec77a5074aa7d894844ec166207 emissiontrue.out -278c45900488ee4bc457f36b1ff413b0 gamma_light_curve.out +4464b8c6ef9c0e68413e86a81b6e8ac4 deposition.out +b75314233c76fda294032e04b257d106 emission.out +1177f9ca9346745a6436ebc106022b40 emissiontrue.out +f626551dcfd386c318fab42ae9a7f1b8 gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out e08bbb965fac36412810b8769a13ab9d grid.out -0440dc46a5b58d64e60f6c1df8f4b43d light_curve.out +076e72bd1967d1baf52db88300446693 light_curve.out c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -0aa35be1178e74ba049bab976cd4a53a packets00_0000.out -241511f53ee7368b8bf212de0a08f924 packets00_0001.out -0bab8771cc794e813e2c6fbad0555862 packets00_0002.out -62732c40e733011f354a8c44ad3b79f1 packets00_0003.out -98c95bf501f2fb6311e4f06a705052ab spec.out +1e81ef6f94c8332c880d8be2f0ffba5d packets00_0000.out +1e44ed84716f7f2b2de2b445456c4a69 packets00_0001.out +1c7de0c56fdae989ac20c34ee75cf0ae packets00_0002.out +8fdf70de6cd92502cd925f66c3824a41 packets00_0003.out +79606abc60e8efc6546ef0844303e152 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -fb5f4328af54eeed1c14fbac339e7cb5 job0/estimators_0000.out -79730a9e4fa9814eac0f66f00a776c86 job0/estimators_0001.out -4e4de9e1b6c204d2ec8d7a6b99a68fe8 job0/estimators_0002.out -6653b09650df3dca8f231b48d4211b91 job0/estimators_0003.out +d301fc9a5830434377ebc654a613205b job0/estimators_0000.out +300db7f07756e1422920365b813b34c6 job0/estimators_0001.out +8e15c18e3826654f6ac9e9edbd464b94 job0/estimators_0002.out +d121dd1c35a35ccfafb34f6a37703e73 job0/estimators_0003.out From 9a31c2bf0ee9592ed72b805722d7badccfc11c6f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 27 Aug 2024 15:55:58 +0100 Subject: [PATCH 030/117] Improve checks during phixs file reads and make PHIXS_CLASSIC_NO_INTERPOLATION constexpr (#114) --- artisoptions_classic.h | 2 + artisoptions_doc.md | 4 ++ artisoptions_kilonova_lte.h | 2 + artisoptions_nltenebular.h | 3 +- artisoptions_nltewithoutnonthermal.h | 3 +- atomic.h | 2 +- input.cc | 63 +++++++++++++++------------- 7 files changed, 48 insertions(+), 31 deletions(-) diff --git a/artisoptions_classic.h b/artisoptions_classic.h index bf6534a0d..f937a2687 100644 --- a/artisoptions_classic.h +++ b/artisoptions_classic.h @@ -57,6 +57,8 @@ constexpr double NU_MIN_R = 1e14; constexpr double NU_MAX_R = 5e15; +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = true; + constexpr bool MULTIBIN_RADFIELD_MODEL_ON = false; constexpr int RADFIELDBINCOUNT = 256; diff --git a/artisoptions_doc.md b/artisoptions_doc.md index 8e02ba737..33fa80913 100644 --- a/artisoptions_doc.md +++ b/artisoptions_doc.md @@ -77,6 +77,10 @@ constexpr double MINPOP; constexpr double NU_MIN_R; // lower frequency boundary for UVOIR spectra and BB sampling constexpr double NU_MAX_R; // upper frequency boundary for UVOIR spectra and BB sampling +// use nearest-neighbour instead of linear interpolation of photoionisation cross sections +// to match classic artis +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION; + // ** Start of radiation field model options ** // if using this, avoid look up tables and switch on the direct integration options below diff --git a/artisoptions_kilonova_lte.h b/artisoptions_kilonova_lte.h index 27790b5b6..f0be2ea4a 100644 --- a/artisoptions_kilonova_lte.h +++ b/artisoptions_kilonova_lte.h @@ -58,6 +58,8 @@ constexpr double MINPOP = 1e-40; constexpr double NU_MIN_R = 1e13; constexpr double NU_MAX_R = 5e16; +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = false; + constexpr bool MULTIBIN_RADFIELD_MODEL_ON = false; constexpr int RADFIELDBINCOUNT = 256; diff --git a/artisoptions_nltenebular.h b/artisoptions_nltenebular.h index 8b055acdf..276b0d4e2 100644 --- a/artisoptions_nltenebular.h +++ b/artisoptions_nltenebular.h @@ -61,9 +61,10 @@ constexpr bool TRACK_ION_STATS = false; constexpr double MINPOP = 1e-40; constexpr double NU_MIN_R = 1e13; - constexpr double NU_MAX_R = 5e15; +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = false; + constexpr bool MULTIBIN_RADFIELD_MODEL_ON = true; constexpr int RADFIELDBINCOUNT = 256; diff --git a/artisoptions_nltewithoutnonthermal.h b/artisoptions_nltewithoutnonthermal.h index e48d2d86a..475bcaa67 100644 --- a/artisoptions_nltewithoutnonthermal.h +++ b/artisoptions_nltewithoutnonthermal.h @@ -59,9 +59,10 @@ constexpr bool TRACK_ION_STATS = false; constexpr double MINPOP = 1e-40; constexpr double NU_MIN_R = 1e14; - constexpr double NU_MAX_R = 5e16; +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = false; + constexpr bool MULTIBIN_RADFIELD_MODEL_ON = true; constexpr int RADFIELDBINCOUNT = 512; diff --git a/atomic.h b/atomic.h index 3dcb210d3..8b1334594 100644 --- a/atomic.h +++ b/atomic.h @@ -136,7 +136,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) float sigma_bf = 0.; - if (phixs_file_version_exists[1] && !phixs_file_version_exists[2]) { + if constexpr (PHIXS_CLASSIC_NO_INTERPOLATION) { // classic mode: no interpolation if (nu == nu_edge) { sigma_bf = photoion_xs[0]; diff --git a/input.cc b/input.cc index 2f2dd8eb4..7c66e3a1a 100644 --- a/input.cc +++ b/input.cc @@ -95,8 +95,8 @@ CellCachePhixsTargets *chphixstargetsblock{}; void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_inputtable, const int element, const int lowerion, const int lowerlevel, const int upperion, int upperlevel_in, size_t *mem_usage_phixs, const int phixs_file_version) { - if (upperlevel_in >= 0) // file gives photoionisation to a single target state only - { + std::string phixsline; + if (upperlevel_in >= 0) { // file gives photoionisation to a single target state only int upperlevel = upperlevel_in - groundstate_index_in; assert_always(upperlevel >= 0); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets == 0); @@ -108,17 +108,17 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input static_cast(calloc(1, sizeof(PhotoionTarget))); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); - if (single_level_top_ion && - (upperion == get_nions(element) - 1)) // top ion has only one level, so send it to that level - { + if (single_level_top_ion && (upperion == get_nions(element) - 1)) { + // top ion has only one level, so send it to that level upperlevel = 0; } + globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].levelindex = upperlevel; globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].probability = 1.; - } else // upperlevel < 0, indicating that a table of upper levels and their probabilities will follow - { + } else { // upperlevel < 0, indicating that a table of upper levels and their probabilities will follow int in_nphixstargets = 0; - assert_always(phixsfile >> in_nphixstargets); + assert_always(get_noncommentline(phixsfile, phixsline)); + assert_always(std::stringstream(phixsline) >> in_nphixstargets); assert_always(in_nphixstargets >= 0); // read in a table of target states and probabilities and store them if (!single_level_top_ion || upperion < get_nions(element) - 1) // in case the top ion has nlevelsmax = 1 @@ -133,7 +133,8 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input double probability_sum = 0.; for (int i = 0; i < in_nphixstargets; i++) { double phixstargetprobability{NAN}; - assert_always(phixsfile >> upperlevel_in >> phixstargetprobability); + assert_always(get_noncommentline(phixsfile, phixsline)); + assert_always(std::stringstream(phixsline) >> upperlevel_in >> phixstargetprobability); const int upperlevel = upperlevel_in - groundstate_index_in; assert_always(upperlevel >= 0); assert_always(phixstargetprobability > 0); @@ -146,8 +147,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input printout("WARNING: photoionisation table for Z=%d ionstage %d has probabilities that sum to %g", get_atomicnumber(element), get_ionstage(element, lowerion), probability_sum); } - } else // file has table of target states and probabilities but our top ion is limited to one level - { + } else { // file has table of target states and probabilities but our top ion is limited to one level globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = 1; *mem_usage_phixs += sizeof(PhotoionTarget); globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = @@ -155,8 +155,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); for (int i = 0; i < in_nphixstargets; i++) { - double phixstargetprobability{NAN}; - assert_always(phixsfile >> upperlevel_in >> phixstargetprobability); + assert_always(get_noncommentline(phixsfile, phixsline)); } // send it to the ground state of the top ion @@ -191,15 +190,16 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input const double nu_edge = (epsilon(element, upperion, 0) - epsilon(element, lowerion, lowerlevel)) / H; - auto *nutable = static_cast(calloc(nphixspoints_inputtable, sizeof(double))); - assert_always(nutable != nullptr); - auto *phixstable = static_cast(calloc(nphixspoints_inputtable, sizeof(double))); - assert_always(phixstable != nullptr); + auto nutable = std::vector(nphixspoints_inputtable); + auto phixstable = std::vector(nphixspoints_inputtable); for (int i = 0; i < nphixspoints_inputtable; i++) { double energy = -1.; double phixs = -1.; - assert_always(phixsfile >> energy >> phixs); + assert_always(get_noncommentline(phixsfile, phixsline)); + assert_always(std::stringstream(phixsline) >> energy >> phixs); + assert_always(energy >= 0); + assert_always(phixs >= 0); nutable[i] = nu_edge + (energy * 13.6 * EV) / H; // the photoionisation cross-sections in the database are given in Mbarn=1e6 * 1e-28m^2 // to convert to cgs units multiply by 1e-18 @@ -212,7 +212,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input gsl_interp_accel *acc = gsl_interp_accel_alloc(); gsl_spline *spline = gsl_spline_alloc(gsl_interp_linear, nphixspoints_inputtable); - gsl_spline_init(spline, nutable, phixstable, nphixspoints_inputtable); + gsl_spline_init(spline, nutable.data(), phixstable.data(), nphixspoints_inputtable); for (int i = 1; i < globals::NPHIXSPOINTS; i++) { const double nu = nu_edge * (1. + i * globals::NPHIXSNUINCREMENT); if (nu > nu_max) { @@ -225,8 +225,6 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } gsl_spline_free(spline); gsl_interp_accel_free(acc); - free(nutable); - free(phixstable); } else { for (int i = 0; i < globals::NPHIXSPOINTS; i++) { float phixs{NAN}; @@ -254,6 +252,7 @@ void read_phixs_data(const int phixs_file_version) { printout("readin phixs data from %s\n", phixsdata_filenames[phixs_file_version]); auto phixsfile = fstream_required(phixsdata_filenames[phixs_file_version], std::ios::in); + std::string phixsline; if (phixs_file_version == 1 && phixs_file_version_exists[2]) { printout( @@ -284,7 +283,6 @@ void read_phixs_data(const int phixs_file_version) { double phixs_threshold_ev = -1; // currently just ignored, and epilson is used instead while (true) { int nphixspoints_inputtable = 0; - std::string phixsline; if (!get_noncommentline(phixsfile, phixsline)) { break; } @@ -330,19 +328,20 @@ void read_phixs_data(const int phixs_file_version) { if (upperlevel_in < 0) // a table of target states and probabilities will follow, so read past those lines { int nphixstargets = 0; - assert_always(phixsfile >> nphixstargets); + assert_always(get_noncommentline(phixsfile, phixsline)); + assert_always(std::stringstream(phixsline) >> nphixstargets); for (int i = 0; i < nphixstargets; i++) { - double phixstargetprobability{NAN}; - assert_always(phixsfile >> upperlevel_in >> phixstargetprobability); + assert_always(get_noncommentline(phixsfile, phixsline)); } } for (int i = 0; i < nphixspoints_inputtable; i++) // skip through cross section list { - float phixs = 0; if (phixs_file_version == 1) { - double energy = 0; - assert_always(phixsfile >> energy >> phixs); + assert_always(get_noncommentline(phixsfile, phixsline)); } else { + // one day we might want to put all of the cross section points onto a single line, + // so don't use getline here + float phixs = 0; assert_always(phixsfile >> phixs); } } @@ -1074,8 +1073,16 @@ void read_atomicdata_files() { globals::nbfcontinua = 0; // read in photoionisation cross sections + phixs_file_version_exists[0] = false; phixs_file_version_exists[1] = std::filesystem::exists(phixsdata_filenames[1]); phixs_file_version_exists[2] = std::filesystem::exists(phixsdata_filenames[2]); + +#ifdef MPI_ON + // just in case the file system was faulty and the ranks disagree on the existence of the files + // broadcast the existence of the files to all ranks from rank 0 + + MPI_Bcast(phixs_file_version_exists.data(), sizeof(phixs_file_version_exists), MPI_BYTE, 0, MPI_COMM_WORLD); +#endif assert_always(phixs_file_version_exists[1] || phixs_file_version_exists[2]); // at least one must exist if (phixs_file_version_exists[1] && phixs_file_version_exists[2]) { printout( From 9bd14ee295e6dbbe02ba718c1004ee640fba5653 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 28 Aug 2024 13:41:04 +0100 Subject: [PATCH 031/117] Detect and disallow variable shadowing (#115) --- .clang-tidy | 1 + Makefile | 2 +- decay.cc | 9 ++--- grid.cc | 75 ++++++++++++++--------------------------- input.cc | 59 +++++++++++++++----------------- nonthermal.cc | 76 ++++++++++++++++++------------------------ radfield.cc | 28 ++++++---------- rpkt.cc | 25 +++++++------- sn3d.cc | 5 ++- sn3d.h | 22 +++++++----- spectrum_lightcurve.cc | 12 +++---- update_packets.cc | 2 -- 12 files changed, 133 insertions(+), 183 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index fb08c158a..deac71a1f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -26,6 +26,7 @@ Checks: > -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-cstyle-cast, -cppcoreguidelines-pro-type-vararg, -fuchsia-*, -google-objc*, diff --git a/Makefile b/Makefile index 9acb91a9d..e185ea206 100644 --- a/Makefile +++ b/Makefile @@ -237,7 +237,7 @@ else # endif endif -CXXFLAGS += -Winline -Wall -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare +CXXFLAGS += -Winline -Wall -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow # sn3d.cc and exspec.cc have main() defined common_files := $(filter-out sn3d.cc exspec.cc, $(wildcard *.cc)) diff --git a/decay.cc b/decay.cc index 84d21792a..1c260fbcd 100644 --- a/decay.cc +++ b/decay.cc @@ -1057,12 +1057,9 @@ void setup_decaypath_energy_per_mass() { nonempty_npts_model * get_num_decaypaths() * sizeof(double) / 1024. / 1024.); double *decaypath_energy_per_mass_data{nullptr}; #ifdef MPI_ON - size_t my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); - } - auto size = static_cast(my_rank_cells * get_num_decaypaths() * sizeof(double)); + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); + auto size = static_cast(noderank_nonemptycellcount * get_num_decaypaths() * sizeof(double)); int disp_unit = sizeof(double); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &decaypath_energy_per_mass_data, diff --git a/grid.cc b/grid.cc index 5e5b87cee..2cef7513e 100644 --- a/grid.cc +++ b/grid.cc @@ -134,16 +134,9 @@ void allocate_initradiobund() { const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); #ifdef MPI_ON - const auto my_rank_cells = [] { - auto my_rank_cells = (npts_model + 1) / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += (npts_model + 1) - (my_rank_cells * globals::node_nprocs); - } - return my_rank_cells; - }(); + const auto [_, noderank_cells] = get_range_chunk(npts_model + 1, globals::node_nprocs, globals::rank_in_node); - MPI_Aint size = my_rank_cells * num_nuclides * sizeof(float); + auto size = static_cast(noderank_cells * num_nuclides * sizeof(float)); int disp_unit = sizeof(float); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, @@ -281,24 +274,11 @@ void allocate_nonemptycells_composition_cooling() const size_t npts_nonempty = get_nonempty_npts_model(); #ifdef MPI_ON - int my_rank_nonemptycells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_nonemptycells += nonempty_npts_model - (my_rank_nonemptycells * globals::node_nprocs); - } -#endif + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); -#ifdef MPI_ON - size_t my_rank_cells_nonempty = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells_nonempty += nonempty_npts_model - (my_rank_cells_nonempty * globals::node_nprocs); - } -#endif - -#ifdef MPI_ON { - MPI_Aint size = my_rank_cells_nonempty * get_nelements() * sizeof(float); + auto size = static_cast(noderank_nonemptycellcount * get_nelements() * sizeof(float)); int disp_unit = sizeof(float); MPI_Win mpiwin = MPI_WIN_NULL; assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, @@ -308,7 +288,7 @@ void allocate_nonemptycells_composition_cooling() } { - auto size = static_cast(my_rank_cells_nonempty * get_nelements() * sizeof(float)); + auto size = static_cast(noderank_nonemptycellcount * get_nelements() * sizeof(float)); int disp_unit = sizeof(float); MPI_Win mpiwin = MPI_WIN_NULL; @@ -325,7 +305,7 @@ void allocate_nonemptycells_composition_cooling() double *nltepops_allcells{}; if (globals::total_nlte_levels > 0) { #ifdef MPI_ON - auto size = static_cast(my_rank_nonemptycells * globals::total_nlte_levels * sizeof(double)); + auto size = static_cast(noderank_nonemptycellcount * globals::total_nlte_levels * sizeof(double)); int disp_unit = sizeof(double); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nltepops_allcells, &win_nltepops_allcells) == MPI_SUCCESS); @@ -473,13 +453,10 @@ void allocate_nonemptymodelcells() { if (USE_LUT_PHOTOION && ionestimsize > 0) { #ifdef MPI_ON - auto my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); - } + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - auto size = static_cast(my_rank_cells * globals::nbfcontinua_ground * sizeof(double)); + auto size = static_cast(noderank_nonemptycellcount * globals::nbfcontinua_ground * sizeof(double)); int disp_unit = sizeof(double); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &globals::corrphotoionrenorm, @@ -560,10 +537,9 @@ void map_2dmodelto3dgrid() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { // map to 3D Cartesian grid - std::array pos_mid{}; - for (int d = 0; d < 3; d++) { - pos_mid[d] = (get_cellcoordmin(cellindex, d) + (0.5 * wid_init(cellindex, d))); - } + const auto pos_mid = std::array{get_cellcoordmin(cellindex, 0) + (0.5 * wid_init(cellindex, 0)), + get_cellcoordmin(cellindex, 1) + (0.5 * wid_init(cellindex, 1)), + get_cellcoordmin(cellindex, 2) + (0.5 * wid_init(cellindex, 2))}; const double rcylindrical = std::sqrt(std::pow(pos_mid[0], 2) + std::pow(pos_mid[1], 2)); @@ -1536,21 +1512,20 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - } constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { - auto posgridcoord = std::array{}; if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { - posgridcoord[0] = pos_xyz[0]; - posgridcoord[1] = pos_xyz[1]; - posgridcoord[2] = pos_xyz[2]; - } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { - posgridcoord[0] = std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)); - posgridcoord[1] = pos_xyz[2]; - posgridcoord[2] = 0.; - } else if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { - posgridcoord[0] = vec_len(pos_xyz); - posgridcoord[1] = 0.; - posgridcoord[2] = 0.; + return pos_xyz; + } + + if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { + return {std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)), pos_xyz[2], 0.}; } - return posgridcoord; + + if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { + return {vec_len(pos_xyz), 0., 0.}; + } + + assert_always(false); + return {0., 0., 0.}; } template diff --git a/input.cc b/input.cc index 7c66e3a1a..f3debe0c7 100644 --- a/input.cc +++ b/input.cc @@ -246,7 +246,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } } -void read_phixs_data(const int phixs_file_version) { +void read_phixs_file(const int phixs_file_version) { size_t mem_usage_phixs = 0; printout("readin phixs data from %s\n", phixsdata_filenames[phixs_file_version]); @@ -297,14 +297,11 @@ void read_phixs_data(const int phixs_file_version) { assert_always(Z > 0); assert_always(upperionstage >= 2); assert_always(lowerionstage >= 1); - bool skip_this_phixs_table = false; - // printout("[debug] Z %d, upperion %d, upperlevel %d, lowerion %d, lowerlevel, - // %d\n",Z,upperion,upperlevel,lowerion,lowerlevel); - // translate readin anumber to element index + const int element = get_elementindex(Z); // store only photoionization crosssections for elements that are part of the current model atom - skip_this_phixs_table = true; // will be set to false for good data + bool skip_this_phixs_table = true; // will be set to false for good data if (element >= 0 && get_nions(element) > 0) { // translate readin ionstages to ion indices @@ -313,6 +310,7 @@ void read_phixs_data(const int phixs_file_version) { const int lowerlevel = lowerlevel_in - groundstate_index_in; assert_always(lowerionstage >= 0); assert_always(lowerlevel >= 0); + // store only photoionization crosssections for ions that are part of the current model atom if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_nlevels(element, lowerion)) { read_phixs_data_table(phixsfile, nphixspoints_inputtable, element, lowerion, lowerlevel, upperion, @@ -322,11 +320,9 @@ void read_phixs_data(const int phixs_file_version) { } } - if (skip_this_phixs_table) // for ions or elements that are not part of the current model atom, proceed through the - // lines and throw away the data - { - if (upperlevel_in < 0) // a table of target states and probabilities will follow, so read past those lines - { + if (skip_this_phixs_table) { // for ions or elements that are not part of the current model atom, proceed through + // the table and throw away the data + if (upperlevel_in < 0) { // a table of target states and probabilities will follow, so read past those lines int nphixstargets = 0; assert_always(get_noncommentline(phixsfile, phixsline)); assert_always(std::stringstream(phixsline) >> nphixstargets); @@ -334,8 +330,8 @@ void read_phixs_data(const int phixs_file_version) { assert_always(get_noncommentline(phixsfile, phixsline)); } } - for (int i = 0; i < nphixspoints_inputtable; i++) // skip through cross section list - { + // skip through cross section list + for (int i = 0; i < nphixspoints_inputtable; i++) { if (phixs_file_version == 1) { assert_always(get_noncommentline(phixsfile, phixsline)); } else { @@ -511,9 +507,9 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons MPI_Barrier(MPI_COMM_WORLD); MPI_Win win_alltransblock = MPI_WIN_NULL; - const auto [_, my_rank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); + const auto [_, noderank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); - auto size = static_cast(my_rank_trans * sizeof(LevelTransition)); + auto size = static_cast(noderank_trans * sizeof(LevelTransition)); int disp_unit = sizeof(LevelTransition); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &alltransblock, &win_alltransblock); @@ -969,13 +965,9 @@ void read_atomicdata_files() { #ifdef MPI_ON MPI_Win win_nonconstlinelist = MPI_WIN_NULL; - size_t my_rank_lines = globals::nlines / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_lines += globals::nlines - (my_rank_lines * globals::node_nprocs); - } + const auto [_, noderank_lines] = get_range_chunk(globals::nlines, globals::node_nprocs, globals::rank_in_node); - MPI_Aint size = my_rank_lines * static_cast(sizeof(TransitionLine)); + MPI_Aint size = noderank_lines * static_cast(sizeof(TransitionLine)); int disp_unit = sizeof(TransitionLine); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nonconstlinelist, &win_nonconstlinelist); @@ -1035,20 +1027,21 @@ void read_atomicdata_files() { // so find the first matching the upper and lower transition const int nupperdowntrans = get_ndowntrans(element, ion, upperlevel); - auto *downtranslist = globals::elements[element].ions[ion].levels[upperlevel].downtrans; - auto *downtrans = std::find_if(downtranslist, downtranslist + nupperdowntrans, - [=](const auto &downtrans) { return downtrans.targetlevelindex == lowerlevel; }); - assert_always(downtrans != (downtranslist + nupperdowntrans)); + auto &downtranslist = globals::elements[element].ions[ion].levels[upperlevel].downtrans; + auto *downtransition = std::find_if(downtranslist, downtranslist + nupperdowntrans, [=](const auto &downtrans) { + return downtrans.targetlevelindex == lowerlevel; + }); + assert_always(downtransition != (downtranslist + nupperdowntrans)); // assert_always(downtrans->targetlevelindex == lowerlevel); - downtrans->lineindex = lineindex; + downtransition->lineindex = lineindex; const int nloweruptrans = get_nuptrans(element, ion, lowerlevel); - auto *uptranslist = globals::elements[element].ions[ion].levels[lowerlevel].uptrans; - auto *uptrans = std::find_if(uptranslist, uptranslist + nloweruptrans, - [=](const auto &uptrans) { return uptrans.targetlevelindex == upperlevel; }); - assert_always(uptrans != (uptranslist + nloweruptrans)); + auto &uptranslist = globals::elements[element].ions[ion].levels[lowerlevel].uptrans; + auto *uptransition = std::find_if(uptranslist, uptranslist + nloweruptrans, + [=](const auto &uptr) { return uptr.targetlevelindex == upperlevel; }); + assert_always(uptransition != (uptranslist + nloweruptrans)); // assert_always(uptrans->targetlevelindex == upperlevel); - uptrans->lineindex = lineindex; + uptransition->lineindex = lineindex; } printout(" took %lds\n", std::time(nullptr) - time_start_establish_linelist_connections); @@ -1090,10 +1083,10 @@ void read_atomicdata_files() { "from phixsdata_v2.txt to interpolate the phixsdata.txt data\n"); } if (phixs_file_version_exists[2]) { - read_phixs_data(2); + read_phixs_file(2); } if (phixs_file_version_exists[1]) { - read_phixs_data(1); + read_phixs_file(1); } int cont_index = -1; diff --git a/nonthermal.cc b/nonthermal.cc index 16d5914ec..80e5f29a4 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -116,11 +116,11 @@ constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); constexpr auto engrid(int index) -> double { return SF_EMIN + (index * DELTA_E); } const auto logengrid = []() { - std::vector logengrid(SFPTS); + std::vector _logengrid(SFPTS); for (int i = 0; i < SFPTS; i++) { - logengrid[i] = std::log(engrid(i)); + _logengrid[i] = std::log(engrid(i)); } - return logengrid; + return _logengrid; }(); // samples of the source function (energy distribution of deposited energy) @@ -151,13 +151,13 @@ constexpr double E_init_ev = []() { // rhs is the constant term (not dependent on y func) in each equation constexpr auto rhsvec = []() { - std::array rhsvec{}; + std::array _rhsvec{}; double source_integral_to_SF_EMAX = 0.; for (int i = SFPTS - 1; i >= 0; i--) { - rhsvec[i] = source_integral_to_SF_EMAX * DELTA_E; + _rhsvec[i] = source_integral_to_SF_EMAX * DELTA_E; source_integral_to_SF_EMAX += sourcevec(i); } - return rhsvec; + return _rhsvec; }(); // Monte Carlo result - compare to analytical expectation @@ -203,8 +203,7 @@ struct NonThermalCellSolution { std::vector nt_solution; -std::vector deposition_rate_density; -std::vector deposition_rate_density_timestep; +std::vector deposition_rate_density_all_cells; constexpr auto uppertriangular(const int i, const int j) -> int { assert_testmodeonly(i >= 0); @@ -674,16 +673,16 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it // xs_vec will be set with impact ionization cross sections for E > ionpot_ev (and zeros below this energy) // returns the index of the first energy point >= ionpot_ev -auto get_xs_ionization_vector(std::array &xs_vec, const collionrow &colliondata) -> int { - const double ionpot_ev = colliondata.ionpot_ev; +auto get_xs_ionization_vector(std::array &xs_vec, const collionrow &colliondata_ion) -> int { + const double ionpot_ev = colliondata_ion.ionpot_ev; const int startindex = get_energyindex_ev_gteq(ionpot_ev); std::fill_n(xs_vec.begin(), startindex, 0.); - const double A = colliondata.A; - const double B = colliondata.B; - const double C = colliondata.C; - const double D = colliondata.D; + const double A = colliondata_ion.A; + const double B = colliondata_ion.B; + const double C = colliondata_ion.C; + const double D = colliondata_ion.D; for (int i = startindex; i < SFPTS; i++) { const double u = engrid(i) / ionpot_ev; @@ -789,17 +788,17 @@ constexpr auto electron_loss_rate(const double energy, const double nne) -> doub // energy and ionization_potential should be in eV // fitting forumula of Younger 1981 // called Q_i(E) in KF92 equation 7 -constexpr auto xs_impactionization(const double energy_ev, const collionrow &colliondata) -> double { - const double ionpot_ev = colliondata.ionpot_ev; +constexpr auto xs_impactionization(const double energy_ev, const collionrow &colliondata_ion) -> double { + const double ionpot_ev = colliondata_ion.ionpot_ev; const double u = energy_ev / ionpot_ev; if (u <= 1.) { return 0; } - const double A = colliondata.A; - const double B = colliondata.B; - const double C = colliondata.C; - const double D = colliondata.D; + const double A = colliondata_ion.A; + const double B = colliondata_ion.B; + const double C = colliondata_ion.C; + const double D = colliondata_ion.D; return 1e-14 * (A * (1 - 1 / u) + B * std::pow((1 - (1 / u)), 2) + C * std::log(u) + D * std::log(u) / u) / (u * std::pow(ionpot_ev, 2)); @@ -1956,11 +1955,9 @@ void init(const int my_rank, const int ndo_nonempty) { assert_always(nonthermal_initialized == false); nonthermal_initialized = true; - deposition_rate_density.resize(grid::get_npts_model()); - deposition_rate_density_timestep.resize(grid::get_npts_model()); + deposition_rate_density_all_cells.resize(grid::get_npts_model()); - std::ranges::fill(deposition_rate_density, -1.); - std::ranges::fill(deposition_rate_density_timestep, -1); + std::ranges::fill(deposition_rate_density_all_cells, -1.); if (!NT_ON) { return; @@ -2005,13 +2002,11 @@ void init(const int my_rank, const int ndo_nonempty) { MPI_Win win_shared_excitations_list{}; - int my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); - } + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - auto size = static_cast(my_rank_cells * sizeof(NonThermalExcitation) * nt_excitations_stored); + auto size = + static_cast(noderank_nonemptycellcount * sizeof(NonThermalExcitation) * nt_excitations_stored); int disp_unit = sizeof(NonThermalExcitation); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &excitations_list_all_cells, @@ -2109,18 +2104,16 @@ void calculate_deposition_rate_density(const int modelgridindex, const int times heatingcoolingrates->dep_alpha = globals::dep_estimator_alpha[nonemptymgi]; } - deposition_rate_density[modelgridindex] = (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + - heatingcoolingrates->dep_electron + heatingcoolingrates->dep_alpha); - - deposition_rate_density_timestep[modelgridindex] = timestep; + deposition_rate_density_all_cells[modelgridindex] = + (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron + + heatingcoolingrates->dep_alpha); } __host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double // get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() { - assert_testmodeonly(deposition_rate_density_timestep[modelgridindex] == globals::timestep); - assert_always(deposition_rate_density[modelgridindex] >= 0); - return deposition_rate_density[modelgridindex]; + assert_always(deposition_rate_density_all_cells[modelgridindex] >= 0); + return deposition_rate_density_all_cells[modelgridindex]; } void close_file() { @@ -2572,8 +2565,7 @@ void write_restart_data(FILE *gridsave_file) { for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - fprintf(gridsave_file, "%d %d %la ", modelgridindex, deposition_rate_density_timestep[modelgridindex], - deposition_rate_density[modelgridindex]); + fprintf(gridsave_file, "%d %la ", modelgridindex, deposition_rate_density_all_cells[modelgridindex]); if (NT_ON && NT_SOLVE_SPENCERFANO) { check_auger_probabilities(modelgridindex); @@ -2630,8 +2622,7 @@ void read_restart_data(FILE *gridsave_file) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); int mgi_in = 0; - assert_always(fscanf(gridsave_file, "%d %d %la ", &mgi_in, &deposition_rate_density_timestep[modelgridindex], - &deposition_rate_density[modelgridindex]) == 3); + assert_always(fscanf(gridsave_file, "%d %la ", &mgi_in, &deposition_rate_density_all_cells[modelgridindex]) == 2); if (NT_ON && NT_SOLVE_SPENCERFANO) { assert_always(fscanf(gridsave_file, "%a %a %a %a\n", &nt_solution[modelgridindex].nneperion_when_solved, @@ -2687,8 +2678,7 @@ void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ // nt_ionization_ratecoeff_sf(modelgridindex, logged_element_index, logged_ion_index), // get_eff_ionpot(modelgridindex, logged_element_index, logged_ion_index) / EV); - MPI_Bcast(&deposition_rate_density_timestep[modelgridindex], 1, MPI_INT, root, MPI_COMM_WORLD); - MPI_Bcast(&deposition_rate_density[modelgridindex], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); + MPI_Bcast(&deposition_rate_density_all_cells[modelgridindex], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); if (NT_ON && NT_SOLVE_SPENCERFANO) { assert_always(nonthermal_initialized); diff --git a/radfield.cc b/radfield.cc index c0c4eec14..aa8635771 100644 --- a/radfield.cc +++ b/radfield.cc @@ -260,8 +260,8 @@ void update_bfestimators(const int nonemptymgi, const double distance_e_cmf, con const auto bfestimbegin = std::lower_bound(globals::bfestim_nu_edge.data() + phixslist.bfestimbegin, globals::bfestim_nu_edge.data() + bfestimend, nu_cmf, - [](const double nu_edge, const double nu_cmf) { - return nu_edge * last_phixs_nuovernuedge < nu_cmf; + [](const double nu_edge, const double find_nu_cmf) { + return nu_edge * last_phixs_nuovernuedge < find_nu_cmf; }) - globals::bfestim_nu_edge.data(); @@ -548,6 +548,10 @@ void init(const int my_rank, const int ndo_nonempty) { } else { printout("\n"); } +#ifdef MPI_ON + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); +#endif if (MULTIBIN_RADFIELD_MODEL_ON) { printout("The multibin radiation field is being used from timestep %d onwards.\n", FIRST_NLTE_RADFIELD_TIMESTEP); @@ -571,12 +575,7 @@ void init(const int my_rank, const int ndo_nonempty) { #ifdef MPI_ON { - int my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); - } - auto size = static_cast(my_rank_cells * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution)); + auto size = static_cast(noderank_nonemptycellcount * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution)); int disp_unit = sizeof(RadFieldBinSolution); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &radfieldbin_solutions, &win_radfieldbin_solutions); @@ -600,24 +599,17 @@ void init(const int my_rank, const int ndo_nonempty) { } if constexpr (DETAILED_BF_ESTIMATORS_ON) { -#ifdef MPI_ON { - int my_rank_cells = nonempty_npts_model / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_cells += nonempty_npts_model - (my_rank_cells * globals::node_nprocs); - } - auto size = static_cast(my_rank_cells * globals::bfestimcount * sizeof(float)); +#ifdef MPI_ON + auto size = static_cast(noderank_nonemptycellcount * globals::bfestimcount * sizeof(float)); int disp_unit = sizeof(float); MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &prev_bfrate_normed, &win_prev_bfrate_normed); MPI_Win_shared_query(win_prev_bfrate_normed, 0, &size, &disp_unit, &prev_bfrate_normed); - } #else - { prev_bfrate_normed = static_cast(malloc(nonempty_npts_model * globals::bfestimcount * sizeof(float))); - } #endif + } printout("[info] mem_usage: detailed bf estimators for non-empty cells occupy %.3f MB (node shared memory)\n", nonempty_npts_model * globals::bfestimcount * sizeof(float) / 1024. / 1024.); diff --git a/rpkt.cc b/rpkt.cc index a764d83b9..b7efcfee9 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -1003,21 +1003,22 @@ void allocate_expansionopacities() { const auto npts_nonempty = grid::get_nonempty_npts_model(); float *expansionopacities_data{}; double *expansionopacity_planck_cumulative_data{}; + #ifdef MPI_ON - int my_rank_nonemptycells = npts_nonempty / globals::node_nprocs; - // rank_in_node 0 gets any remainder - if (globals::rank_in_node == 0) { - my_rank_nonemptycells += npts_nonempty - (my_rank_nonemptycells * globals::node_nprocs); + const auto [_, noderank_nonemptycellcount] = + get_range_chunk(npts_nonempty, globals::node_nprocs, globals::rank_in_node); + + { + MPI_Aint size = noderank_nonemptycellcount * expopac_nbins * static_cast(sizeof(float)); + int disp_unit = sizeof(float); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &expansionopacities_data, &win_expansionopacities) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win_expansionopacities, 0, &size, &disp_unit, &expansionopacities_data) == + MPI_SUCCESS); } - MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(float)); - int disp_unit = sizeof(float); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &expansionopacities_data, &win_expansionopacities) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_expansionopacities, 0, &size, &disp_unit, &expansionopacities_data) == - MPI_SUCCESS); if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { - MPI_Aint size = my_rank_nonemptycells * expopac_nbins * static_cast(sizeof(double)); + MPI_Aint size = noderank_nonemptycellcount * expopac_nbins * static_cast(sizeof(double)); int disp_unit = sizeof(double); assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &expansionopacity_planck_cumulative_data, @@ -1072,7 +1073,7 @@ __host__ __device__ auto closest_transition(const double nu_cmf, const int next_ // lower_bound matches the first element where the comparison function is false const int matchindex = static_cast( std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, - [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - + [](const auto &line, const double find_nu_cmf) -> bool { return line.nu > find_nu_cmf; }) - globals::linelist); if (matchindex >= globals::nlines) [[unlikely]] { diff --git a/sn3d.cc b/sn3d.cc index fdb52cbaa..a2f8907dd 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -219,8 +219,7 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c } #ifdef MPI_ON -void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const int nstart, const int ndo, - char *mpi_grid_buffer, const size_t mpi_grid_buffer_size) { +void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const int nstart, const int ndo) { int position = 0; for (int root = 0; root < nprocs; root++) { MPI_Barrier(MPI_COMM_WORLD); @@ -693,7 +692,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns // Each process has now updated its own set of cells. The results now need to be communicated between processes. #ifdef MPI_ON - mpi_communicate_grid_properties(my_rank, globals::nprocs, nstart, ndo, mpi_grid_buffer, mpi_grid_buffer_size); + mpi_communicate_grid_properties(my_rank, globals::nprocs, nstart, ndo); #endif printout("timestep %d: time after grid properties have been communicated %ld (took %ld seconds)\n", nts, diff --git a/sn3d.h b/sn3d.h index e30cbfa9d..d679e82bb 100644 --- a/sn3d.h +++ b/sn3d.h @@ -121,8 +121,8 @@ inline void print_line_start() { #define __artis_assert(e) \ { \ - const bool pass = static_cast(e); \ - if (!pass) { \ + const bool assertpass = static_cast(e); \ + if (!assertpass) { \ if (output_file) { \ output_file << "\n[rank " << globals::rank_global << "] " << __FILE__ << ":" << __LINE__ \ << ": failed assertion `" << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ @@ -132,7 +132,7 @@ inline void print_line_start() { << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ std::abort(); \ } \ - assert(pass); \ + assert(assertpass); \ } #endif @@ -311,13 +311,17 @@ inline void check_already_running() { #endif } -constexpr auto get_range_chunk(int size, int nchunks, int nchunk) -> std::tuple { - const int minchunksize = size / nchunks; // integer division, minimum non-empty cells per process - const int n_remainder = size % nchunks; - const auto nstart = - (minchunksize + 1) * std::min(n_remainder, nchunk) + minchunksize * std::max(0, nchunk - n_remainder); +template + requires std::is_integral::value +constexpr auto get_range_chunk(const T size, const auto nchunks_in, const auto nchunk_in) -> std::tuple { + const auto nchunks = static_cast(nchunks_in); + const auto nchunk = static_cast(nchunk_in); + const auto minchunksize = size / nchunks; // integer division, minimum non-empty cells per process + const auto n_remainder = size % nchunks; + const auto nstart = (minchunksize + 1) * std::min(n_remainder, nchunk) + + minchunksize * std::max(static_cast(0), nchunk - n_remainder); const auto nsize = (nchunk < n_remainder) ? minchunksize + 1 : minchunksize; - return {nstart, nsize}; + return std::tuple{nstart, nsize}; } #endif // SN3D_H diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 41d7ac871..79ae146b5 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -114,16 +114,16 @@ void printout_tracemission_stats() { const double B_lu = statweight_target / statweight_lower * B_ul; const int nupperdowntrans = get_ndowntrans(element, ion, upper); - auto *downtranslist = globals::elements[element].ions[ion].levels[upper].downtrans; - auto *downtrans = std::find_if(downtranslist, downtranslist + nupperdowntrans, - [=](const auto &downtrans) { return downtrans.targetlevelindex == lower; }); - assert_always(downtrans != (downtranslist + nupperdowntrans)); + auto &downtranslist = globals::elements[element].ions[ion].levels[upper].downtrans; + auto *downtransition = std::find_if(downtranslist, downtranslist + nupperdowntrans, + [=](const auto &downtr) { return downtr.targetlevelindex == lower; }); + assert_always(downtransition != (downtranslist + nupperdowntrans)); printout("%7.2e (%5.1f%%) %4d %9d %5d %5d %8.1f %8.2e %4d %7.1f %7.1f %7.1e %7.1e\n", encontrib, 100 * encontrib / totalenergy, get_atomicnumber(element), get_ionstage(element, ion), globals::linelist[lineindex].upperlevelindex, globals::linelist[lineindex].lowerlevelindex, - downtrans->coll_str, globals::linelist[lineindex].einstein_A, downtrans->forbidden, linelambda, v_rad, - B_lu, B_ul); + downtransition->coll_str, globals::linelist[lineindex].einstein_A, downtransition->forbidden, + linelambda, v_rad, B_lu, B_ul); } else { break; } diff --git a/update_packets.cc b/update_packets.cc index 75ba8d29e..196eb706d 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -57,7 +57,6 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::WOLLAEGER) { // particle thermalisation from Wollaeger+2018, similar to Barnes but using a slightly different expression const double A = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 1.2 * 1.e-11 : 1.3 * 1.e-11; - const int mgi = grid::get_cell_modelgridindex(pkt.where); const double aux_term = 2 * A / (ts * grid::get_rho(mgi)); // In Bulla 2023 (arXiv:2211.14348), the following line contains (<-> eq. 7) contains a typo. The way implemented // here is the original from Wollaeger paper without the typo @@ -79,7 +78,6 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { // endot [erg/s] from Barnes et al. (2016). see their figure 6. const double endot = (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? 5.e11 * MEV * rho : 4.e10 * MEV * rho; - const double ts = pkt.prop_time; const double particle_en = H * pkt.nu_cmf; // energy of the particles in the packet // for endot independent of energy, the next line is trival (for E dependent endot, an integral would be needed) From 28d59afdecfd903d336a3d2d74ca99f8094af5f7 Mon Sep 17 00:00:00 2001 From: gleck97 <86471143+gleck97@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:58:49 +0200 Subject: [PATCH 032/117] Barnes particle thermalisation: Fix tau_ineff formula (#117) Co-authored-by: Luke Shingles --- .../results_md5_final.txt | 434 +++++------------- .../results_md5_job0.txt | 24 +- update_packets.cc | 2 +- 3 files changed, 130 insertions(+), 330 deletions(-) diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index c17f3aeb4..4b2fc6fce 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,324 +1,124 @@ -f9e8c462e7ef8bd0c0fade07bb715f3b absorption.out -274f502b0c431c87692eedaf5919ce4d absorption_res_00.out -1b23e9efcf255979d6e8dc1c9830e520 absorption_res_01.out -8f2d66054dd29553336e6b8a5491bbb6 absorption_res_02.out -e386c3bcbe983401a17bd95dc3d121d0 absorption_res_03.out -6a329922993d5f74dd860dbed3212635 absorption_res_04.out -4c73b13c528ea23c57bce1a988690cfb absorption_res_05.out -89efb4289fe1d9d399128d41a6642a05 absorption_res_06.out -18139fddb12924162c061157f9747207 absorption_res_07.out -c361a8425799dc3c16444f04fc197dcd absorption_res_08.out -24b714a39d7728e2e39c091a35e6241c absorption_res_09.out -acbca6ff80b948fa1c04ccab4037000f absorption_res_10.out -339b7c36dda10cf55418f2cacc59107f absorption_res_11.out -fabaefc81410ade72b31a9e6111af0e8 absorption_res_12.out -5ba48c6fced17fa5c84ba19ceb2c987e absorption_res_13.out -0899f426f6940ead33ef8c672f1fde00 absorption_res_14.out -f0ec41e87d648be6c2734d81e9b2a131 absorption_res_15.out -6e2cbfdb33a712025e11fec3ef58430a absorption_res_16.out -78cdb5e1399efa97c2cf87b5f30cb3d6 absorption_res_17.out -2bb07657b2a766dee543d3da2d154e41 absorption_res_18.out -39f1391db15fcd364f74689c05fae1d1 absorption_res_19.out -25f676d65df111740bee8deca71996b6 absorption_res_20.out -563a11129d764a915c89a9550b79408a absorption_res_21.out -d8d9d0df34288fef286dc46689a9ee03 absorption_res_22.out -516083a4ac583d51efca3e9b4bd6109a absorption_res_23.out -955163e7185855887b69ccacb553dddb absorption_res_24.out -8246b28aacb57b55aec1413793412344 absorption_res_25.out -2b481d6c113c632ddf7bbc15e4aecf8a absorption_res_26.out -99f5de348249be74f8cd4922927666a4 absorption_res_27.out -dd75e3b757da769ce06ea9ab3f854f90 absorption_res_28.out -af8da6bb3e95edd423441c817e1dc37d absorption_res_29.out -27c62988f57b5d905939782bfb3b0efe absorption_res_30.out -9371d71de8c01d9699811f29fb8a85c4 absorption_res_31.out -6e36bcef06a0605acfc3707604f36014 absorption_res_32.out -65c7ffbc0002be87c56bab4d797dfe19 absorption_res_33.out -67409a5ecea0880828b8a7234c8f3bf7 absorption_res_34.out -f10c90f165eec7bcba64ad9121989011 absorption_res_35.out -fbcd7f2ab65c0c535a657e72cc7edb3e absorption_res_36.out -635a99eaffd5d9f94b793e6f7ec73048 absorption_res_37.out -060b661d3a2e3ef001b2f9aeeffe10cb absorption_res_38.out -0863ed003882654f41655ad1665c20d5 absorption_res_39.out -1358786cd5a80c38f6b92b99e6b557f7 absorption_res_40.out -4caa8b9dbae91dc0c1882234b4ec0274 absorption_res_41.out -db49da7c14b3d32a62fabed98bb9c9c2 absorption_res_42.out -7d97f8989a5db571735d1a7b3f5b37bd absorption_res_43.out -ef4d0a36fec4da1705a10f98fa7a69c4 absorption_res_44.out -18cad46ac655c6cfafb9824fd2e5dfb2 absorption_res_45.out -2ffee6d7cb0c23e5ffb65db38d8a79af absorption_res_46.out -e8fec2be24fd7c1fe2c60941e74c990b absorption_res_47.out -89970ea8b3d5f85c069a7850f603e2ed absorption_res_48.out -a153dcd23cbd0e575579f5530bf0feb5 absorption_res_49.out -19dec21ea4ca6d122d4e6402e413e239 absorption_res_50.out -e2690942c3b57a50ced741027c94fb0a absorption_res_51.out -dc28aeb8509b183139472d242eb705f7 absorption_res_52.out -d4105a99be3e63e6351a077dd4e611f0 absorption_res_53.out -077e591ad2a1acb81412826e93a7b46b absorption_res_54.out -24035fc228f793f64cfcd1d96f0c6e23 absorption_res_55.out -471a08a1da666ae13f1f687ae868fa25 absorption_res_56.out -f6c6ef61dc942b2ad9735f67b528b4ac absorption_res_57.out -b857a70faa8d869c165d08763b85225c absorption_res_58.out -ae4d59c2630ca6b8ab8dd696dfc25fd4 absorption_res_59.out -bfd97c4e5495dffa84b2747896497e1f absorption_res_60.out -8db139458bb9280d9191540feb7f22aa absorption_res_61.out -23678df0058e7b136d548447c9247a5a absorption_res_62.out -1746f4b528f81b64f8c5ce789430d76a absorption_res_63.out -17b01b01353c695793e7956663dbaaf9 absorption_res_64.out -8700cba4ae77d530a3622c0ce5bbc8a8 absorption_res_65.out -67a9bdf952985811e14f60c8aadde0e5 absorption_res_66.out -528f8be97188ed25e32e3b3258ac5856 absorption_res_67.out -3eb4717018783c3aed3f298fb31583f7 absorption_res_68.out -6ad940791b99711306d5b3d5b947ee19 absorption_res_69.out -9d583ed1e8372c45f90a671df0e4dcb0 absorption_res_70.out -30fba9edf8484101009db72700fc3718 absorption_res_71.out -9c3332a1a4bc7d4ebbba1b6212e14d6c absorption_res_72.out -2e5b57f4f1adf29f21a0af09d7ee20d0 absorption_res_73.out -bd587ea7ccabea5c061acb24a62db797 absorption_res_74.out -14003f97741c6e428dba2ab2ee61aa9b absorption_res_75.out -f380a1f5f10e23a9eae4ddc860fec4b0 absorption_res_76.out -b9af5fe86e7e4601cb9ab0b5537e7303 absorption_res_77.out -e35b607f63d833a39e2936ca0528be1f absorption_res_78.out -b3d003d76facde4842f80b373cfe67aa absorption_res_79.out -54755075322b22a6f9014cc52c1145d5 absorption_res_80.out -ef297f2cca47bb00bf977a8053e15081 absorption_res_81.out -1b8fd6e037b3f508c08e814a4bb3f1ef absorption_res_82.out -357b5a10e02e415648c4f6bed251ba5d absorption_res_83.out -fc1cae8802aa49f3ee6111f8d8cfe287 absorption_res_84.out -5ca5d9d11fe1ef510f67c1e0eb073568 absorption_res_85.out -dedf1b98f85b928daad12bef4c373681 absorption_res_86.out -3aaa4d6ca5732a9536035e3559170e6c absorption_res_87.out -06fefa329cde29f5d86e77c0fa8d4c5c absorption_res_88.out -39d74ef9cc6c92c23200e6d400c28762 absorption_res_89.out -f7135992bb8a81787479ba759007d411 absorption_res_90.out -0bd9fdf583d626000f5d25aff31d071e absorption_res_91.out -a9c2a4462385ab0555d801ea431f5562 absorption_res_92.out -4bd91060043c8f96553bfd5a0ba6ec1a absorption_res_93.out -f52b5597e3d1f0f8e2a9b03e8d71e349 absorption_res_94.out -f8efb652b3b62df30d6490bbfdaf42fe absorption_res_95.out -4af3a8bbe04cd83ffca6201705ded960 absorption_res_96.out -6f63b6cbff3c903c64e7e6ecdea50c4c absorption_res_97.out -e62dba7cbb6826d15f6cb2fdde45c69b absorption_res_98.out -eb05e3560a97e99403464e9c79845341 absorption_res_99.out -897316929176464ebc9ad085f31e7284 bflist.out -f421b46da29529e44e57cb7caeac62db deposition.out -94e7893f4d16eaedf276ca3bb09408e2 emission.out -802067a4cd06e68099ae5d93d3e29773 emission_res_00.out -e885f6a4f62b14a6b45dd9423c20a98a emission_res_01.out -96dec81fc301a72fb5c7e08dc3637429 emission_res_02.out -3d95332d326b8ac4af0adf5af879543a emission_res_03.out -8a1f1252089b7f18d86b5738f3e37ab8 emission_res_04.out -3f7585082f3b3ebe844ceaa89863aedb emission_res_05.out -1d1555ab1c568793fcd362e9c5050d31 emission_res_06.out -57f31f3962ce4a18463d74841ff1b210 emission_res_07.out -0773ad2f6294f67ee91af110e7c64bd0 emission_res_08.out -f72ed64f15567c2317a4bbe238f31501 emission_res_09.out -064c28ace251811bdb07a9b7df383509 emission_res_10.out -06da84c944e866d0a85f292f799da601 emission_res_11.out -b98e07714fd362a755f3f12f35bb5084 emission_res_12.out -bc65982be583d84728ee39fdba1fda8b emission_res_13.out -95c634859bbc07187da5b7ae438fedd6 emission_res_14.out -1ee4dc26615d50737cc1c13c0811fcce emission_res_15.out -a21463ef64bfcccaf4f598cfbb6afae1 emission_res_16.out -0a6a79c5a0115fd3b331e45d8e242668 emission_res_17.out -3bdba3c4db9aeb5ada76d6198a911bdc emission_res_18.out -82ed3b9a44cbeab1e15c6c24967de7ff emission_res_19.out -e12b0df30e35686164792e078070f3ab emission_res_20.out -2d642d0d278d4b691187b7265b744610 emission_res_21.out -6c6389ec62f9aa14ef953772290b2d00 emission_res_22.out -84975687d246f6f7c78d6f2d04fd88ad emission_res_23.out -c6aa79e2280c41e13ff8461be02c0bb0 emission_res_24.out -2f92a55f470fb77669cf43f1e77dab89 emission_res_25.out -0d06fd2b501b740e876e72da835420e8 emission_res_26.out -ebed62e732f039a9b693f0271febc89e emission_res_27.out -f62e2aa4c4258a0379e95de144a8f694 emission_res_28.out -3e03b1bc7eedc9ac11fab9b362ac7ba4 emission_res_29.out -f95fce0026987aa1e2d45e9f42601799 emission_res_30.out -c44d05f443a167a9dbfbc12022fcf9f0 emission_res_31.out -4a106ace1b7bcc45ad4b0c985b704747 emission_res_32.out -6fddeaa911102604cb08a60922f518dc emission_res_33.out -de38fed5e2488f1cf5c8c67231135eab emission_res_34.out -b6450142bfeeeba4d8d9fb4546b8e00d emission_res_35.out -13f2b982cdf2c17e58b1128522637a27 emission_res_36.out -8a390b9d14dd186ea99117252ba69866 emission_res_37.out -bc9cab540155a5051fa9c72a9bde4904 emission_res_38.out -2cd6b2c4bd210424c75a0845a3bcb865 emission_res_39.out -6a462299b5a9556071a015616e735b22 emission_res_40.out -04bed39cfdda981d226aaf52a3f14446 emission_res_41.out -d8119b704c3c756907158cae1599b50b emission_res_42.out -180c543799c8222f5eb65eab46703390 emission_res_43.out -319e422dc7d67d5302c0af46031fa2ff emission_res_44.out -de9ff223f750723829be02852fcebe2c emission_res_45.out -ea6adaa69ef43bf3f77a5ddb02b9923b emission_res_46.out -e7251578e966a3d7411f45dd9ec7bcf0 emission_res_47.out -f7bfe17e81549093e7c1a55c6c41a8f6 emission_res_48.out -1d630e5b44474b813f4658b810dd1c51 emission_res_49.out -c96e48f5d4c22ed6795bf3c97634d478 emission_res_50.out -1a99b5727cba51bbb5579679c3c35e7a emission_res_51.out -08fb4109b9d80434bff19f74156dab93 emission_res_52.out -ad14b7efa870245ca7930cbbfd485f59 emission_res_53.out -16508a2eddfe4378122804eb08417ced emission_res_54.out -4e9ef3ddc1bad58af3ed46d353f10086 emission_res_55.out -6868217b5d9dd93da1193113416a8366 emission_res_56.out -2bee3ffecd99642130f792e6ad682253 emission_res_57.out -0446b4f5f267c6961811fb69f59fa250 emission_res_58.out -b1e4645cd0b8f29a6257a2adc07b8274 emission_res_59.out -435336fbabef2041315ca3005194cc4f emission_res_60.out -fb4cbb5640c27518f4f17a848d6a69c5 emission_res_61.out -f981fffabb8bc6d0f748a7316e3b0952 emission_res_62.out -2194689ac46a015e6909ff65892b011c emission_res_63.out -cc07bf8459f2e7d6875e2d179c7a0106 emission_res_64.out -1d5ae514e4fc6282201e78fe85484669 emission_res_65.out -d675c2588fc42731145a1d3c0b5c687b emission_res_66.out -2cf76193138ce584e31cadc9f5b3bd84 emission_res_67.out -8affb443ca4d8b0a77e7c88733debb94 emission_res_68.out -bc854df639f68c8b149124f1ea61c6bb emission_res_69.out -21517ada149c5cf22e13a74d2d0863a8 emission_res_70.out -2da4e995d536c0e54696515aff752e46 emission_res_71.out -cc0c3b1680328bc927c0f54482126c5b emission_res_72.out -8613f32cf8d3e29f5b8edd894c659f73 emission_res_73.out -c1994baf84849f372662843412c5de68 emission_res_74.out -52e5fa9e3717b0fb3dde8ba471b49bbb emission_res_75.out -1ea14b097540b319a03e199df3611e11 emission_res_76.out -a98f6a81be8953903c1086eb0a5be8c6 emission_res_77.out -9cebab17a7dd36b1c6d3ad384ad63225 emission_res_78.out -07890efda1402d7ca57e036986bb94e0 emission_res_79.out -402cabe1089be744674d03177da02bb5 emission_res_80.out -53e829019a110181ce49443a2a456c60 emission_res_81.out -3259348d2c75947f90d850a5f7edeebb emission_res_82.out -d2b3a5952c3070ba7022190ee1e01b3a emission_res_83.out -ace32f45b7f9acfe5bda96d10bd6a39c emission_res_84.out -fc3f2ffb314a2c36853f242d8afd2f18 emission_res_85.out -9c89eeab349e729d247aa103dc91e48a emission_res_86.out -7fc3cb5d79a61059025fb5ab94d5be0e emission_res_87.out -f3211188c037e359c947d69eb68fc855 emission_res_88.out -308f7883bc6b64f625dd0d177d5168f0 emission_res_89.out -fbfd42a65e22751bcbf42bfa2aca3b40 emission_res_90.out -1a1a8172c8907f9a615c2d6cbdbdcc25 emission_res_91.out -f0853330612ec6644947aa0cab728b1c emission_res_92.out -45f17ebf98700b22aaaf2534948f3739 emission_res_93.out -8e20cb52ecb1ada6dce9db0a1bdefca3 emission_res_94.out -5c99bbb14897b0d0228aded66a96c022 emission_res_95.out -d03f934f750cf063cfdcde6b7e1f274c emission_res_96.out -81168b09e51669a848901263b9b0d69f emission_res_97.out -f603c942ee34d4b4b12a910141e8f9cc emission_res_98.out -0e86758a606793c97614e61fa00e18bd emission_res_99.out -ddc4ce928abab65d46d480f89c2e574b emissiontrue.out -e86a156efcfe3b34f7436f4477868ccd emissiontrue_res_00.out -4f12e1ee9d7e764268d832470b6c3ae8 emissiontrue_res_01.out -03e5b5b9bb711cd002734e843e462ee9 emissiontrue_res_02.out -7ac89cf9180ffb2fca31007892a2138e emissiontrue_res_03.out -6d39ca494abf5e58f3c042d1eab6e8ac emissiontrue_res_04.out -57d913d72de624546786fd1adc6936d5 emissiontrue_res_05.out -b3a7774e7f90432cfd5041465f58c41a emissiontrue_res_06.out -46a2dd8ed093b86abbb33ab716b8fda3 emissiontrue_res_07.out -e8bf23ffd98fa0e4efc0fa44ec3ebc86 emissiontrue_res_08.out -2d495595ae8d7ce2798c69e61d70215f emissiontrue_res_09.out -fc9badf3dbf024782155aa3b15e88034 emissiontrue_res_10.out -647f4d3acea36b412dd3db484d0b7db1 emissiontrue_res_11.out -9d57d4aace7f6239b4998511bc31b2c4 emissiontrue_res_12.out -917648be6892d25b44b4f1024bd19901 emissiontrue_res_13.out -2d92697892551d8ff8831c2ea394164c emissiontrue_res_14.out -29a9d87a2ea0032ed40eff83e84bd91f emissiontrue_res_15.out -194129d693d005005aa5c022a2091693 emissiontrue_res_16.out -7adcd28f45232f7550a7e778e66ba17f emissiontrue_res_17.out -625a21043483d85de186ebd65173dfca emissiontrue_res_18.out -401ca73df0574e3460786f1bbdbb0886 emissiontrue_res_19.out -58e83e9a97c1cc581adf5d2b19c40ec3 emissiontrue_res_20.out -8501ad496eec2760c0ef67135767de2b emissiontrue_res_21.out -6083024a98dcd371bff283c80a6bfea5 emissiontrue_res_22.out -a3813332e1739c2613bc8469861550b2 emissiontrue_res_23.out -c7dd72feff75b0289389681471b35cfd emissiontrue_res_24.out -8372c7921bdf58199ac416677ac71573 emissiontrue_res_25.out -398f16256b356464e5511726e64114ef emissiontrue_res_26.out -7f7c72d10636e797c3dc6a019aaac7fc emissiontrue_res_27.out -bb8a2cc7f83d38a4aa5d04611df7c6bf emissiontrue_res_28.out -7a188814bf3c63160a0afcfcf046d250 emissiontrue_res_29.out -b2f7d4744092b5779876f8823e12e963 emissiontrue_res_30.out -e76d94d9cbb15be8af6e5007cfebf489 emissiontrue_res_31.out -98c07bcc9786a6f03bc15242cfc079f8 emissiontrue_res_32.out -351b911335c672f627b2e090c968bf16 emissiontrue_res_33.out -96bc46d50765b98ce3ee870ef9df4b52 emissiontrue_res_34.out -4460994748a4394f0f8ac79d59d177bd emissiontrue_res_35.out -cf31f73fcb64cdda5167507e0346e4f3 emissiontrue_res_36.out -4a502cd7f1881388589c122258265536 emissiontrue_res_37.out -e6336332dc88919f38ff742f37fb0a21 emissiontrue_res_38.out -804069802c8fde481bc95ce84fe82b4c emissiontrue_res_39.out -46bb77b2b0c2ae15dd0e91bdd9003fbd emissiontrue_res_40.out -a50a6600d9bdc78939539033a7d09106 emissiontrue_res_41.out -052f0eb5db6423d69887704483ba032e emissiontrue_res_42.out -4ba6bec99680742ade65c6690c4aaeaf emissiontrue_res_43.out -22b0143252ea8bcb364dcb93362ad735 emissiontrue_res_44.out -0c9847e9d43702a168f3dae685345e4d emissiontrue_res_45.out -be7ad75e02dd55a1c3ef0b5c0ef73aa7 emissiontrue_res_46.out -c9cad8ef312b13a8d4b44dba6f6c80f5 emissiontrue_res_47.out -a5496f4ed80af479e4bfeda1cf0edada emissiontrue_res_48.out -5ac17a32ed4d81f7ec3a21cd441761d6 emissiontrue_res_49.out -1e6243408c1397667bc52d08aab3fdc5 emissiontrue_res_50.out -573ba7e8afb89e8396b846cfdcfbe6f0 emissiontrue_res_51.out -e0dcc6d7cfa1e8917cbf5231b4f2470e emissiontrue_res_52.out -c71ef5e51679b446458b8c15d614ab80 emissiontrue_res_53.out -1c93d9ab3e6746f37bb284da3df685a0 emissiontrue_res_54.out -d5062a8c2c2ab51956ca2cb7e0cd847b emissiontrue_res_55.out -e550cb7d9b3c5144d82cc594b6ba8ae4 emissiontrue_res_56.out -54d230e990bfea095231c3010ee914fe emissiontrue_res_57.out -4694877ebf8197a4480552b953db45b9 emissiontrue_res_58.out -fa39c5bfe6c13eb5324fba201e9ab7e1 emissiontrue_res_59.out -d8bf15fbc7c518d763b2efa9d3d28ef2 emissiontrue_res_60.out -7a160fb9f07317b53c13ea6d63cb978e emissiontrue_res_61.out -048a5e3161bcd03dd782d8027e6925f4 emissiontrue_res_62.out -ff67b5dc757380bffc4f87d90a6898c6 emissiontrue_res_63.out -2881f44b20a65d31dff4a5414f6f2362 emissiontrue_res_64.out -3b31536580cb9cffd316a4e3caba08dd emissiontrue_res_65.out -273428d42380f08e9429d0109d06ae40 emissiontrue_res_66.out -e1792d1e140582983099dcd9f786492f emissiontrue_res_67.out -9fbf864fa61116e9f28b8b63411882f7 emissiontrue_res_68.out -671120c57fbee246a946adc22b8c2ba3 emissiontrue_res_69.out -f4270005c328a93fbe4dfa36d45a4b7d emissiontrue_res_70.out -61a345a7a515d7d18e1cc80dce1fd43c emissiontrue_res_71.out -a7be8c91f0cc5bea9a611debf14cbacf emissiontrue_res_72.out -be432fa37bacf3dcac8c062b5a32bf6d emissiontrue_res_73.out -c998e8db6da25720422497ec9004728e emissiontrue_res_74.out -dd0379f8cee49aed12a0cb16c375acdb emissiontrue_res_75.out -a730184bfb9f4f49fc0a85f6ff6c7b80 emissiontrue_res_76.out -041bf247a36a676297c6e572dd6076e8 emissiontrue_res_77.out -1f622bac25f4ede015e41c2cfab26f91 emissiontrue_res_78.out -03880bf9a5ccbb153e9b9cb7252507de emissiontrue_res_79.out -d6b91a8a879c41db91d6d8a1fd2e1cfa emissiontrue_res_80.out -afbb435db75bcac21f7097bb5b44c265 emissiontrue_res_81.out -8a3d1024a8546ed2d0bcad762baac39a emissiontrue_res_82.out -66cebcafcfa171672b95c695cd9f821b emissiontrue_res_83.out -ee722f27d5f6b82c4a8bc0772e6681f8 emissiontrue_res_84.out -e945a94c3c76e40fcc9a7f8b9bfa31e4 emissiontrue_res_85.out -b8929a4b94a29d50b986e6019caee4ea emissiontrue_res_86.out -bc4c78dfeb2b70b4e03e22ae4aad0306 emissiontrue_res_87.out -6b5252ea88bc79daf1df62c5a5f61fe7 emissiontrue_res_88.out -d340b8404b5f993c487de0f9e5be0464 emissiontrue_res_89.out -195d32c0039f58ac7203c549453f8ec1 emissiontrue_res_90.out -5c8d8902822e7925e83d64bf4d67bc90 emissiontrue_res_91.out -b18f8730f9de6d8f56f34b948489ec8d emissiontrue_res_92.out -aa9f9d8317db0f97019be1bf05c36a32 emissiontrue_res_93.out -df1484f3b24e5173a31a2e496c04166e emissiontrue_res_94.out -0cbdc62ffce5688bd58805c873be9f89 emissiontrue_res_95.out -cfbedb1f6be28a5205686538e0a0e102 emissiontrue_res_96.out -ee7b117bcc203fa9da9c1f530859725e emissiontrue_res_97.out -17ae8f115a621c762b01fbb522b590cc emissiontrue_res_98.out -f488ecba4cbe41a57e365c4b04b7c861 emissiontrue_res_99.out +2d4f433030dd4016f4513993bbb12e71 absorption.out +16638f8b6020b6f933df5775d752c1eb absorption_res_00.out +8155896fd62b6302db716a9c456337a1 absorption_res_01.out +8f197b23b0c787dd21705138195a70bd absorption_res_02.out +221b5545da41b3a0e4959435c0bbe67c absorption_res_03.out +38510a3b305807f912d48f219e7d5b49 absorption_res_04.out +1c039d4edc9aa717e83b197cdc1bfeca absorption_res_05.out +f573103eefbee1f29044ab0a119f55c1 absorption_res_06.out +1056e03c4eeb7a5ac7ef6f99a92664ad absorption_res_07.out +072b2c8e6568ee84dfd99a0d9d08b4c2 absorption_res_08.out +9c521c594e918e5797627c28a48547cf absorption_res_09.out +94bc0c7c3160fdc91f1e396680215697 absorption_res_10.out +ebff8ba12c879f5c85366b9c2d11584e absorption_res_11.out +5f8e9090618c44042bfa9ffb2c263f05 absorption_res_12.out +d4a2925cd44e02294bea3549ece068f3 absorption_res_13.out +51a3af032af5540c4df4759788179695 absorption_res_14.out +fee58b08eef55360815b4661db58bfb1 absorption_res_15.out +35fd1fefb6142897d07c08bc026b0e68 absorption_res_16.out +86105144ff0ddd4037eaa28216075a20 absorption_res_17.out +44ce35bee640e62c60fcaab4b7274827 absorption_res_18.out +ce76aab764b1b238fae9a226670d9c79 absorption_res_19.out +54899d0a5f7bba56381ca0bd8f6835f2 absorption_res_20.out +a56dd9ec8662e567f386be914336444e absorption_res_21.out +04d28bf5c2f669d1d7cb66581659d2a5 absorption_res_22.out +fb3d5e7bd67890bad3bd7499468d7809 absorption_res_23.out +bcc1ad33e1e7c406b53ffbb54dca1a08 absorption_res_24.out +bd2c96d977c79d29f72b102901a638cd absorption_res_25.out +ecb0b3f1657c12144c281875ae502ce8 absorption_res_26.out +bedb968a79cb669ac2e96516d69dc4cb absorption_res_27.out +cc5a966fd75c904665d9f7e7d5196350 absorption_res_28.out +82b0a9ac5fcc5018c69e0151646caef3 absorption_res_29.out +a921089a7a13d5c55405f1756fbc47df emissiontrue_res_26.out +25c8df79874be3baa86f1b558209da85 emissiontrue_res_27.out +453198517806b48c49b90922d822ce44 emissiontrue_res_28.out +9841f4ac0ebe064d37713cd65c2f40e7 emissiontrue_res_29.out +5d5e41c244f2d1c210fa8a335ec528f7 emissiontrue_res_30.out +9a242b9f6ea6c63b52e32127ecb7a181 emissiontrue_res_31.out +e46a4ed9114901d97a60e1a690b882a3 emissiontrue_res_32.out +1db0f07906fdb96f1fa96852d4ffba4e emissiontrue_res_33.out +c9e09c7ad1cc2372bfd5a519ab7fdc81 emissiontrue_res_34.out +4556562b0aa165e689fe657d24ac08e3 emissiontrue_res_35.out +42a20c52ece684ea79011e00d1dd834a emissiontrue_res_36.out +f4dd5502f4a3be7de13b0b4ca9660152 emissiontrue_res_37.out +fd97e2d9f12867d21323568a1c15be55 emissiontrue_res_38.out +fb2920b08da65f125e562104e43149f9 emissiontrue_res_39.out +9f8c314c42e593d4f4fb57bc73e8f85b emissiontrue_res_40.out +adecfebc9d7f5f60d312f1eb67780131 emissiontrue_res_41.out +aee0e58ad9806ed295a296198c5ec930 emissiontrue_res_42.out +e781ffef53eb20c9d1952deba56f13a0 emissiontrue_res_43.out +b6d92ea77f767eac86d798c9d6ae85e2 emissiontrue_res_44.out +8b7dab69cade6e8d72507a1d2fc99f21 emissiontrue_res_45.out +dadfd481448680eb357843530741dc7f emissiontrue_res_46.out +e780c0a563a99bd7c58ba07712d6c47c emissiontrue_res_47.out +a8ee5cbcbba577e3bb3c0d152350f903 emissiontrue_res_48.out +09dae8f669a2364bd4f672e9e0cd57eb emissiontrue_res_49.out +6999f59689b05cda9b05c125e1709ef7 emissiontrue_res_50.out +028d4e8140375bd7812e9c9ca9878344 emissiontrue_res_51.out +1bbdbdf49023da1e2b6945e711bf314e emissiontrue_res_52.out +b58e80f3cf37e585662205c343325f0b emissiontrue_res_53.out +6e1a48a17d9b393fc9ed82e4400317c5 emissiontrue_res_54.out +84bb6a1dcc047178b8b634ad66c37302 emissiontrue_res_55.out +7a69055b480e7b86529cc75ee9013dff emissiontrue_res_56.out +d1f888cdf16946981e46893b53aa9359 emissiontrue_res_57.out +999eb7330289b328abe291d329e37f79 emissiontrue_res_58.out +6e35905e1c3ee6a2af778e4180d13196 emissiontrue_res_59.out +ceceac460dacdc099d3cb73ab6465e05 emissiontrue_res_60.out +d8973031a918fd281076cb87c5358b3c emissiontrue_res_61.out +529da7cbfc8ea9876db535ee9a6c886b emissiontrue_res_62.out +047b3c6c863ee5e16244831b36c3c858 emissiontrue_res_63.out +38e5f31ca6cca246cad54557cc245683 emissiontrue_res_64.out +3879c20f6a0fb41b5d4f0030a53a7a39 emissiontrue_res_65.out +56cf72759bfccd4c77cbf27a46d4bba6 emissiontrue_res_66.out +d3c5c42de41a2aa98fc42af6b2010d19 emissiontrue_res_67.out +f8af387e1e8d16d39c60107904e3f251 emissiontrue_res_68.out +c396ac55cc37eae1a647eb147dc871e2 emissiontrue_res_69.out +48e20b2e1e2fc8287f0deb79a76ca9d2 emissiontrue_res_70.out +80d06eb01ad5490d5cd1c32220d3fa3b emissiontrue_res_71.out +6fcde5a09c9fe1d540808df2168a7520 emissiontrue_res_72.out +9253e9bd1d043627d4bef9c966beb603 emissiontrue_res_73.out +ffb0c062d59174f0b1b45410346edbd0 emissiontrue_res_74.out +781189e0ba2017253d5203d43cf50d88 emissiontrue_res_75.out +8ce9779a3bee78aa9c1deaf232d4082b emissiontrue_res_76.out +3710f5e0ec8c9b4ecb39cbefa5888c3b emissiontrue_res_77.out +89e30c34c068534995edb459d99afd7c emissiontrue_res_78.out +30f926c456a010ad0eed5828f46ebb39 emissiontrue_res_79.out +adaedef3b8d69d1f373f67b71cbf8af7 emissiontrue_res_80.out +ad2d9a443eab39821deeb5cb89fccbc4 emissiontrue_res_81.out +43c19eba8cc751655ea98385f9e71cd3 emissiontrue_res_82.out +188c89cc9810969958054aa1e1304377 emissiontrue_res_83.out +57f0e055c0d636cec3177cc992cd4eb0 emissiontrue_res_84.out +b97ad2670e95328ccb868c5ed46415e4 emissiontrue_res_85.out +ccb2764064ca8da3d2ee37887755aa20 emissiontrue_res_86.out +e80334851b35366fb13ee78dcda1b0ea emissiontrue_res_87.out +0e8f1e6e5087944dbbbc914ffa1a80b2 emissiontrue_res_88.out +788744dfedfbe97475d6327c45af6664 emissiontrue_res_89.out +854d1a563aa8f2faae36faa20d2b906a emissiontrue_res_90.out +6fa9c18760ef219749feb4cc20d7f9a1 emissiontrue_res_91.out +ff6238240a3801706c099dd1c574afa2 emissiontrue_res_92.out +8c95640d069730c24975b357be681692 emissiontrue_res_93.out +6350ac3c0c88af2d78ed5601632e68e8 emissiontrue_res_94.out +a7517af99ac98786eb6d140f97f77b04 emissiontrue_res_95.out +1c31fedd06cf45bfc32f51e2b2a5729b emissiontrue_res_96.out +cabc01b5d90b539973d938a0eaeb7af3 emissiontrue_res_97.out +18b39599557c0848dbe760b8e5fd5480 emissiontrue_res_98.out +9a8ecf5e5add1c94390be3b2b682def5 emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -b1e9d6e1b0460ddb425ebe296ef0eaee light_curve.out -c4376a7fa8ea4fc8a0345dc0c3231889 light_curve_res.out +7c5c000e85e3a6f217660a65f951bc16 light_curve.out +ab45c4b292e8522606641ba3069bc5dd light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d88772c9f2f982809105433aa1ef43ed packets00_0000.out -8b2b12f83be94c74e6b452ed629a01e6 packets00_0001.out -8eda58f172cdcb88a86e018a286ee9f2 packets00_0002.out -3492c21b7da16033c832dbbb53e23c04 packets00_0003.out -2013eb78c14b8ab574b3e7d045ee9f7f spec.out -f7aae73b1abecba91128abc65b17f4be spec_res.out +9c480fe54f7d267853b77aa7ee27f9c4 packets00_0000.out +ec9e7163b12f18865279b436d0a7a2c7 packets00_0001.out +33b37b7eb63a81de43a1a29e5de8ec68 packets00_0002.out +345baa17d316a1ab467cf7fd8576e64b packets00_0003.out +7c59f3600ef4024c5f951baacc505388 spec.out +bc4f2eb925920a5598088a80544fc4a1 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -00b8474e1bec3df40f2f643d6b34fc4e job1/estimators_0000.out -ad01423a9531a1c364a1901682609112 job1/estimators_0001.out -b630267042391a009fad2f00b0f0ce2f job1/estimators_0002.out -eb8561e04928876e09d70ba46585054a job1/estimators_0003.out +71a749b62221c39bf8fff3cf21943bc3 job1/estimators_0000.out +4c261dc1c0fd504c72ccf7d5c181fbb4 job1/estimators_0001.out +a170c449679c91ccc7671d115ed57424 job1/estimators_0002.out +4ef84502fbe361cffe36968545de8ced job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 2475bebe2..ee69024b2 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -e9aae3a7ab36a1a44e40ea57355e1ba0 deposition.out -afe66f023087001ce7a9fff264f87b2b gamma_light_curve.out +406cd1f623c734534f62a32d5173496a deposition.out +9c1df62caa6bc28e29154c334c6ab215 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -c167f0a32585932e22e6265b0c9ebbbb light_curve.out +fdc9204a62e90f07dd9d15e726844144 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -c5d9f0d8d6ea6137782e7f73cceb2a99 packets00_0000.out -2f157c26d84a5002e5f88f1ffe881654 packets00_0001.out -d395efd35c062824dd6ab0104e0867f8 packets00_0002.out -e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out -88a0e6320da73f235aec8739d4a123a3 spec.out +4af65166525fbe901e45853d19fefe2f packets00_0000.out +8e19203368d982b1813a832ac395ecfb packets00_0001.out +cc96fd2e94f90732d24f4d590b4b8958 packets00_0002.out +e8fc6e9f9954572b37f2d5eb7ee7f514 packets00_0003.out +f9d67bf3c4e8faa8ad73f50199c60a09 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -76e3af84b3a66c9a282e41a6627dc4e6 job0/estimators_0000.out -0feb35456d8d8e9bbfc6548ffa0ae332 job0/estimators_0001.out -edd1c258e08cac13e09fcae4bac10992 job0/estimators_0002.out -f7550c181706595984aaf71e651a381f job0/estimators_0003.out +ab0470f3b05d07c046b3e2435efdc980 job0/estimators_0000.out +2be03f48bd4e924948619e820291869e job0/estimators_0001.out +acf35bf488b525b61436ddf6f86116d2 job0/estimators_0002.out +39344b6d47744a6f8266cb744b1bfebe job0/estimators_0003.out diff --git a/update_packets.cc b/update_packets.cc index 196eb706d..d75839306 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -42,7 +42,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double v_ej = std::sqrt(E_kin * 2 / grid::mtot_input); const double prefactor = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 7.74 : 7.4; - const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * + const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) / std::pow((0.2 * 29979200000) / v_ej, 3. / 2.); const double f_p = std::log(1 + (2. * ts * ts / tau_ineff / tau_ineff)) / (2. * ts * ts / tau_ineff / tau_ineff); assert_always(f_p >= 0.); From fe38c4a8c8a3d6fc8eab1292e086db9197114554 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 31 Aug 2024 00:05:59 +0100 Subject: [PATCH 033/117] Perf: Add nu_edge-ordered nnlevel array to cellcache (#118) Improves nebular one-zone packet prop duration on Apple M1 by about 20%. --- globals.h | 1 + input.cc | 1 + rpkt.cc | 2 +- update_grid.cc | 44 ++++++++++++++++++++------------------------ 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/globals.h b/globals.h index fbb252898..121e454f7 100644 --- a/globals.h +++ b/globals.h @@ -201,6 +201,7 @@ struct CellCache { CellCacheElements *chelements{}; std::vector ch_all_levels; std::vector ch_allcont_departureratios; + std::vector ch_allcont_nnlevel; double chi_ff_nnionpart{-1}; int cellnumber{-1}; // Identifies the cell the data is valid for. }; diff --git a/input.cc b/input.cc index f3debe0c7..6ee793929 100644 --- a/input.cc +++ b/input.cc @@ -1290,6 +1290,7 @@ void setup_cellcache() { assert_always(globals::nbfcontinua >= 0); globals::cellcache[cellcachenum].ch_allcont_departureratios.resize(globals::nbfcontinua); + globals::cellcache[cellcachenum].ch_allcont_nnlevel.resize(globals::nbfcontinua); mem_usage_cellcache += globals::nbfcontinua * sizeof(double); printout("[info] mem_usage: cellcache for thread %d occupies %.3f MB\n", cellcachenum, diff --git a/rpkt.cc b/rpkt.cc index b7efcfee9..0f321e558 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -928,7 +928,7 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix if ((DETAILED_BF_ESTIMATORS_ON && grid::get_elem_abundance(modelgridindex, element) > 0) || (!DETAILED_BF_ESTIMATORS_ON && ((get_nnion(modelgridindex, element, ion) / nnetot > 1.e-6) || (level == 0)))) [[likely]] { - const double nnlevel = USECELLHISTANDUPDATEPHIXSLIST ? get_levelpop(modelgridindex, element, ion, level) + const double nnlevel = USECELLHISTANDUPDATEPHIXSLIST ? globals::cellcache[cellcacheslotid].ch_allcont_nnlevel[i] : calculate_levelpop(modelgridindex, element, ion, level); if (nnlevel > 0) { diff --git a/update_grid.cc b/update_grid.cc index b603685ca..a42c49131 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1192,65 +1192,61 @@ void cellcache_change_cell(const int modelgridindex) { // onset of the new timestep. Also, boundary crossing? // Calculate the level populations for this cell, and flag the other entries // as empty. - if (modelgridindex == globals::cellcache[cellcacheslotid].cellnumber) { + auto &cacheslot = globals::cellcache[cellcacheslotid]; + if (modelgridindex == cacheslot.cellnumber) { return; } - globals::cellcache[cellcacheslotid].cellnumber = modelgridindex; - globals::cellcache[cellcacheslotid].chi_ff_nnionpart = -1.; + cacheslot.cellnumber = modelgridindex; + cacheslot.chi_ff_nnionpart = -1.; const int nelements = get_nelements(); for (int element = 0; element < nelements; element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - globals::cellcache[cellcacheslotid] + cacheslot .cooling_contrib[kpkt::get_coolinglistoffset(element, ion) + kpkt::get_ncoolingterms_ion(element, ion) - 1] = COOLING_UNDEFINED; if (modelgridindex >= 0) { const int nlevels = get_nlevels(element, ion); + auto &chion = cacheslot.chelements[element].chions[ion]; #ifdef _OPENMP #pragma omp parallel for #endif for (int level = 0; level < nlevels; level++) { - globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].population = - calculate_levelpop(modelgridindex, element, ion, level); + chion.chlevels[level].population = calculate_levelpop(modelgridindex, element, ion, level); } } } for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); + auto &chion = cacheslot.chelements[element].chions[ion]; for (int level = 0; level < nlevels; level++) { const auto nphixstargets = get_nphixstargets(element, ion, level); + auto &chlevel = chion.chlevels[level]; for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[ion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .corrphotoioncoeff = -99.; + chlevel.chphixstargets[phixstargetindex].corrphotoioncoeff = -99.; #if (SEPARATE_STIMRECOMB) - globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[ion] - .chlevels[level] - .chphixstargets[phixstargetindex] - .stimrecombcoeff = -99.; + chlevel.chphixstargets[phixstargetindex].stimrecombcoeff = -99.; #endif } - globals::cellcache[cellcacheslotid] - .chelements[element] - .chions[ion] - .chlevels[level] - .processrates[MA_ACTION_INTERNALUPHIGHER] = -99.; + chlevel.processrates[MA_ACTION_INTERNALUPHIGHER] = -99.; } } } if (modelgridindex >= 0) { - std::ranges::fill(globals::cellcache[cellcacheslotid].ch_allcont_departureratios, -1.); + std::ranges::fill(cacheslot.ch_allcont_departureratios, -1.); + + for (int i = 0; i < globals::nbfcontinua; i++) { + const int element = globals::allcont[i].element; + const int ion = globals::allcont[i].ion; + const int level = globals::allcont[i].level; + cacheslot.ch_allcont_nnlevel[i] = get_levelpop(modelgridindex, element, ion, level); + } } } From 730ce45fe5888f05ff52eb27bc531274eaf3d9b7 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 1 Sep 2024 20:09:26 +0100 Subject: [PATCH 034/117] Fix cppcheck 2.15.0 warnings (#119) --- .clang-tidy | 1 + .github/workflows/ci-checks.yml | 4 ++-- grid.cc | 6 +++--- sn3d.h | 6 +++++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index deac71a1f..5573209cd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -8,6 +8,7 @@ Checks: > -abseil-*, -android-*, -altera-*, + -bugprone-casting-through-void, -bugprone-easily-swappable-parameters, -bugprone-exception-escape, -bugprone-implicit-widening-of-multiplication-result, diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index a219be667..66146a119 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -25,12 +25,12 @@ jobs: - name: run cppcheck and check for errors run: | cppcheck --version - cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=warning,performance,portability --suppress=memleak --check-level=exhaustive . + cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=warning,performance,portability --suppress=memleak --suppress=passedByValue --check-level=exhaustive . - name: show cppcheck style suggestions run: | cppcheck --version - cppcheck --force --language=c++ --std=c++20 --enable=style --suppress=knownConditionTrueFalse --check-level=exhaustive . + cppcheck --force --language=c++ --std=c++20 --enable=style,performance --suppress=knownConditionTrueFalse --check-level=exhaustive . clang-format: runs-on: ubuntu-24.04 diff --git a/grid.cc b/grid.cc index 2cef7513e..48e5625d8 100644 --- a/grid.cc +++ b/grid.cc @@ -1505,10 +1505,10 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - return n_r; } } - assert_always(false); - } else { - assert_always(false); } + + assert_always(false); + return -1; } constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { diff --git a/sn3d.h b/sn3d.h index d679e82bb..fcffeefae 100644 --- a/sn3d.h +++ b/sn3d.h @@ -99,7 +99,11 @@ inline thread_local auto gslworkspace = #ifdef __NVCOMPILER_CUDA_ARCH__ #define printout(...) printf(__VA_ARGS__) -#define __artis_assert(e) assert(e) +#define __artis_assert(e) \ + { \ + const bool assertpass = static_cast(e); \ + assert(assertpass); \ + } #else inline void print_line_start() { From 97ea94fb8ca116279882f2624e2f3dcbc1cd5e91 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 2 Sep 2024 11:43:26 +0100 Subject: [PATCH 035/117] Revert "Barnes particle thermalisation: Fix tau_ineff formula" (#121) Reverts artis-mcrt/artis#117 --- .../results_md5_final.txt | 434 +++++++++++++----- .../results_md5_job0.txt | 24 +- update_packets.cc | 2 +- 3 files changed, 330 insertions(+), 130 deletions(-) diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index 4b2fc6fce..c17f3aeb4 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,124 +1,324 @@ -2d4f433030dd4016f4513993bbb12e71 absorption.out -16638f8b6020b6f933df5775d752c1eb absorption_res_00.out -8155896fd62b6302db716a9c456337a1 absorption_res_01.out -8f197b23b0c787dd21705138195a70bd absorption_res_02.out -221b5545da41b3a0e4959435c0bbe67c absorption_res_03.out -38510a3b305807f912d48f219e7d5b49 absorption_res_04.out -1c039d4edc9aa717e83b197cdc1bfeca absorption_res_05.out -f573103eefbee1f29044ab0a119f55c1 absorption_res_06.out -1056e03c4eeb7a5ac7ef6f99a92664ad absorption_res_07.out -072b2c8e6568ee84dfd99a0d9d08b4c2 absorption_res_08.out -9c521c594e918e5797627c28a48547cf absorption_res_09.out -94bc0c7c3160fdc91f1e396680215697 absorption_res_10.out -ebff8ba12c879f5c85366b9c2d11584e absorption_res_11.out -5f8e9090618c44042bfa9ffb2c263f05 absorption_res_12.out -d4a2925cd44e02294bea3549ece068f3 absorption_res_13.out -51a3af032af5540c4df4759788179695 absorption_res_14.out -fee58b08eef55360815b4661db58bfb1 absorption_res_15.out -35fd1fefb6142897d07c08bc026b0e68 absorption_res_16.out -86105144ff0ddd4037eaa28216075a20 absorption_res_17.out -44ce35bee640e62c60fcaab4b7274827 absorption_res_18.out -ce76aab764b1b238fae9a226670d9c79 absorption_res_19.out -54899d0a5f7bba56381ca0bd8f6835f2 absorption_res_20.out -a56dd9ec8662e567f386be914336444e absorption_res_21.out -04d28bf5c2f669d1d7cb66581659d2a5 absorption_res_22.out -fb3d5e7bd67890bad3bd7499468d7809 absorption_res_23.out -bcc1ad33e1e7c406b53ffbb54dca1a08 absorption_res_24.out -bd2c96d977c79d29f72b102901a638cd absorption_res_25.out -ecb0b3f1657c12144c281875ae502ce8 absorption_res_26.out -bedb968a79cb669ac2e96516d69dc4cb absorption_res_27.out -cc5a966fd75c904665d9f7e7d5196350 absorption_res_28.out -82b0a9ac5fcc5018c69e0151646caef3 absorption_res_29.out -a921089a7a13d5c55405f1756fbc47df emissiontrue_res_26.out -25c8df79874be3baa86f1b558209da85 emissiontrue_res_27.out -453198517806b48c49b90922d822ce44 emissiontrue_res_28.out -9841f4ac0ebe064d37713cd65c2f40e7 emissiontrue_res_29.out -5d5e41c244f2d1c210fa8a335ec528f7 emissiontrue_res_30.out -9a242b9f6ea6c63b52e32127ecb7a181 emissiontrue_res_31.out -e46a4ed9114901d97a60e1a690b882a3 emissiontrue_res_32.out -1db0f07906fdb96f1fa96852d4ffba4e emissiontrue_res_33.out -c9e09c7ad1cc2372bfd5a519ab7fdc81 emissiontrue_res_34.out -4556562b0aa165e689fe657d24ac08e3 emissiontrue_res_35.out -42a20c52ece684ea79011e00d1dd834a emissiontrue_res_36.out -f4dd5502f4a3be7de13b0b4ca9660152 emissiontrue_res_37.out -fd97e2d9f12867d21323568a1c15be55 emissiontrue_res_38.out -fb2920b08da65f125e562104e43149f9 emissiontrue_res_39.out -9f8c314c42e593d4f4fb57bc73e8f85b emissiontrue_res_40.out -adecfebc9d7f5f60d312f1eb67780131 emissiontrue_res_41.out -aee0e58ad9806ed295a296198c5ec930 emissiontrue_res_42.out -e781ffef53eb20c9d1952deba56f13a0 emissiontrue_res_43.out -b6d92ea77f767eac86d798c9d6ae85e2 emissiontrue_res_44.out -8b7dab69cade6e8d72507a1d2fc99f21 emissiontrue_res_45.out -dadfd481448680eb357843530741dc7f emissiontrue_res_46.out -e780c0a563a99bd7c58ba07712d6c47c emissiontrue_res_47.out -a8ee5cbcbba577e3bb3c0d152350f903 emissiontrue_res_48.out -09dae8f669a2364bd4f672e9e0cd57eb emissiontrue_res_49.out -6999f59689b05cda9b05c125e1709ef7 emissiontrue_res_50.out -028d4e8140375bd7812e9c9ca9878344 emissiontrue_res_51.out -1bbdbdf49023da1e2b6945e711bf314e emissiontrue_res_52.out -b58e80f3cf37e585662205c343325f0b emissiontrue_res_53.out -6e1a48a17d9b393fc9ed82e4400317c5 emissiontrue_res_54.out -84bb6a1dcc047178b8b634ad66c37302 emissiontrue_res_55.out -7a69055b480e7b86529cc75ee9013dff emissiontrue_res_56.out -d1f888cdf16946981e46893b53aa9359 emissiontrue_res_57.out -999eb7330289b328abe291d329e37f79 emissiontrue_res_58.out -6e35905e1c3ee6a2af778e4180d13196 emissiontrue_res_59.out -ceceac460dacdc099d3cb73ab6465e05 emissiontrue_res_60.out -d8973031a918fd281076cb87c5358b3c emissiontrue_res_61.out -529da7cbfc8ea9876db535ee9a6c886b emissiontrue_res_62.out -047b3c6c863ee5e16244831b36c3c858 emissiontrue_res_63.out -38e5f31ca6cca246cad54557cc245683 emissiontrue_res_64.out -3879c20f6a0fb41b5d4f0030a53a7a39 emissiontrue_res_65.out -56cf72759bfccd4c77cbf27a46d4bba6 emissiontrue_res_66.out -d3c5c42de41a2aa98fc42af6b2010d19 emissiontrue_res_67.out -f8af387e1e8d16d39c60107904e3f251 emissiontrue_res_68.out -c396ac55cc37eae1a647eb147dc871e2 emissiontrue_res_69.out -48e20b2e1e2fc8287f0deb79a76ca9d2 emissiontrue_res_70.out -80d06eb01ad5490d5cd1c32220d3fa3b emissiontrue_res_71.out -6fcde5a09c9fe1d540808df2168a7520 emissiontrue_res_72.out -9253e9bd1d043627d4bef9c966beb603 emissiontrue_res_73.out -ffb0c062d59174f0b1b45410346edbd0 emissiontrue_res_74.out -781189e0ba2017253d5203d43cf50d88 emissiontrue_res_75.out -8ce9779a3bee78aa9c1deaf232d4082b emissiontrue_res_76.out -3710f5e0ec8c9b4ecb39cbefa5888c3b emissiontrue_res_77.out -89e30c34c068534995edb459d99afd7c emissiontrue_res_78.out -30f926c456a010ad0eed5828f46ebb39 emissiontrue_res_79.out -adaedef3b8d69d1f373f67b71cbf8af7 emissiontrue_res_80.out -ad2d9a443eab39821deeb5cb89fccbc4 emissiontrue_res_81.out -43c19eba8cc751655ea98385f9e71cd3 emissiontrue_res_82.out -188c89cc9810969958054aa1e1304377 emissiontrue_res_83.out -57f0e055c0d636cec3177cc992cd4eb0 emissiontrue_res_84.out -b97ad2670e95328ccb868c5ed46415e4 emissiontrue_res_85.out -ccb2764064ca8da3d2ee37887755aa20 emissiontrue_res_86.out -e80334851b35366fb13ee78dcda1b0ea emissiontrue_res_87.out -0e8f1e6e5087944dbbbc914ffa1a80b2 emissiontrue_res_88.out -788744dfedfbe97475d6327c45af6664 emissiontrue_res_89.out -854d1a563aa8f2faae36faa20d2b906a emissiontrue_res_90.out -6fa9c18760ef219749feb4cc20d7f9a1 emissiontrue_res_91.out -ff6238240a3801706c099dd1c574afa2 emissiontrue_res_92.out -8c95640d069730c24975b357be681692 emissiontrue_res_93.out -6350ac3c0c88af2d78ed5601632e68e8 emissiontrue_res_94.out -a7517af99ac98786eb6d140f97f77b04 emissiontrue_res_95.out -1c31fedd06cf45bfc32f51e2b2a5729b emissiontrue_res_96.out -cabc01b5d90b539973d938a0eaeb7af3 emissiontrue_res_97.out -18b39599557c0848dbe760b8e5fd5480 emissiontrue_res_98.out -9a8ecf5e5add1c94390be3b2b682def5 emissiontrue_res_99.out +f9e8c462e7ef8bd0c0fade07bb715f3b absorption.out +274f502b0c431c87692eedaf5919ce4d absorption_res_00.out +1b23e9efcf255979d6e8dc1c9830e520 absorption_res_01.out +8f2d66054dd29553336e6b8a5491bbb6 absorption_res_02.out +e386c3bcbe983401a17bd95dc3d121d0 absorption_res_03.out +6a329922993d5f74dd860dbed3212635 absorption_res_04.out +4c73b13c528ea23c57bce1a988690cfb absorption_res_05.out +89efb4289fe1d9d399128d41a6642a05 absorption_res_06.out +18139fddb12924162c061157f9747207 absorption_res_07.out +c361a8425799dc3c16444f04fc197dcd absorption_res_08.out +24b714a39d7728e2e39c091a35e6241c absorption_res_09.out +acbca6ff80b948fa1c04ccab4037000f absorption_res_10.out +339b7c36dda10cf55418f2cacc59107f absorption_res_11.out +fabaefc81410ade72b31a9e6111af0e8 absorption_res_12.out +5ba48c6fced17fa5c84ba19ceb2c987e absorption_res_13.out +0899f426f6940ead33ef8c672f1fde00 absorption_res_14.out +f0ec41e87d648be6c2734d81e9b2a131 absorption_res_15.out +6e2cbfdb33a712025e11fec3ef58430a absorption_res_16.out +78cdb5e1399efa97c2cf87b5f30cb3d6 absorption_res_17.out +2bb07657b2a766dee543d3da2d154e41 absorption_res_18.out +39f1391db15fcd364f74689c05fae1d1 absorption_res_19.out +25f676d65df111740bee8deca71996b6 absorption_res_20.out +563a11129d764a915c89a9550b79408a absorption_res_21.out +d8d9d0df34288fef286dc46689a9ee03 absorption_res_22.out +516083a4ac583d51efca3e9b4bd6109a absorption_res_23.out +955163e7185855887b69ccacb553dddb absorption_res_24.out +8246b28aacb57b55aec1413793412344 absorption_res_25.out +2b481d6c113c632ddf7bbc15e4aecf8a absorption_res_26.out +99f5de348249be74f8cd4922927666a4 absorption_res_27.out +dd75e3b757da769ce06ea9ab3f854f90 absorption_res_28.out +af8da6bb3e95edd423441c817e1dc37d absorption_res_29.out +27c62988f57b5d905939782bfb3b0efe absorption_res_30.out +9371d71de8c01d9699811f29fb8a85c4 absorption_res_31.out +6e36bcef06a0605acfc3707604f36014 absorption_res_32.out +65c7ffbc0002be87c56bab4d797dfe19 absorption_res_33.out +67409a5ecea0880828b8a7234c8f3bf7 absorption_res_34.out +f10c90f165eec7bcba64ad9121989011 absorption_res_35.out +fbcd7f2ab65c0c535a657e72cc7edb3e absorption_res_36.out +635a99eaffd5d9f94b793e6f7ec73048 absorption_res_37.out +060b661d3a2e3ef001b2f9aeeffe10cb absorption_res_38.out +0863ed003882654f41655ad1665c20d5 absorption_res_39.out +1358786cd5a80c38f6b92b99e6b557f7 absorption_res_40.out +4caa8b9dbae91dc0c1882234b4ec0274 absorption_res_41.out +db49da7c14b3d32a62fabed98bb9c9c2 absorption_res_42.out +7d97f8989a5db571735d1a7b3f5b37bd absorption_res_43.out +ef4d0a36fec4da1705a10f98fa7a69c4 absorption_res_44.out +18cad46ac655c6cfafb9824fd2e5dfb2 absorption_res_45.out +2ffee6d7cb0c23e5ffb65db38d8a79af absorption_res_46.out +e8fec2be24fd7c1fe2c60941e74c990b absorption_res_47.out +89970ea8b3d5f85c069a7850f603e2ed absorption_res_48.out +a153dcd23cbd0e575579f5530bf0feb5 absorption_res_49.out +19dec21ea4ca6d122d4e6402e413e239 absorption_res_50.out +e2690942c3b57a50ced741027c94fb0a absorption_res_51.out +dc28aeb8509b183139472d242eb705f7 absorption_res_52.out +d4105a99be3e63e6351a077dd4e611f0 absorption_res_53.out +077e591ad2a1acb81412826e93a7b46b absorption_res_54.out +24035fc228f793f64cfcd1d96f0c6e23 absorption_res_55.out +471a08a1da666ae13f1f687ae868fa25 absorption_res_56.out +f6c6ef61dc942b2ad9735f67b528b4ac absorption_res_57.out +b857a70faa8d869c165d08763b85225c absorption_res_58.out +ae4d59c2630ca6b8ab8dd696dfc25fd4 absorption_res_59.out +bfd97c4e5495dffa84b2747896497e1f absorption_res_60.out +8db139458bb9280d9191540feb7f22aa absorption_res_61.out +23678df0058e7b136d548447c9247a5a absorption_res_62.out +1746f4b528f81b64f8c5ce789430d76a absorption_res_63.out +17b01b01353c695793e7956663dbaaf9 absorption_res_64.out +8700cba4ae77d530a3622c0ce5bbc8a8 absorption_res_65.out +67a9bdf952985811e14f60c8aadde0e5 absorption_res_66.out +528f8be97188ed25e32e3b3258ac5856 absorption_res_67.out +3eb4717018783c3aed3f298fb31583f7 absorption_res_68.out +6ad940791b99711306d5b3d5b947ee19 absorption_res_69.out +9d583ed1e8372c45f90a671df0e4dcb0 absorption_res_70.out +30fba9edf8484101009db72700fc3718 absorption_res_71.out +9c3332a1a4bc7d4ebbba1b6212e14d6c absorption_res_72.out +2e5b57f4f1adf29f21a0af09d7ee20d0 absorption_res_73.out +bd587ea7ccabea5c061acb24a62db797 absorption_res_74.out +14003f97741c6e428dba2ab2ee61aa9b absorption_res_75.out +f380a1f5f10e23a9eae4ddc860fec4b0 absorption_res_76.out +b9af5fe86e7e4601cb9ab0b5537e7303 absorption_res_77.out +e35b607f63d833a39e2936ca0528be1f absorption_res_78.out +b3d003d76facde4842f80b373cfe67aa absorption_res_79.out +54755075322b22a6f9014cc52c1145d5 absorption_res_80.out +ef297f2cca47bb00bf977a8053e15081 absorption_res_81.out +1b8fd6e037b3f508c08e814a4bb3f1ef absorption_res_82.out +357b5a10e02e415648c4f6bed251ba5d absorption_res_83.out +fc1cae8802aa49f3ee6111f8d8cfe287 absorption_res_84.out +5ca5d9d11fe1ef510f67c1e0eb073568 absorption_res_85.out +dedf1b98f85b928daad12bef4c373681 absorption_res_86.out +3aaa4d6ca5732a9536035e3559170e6c absorption_res_87.out +06fefa329cde29f5d86e77c0fa8d4c5c absorption_res_88.out +39d74ef9cc6c92c23200e6d400c28762 absorption_res_89.out +f7135992bb8a81787479ba759007d411 absorption_res_90.out +0bd9fdf583d626000f5d25aff31d071e absorption_res_91.out +a9c2a4462385ab0555d801ea431f5562 absorption_res_92.out +4bd91060043c8f96553bfd5a0ba6ec1a absorption_res_93.out +f52b5597e3d1f0f8e2a9b03e8d71e349 absorption_res_94.out +f8efb652b3b62df30d6490bbfdaf42fe absorption_res_95.out +4af3a8bbe04cd83ffca6201705ded960 absorption_res_96.out +6f63b6cbff3c903c64e7e6ecdea50c4c absorption_res_97.out +e62dba7cbb6826d15f6cb2fdde45c69b absorption_res_98.out +eb05e3560a97e99403464e9c79845341 absorption_res_99.out +897316929176464ebc9ad085f31e7284 bflist.out +f421b46da29529e44e57cb7caeac62db deposition.out +94e7893f4d16eaedf276ca3bb09408e2 emission.out +802067a4cd06e68099ae5d93d3e29773 emission_res_00.out +e885f6a4f62b14a6b45dd9423c20a98a emission_res_01.out +96dec81fc301a72fb5c7e08dc3637429 emission_res_02.out +3d95332d326b8ac4af0adf5af879543a emission_res_03.out +8a1f1252089b7f18d86b5738f3e37ab8 emission_res_04.out +3f7585082f3b3ebe844ceaa89863aedb emission_res_05.out +1d1555ab1c568793fcd362e9c5050d31 emission_res_06.out +57f31f3962ce4a18463d74841ff1b210 emission_res_07.out +0773ad2f6294f67ee91af110e7c64bd0 emission_res_08.out +f72ed64f15567c2317a4bbe238f31501 emission_res_09.out +064c28ace251811bdb07a9b7df383509 emission_res_10.out +06da84c944e866d0a85f292f799da601 emission_res_11.out +b98e07714fd362a755f3f12f35bb5084 emission_res_12.out +bc65982be583d84728ee39fdba1fda8b emission_res_13.out +95c634859bbc07187da5b7ae438fedd6 emission_res_14.out +1ee4dc26615d50737cc1c13c0811fcce emission_res_15.out +a21463ef64bfcccaf4f598cfbb6afae1 emission_res_16.out +0a6a79c5a0115fd3b331e45d8e242668 emission_res_17.out +3bdba3c4db9aeb5ada76d6198a911bdc emission_res_18.out +82ed3b9a44cbeab1e15c6c24967de7ff emission_res_19.out +e12b0df30e35686164792e078070f3ab emission_res_20.out +2d642d0d278d4b691187b7265b744610 emission_res_21.out +6c6389ec62f9aa14ef953772290b2d00 emission_res_22.out +84975687d246f6f7c78d6f2d04fd88ad emission_res_23.out +c6aa79e2280c41e13ff8461be02c0bb0 emission_res_24.out +2f92a55f470fb77669cf43f1e77dab89 emission_res_25.out +0d06fd2b501b740e876e72da835420e8 emission_res_26.out +ebed62e732f039a9b693f0271febc89e emission_res_27.out +f62e2aa4c4258a0379e95de144a8f694 emission_res_28.out +3e03b1bc7eedc9ac11fab9b362ac7ba4 emission_res_29.out +f95fce0026987aa1e2d45e9f42601799 emission_res_30.out +c44d05f443a167a9dbfbc12022fcf9f0 emission_res_31.out +4a106ace1b7bcc45ad4b0c985b704747 emission_res_32.out +6fddeaa911102604cb08a60922f518dc emission_res_33.out +de38fed5e2488f1cf5c8c67231135eab emission_res_34.out +b6450142bfeeeba4d8d9fb4546b8e00d emission_res_35.out +13f2b982cdf2c17e58b1128522637a27 emission_res_36.out +8a390b9d14dd186ea99117252ba69866 emission_res_37.out +bc9cab540155a5051fa9c72a9bde4904 emission_res_38.out +2cd6b2c4bd210424c75a0845a3bcb865 emission_res_39.out +6a462299b5a9556071a015616e735b22 emission_res_40.out +04bed39cfdda981d226aaf52a3f14446 emission_res_41.out +d8119b704c3c756907158cae1599b50b emission_res_42.out +180c543799c8222f5eb65eab46703390 emission_res_43.out +319e422dc7d67d5302c0af46031fa2ff emission_res_44.out +de9ff223f750723829be02852fcebe2c emission_res_45.out +ea6adaa69ef43bf3f77a5ddb02b9923b emission_res_46.out +e7251578e966a3d7411f45dd9ec7bcf0 emission_res_47.out +f7bfe17e81549093e7c1a55c6c41a8f6 emission_res_48.out +1d630e5b44474b813f4658b810dd1c51 emission_res_49.out +c96e48f5d4c22ed6795bf3c97634d478 emission_res_50.out +1a99b5727cba51bbb5579679c3c35e7a emission_res_51.out +08fb4109b9d80434bff19f74156dab93 emission_res_52.out +ad14b7efa870245ca7930cbbfd485f59 emission_res_53.out +16508a2eddfe4378122804eb08417ced emission_res_54.out +4e9ef3ddc1bad58af3ed46d353f10086 emission_res_55.out +6868217b5d9dd93da1193113416a8366 emission_res_56.out +2bee3ffecd99642130f792e6ad682253 emission_res_57.out +0446b4f5f267c6961811fb69f59fa250 emission_res_58.out +b1e4645cd0b8f29a6257a2adc07b8274 emission_res_59.out +435336fbabef2041315ca3005194cc4f emission_res_60.out +fb4cbb5640c27518f4f17a848d6a69c5 emission_res_61.out +f981fffabb8bc6d0f748a7316e3b0952 emission_res_62.out +2194689ac46a015e6909ff65892b011c emission_res_63.out +cc07bf8459f2e7d6875e2d179c7a0106 emission_res_64.out +1d5ae514e4fc6282201e78fe85484669 emission_res_65.out +d675c2588fc42731145a1d3c0b5c687b emission_res_66.out +2cf76193138ce584e31cadc9f5b3bd84 emission_res_67.out +8affb443ca4d8b0a77e7c88733debb94 emission_res_68.out +bc854df639f68c8b149124f1ea61c6bb emission_res_69.out +21517ada149c5cf22e13a74d2d0863a8 emission_res_70.out +2da4e995d536c0e54696515aff752e46 emission_res_71.out +cc0c3b1680328bc927c0f54482126c5b emission_res_72.out +8613f32cf8d3e29f5b8edd894c659f73 emission_res_73.out +c1994baf84849f372662843412c5de68 emission_res_74.out +52e5fa9e3717b0fb3dde8ba471b49bbb emission_res_75.out +1ea14b097540b319a03e199df3611e11 emission_res_76.out +a98f6a81be8953903c1086eb0a5be8c6 emission_res_77.out +9cebab17a7dd36b1c6d3ad384ad63225 emission_res_78.out +07890efda1402d7ca57e036986bb94e0 emission_res_79.out +402cabe1089be744674d03177da02bb5 emission_res_80.out +53e829019a110181ce49443a2a456c60 emission_res_81.out +3259348d2c75947f90d850a5f7edeebb emission_res_82.out +d2b3a5952c3070ba7022190ee1e01b3a emission_res_83.out +ace32f45b7f9acfe5bda96d10bd6a39c emission_res_84.out +fc3f2ffb314a2c36853f242d8afd2f18 emission_res_85.out +9c89eeab349e729d247aa103dc91e48a emission_res_86.out +7fc3cb5d79a61059025fb5ab94d5be0e emission_res_87.out +f3211188c037e359c947d69eb68fc855 emission_res_88.out +308f7883bc6b64f625dd0d177d5168f0 emission_res_89.out +fbfd42a65e22751bcbf42bfa2aca3b40 emission_res_90.out +1a1a8172c8907f9a615c2d6cbdbdcc25 emission_res_91.out +f0853330612ec6644947aa0cab728b1c emission_res_92.out +45f17ebf98700b22aaaf2534948f3739 emission_res_93.out +8e20cb52ecb1ada6dce9db0a1bdefca3 emission_res_94.out +5c99bbb14897b0d0228aded66a96c022 emission_res_95.out +d03f934f750cf063cfdcde6b7e1f274c emission_res_96.out +81168b09e51669a848901263b9b0d69f emission_res_97.out +f603c942ee34d4b4b12a910141e8f9cc emission_res_98.out +0e86758a606793c97614e61fa00e18bd emission_res_99.out +ddc4ce928abab65d46d480f89c2e574b emissiontrue.out +e86a156efcfe3b34f7436f4477868ccd emissiontrue_res_00.out +4f12e1ee9d7e764268d832470b6c3ae8 emissiontrue_res_01.out +03e5b5b9bb711cd002734e843e462ee9 emissiontrue_res_02.out +7ac89cf9180ffb2fca31007892a2138e emissiontrue_res_03.out +6d39ca494abf5e58f3c042d1eab6e8ac emissiontrue_res_04.out +57d913d72de624546786fd1adc6936d5 emissiontrue_res_05.out +b3a7774e7f90432cfd5041465f58c41a emissiontrue_res_06.out +46a2dd8ed093b86abbb33ab716b8fda3 emissiontrue_res_07.out +e8bf23ffd98fa0e4efc0fa44ec3ebc86 emissiontrue_res_08.out +2d495595ae8d7ce2798c69e61d70215f emissiontrue_res_09.out +fc9badf3dbf024782155aa3b15e88034 emissiontrue_res_10.out +647f4d3acea36b412dd3db484d0b7db1 emissiontrue_res_11.out +9d57d4aace7f6239b4998511bc31b2c4 emissiontrue_res_12.out +917648be6892d25b44b4f1024bd19901 emissiontrue_res_13.out +2d92697892551d8ff8831c2ea394164c emissiontrue_res_14.out +29a9d87a2ea0032ed40eff83e84bd91f emissiontrue_res_15.out +194129d693d005005aa5c022a2091693 emissiontrue_res_16.out +7adcd28f45232f7550a7e778e66ba17f emissiontrue_res_17.out +625a21043483d85de186ebd65173dfca emissiontrue_res_18.out +401ca73df0574e3460786f1bbdbb0886 emissiontrue_res_19.out +58e83e9a97c1cc581adf5d2b19c40ec3 emissiontrue_res_20.out +8501ad496eec2760c0ef67135767de2b emissiontrue_res_21.out +6083024a98dcd371bff283c80a6bfea5 emissiontrue_res_22.out +a3813332e1739c2613bc8469861550b2 emissiontrue_res_23.out +c7dd72feff75b0289389681471b35cfd emissiontrue_res_24.out +8372c7921bdf58199ac416677ac71573 emissiontrue_res_25.out +398f16256b356464e5511726e64114ef emissiontrue_res_26.out +7f7c72d10636e797c3dc6a019aaac7fc emissiontrue_res_27.out +bb8a2cc7f83d38a4aa5d04611df7c6bf emissiontrue_res_28.out +7a188814bf3c63160a0afcfcf046d250 emissiontrue_res_29.out +b2f7d4744092b5779876f8823e12e963 emissiontrue_res_30.out +e76d94d9cbb15be8af6e5007cfebf489 emissiontrue_res_31.out +98c07bcc9786a6f03bc15242cfc079f8 emissiontrue_res_32.out +351b911335c672f627b2e090c968bf16 emissiontrue_res_33.out +96bc46d50765b98ce3ee870ef9df4b52 emissiontrue_res_34.out +4460994748a4394f0f8ac79d59d177bd emissiontrue_res_35.out +cf31f73fcb64cdda5167507e0346e4f3 emissiontrue_res_36.out +4a502cd7f1881388589c122258265536 emissiontrue_res_37.out +e6336332dc88919f38ff742f37fb0a21 emissiontrue_res_38.out +804069802c8fde481bc95ce84fe82b4c emissiontrue_res_39.out +46bb77b2b0c2ae15dd0e91bdd9003fbd emissiontrue_res_40.out +a50a6600d9bdc78939539033a7d09106 emissiontrue_res_41.out +052f0eb5db6423d69887704483ba032e emissiontrue_res_42.out +4ba6bec99680742ade65c6690c4aaeaf emissiontrue_res_43.out +22b0143252ea8bcb364dcb93362ad735 emissiontrue_res_44.out +0c9847e9d43702a168f3dae685345e4d emissiontrue_res_45.out +be7ad75e02dd55a1c3ef0b5c0ef73aa7 emissiontrue_res_46.out +c9cad8ef312b13a8d4b44dba6f6c80f5 emissiontrue_res_47.out +a5496f4ed80af479e4bfeda1cf0edada emissiontrue_res_48.out +5ac17a32ed4d81f7ec3a21cd441761d6 emissiontrue_res_49.out +1e6243408c1397667bc52d08aab3fdc5 emissiontrue_res_50.out +573ba7e8afb89e8396b846cfdcfbe6f0 emissiontrue_res_51.out +e0dcc6d7cfa1e8917cbf5231b4f2470e emissiontrue_res_52.out +c71ef5e51679b446458b8c15d614ab80 emissiontrue_res_53.out +1c93d9ab3e6746f37bb284da3df685a0 emissiontrue_res_54.out +d5062a8c2c2ab51956ca2cb7e0cd847b emissiontrue_res_55.out +e550cb7d9b3c5144d82cc594b6ba8ae4 emissiontrue_res_56.out +54d230e990bfea095231c3010ee914fe emissiontrue_res_57.out +4694877ebf8197a4480552b953db45b9 emissiontrue_res_58.out +fa39c5bfe6c13eb5324fba201e9ab7e1 emissiontrue_res_59.out +d8bf15fbc7c518d763b2efa9d3d28ef2 emissiontrue_res_60.out +7a160fb9f07317b53c13ea6d63cb978e emissiontrue_res_61.out +048a5e3161bcd03dd782d8027e6925f4 emissiontrue_res_62.out +ff67b5dc757380bffc4f87d90a6898c6 emissiontrue_res_63.out +2881f44b20a65d31dff4a5414f6f2362 emissiontrue_res_64.out +3b31536580cb9cffd316a4e3caba08dd emissiontrue_res_65.out +273428d42380f08e9429d0109d06ae40 emissiontrue_res_66.out +e1792d1e140582983099dcd9f786492f emissiontrue_res_67.out +9fbf864fa61116e9f28b8b63411882f7 emissiontrue_res_68.out +671120c57fbee246a946adc22b8c2ba3 emissiontrue_res_69.out +f4270005c328a93fbe4dfa36d45a4b7d emissiontrue_res_70.out +61a345a7a515d7d18e1cc80dce1fd43c emissiontrue_res_71.out +a7be8c91f0cc5bea9a611debf14cbacf emissiontrue_res_72.out +be432fa37bacf3dcac8c062b5a32bf6d emissiontrue_res_73.out +c998e8db6da25720422497ec9004728e emissiontrue_res_74.out +dd0379f8cee49aed12a0cb16c375acdb emissiontrue_res_75.out +a730184bfb9f4f49fc0a85f6ff6c7b80 emissiontrue_res_76.out +041bf247a36a676297c6e572dd6076e8 emissiontrue_res_77.out +1f622bac25f4ede015e41c2cfab26f91 emissiontrue_res_78.out +03880bf9a5ccbb153e9b9cb7252507de emissiontrue_res_79.out +d6b91a8a879c41db91d6d8a1fd2e1cfa emissiontrue_res_80.out +afbb435db75bcac21f7097bb5b44c265 emissiontrue_res_81.out +8a3d1024a8546ed2d0bcad762baac39a emissiontrue_res_82.out +66cebcafcfa171672b95c695cd9f821b emissiontrue_res_83.out +ee722f27d5f6b82c4a8bc0772e6681f8 emissiontrue_res_84.out +e945a94c3c76e40fcc9a7f8b9bfa31e4 emissiontrue_res_85.out +b8929a4b94a29d50b986e6019caee4ea emissiontrue_res_86.out +bc4c78dfeb2b70b4e03e22ae4aad0306 emissiontrue_res_87.out +6b5252ea88bc79daf1df62c5a5f61fe7 emissiontrue_res_88.out +d340b8404b5f993c487de0f9e5be0464 emissiontrue_res_89.out +195d32c0039f58ac7203c549453f8ec1 emissiontrue_res_90.out +5c8d8902822e7925e83d64bf4d67bc90 emissiontrue_res_91.out +b18f8730f9de6d8f56f34b948489ec8d emissiontrue_res_92.out +aa9f9d8317db0f97019be1bf05c36a32 emissiontrue_res_93.out +df1484f3b24e5173a31a2e496c04166e emissiontrue_res_94.out +0cbdc62ffce5688bd58805c873be9f89 emissiontrue_res_95.out +cfbedb1f6be28a5205686538e0a0e102 emissiontrue_res_96.out +ee7b117bcc203fa9da9c1f530859725e emissiontrue_res_97.out +17ae8f115a621c762b01fbb522b590cc emissiontrue_res_98.out +f488ecba4cbe41a57e365c4b04b7c861 emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -7c5c000e85e3a6f217660a65f951bc16 light_curve.out -ab45c4b292e8522606641ba3069bc5dd light_curve_res.out +b1e9d6e1b0460ddb425ebe296ef0eaee light_curve.out +c4376a7fa8ea4fc8a0345dc0c3231889 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -9c480fe54f7d267853b77aa7ee27f9c4 packets00_0000.out -ec9e7163b12f18865279b436d0a7a2c7 packets00_0001.out -33b37b7eb63a81de43a1a29e5de8ec68 packets00_0002.out -345baa17d316a1ab467cf7fd8576e64b packets00_0003.out -7c59f3600ef4024c5f951baacc505388 spec.out -bc4f2eb925920a5598088a80544fc4a1 spec_res.out +d88772c9f2f982809105433aa1ef43ed packets00_0000.out +8b2b12f83be94c74e6b452ed629a01e6 packets00_0001.out +8eda58f172cdcb88a86e018a286ee9f2 packets00_0002.out +3492c21b7da16033c832dbbb53e23c04 packets00_0003.out +2013eb78c14b8ab574b3e7d045ee9f7f spec.out +f7aae73b1abecba91128abc65b17f4be spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -71a749b62221c39bf8fff3cf21943bc3 job1/estimators_0000.out -4c261dc1c0fd504c72ccf7d5c181fbb4 job1/estimators_0001.out -a170c449679c91ccc7671d115ed57424 job1/estimators_0002.out -4ef84502fbe361cffe36968545de8ced job1/estimators_0003.out +00b8474e1bec3df40f2f643d6b34fc4e job1/estimators_0000.out +ad01423a9531a1c364a1901682609112 job1/estimators_0001.out +b630267042391a009fad2f00b0f0ce2f job1/estimators_0002.out +eb8561e04928876e09d70ba46585054a job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index ee69024b2..2475bebe2 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -406cd1f623c734534f62a32d5173496a deposition.out -9c1df62caa6bc28e29154c334c6ab215 gamma_light_curve.out +e9aae3a7ab36a1a44e40ea57355e1ba0 deposition.out +afe66f023087001ce7a9fff264f87b2b gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -fdc9204a62e90f07dd9d15e726844144 light_curve.out +c167f0a32585932e22e6265b0c9ebbbb light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -4af65166525fbe901e45853d19fefe2f packets00_0000.out -8e19203368d982b1813a832ac395ecfb packets00_0001.out -cc96fd2e94f90732d24f4d590b4b8958 packets00_0002.out -e8fc6e9f9954572b37f2d5eb7ee7f514 packets00_0003.out -f9d67bf3c4e8faa8ad73f50199c60a09 spec.out +c5d9f0d8d6ea6137782e7f73cceb2a99 packets00_0000.out +2f157c26d84a5002e5f88f1ffe881654 packets00_0001.out +d395efd35c062824dd6ab0104e0867f8 packets00_0002.out +e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out +88a0e6320da73f235aec8739d4a123a3 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -ab0470f3b05d07c046b3e2435efdc980 job0/estimators_0000.out -2be03f48bd4e924948619e820291869e job0/estimators_0001.out -acf35bf488b525b61436ddf6f86116d2 job0/estimators_0002.out -39344b6d47744a6f8266cb744b1bfebe job0/estimators_0003.out +76e3af84b3a66c9a282e41a6627dc4e6 job0/estimators_0000.out +0feb35456d8d8e9bbfc6548ffa0ae332 job0/estimators_0001.out +edd1c258e08cac13e09fcae4bac10992 job0/estimators_0002.out +f7550c181706595984aaf71e651a381f job0/estimators_0003.out diff --git a/update_packets.cc b/update_packets.cc index d75839306..196eb706d 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -42,7 +42,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double v_ej = std::sqrt(E_kin * 2 / grid::mtot_input); const double prefactor = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 7.74 : 7.4; - const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) / + const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * std::pow((0.2 * 29979200000) / v_ej, 3. / 2.); const double f_p = std::log(1 + (2. * ts * ts / tau_ineff / tau_ineff)) / (2. * ts * ts / tau_ineff / tau_ineff); assert_always(f_p >= 0.); From 96ec7e059816b37d3b4aa691f2fbc075911dbfd4 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 2 Sep 2024 12:26:12 +0100 Subject: [PATCH 036/117] Reduce heap fragmentation during startup and store allcont keep condition in cell cache (#116) --- .github/workflows/ci-checks.yml | 10 +- .pre-commit-config.yaml | 2 +- Makefile | 3 +- artisoptions_doc.md | 6 +- atomic.h | 40 +- data/collion-auger-reference.txt | 2 +- data/collion-reference.txt | 2 +- decay.cc | 18 +- decay.h | 2 +- exspec.cc | 2 +- gammapkt.cc | 42 +- globals.h | 27 +- grid.cc | 138 ++-- grid.h | 6 +- input.cc | 1216 ++++++++++++++---------------- input.h | 2 +- kpkt.cc | 4 +- ltepop.cc | 17 +- macroatom.cc | 44 +- md5.cc | 2 +- nltepop.cc | 196 ++--- nonthermal.cc | 76 +- packet.cc | 8 +- packet.h | 2 +- radfield.cc | 40 +- ratecoeff.cc | 121 +-- rpkt.cc | 95 +-- rpkt.h | 8 + sn3d.cc | 22 +- sn3d.h | 20 +- spectrum_lightcurve.cc | 14 +- thermalbalance.cc | 9 +- update_grid.cc | 15 +- update_packets.cc | 12 +- vectors.h | 121 ++- vpkt.cc | 48 +- vpkt.h | 2 +- 37 files changed, 1119 insertions(+), 1275 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 66146a119..fa1544e23 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -21,16 +21,12 @@ jobs: brew update brew install gsl openmpi cppcheck || true cp artisoptions_nltenebular.h artisoptions.h + make version.h - - name: run cppcheck and check for errors - run: | - cppcheck --version - cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=warning,performance,portability --suppress=memleak --suppress=passedByValue --check-level=exhaustive . - - - name: show cppcheck style suggestions + - name: run cppcheck run: | cppcheck --version - cppcheck --force --language=c++ --std=c++20 --enable=style,performance --suppress=knownConditionTrueFalse --check-level=exhaustive . + cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: runs-on: ubuntu-24.04 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce7e6e611..a082f1615 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--fix=lf] - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-clang-format - rev: 'v18.1.6' + rev: 'v18.1.8' hooks: - id: clang-format files: '\.(c|cc|cpp|h|hpp|cxx|hh|inc)$' diff --git a/Makefile b/Makefile index e185ea206..051e11682 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ ifeq ($(shell uname -s),Darwin) # LDFLAGS += -lprofiler else - # sometimes the login nodes have slighty different CPUs + # sometimes the login nodes have slightly different CPUs # to the job nodes. Try to find the lowest common denominator here # to enable vector extensions # CXXFLAGS += -march=cascadelake @@ -302,7 +302,6 @@ sn3dwhole: $(BUILD_DIR)/sn3dwhole ln -sf $(BUILD_DIR)/sn3dwhole sn3d $(BUILD_DIR)/exspec: $(exspec_objects) - ln -sf $(BUILD_DIR)/exspec exspec $(CXX) $(CXXFLAGS) $(exspec_objects) $(LDFLAGS) -o $(BUILD_DIR)/exspec -include $(exspec_dep) diff --git a/artisoptions_doc.md b/artisoptions_doc.md index 33fa80913..e511f0c20 100644 --- a/artisoptions_doc.md +++ b/artisoptions_doc.md @@ -20,7 +20,7 @@ constexpr int NLTEITER; // (i.e. level indices < X should return true for some X) constexpr bool LEVEL_IS_NLTE(int element_z, int ionstage, int level) { return false; } -// Use TJ radiation density temperature for Boltzmann excitation formua instead of electron temperature Te +// Use TJ radiation density temperature for Boltzmann excitation formula instead of electron temperature Te // This is default on for classic, and off for nebularnlte, where it affects the super-level constexpr bool LTEPOP_EXCITATION_USE_TJ = false; @@ -42,7 +42,7 @@ constexpr bool UNIFORM_PELLET_ENERGIES; constexpr bool DIRECT_COL_HEAT; // INITIAL PACKETS will seed the cells on the first timestep at tmin with K-packets -// repesenting decay energy from t_model to tmin, and, +// representing decay energy from t_model to tmin, and, // if USE_MODEL_INITIAL_ENERGY is true, also the snapshot energy at t_model constexpr bool INITIAL_PACKETS_ON; @@ -193,7 +193,7 @@ constexpr double IONGAMMA_POPFRAC_LEVELS_INCLUDED; constexpr bool USE_RELATIVISTIC_DOPPLER_SHIFT; // when converting mass fraction to a number density, use a mean atomic mass -// calcuated from the nuclear composition (plus stable component), +// calculated from the nuclear composition (plus stable component), // rather than just from the compositiondata.txt values constexpr bool USE_CALCULATED_MEANATOMICWEIGHT; diff --git a/atomic.h b/atomic.h index 8b1334594..a3b3993ed 100644 --- a/atomic.h +++ b/atomic.h @@ -125,6 +125,12 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return globals::elements[element].ions[ion].maxrecombininglevel; } +inline auto get_phixs_table(const int element, const int ion, const int level) -> float * { + const auto phixsstart = globals::elements[element].ions[ion].levels[level].phixsstart; + assert_testmodeonly(phixsstart >= 0); + return globals::allphixs + (phixsstart * globals::NPHIXSPOINTS); +} + // Calculate the photoionisation cross-section at frequency nu out of the atomic data. [[nodiscard]] inline auto photoionization_crosssection_fromtable(const float *const photoion_xs, const double nu_edge, const double nu) -> double { @@ -158,15 +164,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) if (i < 0) { sigma_bf = 0.; - // printout("[warning] photoionization_crosssection was called with nu=%g < nu_edge=%g\n",nu,nu_edge); - // printout("[warning] element %d, ion %d, level %d, epsilon %g, ionpot - // %g\n",element,ion,level,epsilon(element,ion,level),elements[element].ions[ion].ionpot); printout("[warning] - // element %d, ion+1 %d, level %d epsilon %g, ionpot - // %g\n",element,ion+1,0,epsilon(element,ion+1,0),elements[element].ions[ion].ionpot); printout("[warning] - // photoionization_crosssection %g\n",sigma_bf); abort(); } else if (i < globals::NPHIXSPOINTS - 1) { - // sigma_bf = globals::elements[element].ions[ion].levels[level].photoion_xs[i]; - const double sigma_bf_a = photoion_xs[i]; const double sigma_bf_b = photoion_xs[i + 1]; const double factor_b = ireal - i; @@ -179,28 +177,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) sigma_bf = photoion_xs[globals::NPHIXSPOINTS - 1] * pow(nu_max_phixs / nu, 3); } - // if (sigma_bf < 0) - // { - // printout("[warning] photoionization_crosssection returns negative cross-section %g\n",sigma_bf); - // printout("[warning] nu=%g, nu_edge=%g\n",nu,nu_edge); - // printout("[warning] xs@edge=%g, - // xs@maxfreq\n",elements[element].ions[ion].levels[level].photoion_xs[0],elements[element].ions[ion].levels[level].photoion_xs[NPHIXSPOINTS-1]); - // printout("[warning] element %d, ion %d, level %d, epsilon %g, ionpot - // %g\n",element,ion,level,epsilon(element,ion,level),elements[element].ions[ion].ionpot); - // } - return sigma_bf; } -[[nodiscard]] inline auto photoionization_crosssection(const int element, const int ion, const int level, - const double nu_edge, const double nu) -> double { - assert_testmodeonly(element < get_nelements()); - assert_testmodeonly(ion < get_nions(element)); - assert_testmodeonly(level < get_nlevels(element, ion)); - return photoionization_crosssection_fromtable(globals::elements[element].ions[ion].levels[level].photoion_xs, nu_edge, - nu); -} - [[nodiscard]] inline auto get_tau_sobolev(const int modelgridindex, const int lineindex, const double t_current, bool sub_updown) -> double { const int element = globals::linelist[lineindex].elementindex; @@ -222,8 +201,6 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) return std::max(B_lu * n_l * HCLIGHTOVERFOURPI * t_current, 0.); } -inline void set_nelements(const int nelements_in) { globals::elements.resize(nelements_in); } - // Returns the atomic number associated with a given elementindex. inline auto get_atomicnumber(const int element) -> int { assert_testmodeonly(element >= 0); @@ -269,7 +246,10 @@ inline void update_includedionslevels_maxnions() { } // return the number of ions of all elements combined -inline auto get_includedions() -> int { return includedions; } +inline auto get_includedions() -> int { + assert_testmodeonly(includedions > 0); + return includedions; +} // return the number of ions of all elements combined inline auto get_includedlevels() -> int { return includedlevels; } diff --git a/data/collion-auger-reference.txt b/data/collion-auger-reference.txt index 325c89937..85cc3795b 100644 --- a/data/collion-auger-reference.txt +++ b/data/collion-auger-reference.txt @@ -19,7 +19,7 @@ Byte-per-byte description of file: ci.dat (391 records) 48- 53 F6.4 --- prob_double Probability of one Auger electron emitted 55- 60 F6.4 --- prob_triple Probability of one Auger electron emitted ------------------------------------------------------------------------------- - Note two inaccuraces in Arnaud & Rothenflug (1985) fitting formulae. + Note two inaccuracies in Arnaud & Rothenflug (1985) fitting formulae. 1. (x-1) should be replaced by (x+1) in the denominator of the equation for f1(x) at 0.02 &custom_zlist, const std::vector &custom_zlist, const std::vector 0.; })); // convert mean lifetimes to decay constants - decaypath.lambdas.resize(decaypath.nucindex.size()); + decaypath.lambdas.resize(decaypath.nucindex.size(), -1.); std::ranges::transform(decaypath.nucindex, decaypath.lambdas.begin(), [](const auto nucindex) { const double meanlife = get_meanlife(nucindex); // last nuclide might be stable (meanlife <= 0.) @@ -449,14 +449,14 @@ void filter_unused_nuclides(const std::vector &custom_zlist, const std::vec return false; } // keep nucleus if it is in the custom list - for (size_t i = 0; i < custom_zlist.size(); i++) { + for (ptrdiff_t i = 0; i < std::ssize(custom_zlist); i++) { if ((nuc.z == custom_zlist[i]) && (nuc.a == custom_alist[i])) { return false; } } const bool in_any_decaypath = std::ranges::any_of(decaypaths, [&nuc](const auto &decaypath) { - for (size_t i = 0; i < decaypath.z.size(); i++) { + for (ptrdiff_t i = 0; i < std::ssize(decaypath.z); i++) { if (decaypath.z[i] == nuc.z && decaypath.a[i] == nuc.a) { // nuc is in the decay path return true; @@ -512,7 +512,7 @@ constexpr auto calculate_decaychain(const double firstinitabund, const std::vect // numnuclides: number of items in lambdas to use // lambdas: array of 1/(mean lifetime) for nuc[0]..nuc[num_nuclides-1] [seconds^-1] // useexpansionfactor: if true, return a modified 'abundance' at the end of the chain, with a weighting factor - // accounting for photon energy loss from expansion since the decays occured + // accounting for photon energy loss from expansion since the decays occurred // (This is needed to get the initial temperature) assert_always(num_nuclides >= 1); @@ -725,7 +725,7 @@ auto calculate_simtime_endecay_per_ejectamass(const int mgi, const int decaypath auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double // get the decay energy released during the simulation time per unit mass [erg/g] { - const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); const double chainendecay = decaypath_energy_per_mass[(nonemptymgi * get_num_decaypaths()) + decaypathindex]; assert_testmodeonly(chainendecay >= 0.); assert_testmodeonly(std::isfinite(chainendecay)); @@ -902,7 +902,7 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector // any nuclides in the custom list that are not in the standard list need beta and alpha decay data bool use_custom_nuclides = false; - for (size_t i = 0; i < custom_zlist.size(); i++) { + for (ptrdiff_t i = 0; i < std::ssize(custom_zlist); i++) { if (custom_zlist[i] < 0 || custom_alist[i] < 0) { continue; } @@ -1078,11 +1078,11 @@ void setup_decaypath_energy_per_mass() { #endif printout("Calculating decaypath_energy_per_mass for all cells..."); - const size_t num_decaypaths = get_num_decaypaths(); + const ptrdiff_t num_decaypaths = get_num_decaypaths(); for (int nonemptymgi = 0; nonemptymgi < nonempty_npts_model; nonemptymgi++) { if (nonemptymgi % globals::node_nprocs == globals::rank_in_node) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - for (size_t decaypathindex = 0; decaypathindex < num_decaypaths; decaypathindex++) { + for (ptrdiff_t decaypathindex = 0; decaypathindex < num_decaypaths; decaypathindex++) { decaypath_energy_per_mass[(nonemptymgi * num_decaypaths) + decaypathindex] = calculate_simtime_endecay_per_ejectamass(mgi, decaypathindex); } diff --git a/decay.h b/decay.h index 47ff5e24e..0fbb2d8b9 100644 --- a/decay.h +++ b/decay.h @@ -25,7 +25,7 @@ constexpr std::array all_decaytypes = { decaytypes::DECAYTYPE_ALPHA, decaytypes::DECAYTYPE_ELECTRONCAPTURE, decaytypes::DECAYTYPE_BETAPLUS, decaytypes::DECAYTYPE_BETAMINUS, decaytypes::DECAYTYPE_NONE}; -void init_nuclides(const std::vector &zlist, const std::vector &alist); +void init_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist); [[nodiscard]] auto get_nucstring_z(const std::string &strnuc) -> int; [[nodiscard]] auto get_nucstring_a(const std::string &strnuc) -> int; [[nodiscard]] auto get_num_nuclides() -> int; diff --git a/exspec.cc b/exspec.cc index af33e3a5c..a877b3a0d 100644 --- a/exspec.cc +++ b/exspec.cc @@ -206,7 +206,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) assert_always(globals::rank_global == 0); assert_always(globals::nprocs == 1); - printout("Begining exspec.\n"); + printout("Beginning exspec.\n"); // Get input stuff printout("time before input %ld\n", std::time(nullptr)); diff --git a/gammapkt.cc b/gammapkt.cc index 15f74c52e..720815db4 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -64,7 +64,7 @@ void read_gamma_spectrum(const int nucindex, const char filename[50]) int nlines = 0; assert_always(fscanf(filein, "%d", &nlines) == 1); - gamma_spectra[nucindex].resize(nlines); + gamma_spectra[nucindex].resize(nlines, {}); double E_gamma_avg = 0.; for (int n = 0; n < nlines; n++) { @@ -85,7 +85,7 @@ void read_gamma_spectrum(const int nucindex, const char filename[50]) void set_trivial_gamma_spectrum(const int nucindex) { // printout("Setting trivial gamma spectrum for z %d a %d engamma %g\n", z, a, decay::nucdecayenergygamma(z, a)); const int nlines = 1; - gamma_spectra[nucindex].resize(nlines); + gamma_spectra[nucindex].resize(nlines, {}); gamma_spectra[nucindex][0].energy = decay::nucdecayenergygamma(nucindex); gamma_spectra[nucindex][0].probability = 1.; } @@ -103,7 +103,7 @@ void read_decaydata() { std::rename("co_lines.txt", "co56_lines.txt"); } - gamma_spectra.resize(decay::get_num_nuclides()); + gamma_spectra.resize(decay::get_num_nuclides(), {}); for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { gamma_spectra[nucindex].clear(); @@ -277,7 +277,7 @@ auto get_chi_compton_rf(const Packet &pkt) -> double { const double chi_cmf = sigma_cmf * grid::get_nnetot(grid::get_cell_modelgridindex(pkt.where)); // convert between frames - const double chi_rf = chi_cmf * doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double chi_rf = chi_cmf * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); assert_testmodeonly(std::isfinite(chi_rf)); @@ -340,7 +340,7 @@ auto thomson_angle() -> double { } // scattering a direction through angle theta. -[[nodiscard]] auto scatter_dir(const std::array dir_in, const double cos_theta) -> std::array { +[[nodiscard]] auto scatter_dir(const std::array &dir_in, const double cos_theta) -> std::array { // begin with setting the direction in coordinates where original direction // is parallel to z-hat. @@ -425,7 +425,7 @@ void compton_scatter(Packet &pkt) { pkt.nu_cmf = pkt.nu_cmf / f; // reduce frequency // The packet has stored the direction in the rest frame. - // Use aberation of angles to get this into the co-moving frame. + // Use aberration of angles to get this into the co-moving frame. auto vel_vec = get_velocity(pkt.pos, pkt.prop_time); @@ -460,7 +460,7 @@ void compton_scatter(Packet &pkt) { // It now has a rest frame direction and a co-moving frequency. // Just need to set the rest frame energy. - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; pkt.e_rf = pkt.e_cmf / dopplerfactor; @@ -566,7 +566,7 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { // Now convert between frames. - const double chi_rf = chi_cmf * doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double chi_rf = chi_cmf * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); return chi_rf; } @@ -622,7 +622,7 @@ auto sigma_pair_prod_rf(const Packet &pkt) -> double { // Now need to convert between frames. - double chi_rf = chi_cmf * doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + double chi_rf = chi_cmf * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); if (chi_rf < 0) { printout("Negative pair production sigma. Setting to zero. Abort? %g\n", chi_rf); @@ -709,7 +709,7 @@ void pair_prod(Packet &pkt) { const auto dir_cmf = get_rand_isotropic_unitvec(); // This direction is in the cmf - we want to convert it to the rest - // frame - use aberation of angles. We want to convert from cmf to + // frame - use aberration of angles. We want to convert from cmf to // rest so need -ve velocity. const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.prop_time); @@ -717,7 +717,7 @@ void pair_prod(Packet &pkt) { pkt.dir = angle_ab(dir_cmf, vel_vec); - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; pkt.e_rf = pkt.e_cmf / dopplerfactor; @@ -786,19 +786,13 @@ void transport_gamma(Packet &pkt, const double t2) { const double edist = chi_tot > 0. ? (tau_next - tau_current) / chi_tot : std::numeric_limits::max(); - if (edist < 0) { - printout("Negative distance (edist). Abort. \n"); - std::abort(); - } + assert_always(edist >= 0); - // Find how far it can travel during the time inverval. + // Find how far it can travel during the time interval. const double tdist = (t2 - pkt.prop_time) * CLIGHT_PROP; - if (tdist < 0) { - printout("Negative distance (tdist). Abort. \n"); - std::abort(); - } + assert_always(tdist >= 0); // printout("sdist, tdist, edist %g %g %g\n",sdist, tdist, edist); @@ -1050,7 +1044,7 @@ __host__ __device__ void pellet_gamma_decay(Packet &pkt) { const auto dir_cmf = get_rand_isotropic_unitvec(); // This direction is in the cmf - we want to convert it to the rest - // frame - use aberation of angles. We want to convert from cmf to + // frame - use aberration of angles. We want to convert from cmf to // rest so need -ve velocity. const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.tdecay); @@ -1066,7 +1060,7 @@ __host__ __device__ void pellet_gamma_decay(Packet &pkt) { // that it's now a gamma ray. pkt.prop_time = pkt.tdecay; - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; pkt.e_rf = pkt.e_cmf / dopplerfactor; @@ -1074,9 +1068,7 @@ __host__ __device__ void pellet_gamma_decay(Packet &pkt) { pkt.last_cross = BOUNDARY_NONE; // initialise polarisation information - pkt.stokes[0] = 1.; - pkt.stokes[1] = 0.; - pkt.stokes[2] = 0.; + pkt.stokes = {1., 0., 0.}; pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); if ((dot(pkt.pol_dir, pkt.pol_dir)) < 1.e-8) { diff --git a/globals.h b/globals.h index 121e454f7..e871a9015 100644 --- a/globals.h +++ b/globals.h @@ -1,4 +1,5 @@ #pragma once +#include #ifndef GLOBALS_H #define GLOBALS_H @@ -87,13 +88,12 @@ struct EnergyLevel { int nuptrans{0}; int ndowntrans{0}; PhotoionTarget *phixstargets{}; // pointer to table of target states and probabilities - float *photoion_xs{}; // Pointer to a lookup-table providing photoionisation cross-sections for this level. + int phixsstart{-1}; // index to start of photoionisation cross-sections table in global::allphixs int nphixstargets{0}; // length of phixstargets array: float stat_weight{0.}; // Statistical weight of this level. int cont_index{-1}; // Index of the continuum associated to this level. Negative number. int closestgroundlevelcont{-1}; - bool metastable{}; /// }; struct Ion { @@ -109,21 +109,15 @@ struct Ion { int ncoolingterms; int uniquelevelindexstart; int groundcontindex; - float *Alpha_sp; double ionpot; // Ionisation threshold to the next ionstage - // int nbfcontinua; - // ionsphixslist *phixslist; + LevelTransition *alltransitions; }; struct Element { - Ion *ions{}; // Carries information for each ion: 0,1,...,nions-1 - int nions{0}; // Number of ions for the current element - int anumber{-1}; // Atomic number - // int uppermost_ion; // Highest ionisation stage which has a decent population for a given - // cell - // Be aware that this must not be used outside of the update_grid routine - // and their daughters. Neither it will work with OpenMP threads. - int uniqueionindexstart{-1}; // Index of the lowest ionisation stage of this element + Ion *ions{}; // Carries information for each ion: 0,1,...,nions-1 + int nions{0}; // Number of ions for the current element + int anumber{-1}; // Atomic number + int uniqueionindexstart{-1}; /// uniqueionindex index of the lowest ionisation stage of this element float initstablemeannucmass = {0.}; // Atomic mass number in multiple of MH bool has_nlte_levels{false}; }; @@ -202,6 +196,7 @@ struct CellCache { std::vector ch_all_levels; std::vector ch_allcont_departureratios; std::vector ch_allcont_nnlevel; + std::vector ch_keep_this_cont; double chi_ff_nnionpart{-1}; int cellnumber{-1}; // Identifies the cell the data is valid for. }; @@ -261,9 +256,13 @@ inline int opacity_case{}; // 0 grey, 1 for Fe-grp dependence. // ATOMIC DATA -inline int nlines{-1}; +inline std::vector ion_alpha_sp; // alpha_sp for each ion and temperature table value + +inline float *allphixs{}; + inline std::vector elements; +inline int nlines{-1}; inline const TransitionLine *linelist{}; inline std::vector bflist; diff --git a/grid.cc b/grid.cc index 48e5625d8..668c55b7a 100644 --- a/grid.cc +++ b/grid.cc @@ -1,13 +1,10 @@ #include "grid.h" -#ifdef MPI_ON -#include -#endif - #include #include #include #include +#include #include #include #include @@ -16,6 +13,9 @@ #include #include #include +#ifdef MPI_ON +#include +#endif #include #include #include @@ -46,8 +46,8 @@ std::array coordlabel{'?', '?', '?'}; std::array ncoordgrid{0}; // propagation grid dimensions auto model_type = GridType::SPHERICAL1D; -size_t npts_model = 0; // number of model grid cells -size_t nonempty_npts_model = 0; // number of allocated non-empty model grid cells +ptrdiff_t npts_model = 0; // number of model grid cells +ptrdiff_t nonempty_npts_model = 0; // number of allocated non-empty model grid cells double t_model = -1.; // time at which densities in input model are correct. std::vector vout_model{}; @@ -57,7 +57,7 @@ double min_den; // minimum model density double mfegroup = 0.; // Total mass of Fe group elements in ejecta -int first_cellindex = -1; // auto-dermine first cell index in model.txt (usually 1 or 0) +int first_cellindex = -1; // auto-determine first cell index in model.txt (usually 1 or 0) struct PropGridCell { std::array pos_min{}; // Initial co-ordinates of inner most corner of cell. @@ -72,6 +72,8 @@ std::vector mgi_of_nonemptymgi; std::span totmassradionuclide{}; // total mass of each radionuclide in the ejecta +double *nltepops_allcells{}; + #ifdef MPI_ON MPI_Win win_nltepops_allcells = MPI_WIN_NULL; MPI_Win win_initnucmassfrac_allcells = MPI_WIN_NULL; @@ -130,7 +132,7 @@ void set_npts_model(const int new_npts_model) { void allocate_initradiobund() { assert_always(npts_model > 0); - const size_t num_nuclides = decay::get_num_nuclides(); + const ptrdiff_t num_nuclides = decay::get_num_nuclides(); const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); #ifdef MPI_ON @@ -147,7 +149,7 @@ void allocate_initradiobund() { initnucmassfrac_allcells = static_cast(malloc(totalradioabundsize)); #endif printout( - "[info] mem_usage: radioabundance data for %zu nuclides for %zu cells occupies %.3f MB (node shared memory)\n", + "[info] mem_usage: radioabundance data for %td nuclides for %td cells occupies %.3f MB (node shared memory)\n", num_nuclides, npts_model, static_cast(totalradioabundsize) / 1024. / 1024.); #ifdef MPI_ON @@ -156,9 +158,9 @@ void allocate_initradiobund() { assert_always(initnucmassfrac_allcells != nullptr); - for (size_t mgi = 0; mgi < (npts_model + 1); mgi++) { + for (ptrdiff_t mgi = 0; mgi < (npts_model + 1); mgi++) { modelgrid[mgi].initnucmassfrac = &initnucmassfrac_allcells[mgi * num_nuclides]; - if (mgi % static_cast(globals::node_nprocs) == static_cast(globals::rank_in_node)) { + if (mgi % static_cast(globals::node_nprocs) == globals::rank_in_node) { for (int i = 0; i < decay::get_num_nuclides(); i++) { modelgrid[mgi].initnucmassfrac[i] = 0.; } @@ -251,7 +253,7 @@ void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, if (massfrac_untrackedstable < 0.) { //  allow some roundoff error before we complain if ((isofracsum - elemabundance - 1.) > 1e-4 && std::abs(isofracsum - elemabundance) > 1e-6) { - printout("WARNING: cell %d Z=%d element abundance is less than the sum of its radioisotope abundances \n", mgi, + printout("WARNING: cell %d Z=%d element abundance is less than the sum of its radioisotope abundances\n", mgi, atomic_number); printout(" massfrac(Z) %g massfrac_radioisotopes(Z) %g\n", elemabundance, isofracsum); printout(" increasing elemental abundance to %g and setting stable isotopic abundance to zero\n", isofracsum); @@ -271,7 +273,7 @@ void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, void allocate_nonemptycells_composition_cooling() // Initialise composition dependent cell data for the given cell { - const size_t npts_nonempty = get_nonempty_npts_model(); + const ptrdiff_t npts_nonempty = get_nonempty_npts_model(); #ifdef MPI_ON const auto [_, noderank_nonemptycellcount] = @@ -302,7 +304,6 @@ void allocate_nonemptycells_composition_cooling() elem_meanweight_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); #endif - double *nltepops_allcells{}; if (globals::total_nlte_levels > 0) { #ifdef MPI_ON auto size = static_cast(noderank_nonemptycellcount * globals::total_nlte_levels * sizeof(double)); @@ -319,7 +320,7 @@ void allocate_nonemptycells_composition_cooling() assert_always(nltepops_allcells != nullptr); } - for (size_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); modelgrid[modelgridindex].elements_uppermost_ion = static_cast(malloc(get_nelements() * sizeof(int))); @@ -412,7 +413,7 @@ void allocate_nonemptymodelcells() { } assert_always(nonempty_npts_model > 0); - mgi_of_nonemptymgi.resize(nonempty_npts_model); + mgi_of_nonemptymgi.resize(nonempty_npts_model, -2); int nonemptymgi = 0; // index within list of non-empty modelgrid cells @@ -506,7 +507,8 @@ void allocate_nonemptymodelcells() { printout("[info] mem_usage: the modelgrid array occupies %.3f MB\n", (get_npts_model() + 1) * sizeof(modelgrid[0]) / 1024. / 1024.); - printout("There are %zu modelgrid cells with associated propagation cells\n", nonempty_npts_model); + printout("There are %td modelgrid cells with associated propagation cells (nonempty_npts_model)\n", + nonempty_npts_model); printout( "[info] mem_usage: NLTE populations for all allocated cells occupy a total of %.3f MB (node shared memory)\n", @@ -722,7 +724,7 @@ void read_model_radioabundances(std::fstream &fmodel, std::istringstream &ssline return; } - for (size_t i = 0; i < colnames.size(); i++) { + for (ptrdiff_t i = 0; i < std::ssize(colnames); i++) { double valuein = 0.; assert_always(ssline >> valuein); // usually a mass fraction, but now can be anything @@ -814,7 +816,7 @@ auto read_model_columns(std::fstream &fmodel) -> std::tuple nucindexlist(zlist.size()); - for (std::size_t i = 0; i < zlist.size(); i++) { + for (ptrdiff_t i = 0; i < std::ssize(zlist); i++) { nucindexlist[i] = (zlist[i] > 0) ? decay::get_nucindex(zlist[i], alist[i]) : -1; } @@ -837,7 +839,7 @@ void read_1d_model() { set_npts_model(npts_model_in); ncoord_model[0] = npts_model_in; - vout_model.resize(get_npts_model()); + vout_model.resize(get_npts_model(), NAN); // Now read the time (in days) at which the model is specified. double t_model_days{NAN}; @@ -925,7 +927,6 @@ void read_2d_model() { // Second is the total FeG mass, initial 56Ni mass, initial 56Co mass int mgi = 0; - int nonemptymgi = 0; while (std::getline(fmodel, line)) { int cellnumberin = 0; float cell_r_in{NAN}; @@ -958,10 +959,6 @@ void read_2d_model() { read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - if (keepcell) { - nonemptymgi++; - } - mgi++; } @@ -969,8 +966,6 @@ void read_2d_model() { printout("ERROR in model.txt. Found %d only cells instead of %d expected.\n", mgi - 1, get_npts_model()); std::abort(); } - - printout("effectively used model grid cells: %d\n", nonemptymgi); } // read a 3D Cartesian model @@ -989,10 +984,8 @@ void read_3d_model() { ncoord_model[0] = ncoord_model[1] = ncoord_model[2] = static_cast(round(pow(npts_model_in, 1 / 3.))); assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_model_in); - // for a 3D input model, the progation cells will match the input cells exactly - ncoordgrid[0] = ncoord_model[0]; - ncoordgrid[1] = ncoord_model[1]; - ncoordgrid[2] = ncoord_model[2]; + // for a 3D input model, the propagation cells will match the input cells exactly + ncoordgrid = ncoord_model; ngrid = npts_model_in; double t_model_days{NAN}; @@ -1019,7 +1012,6 @@ void read_3d_model() { // mgi is the index to the model grid - empty cells are sent to special value get_npts_model(), // otherwise each input cell is one modelgrid cell int mgi = 0; // corresponds to model.txt index column, but zero indexed! (model.txt might be 1-indexed) - int nonemptymgi = 0; while (std::getline(fmodel, line)) { int cellnumberin = 0; std::array cellpos_in{}; @@ -1074,10 +1066,6 @@ void read_3d_model() { read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - if (keepcell) { - nonemptymgi++; - } - mgi++; } if (mgi != npts_model_in) { @@ -1100,7 +1088,6 @@ void read_3d_model() { } printout("min_den %g [g/cm3]\n", min_den); - printout("effectively used model grid cells: %d\n", nonemptymgi); } void calc_modelinit_totmassradionuclides() { @@ -1304,9 +1291,9 @@ void setup_nstart_ndo() { const int n_remainder = npts_nonempty % nprocesses; maxndo = 0; - ranks_nstart.resize(nprocesses); - ranks_ndo.resize(nprocesses); - ranks_ndo_nonempty.resize(nprocesses); + ranks_nstart.resize(nprocesses, -1); + ranks_ndo.resize(nprocesses, 0); + ranks_ndo_nonempty.resize(nprocesses, 0); // begin with no cell assignments std::ranges::fill(ranks_nstart, 0); @@ -1376,18 +1363,12 @@ void setup_grid_cartesian_3d() { // Set grid size for uniform xyz grid if (get_model_type() == GridType::CARTESIAN3D) { // if we used in a 3D ejecta model, the propagation grid must match the input grid exactly - ncoordgrid[0] = ncoord_model[0]; - ncoordgrid[1] = ncoord_model[1]; - ncoordgrid[2] = ncoord_model[2]; - // in case the user specified a grid size, we should ensure that it matches assert_always(ncoordgrid[0] == CUBOID_NCOORDGRID_X || CUBOID_NCOORDGRID_X < 0); assert_always(ncoordgrid[1] == CUBOID_NCOORDGRID_Y || CUBOID_NCOORDGRID_Y < 0); assert_always(ncoordgrid[2] == CUBOID_NCOORDGRID_Z || CUBOID_NCOORDGRID_Z < 0); } else { - ncoordgrid[0] = CUBOID_NCOORDGRID_X; - ncoordgrid[1] = CUBOID_NCOORDGRID_Y; - ncoordgrid[2] = CUBOID_NCOORDGRID_Z; + ncoordgrid = {CUBOID_NCOORDGRID_X, CUBOID_NCOORDGRID_Y, CUBOID_NCOORDGRID_Z}; } // artis assumes in some places that the cells are cubes, not cubioids @@ -1395,11 +1376,9 @@ void setup_grid_cartesian_3d() { assert_always(ncoordgrid[0] == ncoordgrid[2]); ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell.resize(ngrid); + cell.resize(ngrid, {}); - coordlabel[0] = 'X'; - coordlabel[1] = 'Y'; - coordlabel[2] = 'Z'; + coordlabel = {'X', 'Y', 'Z'}; std::array nxyz = {0, 0, 0}; for (int n = 0; n < ngrid; n++) { for (int axis = 0; axis < 3; axis++) { @@ -1424,23 +1403,17 @@ void setup_grid_cartesian_3d() { void setup_grid_spherical1d() { assert_always(get_model_type() == GridType::SPHERICAL1D); - coordlabel[0] = 'r'; - coordlabel[1] = '_'; - coordlabel[2] = '_'; + coordlabel = {'r', '_', '_'}; - ncoordgrid[0] = get_npts_model(); - ncoordgrid[1] = 1; - ncoordgrid[2] = 1; + ncoordgrid = {get_npts_model(), 1, 1}; ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell.resize(ngrid); + cell.resize(ngrid, {}); for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { const int mgi = cellindex; // interchangeable in this mode const double v_inner = mgi > 0 ? vout_model[mgi - 1] : 0.; - cell[cellindex].pos_min[0] = v_inner * globals::tmin; - cell[cellindex].pos_min[1] = 0.; - cell[cellindex].pos_min[2] = 0.; + cell[cellindex].pos_min = {v_inner * globals::tmin, 0., 0.}; } } @@ -1450,24 +1423,19 @@ void setup_grid_cylindrical_2d() { assert_always(vmax_corner < CLIGHT); assert_always(get_model_type() == GridType::CYLINDRICAL2D); - coordlabel[0] = 'r'; - coordlabel[1] = 'z'; - coordlabel[2] = '_'; + coordlabel = {'r', 'z', '_'}; - ncoordgrid[0] = ncoord_model[0]; - ncoordgrid[1] = ncoord_model[1]; - ncoordgrid[2] = ncoord_model[2]; + ncoordgrid = ncoord_model; ngrid = ncoordgrid[0] * ncoordgrid[1]; - cell.resize(ngrid); + cell.resize(ngrid, {}); for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { const int n_rcyl = get_cellcoordpointnum(cellindex, 0); const int n_z = get_cellcoordpointnum(cellindex, 1); - cell[cellindex].pos_min[0] = n_rcyl * globals::rmax / ncoord_model[0]; - cell[cellindex].pos_min[1] = globals::rmax * (-1 + n_z * 2. / ncoord_model[1]); - cell[cellindex].pos_min[2] = 0.; + cell[cellindex].pos_min = {n_rcyl * globals::rmax / ncoord_model[0], + globals::rmax * (-1 + n_z * 2. / ncoord_model[1]), 0.}; } } @@ -1511,7 +1479,7 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - return -1; } -constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> std::array { +constexpr auto get_gridcoords_from_xyz(const std::array &pos_xyz) -> std::array { if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return pos_xyz; } @@ -1529,14 +1497,16 @@ constexpr auto get_gridcoords_from_xyz(const std::array pos_xyz) -> s } template -[[nodiscard]] [[gnu::pure]] constexpr auto expanding_shell_intersection( - const std::array pos, const std::array dir, const double speed, - const double shellradiuststart, const bool isinnerboundary, const double tstart) -> double +[[nodiscard]] constexpr auto expanding_shell_intersection(const std::array &pos, + const std::array &dir, const double speed, + const double shellradiuststart, const bool isinnerboundary, + const double tstart) -> double // find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are // 3-vectors) or expanding circle (2D vectors) // returns -1 if there are no forward intersections (or if the intersection // is tangential to the shell) { + static_assert(S1 == 2 || S1 == 3); assert_always(shellradiuststart > 0); // quadratic equation for intersection of ray with sphere @@ -1562,7 +1532,7 @@ template auto posfinal1 = std::array{0.}; auto posfinal2 = std::array{0.}; - for (size_t d = 0; d < pos.size(); d++) { + for (int d = 0; d < std::ssize(pos); d++) { posfinal1[d] = pos[d] + dist1 * dir[d]; posfinal2[d] = pos[d] + dist2 * dir[d]; } @@ -1624,11 +1594,11 @@ template return -1.; } -auto get_coordboundary_distances_cylindrical2d(const std::array pkt_pos, const std::array pkt_dir, - const std::array pktposgridcoord, - const std::array pktvelgridcoord, const int cellindex, - const double tstart, const std::array cellcoordmax) - -> std::tuple, std::array> { +auto get_coordboundary_distances_cylindrical2d( + const std::array &pkt_pos, const std::array &pkt_dir, + const std::array &pktposgridcoord, const std::array &pktvelgridcoord, const int cellindex, + const double tstart, + const std::array &cellcoordmax) -> std::tuple, std::array> { // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the // propagation speed set to the xy component of the 3-velocity @@ -2415,7 +2385,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } // identify the cell index from an (x,y,z) position and a time. -[[nodiscard]] auto get_cellindex_from_pos(const std::array pos, const double time) -> int { +[[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, const double time) -> int { auto posgridcoords = get_gridcoords_from_xyz(pos); int cellindex = 0; for (int d = 0; d < get_ngriddimensions(); d++) { @@ -2433,7 +2403,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // compute distance to a cell boundary. [[nodiscard]] __host__ __device__ auto boundary_distance( - const std::array dir, const std::array pos, const double tstart, const int cellindex, + const std::array &dir, const std::array &pos, const double tstart, const int cellindex, enum cell_boundary *pkt_last_cross) -> std::tuple { if constexpr (FORCE_SPHERICAL_ESCAPE_SURFACE) { if (get_cell_r_inner(cellindex) > globals::vmax * globals::tmin) { @@ -2639,7 +2609,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } printout("|initpos| %g |dir| %g |pos.dir| %g\n", vec_len(pos), vec_len(dir), dot(pos, dir)); for (int d2 = 0; d2 < ndim; d2++) { - printout("coord %d: dist_posmax %g dist_posmin %g \n", d2, d_coordmaxboundary[d2], d_coordminboundary[d2]); + printout("coord %d: dist_posmax %g dist_posmin %g\n", d2, d_coordmaxboundary[d2], d_coordminboundary[d2]); printout("coord %d: cellcoordmin %g cellcoordmax %g\n", d2, grid::get_cellcoordmin(cellindex, d2) * tstart / globals::tmin, cellcoordmax[d2] * tstart / globals::tmin); diff --git a/grid.h b/grid.h index 3a27f51c8..3e371ecbb 100644 --- a/grid.h +++ b/grid.h @@ -115,7 +115,7 @@ void set_model_type(GridType model_type_value); [[nodiscard]] auto get_nonempty_npts_model() -> int; [[nodiscard]] auto get_t_model() -> double; [[nodiscard]] auto get_cell_modelgridindex(int cellindex) -> int; -[[nodiscard]] auto get_cellindex_from_pos(std::array pos, double time) -> int; +[[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, double time) -> int; void read_ejecta_model(); void write_grid_restart_data(int timestep); [[nodiscard]] auto get_maxndo() -> int; @@ -123,8 +123,8 @@ void write_grid_restart_data(int timestep); [[nodiscard]] auto get_ndo(int rank) -> int; [[nodiscard]] auto get_ndo_nonempty(int rank) -> int; [[nodiscard]] auto get_totmassradionuclide(int z, int a) -> double; -[[nodiscard]] auto boundary_distance(std::array dir, std::array pos, double tstart, int cellindex, - enum cell_boundary *pkt_last_cross) -> std::tuple; +[[nodiscard]] auto boundary_distance(const std::array &dir, const std::array &pos, double tstart, + int cellindex, enum cell_boundary *pkt_last_cross) -> std::tuple; [[nodiscard]] inline auto get_elem_abundance(int modelgridindex, int element) -> float // mass fraction of an element (all isotopes combined) diff --git a/input.cc b/input.cc index 6ee793929..b86106ef0 100644 --- a/input.cc +++ b/input.cc @@ -47,11 +47,6 @@ namespace { const int groundstate_index_in = 1; // starting level index in the input files -float *allphixsblock{}; - -struct Transitions { - int *to; -}; struct Transition { int lower; @@ -94,7 +89,7 @@ CellCachePhixsTargets *chphixstargetsblock{}; void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_inputtable, const int element, const int lowerion, const int lowerlevel, const int upperion, int upperlevel_in, - size_t *mem_usage_phixs, const int phixs_file_version) { + std::vector &tmpallphixs, size_t *mem_usage_phixs, const int phixs_file_version) { std::string phixsline; if (upperlevel_in >= 0) { // file gives photoionisation to a single target state only int upperlevel = upperlevel_in - groundstate_index_in; @@ -105,7 +100,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets == nullptr); globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(calloc(1, sizeof(PhotoionTarget))); + static_cast(malloc(sizeof(PhotoionTarget))); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); if (single_level_top_ion && (upperion == get_nions(element) - 1)) { @@ -119,7 +114,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input int in_nphixstargets = 0; assert_always(get_noncommentline(phixsfile, phixsline)); assert_always(std::stringstream(phixsline) >> in_nphixstargets); - assert_always(in_nphixstargets >= 0); + assert_always(in_nphixstargets > 0); // read in a table of target states and probabilities and store them if (!single_level_top_ion || upperion < get_nions(element) - 1) // in case the top ion has nlevelsmax = 1 { @@ -127,7 +122,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input *mem_usage_phixs += in_nphixstargets * sizeof(PhotoionTarget); globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(calloc(in_nphixstargets, sizeof(PhotoionTarget))); + static_cast(malloc(in_nphixstargets * sizeof(PhotoionTarget))); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); double probability_sum = 0.; @@ -151,7 +146,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = 1; *mem_usage_phixs += sizeof(PhotoionTarget); globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(calloc(1, sizeof(PhotoionTarget))); + static_cast(malloc(sizeof(PhotoionTarget))); assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); for (int i = 0; i < in_nphixstargets; i++) { @@ -180,18 +175,20 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } *mem_usage_phixs += globals::NPHIXSPOINTS * sizeof(float); - globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs = - static_cast(calloc(globals::NPHIXSPOINTS, sizeof(float))); - assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs != nullptr); + assert_always(tmpallphixs.size() % globals::NPHIXSPOINTS == 0); + const auto tmpphixsstart = tmpallphixs.size(); + globals::elements[element].ions[lowerion].levels[lowerlevel].phixsstart = tmpphixsstart / globals::NPHIXSPOINTS; + tmpallphixs.resize(tmpallphixs.size() + globals::NPHIXSPOINTS); + auto *levelphixstable = &tmpallphixs[tmpphixsstart]; if (phixs_file_version == 1) { assert_always(get_nphixstargets(element, lowerion, lowerlevel) == 1); assert_always(get_phixsupperlevel(element, lowerion, lowerlevel, 0) == 0); const double nu_edge = (epsilon(element, upperion, 0) - epsilon(element, lowerion, lowerlevel)) / H; - auto nutable = std::vector(nphixspoints_inputtable); - auto phixstable = std::vector(nphixspoints_inputtable); + auto nugrid_in = std::vector(nphixspoints_inputtable); + auto phixs_in = std::vector(nphixspoints_inputtable); for (int i = 0; i < nphixspoints_inputtable; i++) { double energy = -1.; @@ -200,27 +197,25 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input assert_always(std::stringstream(phixsline) >> energy >> phixs); assert_always(energy >= 0); assert_always(phixs >= 0); - nutable[i] = nu_edge + (energy * 13.6 * EV) / H; + nugrid_in[i] = nu_edge + (energy * 13.6 * EV) / H; // the photoionisation cross-sections in the database are given in Mbarn=1e6 * 1e-28m^2 // to convert to cgs units multiply by 1e-18 - phixstable[i] = phixs * 1e-18; + phixs_in[i] = phixs * 1e-18; } - const double nu_max = nutable[nphixspoints_inputtable - 1]; + const double nu_max = nugrid_in.back(); // Now interpolate these cross-sections - globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs[0] = phixstable[0]; + levelphixstable[0] = phixs_in[0]; gsl_interp_accel *acc = gsl_interp_accel_alloc(); gsl_spline *spline = gsl_spline_alloc(gsl_interp_linear, nphixspoints_inputtable); - gsl_spline_init(spline, nutable.data(), phixstable.data(), nphixspoints_inputtable); + gsl_spline_init(spline, nugrid_in.data(), phixs_in.data(), nphixspoints_inputtable); for (int i = 1; i < globals::NPHIXSPOINTS; i++) { const double nu = nu_edge * (1. + i * globals::NPHIXSNUINCREMENT); if (nu > nu_max) { - const double phixs = phixstable[nphixspoints_inputtable - 1] * pow(nu_max / nu, 3); - globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs[i] = phixs; + levelphixstable[i] = phixs_in[nphixspoints_inputtable - 1] * pow(nu_max / nu, 3); } else { - const double phixs = gsl_spline_eval(spline, nu, acc); - globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs[i] = phixs; + levelphixstable[i] = gsl_spline_eval(spline, nu, acc); } } gsl_spline_free(spline); @@ -233,7 +228,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input // the photoionisation cross-sections in the database are given in Mbarn = 1e6 * 1e-28m^2 // to convert to cgs units multiply by 1e-18 - globals::elements[element].ions[lowerion].levels[lowerlevel].photoion_xs[i] = phixs * 1e-18; + levelphixstable[i] = phixs * 1e-18; // fprintf(database_file,"%g %g\n", nutable[i], phixstable[i]); } } @@ -246,7 +241,7 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } } -void read_phixs_file(const int phixs_file_version) { +void read_phixs_file(const int phixs_file_version, std::vector &tmpallphixs) { size_t mem_usage_phixs = 0; printout("readin phixs data from %s\n", phixsdata_filenames[phixs_file_version]); @@ -312,9 +307,9 @@ void read_phixs_file(const int phixs_file_version) { assert_always(lowerlevel >= 0); // store only photoionization crosssections for ions that are part of the current model atom - if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_nlevels(element, lowerion)) { + if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_ionisinglevels(element, lowerion)) { read_phixs_data_table(phixsfile, nphixspoints_inputtable, element, lowerion, lowerlevel, upperion, - upperlevel_in, &mem_usage_phixs, phixs_file_version); + upperlevel_in, tmpallphixs, &mem_usage_phixs, phixs_file_version); skip_this_phixs_table = false; } @@ -347,14 +342,14 @@ void read_phixs_file(const int phixs_file_version) { printout("[info] mem_usage: photoionisation tables occupy %.3f MB\n", mem_usage_phixs / 1024. / 1024.); } -void read_ion_levels(std::fstream &adata, const int element, const int ion, const int nions, const int nlevels, - int nlevelsmax, const double energyoffset, const double ionpot, Transitions *transitions) { - const ptrdiff_t nlevels_used = std::min(nlevels, nlevelsmax); - // each level contains 0..level elements. seriess sum of 1 + 2 + 3 + 4 + ... + nlevels_used is used here - const ptrdiff_t transitblocksize = nlevels_used * (nlevels_used + 1) / 2; - transitions[0].to = static_cast(malloc(transitblocksize * sizeof(int))); +constexpr auto downtranslevelstart(const int level) { + // each level index is associated with a block of size levelindex spanning all possible down transitions. + // so use the formula for the sum of 1 + 2 + 3 + 4 + ... + level + return level * (level + 1) / 2; +} - ptrdiff_t transitionblockindex = 0; +void read_ion_levels(std::fstream &adata, const int element, const int ion, const int nions, const int nlevels, + int nlevelsmax, const double energyoffset, const double ionpot) { for (int level = 0; level < nlevels; level++) { int levelindex_in = 0; double levelenergy{NAN}; @@ -367,16 +362,13 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons if (level < nlevelsmax) { const double currentlevelenergy = (energyoffset + levelenergy) * EV; + globals::elements[element].ions[ion].levels[level].nphixstargets = 0; + globals::elements[element].ions[ion].levels[level].phixsstart = -1; + globals::elements[element].ions[ion].levels[level].phixstargets = nullptr; globals::elements[element].ions[ion].levels[level].epsilon = currentlevelenergy; - - // if (level == 0 && ion == 0) energyoffset = levelenergy; globals::elements[element].ions[ion].levels[level].stat_weight = statweight; assert_always(statweight > 0.); - // set the metastable flag to true until we find a a downward transition - globals::elements[element].ions[ion].levels[level].metastable = true; - // globals::elements[element].ions[ion].levels[level].main_qn = mainqn; - // The level contributes to the ionisinglevels if its energy // is below the ionization potential and the level doesn't // belong to the topmost ion included. @@ -385,15 +377,7 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons globals::elements[element].ions[ion].ionisinglevels++; } - // store the possible downward transitions from the current level in following order to memory - // A_level,level-1; A_level,level-2; ... A_level,1 - // entries which are not explicitly set are zero (the zero is set/initialized by calloc!) - transitions[level].to = &transitions[0].to[transitionblockindex]; - transitionblockindex += level; - assert_always((transitionblockindex + level) < transitblocksize); - set_ndowntrans(element, ion, level, 0); - set_nuptrans(element, ion, level, 0); } else { // globals::elements[element].ions[ion].levels[nlevelsmax - 1].stat_weight += statweight; @@ -401,15 +385,15 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons } } -void read_ion_transitions(std::fstream &ftransitiondata, const int tottransitions_in_file, int *const tottransitions, - std::vector &transitiontable, const int nlevels_requiretransitions, +void read_ion_transitions(std::fstream &ftransitiondata, const int tottransitions_in_file, int &tottransitions, + std::vector &iontransitiontable, const int nlevels_requiretransitions, const int nlevels_requiretransitions_upperlevels) { - transitiontable.reserve(*tottransitions); - transitiontable.clear(); + iontransitiontable.clear(); + iontransitiontable.reserve(tottransitions); std::string line; - if (*tottransitions == 0) { + if (tottransitions == 0) { // we will not read in any transitions, just skip past these lines in the file for (int i = 0; i < tottransitions_in_file; i++) { assert_always(getline(ftransitiondata, line)); @@ -472,14 +456,14 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition } // printout("+adding transition index %d Z=%02d ionstage %d lower %d upper %d\n", i, Z, ionstage, prev_lower, // tmplevel); - (*tottransitions)++; + tottransitions++; assert_always(tmplevel >= 0); - transitiontable.push_back( + iontransitiontable.push_back( {.lower = prev_lower, .upper = tmplevel, .A = 0., .coll_str = -2., .forbidden = true}); } } - transitiontable.push_back( + iontransitiontable.push_back( {.lower = lower, .upper = upper, .A = A, .coll_str = coll_str, .forbidden = (intforbidden == 1)}); // printout("index %d, lower %d, upper %d, A %g\n",transitionindex,lower,upper,A); // printout("reading transition index %d lower %d upper %d\n", i, transitiontable[i].lower, @@ -491,17 +475,18 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition } void add_transitions_to_unsorted_linelist(const int element, const int ion, const int nlevelsmax, - const std::vector &transitiontable, Transitions *transitions, - int *lineindex, std::vector &temp_linelist) { - const int lineindex_initial = *lineindex; - size_t totupdowntrans = 0; + const std::vector &transitiontable, + std::vector &iondowntranstmplineindicies, int &lineindex, + std::vector &temp_linelist) { + const int lineindex_initial = lineindex; + ptrdiff_t totupdowntrans = 0; // pass 0 to get transition counts of each level // pass 1 to allocate and fill transition arrays for (int pass = 0; pass < 2; pass++) { - *lineindex = lineindex_initial; + lineindex = lineindex_initial; if (pass == 1) { int alltransindex = 0; - LevelTransition *alltransblock{}; + auto &ionalltrans = globals::elements[element].ions[ion].alltransitions; #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); @@ -511,19 +496,18 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons auto size = static_cast(noderank_trans * sizeof(LevelTransition)); int disp_unit = sizeof(LevelTransition); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &alltransblock, - &win_alltransblock); + MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &ionalltrans, &win_alltransblock); - MPI_Win_shared_query(win_alltransblock, 0, &size, &disp_unit, &alltransblock); + MPI_Win_shared_query(win_alltransblock, 0, &size, &disp_unit, &ionalltrans); #else - alltransblock = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); + ionalltrans = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); #endif for (int level = 0; level < nlevelsmax; level++) { - globals::elements[element].ions[ion].levels[level].downtrans = &alltransblock[alltransindex]; + globals::elements[element].ions[ion].levels[level].downtrans = &ionalltrans[alltransindex]; alltransindex += get_ndowntrans(element, ion, level); - globals::elements[element].ions[ion].levels[level].uptrans = &alltransblock[alltransindex]; + globals::elements[element].ions[ion].levels[level].uptrans = &ionalltrans[alltransindex]; alltransindex += get_nuptrans(element, ion, level); set_ndowntrans(element, ion, level, 0); @@ -531,58 +515,53 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons } } - for (int level = 0; level < nlevelsmax; level++) { - std::fill_n(transitions[level].to, level, -99); - } + std::ranges::fill(iondowntranstmplineindicies, -99); totupdowntrans = 0; for (const auto &transition : transitiontable) { const int level = transition.upper; - const int targetlevel = transition.lower; + const int lowerlevel = transition.lower; if (pass == 0) { - assert_always(targetlevel >= 0); - assert_always(level > targetlevel); + assert_always(lowerlevel >= 0); + assert_always(level > lowerlevel); } - double nu_trans = -1.; - if (targetlevel < nlevelsmax && level < nlevelsmax) { - nu_trans = (epsilon(element, ion, level) - epsilon(element, ion, targetlevel)) / H; + if ((lowerlevel >= nlevelsmax) || (level >= nlevelsmax)) { + continue; } + const double nu_trans = (epsilon(element, ion, level) - epsilon(element, ion, lowerlevel)) / H; if (!(nu_trans > 0)) { continue; } // Make sure that we don't allow duplicate. In that case take only the lines // first occurrence - const int transitioncheck = transitions[level].to[(level - targetlevel) - 1]; + int &downtranslineindex = iondowntranstmplineindicies[downtranslevelstart(level) + lowerlevel]; - // -99 means that the transition hasn't been seen yet - if (transitioncheck == -99) { - transitions[level].to[level - targetlevel - 1] = *lineindex; + // negative means that the transition hasn't been seen yet + if (downtranslineindex < 0) { + downtranslineindex = lineindex++; const int nupperdowntrans = get_ndowntrans(element, ion, level) + 1; set_ndowntrans(element, ion, level, nupperdowntrans); - const int nloweruptrans = get_nuptrans(element, ion, targetlevel) + 1; - set_nuptrans(element, ion, targetlevel, nloweruptrans); + const int nloweruptrans = get_nuptrans(element, ion, lowerlevel) + 1; + set_nuptrans(element, ion, lowerlevel, nloweruptrans); totupdowntrans += 2; if (pass == 1 && globals::rank_in_node == 0) { - const float A_ul = transition.A; - const float coll_str = transition.coll_str; - - const auto g_ratio = stat_weight(element, ion, level) / stat_weight(element, ion, targetlevel); - const float f_ul = g_ratio * ME * pow(CLIGHT, 3) / (8 * pow(QE * nu_trans * PI, 2)) * A_ul; + const auto g_ratio = stat_weight(element, ion, level) / stat_weight(element, ion, lowerlevel); + const float f_ul = g_ratio * ME * pow(CLIGHT, 3) / (8 * pow(QE * nu_trans * PI, 2)) * transition.A; assert_always(std::isfinite(f_ul)); temp_linelist.push_back({ .nu = nu_trans, - .einstein_A = A_ul, + .einstein_A = transition.A, .elementindex = element, .ionindex = ion, .upperlevelindex = level, - .lowerlevelindex = targetlevel, + .lowerlevelindex = lowerlevel, }); // the line list has not been sorted yet, so the store the level index for now and @@ -590,63 +569,57 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans - 1] = { .lineindex = -1, - .targetlevelindex = targetlevel, - .einstein_A = static_cast(A_ul), - .coll_str = coll_str, + .targetlevelindex = lowerlevel, + .einstein_A = transition.A, + .coll_str = transition.coll_str, .osc_strength = f_ul, .forbidden = transition.forbidden}; - globals::elements[element].ions[ion].levels[targetlevel].uptrans[nloweruptrans - 1] = { + globals::elements[element].ions[ion].levels[lowerlevel].uptrans[nloweruptrans - 1] = { .lineindex = -1, .targetlevelindex = level, - .einstein_A = static_cast(A_ul), - .coll_str = coll_str, + .einstein_A = transition.A, + .coll_str = transition.coll_str, .osc_strength = f_ul, .forbidden = transition.forbidden}; } - // This is not a metastable level. - globals::elements[element].ions[ion].levels[level].metastable = false; - - (*lineindex)++; } else if (pass == 1 && globals::rank_in_node == 0) { // This is a new branch to deal with lines that have different types of transition. It should trip after a // transition is already known. - const int linelistindex = transitions[level].to[level - targetlevel - 1]; - const float A_ul = transition.A; - const float coll_str = transition.coll_str; - const auto g_ratio = stat_weight(element, ion, level) / stat_weight(element, ion, targetlevel); - const float f_ul = g_ratio * ME * pow(CLIGHT, 3) / (8 * pow(QE * nu_trans * PI, 2)) * A_ul; - - if ((temp_linelist[linelistindex].elementindex != element) || (temp_linelist[linelistindex].ionindex != ion) || - (temp_linelist[linelistindex].upperlevelindex != level) || - (temp_linelist[linelistindex].lowerlevelindex != targetlevel)) { + if ((temp_linelist[downtranslineindex].elementindex != element) || + (temp_linelist[downtranslineindex].ionindex != ion) || + (temp_linelist[downtranslineindex].upperlevelindex != level) || + (temp_linelist[downtranslineindex].lowerlevelindex != lowerlevel)) { printout("[input] Failure to identify level pair for duplicate bb-transition ... going to abort now\n"); - printout("[input] element %d ion %d targetlevel %d level %d\n", element, ion, targetlevel, level); - printout("[input] transitions[level].to[level-targetlevel-1]=linelistindex %d\n", - transitions[level].to[level - targetlevel - 1]); - printout("[input] A_ul %g, coll_str %g\n", A_ul, coll_str); + printout("[input] element %d ion %d targetlevel %d level %d\n", element, ion, lowerlevel, level); + printout("[input] transitions[level].to[targetlevel]=lineindex %d\n", downtranslineindex); + printout("[input] A_ul %g, coll_str %g\n", transition.A, transition.coll_str); printout( - "[input] globals::linelist[linelistindex].elementindex %d, " - "globals::linelist[linelistindex].ionindex %d, globals::linelist[linelistindex].upperlevelindex " - "%d, globals::linelist[linelistindex].lowerlevelindex %d\n", - temp_linelist[linelistindex].elementindex, temp_linelist[linelistindex].ionindex, - temp_linelist[linelistindex].upperlevelindex, temp_linelist[linelistindex].lowerlevelindex); + "[input] globals::linelist[lineindex].elementindex %d, " + "globals::linelist[lineindex].ionindex %d, globals::linelist[lineindex].upperlevelindex " + "%d, globals::linelist[lineindex].lowerlevelindex %d\n", + temp_linelist[downtranslineindex].elementindex, temp_linelist[downtranslineindex].ionindex, + temp_linelist[downtranslineindex].upperlevelindex, temp_linelist[downtranslineindex].lowerlevelindex); std::abort(); } - const int nupperdowntrans = get_ndowntrans(element, ion, level) + 1; - const int nloweruptrans = get_nuptrans(element, ion, targetlevel) + 1; + const auto g_ratio = stat_weight(element, ion, level) / stat_weight(element, ion, lowerlevel); + const float f_ul = g_ratio * ME * pow(CLIGHT, 3) / (8 * pow(QE * nu_trans * PI, 2)) * transition.A; - auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans - 1]; - downtransition.einstein_A += A_ul; + const int nupperdowntrans = get_ndowntrans(element, ion, level); + auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans]; + assert_always(downtransition.targetlevelindex == lowerlevel); + downtransition.einstein_A += transition.A; downtransition.osc_strength += f_ul; - downtransition.coll_str = std::max(downtransition.coll_str, coll_str); + downtransition.coll_str = std::max(downtransition.coll_str, transition.coll_str); - auto &uptransition = globals::elements[element].ions[ion].levels[targetlevel].uptrans[nloweruptrans - 1]; - uptransition.einstein_A += A_ul; + const int nloweruptrans = get_nuptrans(element, ion, lowerlevel); + auto &uptransition = globals::elements[element].ions[ion].levels[lowerlevel].uptrans[nloweruptrans]; + assert_always(uptransition.targetlevelindex == level); + uptransition.einstein_A += transition.A; uptransition.osc_strength += f_ul; - uptransition.coll_str = std::max(uptransition.coll_str, coll_str); + uptransition.coll_str = std::max(uptransition.coll_str, transition.coll_str); } } } @@ -696,144 +669,423 @@ auto calculate_nlevels_groundterm(const int element, const int ion) -> int { return nlevels_groundterm; } -void read_atomicdata_files() { - int totaluptrans = 0; - int totaldowntrans = 0; - - auto compositiondata = fstream_required("compositiondata.txt", std::ios::in); - - auto adata = fstream_required("adata.txt", std::ios::in); +auto search_groundphixslist(const double nu_edge, const int element_in, const int ion_in, const int level_in) -> int +// Return the closest ground level continuum index to the given edge +// frequency. If the given edge frequency is redder than the reddest +// continuum return -1. +// NB: groundphixslist must be in ascending order. +{ + assert_always((USE_LUT_PHOTOION || USE_LUT_BFHEATING)); - printout("single_level_top_ion: %s\n", single_level_top_ion ? "true" : "false"); - printout("single_ground_level: %s\n", single_ground_level ? "true" : "false"); - // initialize atomic data structure to number of elements - int nelements_in = 0; - assert_always(compositiondata >> nelements_in); - set_nelements(nelements_in); + if (nu_edge < globals::groundcont[0].nu_edge) { + return -1; + } - // Initialize the linelist - std::vector temp_linelist; + int i = 1; + for (i = 1; i < globals::nbfcontinua_ground; i++) { + if (nu_edge < globals::groundcont[i].nu_edge) { + break; + } + } - std::vector transitiontable; + if (i == globals::nbfcontinua_ground) { + const int element = globals::groundcont[i - 1].element; + const int ion = globals::groundcont[i - 1].ion; + if (element == element_in && ion == ion_in && level_in == 0) { + return i - 1; + } - // temperature to determine relevant ionstages - int T_preset = 0; - assert_always(compositiondata >> T_preset); - assert_always(T_preset == 0); // no longer in use - int homogeneous_abundances = 0; - assert_always(compositiondata >> homogeneous_abundances); - assert_always(homogeneous_abundances == 0); // no longer in use + printout( + "[fatal] search_groundphixslist: element %d, ion %d, level %d has edge_frequency %g equal to the " + "bluest ground-level continuum\n", + element_in, ion_in, level_in, nu_edge); + printout( + "[fatal] search_groundphixslist: bluest ground level continuum is element %d, ion %d at " + "nu_edge %g\n", + element, ion, globals::groundcont[i - 1].nu_edge); + printout("[fatal] search_groundphixslist: i %d, nbfcontinua_ground %d\n", i, globals::nbfcontinua_ground); + printout( + "[fatal] This shouldn't happen, is hoewever possible if there are multiple levels in the adata file at " + "energy=0\n"); + for (int looplevels = 0; looplevels < get_nlevels(element_in, ion_in); looplevels++) { + printout("[fatal] element %d, ion %d, level %d, energy %g\n", element_in, ion_in, looplevels, + epsilon(element_in, ion_in, looplevels)); + } + printout("[fatal] Abort omitted ... MAKE SURE ATOMIC DATA ARE CONSISTENT\n"); + return i - 1; + // abort(); + } - // open transition data file - auto ftransitiondata = fstream_required("transitiondata.txt", std::ios::in); + const double left_diff = nu_edge - globals::groundcont[i - 1].nu_edge; + const double right_diff = globals::groundcont[i].nu_edge - nu_edge; + return (left_diff <= right_diff) ? i - 1 : i; +} - int lineindex = 0; // counter to determine the total number of lines - int uniqueionindex = 0; // index into list of all ions of all elements - int uniquelevelindex = 0; // index into list of all levels of all ions of all elements - int nbfcheck = 0; - for (int element = 0; element < get_nelements(); element++) { - // read information about the next element which should be stored to memory - int Z = 0; - int nions = 0; - int lowermost_ionstage = 0; - int uppermost_ionstage = 0; - int nlevelsmax_readin = 0; - double uniformabundance{NAN}; // no longer in use mode for setting uniform abundances - double mass_amu{NAN}; - assert_always(compositiondata >> Z >> nions >> lowermost_ionstage >> uppermost_ionstage >> nlevelsmax_readin >> - uniformabundance >> mass_amu); - printout("readin compositiondata: next element Z %d, nions %d, lowermost %d, uppermost %d, nlevelsmax %d\n", Z, - nions, lowermost_ionstage, uppermost_ionstage, nlevelsmax_readin); - assert_always(Z > 0); - assert_always(nions >= 0); - assert_always(nions == 0 || (nions == uppermost_ionstage - lowermost_ionstage + 1)); - assert_always(uniformabundance >= 0); - assert_always(mass_amu >= 0); +// set up the photoionisation transition lists +// and temporary gamma/kappa lists for each thread +void setup_phixs_list() { + printout("[info] read_atomicdata: number of bfcontinua %d\n", globals::nbfcontinua); + printout("[info] read_atomicdata: number of ground-level bfcontinua %d\n", globals::nbfcontinua_ground); - // write this element's data to memory - globals::elements[element].anumber = Z; - globals::elements[element].nions = nions; - globals::elements[element].initstablemeannucmass = mass_amu * MH; - globals::elements[element].uniqueionindexstart = uniqueionindex; + if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { + globals::groundcont.resize(globals::nbfcontinua_ground); - // Initialize the elements ionlist - globals::elements[element].ions = static_cast(calloc(nions, sizeof(Ion))); - assert_always(globals::elements[element].ions != nullptr); + int groundcontindex = 0; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + const int level = 0; + const int nphixstargets = get_nphixstargets(element, ion, level); + if (nphixstargets == 0) { + continue; + } + const double E_threshold = get_phixs_threshold(element, ion, level, 0); + const double nu_edge = E_threshold / H; + assert_always(groundcontindex < globals::nbfcontinua_ground); - // now read in data for all ions of the current element. before doing so initialize - // energy scale for the current element (all level energies are stored relative to - // the ground level of the neutral ion) - double energyoffset = 0.; - double ionpot = 0.; - for (int ion = 0; ion < nions; ion++) { - int nlevelsmax = nlevelsmax_readin; - // printout("element %d ion %d\n", element, ion); - // calculate the current levels ground level energy - assert_always(ionpot >= 0); - energyoffset += ionpot; + globals::groundcont[groundcontindex] = {.nu_edge = nu_edge, .element = element, .ion = ion}; - // read information for the elements next ionstage - int adata_Z_in = -1; - int ionstage = -1; - int nlevels = 0; + groundcontindex++; + } + } + assert_always(groundcontindex == globals::nbfcontinua_ground); + std::ranges::SORT_OR_STABLE_SORT(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); + } - while (adata_Z_in != Z || ionstage != lowermost_ionstage + ion) // skip over this ion block - { - if (adata_Z_in == Z) { - printout("increasing energyoffset by ionpot %g\n", ionpot); - energyoffset += ionpot; + auto *nonconstallcont = + static_cast(malloc(globals::nbfcontinua * sizeof(FullPhotoionTransition))); + printout("[info] mem_usage: photoionisation list occupies %.3f MB\n", + globals::nbfcontinua * (sizeof(FullPhotoionTransition)) / 1024. / 1024.); + int allcontindex = 0; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { + globals::elements[element].ions[ion].groundcontindex = + static_cast(std::ranges::find_if(globals::groundcont, + [=](const auto &groundcont) { + return (groundcont.element == element) && (groundcont.ion == ion); + }) - + globals::groundcont.begin()); + if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { + globals::elements[element].ions[ion].groundcontindex = -1; } - for (int i = 0; i < nlevels; i++) { - double levelenergy{NAN}; - double statweight{NAN}; - int levelindex = 0; - int ntransitions = 0; - std::string line; - std::getline(adata, line); + } + const int nlevels = get_ionisinglevels(element, ion); + for (int level = 0; level < nlevels; level++) { + const int nphixstargets = get_nphixstargets(element, ion, level); - assert_always(std::istringstream(line) >> levelindex >> levelenergy >> statweight >> ntransitions); - } + for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { + const double nu_edge = get_phixs_threshold(element, ion, level, phixstargetindex) / H; - std::string line; - assert_always(get_noncommentline(adata, line)); - assert_always(std::istringstream(line) >> adata_Z_in >> ionstage >> nlevels >> ionpot); - } + assert_always(allcontindex < globals::nbfcontinua); + nonconstallcont[allcontindex].nu_edge = nu_edge; + nonconstallcont[allcontindex].element = element; + nonconstallcont[allcontindex].ion = ion; + nonconstallcont[allcontindex].level = level; + nonconstallcont[allcontindex].phixstargetindex = phixstargetindex; + nonconstallcont[allcontindex].probability = get_phixsprobability(element, ion, level, phixstargetindex); + nonconstallcont[allcontindex].upperlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); - printout("adata header matched: Z %d, ionstage %d, nlevels %d\n", adata_Z_in, ionstage, nlevels); + if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { + const double nu_edge_target0 = get_phixs_threshold(element, ion, level, 0) / H; + const auto groundcontindex = search_groundphixslist(nu_edge_target0, element, ion, level); + nonconstallcont[allcontindex].index_in_groundphixslist = groundcontindex; - if (single_level_top_ion && ion == nions - 1) // limit the top ion to one level and no transitions - { - nlevelsmax = 1; + globals::elements[element].ions[ion].levels[level].closestgroundlevelcont = groundcontindex; + } + allcontindex++; + } } + } + } - // if (adata_Z_in == 26 && ionstage == 1) - // { - // nlevelsmax = 5; - // } + assert_always(allcontindex == globals::nbfcontinua); + assert_always(globals::nbfcontinua >= 0); // was initialised as -1 before startup - if (nlevelsmax < 0) { - nlevelsmax = nlevels; - } else if (nlevels >= nlevelsmax) { - printout("[info] read_atomicdata: reduce number of levels from %d to %d for Z %2d ionstage %d\n", nlevels, - nlevelsmax, adata_Z_in, ionstage); + globals::bfestimcount = 0; + if (globals::nbfcontinua > 0) { + // indicies above were temporary only. continuum index should be to the sorted list + std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, + &FullPhotoionTransition::nu_edge); + + globals::bfestim_nu_edge.clear(); + for (int i = 0; i < globals::nbfcontinua; i++) { + auto &cont = nonconstallcont[i]; + if (DETAILED_BF_ESTIMATORS_ON && + LEVEL_HAS_BFEST(get_atomicnumber(cont.element), get_ionstage(cont.element, cont.ion), cont.level)) { + cont.bfestimindex = globals::bfestimcount; + globals::bfestim_nu_edge.push_back(cont.nu_edge); + globals::bfestimcount++; } else { - printout( - "[warning] read_atomicdata: requested nlevelsmax=%d > nlevels=%d for ion %d of element %d ... reduced " - "nlevelsmax to nlevels\n", - nlevelsmax, nlevels, ion, element); - nlevelsmax = nlevels; + cont.bfestimindex = -1; } + } - // and proceed through the transitionlist till we match this ionstage (if it was not the neutral one) - int transdata_Z_in = -1; - int transdata_ionstage_in = -1; - int tottransitions_in_file = 0; - std::string line; - while (transdata_Z_in != Z || transdata_ionstage_in != ionstage) { - // skip over table - for (int i = 0; i < tottransitions_in_file; i++) { - assert_always(getline(ftransitiondata, line)); - } + globals::allcont_nu_edge.resize(globals::nbfcontinua, 0.); + globals::bfestim_nu_edge.shrink_to_fit(); + assert_always(globals::bfestimcount == std::ssize(globals::bfestim_nu_edge)); + } + printout("[info] bound-free estimators track bfestimcount %d photoionisation transitions\n", globals::bfestimcount); + + if (globals::nbfcontinua > 0) { + for (int i = 0; i < globals::nbfcontinua; i++) { + globals::allcont_nu_edge[i] = nonconstallcont[i].nu_edge; + } + + setup_photoion_luts(); + + for (int i = 0; i < globals::nbfcontinua; i++) { + const int element = nonconstallcont[i].element; + const int ion = nonconstallcont[i].ion; + const int level = nonconstallcont[i].level; + nonconstallcont[i].photoion_xs = get_phixs_table(element, ion, level); + assert_always(nonconstallcont[i].photoion_xs != nullptr); + } + } + globals::allcont = nonconstallcont; + nonconstallcont = nullptr; +} + +void read_phixs_data() { + globals::nbfcontinua_ground = 0; + globals::nbfcontinua = 0; + std::vector tmpallphixs; + + // read in photoionisation cross sections + phixs_file_version_exists[0] = false; + phixs_file_version_exists[1] = std::filesystem::exists(phixsdata_filenames[1]); + phixs_file_version_exists[2] = std::filesystem::exists(phixsdata_filenames[2]); + +#ifdef MPI_ON + // just in case the file system was faulty and the ranks disagree on the existence of the files + MPI_Allreduce(MPI_IN_PLACE, phixs_file_version_exists.data(), 3, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD); +#endif + assert_always(phixs_file_version_exists[1] || phixs_file_version_exists[2]); // at least one must exist + if (phixs_file_version_exists[1] && phixs_file_version_exists[2]) { + printout( + "Reading two phixs files: Reading phixsdata_v2.txt first so we use NPHIXSPOINTS and NPHIXSNUINCREMENT " + "from phixsdata_v2.txt to interpolate the phixsdata.txt data\n"); + } + if (phixs_file_version_exists[2]) { + read_phixs_file(2, tmpallphixs); + } + if (phixs_file_version_exists[1]) { + read_phixs_file(1, tmpallphixs); + } + + int cont_index = -1; + ptrdiff_t nbftables = 0; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + const int nlevels = get_nlevels(element, ion); + for (int level = 0; level < nlevels; level++) { + const int nphixstargets = get_nphixstargets(element, ion, level); + globals::elements[element].ions[ion].levels[level].cont_index = + (nphixstargets > 0) ? cont_index : std::numeric_limits::max(); + cont_index -= nphixstargets; + if (nphixstargets > 0) { + nbftables++; + } + } + + // below is just an extra warning consistency check + const int nlevels_groundterm = globals::elements[element].ions[ion].nlevels_groundterm; + + // all levels in the ground term should be photoionisation targets from the lower ground state + if (ion > 0 && ion < get_nions(element) - 1) { + const int nphixstargets = get_nphixstargets(element, ion - 1, 0); + if (nphixstargets > 0 && get_phixsupperlevel(element, ion - 1, 0, 0) == 0) { + const int phixstargetlevels = get_phixsupperlevel(element, ion - 1, 0, nphixstargets - 1) + 1; + + if (nlevels_groundterm != phixstargetlevels) { + printout("WARNING: Z=%d ionstage %d nlevels_groundterm %d phixstargetlevels(ion-1) %d.\n", + get_atomicnumber(element), get_ionstage(element, ion), nlevels_groundterm, phixstargetlevels); + // if (nlevels_groundterm < phixstargetlevels) + // { + // printout(" -> setting to %d\n", phixstargetlevels); + // globals::elements[element].ions[ion].nlevels_groundterm = phixstargetlevels; + // } + } + } + } + } + } + + printout("cont_index %d\n", cont_index); + + if (!tmpallphixs.empty()) { + assert_always((nbftables * globals::NPHIXSPOINTS) == std::ssize(tmpallphixs)); + // nbftables is not large enough! This is a bug. +// copy the photoionisation tables into one contiguous block of memory +#ifdef MPI_ON + MPI_Win win_allphixsblock = MPI_WIN_NULL; + + const auto [_, noderank_points] = + get_range_chunk(std::ssize(tmpallphixs), globals::node_nprocs, globals::rank_in_node); + + auto size = static_cast(noderank_points * sizeof(float)); + int disp_unit = sizeof(float); + MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &globals::allphixs, + &win_allphixsblock); + MPI_Win_shared_query(win_allphixsblock, MPI_PROC_NULL, &size, &disp_unit, &globals::allphixs); + + MPI_Barrier(MPI_COMM_WORLD); +#else + globals::allphixs = static_cast(malloc(tmpallphixs.size() * sizeof(float))); +#endif + + assert_always(globals::allphixs != nullptr); + + std::copy_n(tmpallphixs.cbegin(), tmpallphixs.size(), globals::allphixs); + +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif + } + + setup_phixs_list(); +} + +void read_atomicdata_files() { + int totaluptrans = 0; + int totaldowntrans = 0; + + auto compositiondata = fstream_required("compositiondata.txt", std::ios::in); + + auto adata = fstream_required("adata.txt", std::ios::in); + + printout("single_level_top_ion: %s\n", single_level_top_ion ? "true" : "false"); + printout("single_ground_level: %s\n", single_ground_level ? "true" : "false"); + // initialize atomic data structure to number of elements + int nelements_in = 0; + assert_always(compositiondata >> nelements_in); + globals::elements.resize(nelements_in); + + std::vector temp_linelist; + + std::vector iontransitiontable; + std::vector iondowntranstmplineindicies; + + // temperature to determine relevant ionstages + int T_preset = 0; + assert_always(compositiondata >> T_preset); + assert_always(T_preset == 0); // no longer in use + int homogeneous_abundances = 0; + assert_always(compositiondata >> homogeneous_abundances); + assert_always(homogeneous_abundances == 0); // no longer in use + + // open transition data file + auto ftransitiondata = fstream_required("transitiondata.txt", std::ios::in); + + int lineindex = 0; // counter to determine the total number of lines + int uniqueionindex = 0; // index into list of all ions of all elements + int uniquelevelindex = 0; // index into list of all levels of all ions of all elements + int nbfcheck = 0; + for (int element = 0; element < get_nelements(); element++) { + // read information about the next element which should be stored to memory + int Z = 0; + int nions = 0; + int lowermost_ionstage = 0; + int uppermost_ionstage = 0; + int nlevelsmax_readin = 0; + double uniformabundance{NAN}; // no longer in use mode for setting uniform abundances + double mass_amu{NAN}; + assert_always(compositiondata >> Z >> nions >> lowermost_ionstage >> uppermost_ionstage >> nlevelsmax_readin >> + uniformabundance >> mass_amu); + printout("readin compositiondata: next element Z %d, nions %d, lowermost %d, uppermost %d, nlevelsmax %d\n", Z, + nions, lowermost_ionstage, uppermost_ionstage, nlevelsmax_readin); + assert_always(Z > 0); + assert_always(nions >= 0); + assert_always(nions == 0 || (nions == uppermost_ionstage - lowermost_ionstage + 1)); + assert_always(uniformabundance >= 0); + assert_always(mass_amu >= 0); + + // write this element's data to memory + globals::elements[element].anumber = Z; + globals::elements[element].nions = nions; + globals::elements[element].initstablemeannucmass = mass_amu * MH; + globals::elements[element].uniqueionindexstart = uniqueionindex; + + // Initialize the elements ionlist + globals::elements[element].ions = static_cast(malloc(nions * sizeof(Ion))); + assert_always(globals::elements[element].ions != nullptr); + + // now read in data for all ions of the current element. before doing so initialize + // energy scale for the current element (all level energies are stored relative to + // the ground level of the neutral ion) + double energyoffset = 0.; + double ionpot = 0.; + for (int ion = 0; ion < nions; ion++) { + int nlevelsmax = nlevelsmax_readin; + // printout("element %d ion %d\n", element, ion); + // calculate the current levels ground level energy + assert_always(ionpot >= 0); + energyoffset += ionpot; + + // read information for the elements next ionstage + int adata_Z_in = -1; + int ionstage = -1; + int nlevels = 0; + + while (adata_Z_in != Z || ionstage != lowermost_ionstage + ion) // skip over this ion block + { + if (adata_Z_in == Z) { + printout("increasing energyoffset by ionpot %g\n", ionpot); + energyoffset += ionpot; + } + for (int i = 0; i < nlevels; i++) { + double levelenergy{NAN}; + double statweight{NAN}; + int levelindex = 0; + int ntransitions = 0; + std::string line; + std::getline(adata, line); + + assert_always(std::istringstream(line) >> levelindex >> levelenergy >> statweight >> ntransitions); + } + + std::string line; + assert_always(get_noncommentline(adata, line)); + assert_always(std::istringstream(line) >> adata_Z_in >> ionstage >> nlevels >> ionpot); + } + + printout("adata header matched: Z %d, ionstage %d, nlevels %d\n", adata_Z_in, ionstage, nlevels); + + if (single_level_top_ion && ion == nions - 1) // limit the top ion to one level and no transitions + { + nlevelsmax = 1; + } + + // if (adata_Z_in == 26 && ionstage == 1) + // { + // nlevelsmax = 5; + // } + + if (nlevelsmax < 0) { + nlevelsmax = nlevels; + } else if (nlevels >= nlevelsmax) { + printout("[info] read_atomicdata: reduce number of levels from %d to %d for Z %2d ionstage %d\n", nlevels, + nlevelsmax, adata_Z_in, ionstage); + } else { + printout( + "[warning] read_atomicdata: requested nlevelsmax=%d > nlevels=%d for ion %d of element %d ... reduced " + "nlevelsmax to nlevels\n", + nlevelsmax, nlevels, ion, element); + nlevelsmax = nlevels; + } + + // and proceed through the transitionlist till we match this ionstage (if it was not the neutral one) + int transdata_Z_in = -1; + int transdata_ionstage_in = -1; + int tottransitions_in_file = 0; + std::string line; + while (transdata_Z_in != Z || transdata_ionstage_in != ionstage) { + // skip over table + for (int i = 0; i < tottransitions_in_file; i++) { + assert_always(getline(ftransitiondata, line)); + } assert_always(get_noncommentline(ftransitiondata, line)); // get_noncommentline to skip over blank lines assert_always(std::istringstream(line) >> transdata_Z_in >> transdata_ionstage_in >> tottransitions_in_file); } @@ -854,16 +1106,10 @@ void read_atomicdata_files() { globals::elements[element].ions[ion].groundcontindex = -1; globals::elements[element].ions[ion].first_nlte = -1; - globals::elements[element].ions[ion].Alpha_sp = static_cast(calloc(TABLESIZE, sizeof(float))); - assert_always(globals::elements[element].ions[ion].Alpha_sp != nullptr); - globals::elements[element].ions[ion].levels = static_cast(calloc(nlevelsmax, sizeof(EnergyLevel))); assert_always(globals::elements[element].ions[ion].levels != nullptr); - auto *transitions = static_cast(calloc(nlevelsmax, sizeof(Transitions))); - assert_always(transitions != nullptr); - - read_ion_levels(adata, element, ion, nions, nlevels, nlevelsmax, energyoffset, ionpot, transitions); + read_ion_levels(adata, element, ion, nions, nlevels, nlevelsmax, energyoffset, ionpot); int tottransitions = tottransitions_in_file; @@ -875,33 +1121,25 @@ void read_atomicdata_files() { assert_always(transdata_Z_in == Z); assert_always(transdata_ionstage_in == ionstage); - // load transition table for the CURRENT ion to temporary memory - - // first levels will be collisionally - // coupled to the first levels (assumed forbidden) + // first nlevels_requiretransitions levels will be collisionally + // coupled to the first nlevels_requiretransitions_upperlevels levels (assumed forbidden) // use 0 to disable adding extra transitions - int nlevels_requiretransitions = NLEVELS_REQUIRETRANSITIONS(Z, ionstage); - int nlevels_requiretransitions_upperlevels = nlevelsmax; // no effect if previous line is zero + const int nlevels_requiretransitions = std::min(nlevelsmax, NLEVELS_REQUIRETRANSITIONS(Z, ionstage)); + // next value with have no effect if nlevels_requiretransitions = 0 + const int nlevels_requiretransitions_upperlevels = nlevelsmax; - nlevels_requiretransitions = std::min(nlevelsmax, nlevels_requiretransitions); - nlevels_requiretransitions_upperlevels = std::min(nlevelsmax, nlevels_requiretransitions_upperlevels); - - read_ion_transitions(ftransitiondata, tottransitions_in_file, &tottransitions, transitiontable, + // load transition table for the current ion to temporary memory + read_ion_transitions(ftransitiondata, tottransitions_in_file, tottransitions, iontransitiontable, nlevels_requiretransitions, nlevels_requiretransitions_upperlevels); - add_transitions_to_unsorted_linelist(element, ion, nlevelsmax, transitiontable, transitions, &lineindex, - temp_linelist); + // last level index is (nlevelsmax - 1), so this is the correct size + iondowntranstmplineindicies.resize(downtranslevelstart(nlevelsmax)); - free(transitions[0].to); - free(transitions); - transitions = nullptr; - transitiontable.clear(); + add_transitions_to_unsorted_linelist(element, ion, nlevelsmax, iontransitiontable, iondowntranstmplineindicies, + lineindex, temp_linelist); for (int level = 0; level < nlevelsmax; level++) { - globals::elements[element].ions[ion].levels[level].nphixstargets = 0; - globals::elements[element].ions[ion].levels[level].phixstargets = nullptr; - globals::elements[element].ions[ion].levels[level].photoion_xs = nullptr; uniquelevelindex++; totaldowntrans += get_ndowntrans(element, ion, level); totaluptrans += get_nuptrans(element, ion, level); @@ -962,20 +1200,22 @@ void read_atomicdata_files() { // create a linelist shared on node and then copy data across, freeing the local copy TransitionLine *nonconstlinelist{}; + { #ifdef MPI_ON - MPI_Win win_nonconstlinelist = MPI_WIN_NULL; + MPI_Win win_nonconstlinelist = MPI_WIN_NULL; - const auto [_, noderank_lines] = get_range_chunk(globals::nlines, globals::node_nprocs, globals::rank_in_node); + const auto [_, noderank_lines] = get_range_chunk(globals::nlines, globals::node_nprocs, globals::rank_in_node); - MPI_Aint size = noderank_lines * static_cast(sizeof(TransitionLine)); - int disp_unit = sizeof(TransitionLine); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nonconstlinelist, - &win_nonconstlinelist); + MPI_Aint size = noderank_lines * static_cast(sizeof(TransitionLine)); + int disp_unit = sizeof(TransitionLine); + MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nonconstlinelist, + &win_nonconstlinelist); - MPI_Win_shared_query(win_nonconstlinelist, 0, &size, &disp_unit, &nonconstlinelist); + MPI_Win_shared_query(win_nonconstlinelist, 0, &size, &disp_unit, &nonconstlinelist); #else - nonconstlinelist = static_cast(malloc(globals::nlines * sizeof(TransitionLine))); + nonconstlinelist = static_cast(malloc(globals::nlines * sizeof(TransitionLine))); #endif + } if (globals::rank_in_node == 0) { memcpy(static_cast(nonconstlinelist), temp_linelist.data(), globals::nlines * sizeof(TransitionLine)); @@ -1044,141 +1284,27 @@ void read_atomicdata_files() { uptransition->lineindex = lineindex; } - printout(" took %lds\n", std::time(nullptr) - time_start_establish_linelist_connections); -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); -#endif - - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - if (globals::elements[element].ions[ion].nlevels_groundterm <= 0) { - if (single_ground_level) { - globals::elements[element].ions[ion].nlevels_groundterm = 1; - } else { - globals::elements[element].ions[ion].nlevels_groundterm = calculate_nlevels_groundterm(element, ion); - } - } - } - } - - globals::nbfcontinua_ground = 0; - globals::nbfcontinua = 0; - - // read in photoionisation cross sections - phixs_file_version_exists[0] = false; - phixs_file_version_exists[1] = std::filesystem::exists(phixsdata_filenames[1]); - phixs_file_version_exists[2] = std::filesystem::exists(phixsdata_filenames[2]); - -#ifdef MPI_ON - // just in case the file system was faulty and the ranks disagree on the existence of the files - // broadcast the existence of the files to all ranks from rank 0 - - MPI_Bcast(phixs_file_version_exists.data(), sizeof(phixs_file_version_exists), MPI_BYTE, 0, MPI_COMM_WORLD); -#endif - assert_always(phixs_file_version_exists[1] || phixs_file_version_exists[2]); // at least one must exist - if (phixs_file_version_exists[1] && phixs_file_version_exists[2]) { - printout( - "Reading two phixs files: Reading phixsdata_v2.txt first so we use NPHIXSPOINTS and NPHIXSNUINCREMENT " - "from phixsdata_v2.txt to interpolate the phixsdata.txt data\n"); - } - if (phixs_file_version_exists[2]) { - read_phixs_file(2); - } - if (phixs_file_version_exists[1]) { - read_phixs_file(1); - } - - int cont_index = -1; - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - const int nlevels = get_nlevels(element, ion); - for (int level = 0; level < nlevels; level++) { - const int nphixstargets = get_nphixstargets(element, ion, level); - globals::elements[element].ions[ion].levels[level].cont_index = - (nphixstargets > 0) ? cont_index : std::numeric_limits::max(); - cont_index -= nphixstargets; - } - - // below is just an extra warning consistency check - const int nlevels_groundterm = globals::elements[element].ions[ion].nlevels_groundterm; - - // all levels in the ground term should be photoionisation targets from the lower ground state - if (ion > 0 && ion < get_nions(element) - 1) { - const int nphixstargets = get_nphixstargets(element, ion - 1, 0); - if (nphixstargets > 0 && get_phixsupperlevel(element, ion - 1, 0, 0) == 0) { - const int phixstargetlevels = get_phixsupperlevel(element, ion - 1, 0, nphixstargets - 1) + 1; - - if (nlevels_groundterm != phixstargetlevels) { - printout("WARNING: Z=%d ionstage %d nlevels_groundterm %d phixstargetlevels(ion-1) %d.\n", - get_atomicnumber(element), get_ionstage(element, ion), nlevels_groundterm, phixstargetlevels); - // if (nlevels_groundterm < phixstargetlevels) - // { - // printout(" -> setting to %d\n", phixstargetlevels); - // globals::elements[element].ions[ion].nlevels_groundterm = phixstargetlevels; - // } - } - } - } - } - } - - printout("cont_index %d\n", cont_index); - - update_includedionslevels_maxnions(); -} - -auto search_groundphixslist(const double nu_edge, const int element_in, const int ion_in, const int level_in) -> int -// Return the closest ground level continuum index to the given edge -// frequency. If the given edge frequency is redder than the reddest -// continuum return -1. -// NB: groundphixslist must be in ascending order. -{ - assert_always((USE_LUT_PHOTOION || USE_LUT_BFHEATING)); - - if (nu_edge < globals::groundcont[0].nu_edge) { - return -1; - } - - int i = 1; - for (i = 1; i < globals::nbfcontinua_ground; i++) { - if (nu_edge < globals::groundcont[i].nu_edge) { - break; - } - } - - if (i == globals::nbfcontinua_ground) { - const int element = globals::groundcont[i - 1].element; - const int ion = globals::groundcont[i - 1].ion; - if (element == element_in && ion == ion_in && level_in == 0) { - return i - 1; - } + printout(" took %lds\n", std::time(nullptr) - time_start_establish_linelist_connections); +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif - printout( - "[fatal] search_groundphixslist: element %d, ion %d, level %d has edge_frequency %g equal to the " - "bluest ground-level continuum\n", - element_in, ion_in, level_in, nu_edge); - printout( - "[fatal] search_groundphixslist: bluest ground level continuum is element %d, ion %d at " - "nu_edge %g\n", - element, ion, globals::groundcont[i - 1].nu_edge); - printout("[fatal] search_groundphixslist: i %d, nbfcontinua_ground %d\n", i, globals::nbfcontinua_ground); - printout( - "[fatal] This shouldn't happen, is hoewever possible if there are multiple levels in the adata file at " - "energy=0\n"); - for (int looplevels = 0; looplevels < get_nlevels(element_in, ion_in); looplevels++) { - printout("[fatal] element %d, ion %d, level %d, energy %g\n", element_in, ion_in, looplevels, - epsilon(element_in, ion_in, looplevels)); + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + if (globals::elements[element].ions[ion].nlevels_groundterm <= 0) { + if (single_ground_level) { + globals::elements[element].ions[ion].nlevels_groundterm = 1; + } else { + globals::elements[element].ions[ion].nlevels_groundterm = calculate_nlevels_groundterm(element, ion); + } + } } - printout("[fatal] Abort omitted ... MAKE SURE ATOMIC DATA ARE CONSISTENT\n"); - return i - 1; - // abort(); } - const double left_diff = nu_edge - globals::groundcont[i - 1].nu_edge; - const double right_diff = globals::groundcont[i].nu_edge - nu_edge; - return (left_diff <= right_diff) ? i - 1 : i; + read_phixs_data(); + + update_includedionslevels_maxnions(); } void setup_cellcache() { @@ -1209,7 +1335,7 @@ void setup_cellcache() { assert_always(globals::cellcache[cellcachenum].chelements != nullptr); - size_t chlevelcount = 0; + ptrdiff_t chlevelcount = 0; size_t chphixsblocksize = 0; int chtransblocksize = 0; for (int element = 0; element < get_nelements(); element++) { @@ -1250,15 +1376,15 @@ void setup_cellcache() { for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); - globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels = - &globals::cellcache[cellcachenum].ch_all_levels[alllevelindex]; + auto &chion = globals::cellcache[cellcachenum].chelements[element].chions[ion]; + chion.chlevels = &globals::cellcache[cellcachenum].ch_all_levels[alllevelindex]; assert_always(alllevelindex == get_uniquelevelindex(element, ion, 0)); alllevelindex += nlevels; for (int level = 0; level < nlevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); - globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].chphixstargets = + chion.chlevels[level].chphixstargets = chphixsblocksize > 0 ? &chphixstargetsblock[allphixstargetindex] : nullptr; allphixstargetindex += nphixstargets; } @@ -1266,22 +1392,19 @@ void setup_cellcache() { for (int level = 0; level < nlevels; level++) { const int ndowntrans = get_ndowntrans(element, ion, level); - globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_epstrans_rad_deexc = - &chtransblock[chtransindex]; + chion.chlevels[level].sum_epstrans_rad_deexc = &chtransblock[chtransindex]; chtransindex += ndowntrans; } for (int level = 0; level < nlevels; level++) { const int ndowntrans = get_ndowntrans(element, ion, level); - globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_internal_down_same = - &chtransblock[chtransindex]; + chion.chlevels[level].sum_internal_down_same = &chtransblock[chtransindex]; chtransindex += ndowntrans; } for (int level = 0; level < nlevels; level++) { const int nuptrans = get_nuptrans(element, ion, level); - globals::cellcache[cellcachenum].chelements[element].chions[ion].chlevels[level].sum_internal_up_same = - &chtransblock[chtransindex]; + chion.chlevels[level].sum_internal_up_same = &chtransblock[chtransindex]; chtransindex += nuptrans; } } @@ -1291,7 +1414,8 @@ void setup_cellcache() { assert_always(globals::nbfcontinua >= 0); globals::cellcache[cellcachenum].ch_allcont_departureratios.resize(globals::nbfcontinua); globals::cellcache[cellcachenum].ch_allcont_nnlevel.resize(globals::nbfcontinua); - mem_usage_cellcache += globals::nbfcontinua * sizeof(double); + globals::cellcache[cellcachenum].ch_keep_this_cont.resize(globals::nbfcontinua); + mem_usage_cellcache += 2 * globals::nbfcontinua * sizeof(double); printout("[info] mem_usage: cellcache for thread %d occupies %.3f MB\n", cellcachenum, mem_usage_cellcache / 1024. / 1024.); @@ -1343,173 +1467,52 @@ void write_bflist_file() { } } -// set up the photoionisation transition lists -// and temporary gamma/kappa lists for each thread -void setup_phixs_list() { - printout("[info] read_atomicdata: number of bfcontinua %d\n", globals::nbfcontinua); - printout("[info] read_atomicdata: number of ground-level bfcontinua %d\n", globals::nbfcontinua_ground); - - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::groundcont.resize(globals::nbfcontinua_ground); - - int groundcontindex = 0; - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - const int level = 0; - const int nphixstargets = get_nphixstargets(element, ion, level); - if (nphixstargets == 0) { - continue; - } - const double E_threshold = get_phixs_threshold(element, ion, level, 0); - const double nu_edge = E_threshold / H; - assert_always(groundcontindex < globals::nbfcontinua_ground); - - globals::groundcont[groundcontindex] = {.nu_edge = nu_edge, .element = element, .ion = ion}; +void setup_nlte_levels() { + globals::total_nlte_levels = 0; + int n_super_levels = 0; - groundcontindex++; - } - } - assert_always(groundcontindex == globals::nbfcontinua_ground); - std::ranges::SORT_OR_STABLE_SORT(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); + for (int element = 0; element < get_nelements(); element++) { + globals::elements[element].has_nlte_levels = elem_has_nlte_levels_search(element); } - auto *nonconstallcont = - static_cast(malloc(globals::nbfcontinua * sizeof(FullPhotoionTransition))); - printout("[info] mem_usage: photoionisation list occupies %.3f MB\n", - globals::nbfcontinua * (sizeof(FullPhotoionTransition)) / 1024. / 1024.); - size_t nbftables = 0; - int allcontindex = 0; for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::elements[element].ions[ion].groundcontindex = - static_cast(std::ranges::find_if(globals::groundcont, - [=](const auto &groundcont) { - return (groundcont.element == element) && (groundcont.ion == ion); - }) - - globals::groundcont.begin()); - if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { - globals::elements[element].ions[ion].groundcontindex = -1; - } - } - const int nlevels = get_ionisinglevels(element, ion); - for (int level = 0; level < nlevels; level++) { - const int nphixstargets = get_nphixstargets(element, ion, level); - - if (nphixstargets > 0) { - nbftables++; - } - - for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { - const double nu_edge = get_phixs_threshold(element, ion, level, phixstargetindex) / H; - - assert_always(allcontindex < globals::nbfcontinua); - nonconstallcont[allcontindex].nu_edge = nu_edge; - nonconstallcont[allcontindex].element = element; - nonconstallcont[allcontindex].ion = ion; - nonconstallcont[allcontindex].level = level; - nonconstallcont[allcontindex].phixstargetindex = phixstargetindex; - nonconstallcont[allcontindex].probability = get_phixsprobability(element, ion, level, phixstargetindex); - nonconstallcont[allcontindex].upperlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); - - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - const double nu_edge_target0 = get_phixs_threshold(element, ion, level, 0) / H; - const auto groundcontindex = search_groundphixslist(nu_edge_target0, element, ion, level); - nonconstallcont[allcontindex].index_in_groundphixslist = groundcontindex; - - globals::elements[element].ions[ion].levels[level].closestgroundlevelcont = groundcontindex; + if (elem_has_nlte_levels(element)) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions; ion++) { + globals::elements[element].ions[ion].first_nlte = globals::total_nlte_levels; + const int nlevels = get_nlevels(element, ion); + int fullnlteexcitedlevelcount = 0; + bool found_lte_only_level = false; + for (int level = 1; level < nlevels; level++) { + if (is_nlte(element, ion, level)) { + fullnlteexcitedlevelcount++; + globals::total_nlte_levels++; + assert_always(found_lte_only_level == false); // NLTE levels must be consecutive + } else { + found_lte_only_level = true; } - allcontindex++; } - } - } - } - - assert_always(allcontindex == globals::nbfcontinua); - assert_always(globals::nbfcontinua >= 0); // was initialised as -1 before startup - - globals::bfestimcount = 0; - if (globals::nbfcontinua > 0) { - // indicies above were temporary only. continum index should be to the sorted list - std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, - &FullPhotoionTransition::nu_edge); - - globals::bfestim_nu_edge.clear(); - for (int i = 0; i < globals::nbfcontinua; i++) { - auto &cont = nonconstallcont[i]; - if (DETAILED_BF_ESTIMATORS_ON && - LEVEL_HAS_BFEST(get_atomicnumber(cont.element), get_ionstage(cont.element, cont.ion), cont.level)) { - cont.bfestimindex = globals::bfestimcount; - globals::bfestim_nu_edge.push_back(cont.nu_edge); - globals::bfestimcount++; - } else { - cont.bfestimindex = -1; - } - } - - globals::allcont_nu_edge.resize(globals::nbfcontinua, 0.); - globals::bfestim_nu_edge.shrink_to_fit(); - assert_always(globals::bfestimcount == std::ssize(globals::bfestim_nu_edge)); - } - printout("[info] bound-free estimators track bfestimcount %d photoionisation transitions\n", globals::bfestimcount); - - if (globals::nbfcontinua > 0) { -// copy the photoionisation tables into one contiguous block of memory -#ifdef MPI_ON - MPI_Win win_allphixsblock = MPI_WIN_NULL; - auto size = - static_cast((globals::rank_in_node == 0) ? nbftables * globals::NPHIXSPOINTS * sizeof(float) : 0); - int disp_unit = sizeof(TransitionLine); - - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &allphixsblock, &win_allphixsblock); - MPI_Win_shared_query(win_allphixsblock, MPI_PROC_NULL, &size, &disp_unit, &allphixsblock); - - MPI_Barrier(MPI_COMM_WORLD); -#else - allphixsblock = static_cast(malloc(nbftables * globals::NPHIXSPOINTS * sizeof(float))); -#endif - - assert_always(allphixsblock != nullptr); - size_t nbftableschanged = 0; - for (int i = 0; i < globals::nbfcontinua; i++) { - globals::allcont_nu_edge[i] = nonconstallcont[i].nu_edge; - - const int element = nonconstallcont[i].element; - const int ion = nonconstallcont[i].ion; - const int level = nonconstallcont[i].level; - const int phixstargetindex = nonconstallcont[i].phixstargetindex; + globals::elements[element].ions[ion].nlevels_nlte = fullnlteexcitedlevelcount; - // different targets share the same cross section table, so don't repeat this process - if (phixstargetindex == 0) { - if (globals::rank_in_node == 0) { - memcpy(allphixsblock, globals::elements[element].ions[ion].levels[level].photoion_xs, - globals::NPHIXSPOINTS * sizeof(float)); + const bool has_superlevel = (nlevels > (fullnlteexcitedlevelcount + 1)); + if (has_superlevel) { + // If there are more levels that the ground state + the number of NLTE levels then we need an extra + // slot to store data for the "superlevel", which is a representation of all the other levels that + // are not treated in detail. + globals::total_nlte_levels++; + n_super_levels++; } - free(globals::elements[element].ions[ion].levels[level].photoion_xs); - globals::elements[element].ions[ion].levels[level].photoion_xs = allphixsblock; + assert_always(has_superlevel == ion_has_superlevel(element, ion)); - allphixsblock += globals::NPHIXSPOINTS; - nbftableschanged++; + printout("[input] element %2d Z=%2d ionstage %2d has %5d NLTE excited levels%s. Starting at %d\n", element, + get_atomicnumber(element), get_ionstage(element, ion), fullnlteexcitedlevelcount, + has_superlevel ? " plus a superlevel" : "", globals::elements[element].ions[ion].first_nlte); } } - assert_always(nbftableschanged == nbftables); -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); -#endif - for (int i = 0; i < globals::nbfcontinua; i++) { - const int element = nonconstallcont[i].element; - const int ion = nonconstallcont[i].ion; - const int level = nonconstallcont[i].level; - nonconstallcont[i].photoion_xs = globals::elements[element].ions[ion].levels[level].photoion_xs; - } } - globals::allcont = nonconstallcont; - nonconstallcont = nullptr; - setup_photoion_luts(); + printout("[input] Total NLTE levels: %d, of which %d are superlevels\n", globals::total_nlte_levels, n_super_levels); } void read_atomicdata() { @@ -1563,55 +1566,7 @@ void read_atomicdata() { write_bflist_file(); - setup_phixs_list(); - - // set-up/gather information for nlte stuff - - globals::total_nlte_levels = 0; - int n_super_levels = 0; - - for (int element = 0; element < get_nelements(); element++) { - globals::elements[element].has_nlte_levels = elem_has_nlte_levels_search(element); - } - - for (int element = 0; element < get_nelements(); element++) { - if (elem_has_nlte_levels(element)) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions; ion++) { - globals::elements[element].ions[ion].first_nlte = globals::total_nlte_levels; - const int nlevels = get_nlevels(element, ion); - int fullnlteexcitedlevelcount = 0; - bool found_lte_only_level = false; - for (int level = 1; level < nlevels; level++) { - if (is_nlte(element, ion, level)) { - fullnlteexcitedlevelcount++; - globals::total_nlte_levels++; - assert_always(found_lte_only_level == false); // NLTE levels must be consecutive - } else { - found_lte_only_level = true; - } - } - globals::elements[element].ions[ion].nlevels_nlte = fullnlteexcitedlevelcount; - - const bool has_superlevel = (nlevels > (fullnlteexcitedlevelcount + 1)); - if (has_superlevel) { - // If there are more levels that the ground state + the number of NLTE levels then we need an extra - // slot to store data for the "superlevel", which is a representation of all the other levels that - // are not treated in detail. - globals::total_nlte_levels++; - n_super_levels++; - } - - assert_always(has_superlevel == ion_has_superlevel(element, ion)); - - printout("[input] element %2d Z=%2d ionstage %2d has %5d NLTE excited levels%s. Starting at %d\n", element, - get_atomicnumber(element), get_ionstage(element, ion), fullnlteexcitedlevelcount, - has_superlevel ? " plus a superlevel" : "", globals::elements[element].ions[ion].first_nlte); - } - } - } - - printout("[input] Total NLTE levels: %d, of which %d are superlevels\n", globals::total_nlte_levels, n_super_levels); + setup_nlte_levels(); } } // anonymous namespace @@ -1776,15 +1731,11 @@ void read_parameterfile(int rank) { const double rr = (syn_dir_in[0] * syn_dir_in[0]) + (syn_dir_in[1] * syn_dir_in[1]) + (syn_dir_in[2] * syn_dir_in[2]); // ensure that this vector is normalised. if (rr > 1.e-6) { - globals::syn_dir[0] = syn_dir_in[0] / sqrt(rr); - globals::syn_dir[1] = syn_dir_in[1] / sqrt(rr); - globals::syn_dir[2] = syn_dir_in[2] / sqrt(rr); + globals::syn_dir = {syn_dir_in[0] / sqrt(rr), syn_dir_in[1] / sqrt(rr), syn_dir_in[2] / sqrt(rr)}; } else { const double z1 = 1. - (2 * rng_uniform()); const double z2 = rng_uniform() * 2.0 * PI; - globals::syn_dir[2] = z1; - globals::syn_dir[0] = sqrt((1. - (z1 * z1))) * cos(z2); - globals::syn_dir[1] = sqrt((1. - (z1 * z1))) * sin(z2); + globals::syn_dir = {sqrt((1. - (z1 * z1))) * cos(z2), sqrt((1. - (z1 * z1))) * sin(z2), z1}; } assert_always(get_noncommentline(file, line)); @@ -1793,7 +1744,7 @@ void read_parameterfile(int rank) { assert_always(get_noncommentline(file, line)); std::istringstream(line) >> globals::rho_crit_para; // free parameter for calculation of rho_crit printout("input: rho_crit_para %g\n", globals::rho_crit_para); - // he calculation of rho_crit itself depends on the time, therfore it happens in grid_init and update_grid + // he calculation of rho_crit itself depends on the time, therefore it happens in grid_init and update_grid assert_always(get_noncommentline(file, line)); int debug_packet = 0; @@ -1924,11 +1875,6 @@ void update_parameterfile(int nts) if (!lineiscommentonly(line)) { noncomment_linenum++; // line number starting from 0, ignoring comment and blank lines (that start with '#') - // if (!preceeding_comment && noncomment_linenum < inputlinecomments.size() - 1) - // { - // fileout << '#' << inputlinecomments[noncomment_linenum] << '\n'; - // } - // overwrite particular lines to enable restarting from the current timestep if (nts >= 0) { if (noncomment_linenum == 2) { @@ -1990,7 +1936,7 @@ void time_init() { // Now set the individual time steps switch (TIMESTEP_SIZE_METHOD) { case TimeStepSizeMethod::LOGARITHMIC: { - for (int n = 0; n < globals::ntimesteps; n++) { // For logarithmic steps, the logarithmic inverval will be + for (int n = 0; n < globals::ntimesteps; n++) { // For logarithmic steps, the logarithmic interval will be const double dlogt = (log(globals::tmax) - log(globals::tmin)) / globals::ntimesteps; globals::timesteps[n].start = globals::tmin * exp(n * dlogt); globals::timesteps[n].mid = globals::tmin * exp((n + 0.5) * dlogt); @@ -2026,7 +1972,7 @@ void time_init() { assert_always((nts_log + nts_fixed) == globals::ntimesteps); for (int n = 0; n < globals::ntimesteps; n++) { if (n < nts_log) { - // For logarithmic steps, the logarithmic inverval will be + // For logarithmic steps, the logarithmic interval will be const double dlogt = (log(t_transition) - log(globals::tmin)) / nts_log; globals::timesteps[n].start = globals::tmin * exp(n * dlogt); globals::timesteps[n].mid = globals::tmin * exp((n + 0.5) * dlogt); diff --git a/input.h b/input.h index 9089080f0..6807c4ba0 100644 --- a/input.h +++ b/input.h @@ -12,7 +12,7 @@ void write_timestep_file(); auto get_noncommentline(std::fstream &input, std::string &line) -> bool; [[nodiscard]] constexpr auto lineiscommentonly(const std::string_view line) -> bool -// return true for whitepace-only lines, and lines that are exclusively whitepace up to a '#' character +// return true for whitespace-only lines, and lines that are exclusively whitespace up to a '#' character { for (char const i : line) { if (i == '#') { // anything to the right of a # character doesn't count diff --git a/kpkt.cc b/kpkt.cc index 7a40f65e2..1e948d2f2 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -427,7 +427,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { assert_always(grid::modelgrid[modelgridindex].totalcooling > 0.); const double rndcool_ion = rng_uniform() * grid::modelgrid[modelgridindex].totalcooling; - // Randomly select the occuring cooling process + // Randomly select the occurring cooling process double coolingsum = 0.; int element = -1; int ion = -1; @@ -491,7 +491,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { globals::cellcache[cellcacheslotid].cooling_contrib; if (i > ihigh) { - printout("do_kpkt: error occured while selecting a cooling channel: low %d, high %d, i %td, rndcool %g\n", ilow, + printout("do_kpkt: error occurred while selecting a cooling channel: low %d, high %d, i %td, rndcool %g\n", ilow, ihigh, i, rndcool_ion_process); printout("element %d, ion %d, offset %d, terms %d, coolingsum %g\n", element, ion, get_coolinglistoffset(element, ion), get_ncoolingterms_ion(element, ion), coolingsum); diff --git a/ltepop.cc b/ltepop.cc index add83bc6a..8cac5b535 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -28,23 +28,20 @@ struct nneSolutionParas { bool force_lte; }; -auto interpolate_ions_spontrecombcoeff(const int element, const int ion, const double T) -> double { - assert_testmodeonly(element < get_nelements()); - assert_testmodeonly(ion < get_nions(element)); - assert_testmodeonly(T >= MINTEMP); - +auto interpolate_ions_spontrecombcoeff(const int uniqueionindex, const double T) -> double { const int lowerindex = floor(log(T / MINTEMP) / T_step_log); + assert_testmodeonly(lowerindex >= 0); if (lowerindex < TABLESIZE - 1) { const int upperindex = lowerindex + 1; const double T_lower = MINTEMP * exp(lowerindex * T_step_log); const double T_upper = MINTEMP * exp(upperindex * T_step_log); - const double f_upper = globals::elements[element].ions[ion].Alpha_sp[upperindex]; - const double f_lower = globals::elements[element].ions[ion].Alpha_sp[lowerindex]; + const double f_upper = globals::ion_alpha_sp[(uniqueionindex * TABLESIZE) + upperindex]; + const double f_lower = globals::ion_alpha_sp[(uniqueionindex * TABLESIZE) + lowerindex]; return f_lower + ((f_upper - f_lower) / (T_upper - T_lower) * (T - T_lower)); } - return globals::elements[element].ions[ion].Alpha_sp[TABLESIZE - 1]; + return globals::ion_alpha_sp[(uniqueionindex * TABLESIZE) + TABLESIZE - 1]; } // use Saha equation for LTE ionization balance @@ -93,7 +90,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, std::abort(); } - const double Alpha_sp = interpolate_ions_spontrecombcoeff(element, ion, T_e); + const double Alpha_sp = interpolate_ions_spontrecombcoeff(uniqueionindex, T_e); // const double Col_rec = calculate_ionrecombcoeff(modelgridindex, T_e, element, ion + 1, false, true, false, false, // false); @@ -251,7 +248,7 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin bool initial = false; if (get_groundlevelpop(modelgridindex, element, ion) < MINPOP) { - // either there reall is none of this ion or this is a first pass through + // either there really is none of this ion or this is a first pass through // in either case, we won't have any real nlte_populations so the actual value of // of groundlevelpop for this calculation doesn't matter, so long as it's not zero! pop_store = get_groundlevelpop(modelgridindex, element, ion); diff --git a/macroatom.cc b/macroatom.cc index a3cbc92ea..9c754d409 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -112,7 +112,7 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele double sum_internal_up_same = 0.; const int nuptrans = get_nuptrans(element, ion, level); for (int i = 0; i < nuptrans; i++) { - const auto &uptrans = globals::elements[element].ions[ion].levels[level].uptrans[i]; + const auto &uptrans = levelref.uptrans[i]; const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; const double R = @@ -160,13 +160,13 @@ auto do_macroatom_internal_down_same(const int element, const int ion, const int const double *sum_internal_down_same = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_down_same; - // Randomly select the occuring transition + // Randomly select the occurring transition const double targetval = rng_uniform() * sum_internal_down_same[ndowntrans - 1]; // first sum_internal_down_same[i] such that sum_internal_down_same[i] > targetval const double *const upperval = - std::upper_bound(&sum_internal_down_same[0], &sum_internal_down_same[ndowntrans], targetval); - const ptrdiff_t downtransindex = upperval - &sum_internal_down_same[0]; + std::upper_bound(sum_internal_down_same, sum_internal_down_same + ndowntrans, targetval); + const ptrdiff_t downtransindex = upperval - sum_internal_down_same; assert_always(downtransindex < ndowntrans); const int lower = globals::elements[element].ions[ion].levels[level].downtrans[downtransindex].targetlevelindex; @@ -290,7 +290,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); - // Randomly select the occuring transition + // Randomly select the occurring transition const double targetrate = rng_uniform() * internal_up_higher; double rate = 0.; const int nphixstargets = get_nphixstargets(element, ion, level); @@ -497,7 +497,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment(stats::COUNTER_MA_STAT_INTERNALDOWNLOWER); - // Randomly select the occuring transition + // Randomly select the occurring transition const double targetrate = rng_uniform() * processrates[MA_ACTION_INTERNALDOWNLOWER]; // zrand = 1. - 1e-14; double rate = 0.; @@ -535,7 +535,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast std::abort(); } if (get_ionstage(element, ion) == 0 && lower == 0) { - printout("internal downward transition to ground level occured ... abort\n"); + printout("internal downward transition to ground level occurred ... abort\n"); printout("element %d, ion %d, level %d, lower %d\n", element, ion, level, lower); printout("Z %d, ionstage %d, energy %g\n", get_atomicnumber(element), get_ionstage(element, ion - 1), globals::elements[element].ions[ion - 1].levels[lower].epsilon); @@ -549,7 +549,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // printout("[debug] do_ma: internal upward jump within current ionstage\n"); stats::increment(stats::COUNTER_INTERACTIONS); - // randomly select the occuring transition + // randomly select the occurring transition const double *sum_internal_up_same = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_up_same; @@ -557,8 +557,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // first sum_internal_up_same[i] such that sum_internal_up_same[i] > targetval const double *const upperval = - std::upper_bound(&sum_internal_up_same[0], &sum_internal_up_same[nuptrans], targetval); - const ptrdiff_t uptransindex = upperval - &sum_internal_up_same[0]; + std::upper_bound(sum_internal_up_same, sum_internal_up_same + nuptrans, targetval); + const ptrdiff_t uptransindex = upperval - sum_internal_up_same; assert_always(uptransindex < nuptrans); const int upper = globals::elements[element].ions[ion].levels[level].uptrans[uptransindex].targetlevelindex; @@ -705,12 +705,13 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const int lineindex, const double t_current) -> double { - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].targetlevelindex; + const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; + const int upper = uptr.targetlevelindex; const double n_u = get_levelpop(modelgridindex, element, ion, upper); const double n_l = get_levelpop(modelgridindex, element, ion, lower); const double nu_trans = epsilon_trans / H; - const double A_ul = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].einstein_A; + const double A_ul = uptr.einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / std::pow(nu_trans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; @@ -816,7 +817,7 @@ auto col_recombination_ratecoeff(const int modelgridindex, const int element, co g = 0.3; } - const double sigma_bf = (globals::elements[element].ions[upperion - 1].levels[lower].photoion_xs[0] * + const double sigma_bf = (get_phixs_table(element, upperion - 1, lower)[0] * get_phixsprobability(element, upperion - 1, lower, phixstargetindex)); const double sf = calculate_sahafact(element, upperion - 1, lower, upper, T_e, epsilon_trans); @@ -851,8 +852,8 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen const double fac1 = epsilon_trans / KB / T_e; - const double sigma_bf = globals::elements[element].ions[ion].levels[lower].photoion_xs[0] * - get_phixsprobability(element, ion, lower, phixstargetindex); + const double sigma_bf = + get_phixs_table(element, ion, lower)[0] * get_phixsprobability(element, ion, lower, phixstargetindex); const double C = nne * 1.55e13 * pow(T_e, -0.5) * g * sigma_bf * exp(-fac1) / fac1; // photoionization at the edge // printout("[debug] col_ion: nne %g, T_e %g, g %g, epsilon_trans %g, sigma_bf %g\n", @@ -916,16 +917,15 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double lowerstatweight) -> double { - // assert_testmodeonly(i < get_nuptrans(element, ion, lower)); - const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; + const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; + const double coll_strength = uptr.coll_str; const double eoverkt = epsilon_trans / (KB * T_e); if (coll_strength < 0) { - const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; + const bool forbidden = uptr.forbidden; if (!forbidden) { // alternative condition: (coll_strength > -1.5) i.e. to catch -1 - const double trans_osc_strength = - globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; + const double trans_osc_strength = uptr.osc_strength; // permitted E1 electric dipole transitions // collisional excitation: formula valid only for atoms!!!!!!!!!!! // Rutten script eq. 3.32. p.50 @@ -945,11 +945,11 @@ auto col_excitation_ratecoeff(const float T_e, const float nne, const int elemen eoverkt / exp_eoverkt * Gamma; } - // alterative condition: (coll_strength > -3.5) to catch -2 or -3 + // alternative condition: (coll_strength > -3.5) to catch -2 or -3 // forbidden transitions: magnetic dipole, electric quadropole... // Axelrod's approximation (thesis 1980) - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].targetlevelindex; + const int upper = uptr.targetlevelindex; const double upperstatweight = stat_weight(element, ion, upper); return nne * 8.629e-6 * 0.01 * std::exp(-eoverkt) * upperstatweight / std::sqrt(T_e); } diff --git a/md5.cc b/md5.cc index 9cb147368..9b3460fa0 100644 --- a/md5.cc +++ b/md5.cc @@ -222,7 +222,7 @@ void md5_file(const char filename[], char hashout[(2 * MD5_BLOCK_SIZE) + 1]) { BYTE buffer[1024]; - size_t numbytes = -1; + size_t numbytes = 1; while (numbytes != 0 && feof(infile) == 0) { numbytes = fread(buffer, sizeof(char), 1024, infile); assert_always(ferror(infile) == 0); diff --git a/nltepop.cc b/nltepop.cc index 16df9b0a1..073fc1641 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -31,7 +31,7 @@ namespace { FILE *nlte_file{}; // can save memory by using a combined rate matrix at the cost of diagnostic information -constexpr bool individual_process_matricies = true; +constexpr bool individual_process_matrices = true; // this is the index for the NLTE solver that is handling all ions of a single element // This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements @@ -290,7 +290,7 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e if (rate_matrix_rad_bb == rate_matrix_coll_bb) { printout( - "print_level_rates: rate_matrix_rad_bb == rate_matrix_coll_bb. check individual_process_matricies is off\n"); + "print_level_rates: rate_matrix_rad_bb == rate_matrix_coll_bb. check individual_process_matrices is off\n"); std::abort(); } @@ -665,10 +665,10 @@ void set_element_pops_lte(const int modelgridindex, const int element) { // solve rate_matrix * x = balance_vector, // then popvec[i] = x[i] / pop_norm_factor_vec[i] -auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, const gsl_vector *balance_vector, - gsl_vector *popvec, const gsl_vector *pop_normfactor_vec, - const int max_nlte_dimension) -> bool { - bool completed_solution = false; +// return true if the solution is successful, or false if the matrix is singular +[[nodiscard]] auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, + const gsl_vector *balance_vector, gsl_vector *popvec, + const gsl_vector *pop_normfactor_vec, const int max_nlte_dimension) -> bool { const size_t nlte_dimension = balance_vector->size; assert_always(pop_normfactor_vec->size == nlte_dimension); assert_always(rate_matrix->size1 == nlte_dimension); @@ -676,19 +676,20 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons // backing storage for gsl vectors THREADLOCALONHOST std::vector vec_x; - vec_x.resize(max_nlte_dimension); + vec_x.resize(max_nlte_dimension, 0.); gsl_vector x = gsl_vector_view_array(vec_x.data(), nlte_dimension).vector; THREADLOCALONHOST std::vector vec_rate_matrix_LU_decomp; - vec_rate_matrix_LU_decomp.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_LU_decomp.resize(max_nlte_dimension * max_nlte_dimension, 0.); // make a copy of the rate matrix for the LU decomp gsl_matrix rate_matrix_LU_decomp = gsl_matrix_view_array(vec_rate_matrix_LU_decomp.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_memcpy(&rate_matrix_LU_decomp, rate_matrix); THREADLOCALONHOST std::vector vec_permutation; - vec_permutation.resize(max_nlte_dimension); + vec_permutation.resize(max_nlte_dimension, 0); gsl_permutation p{.size = nlte_dimension, .data = vec_permutation.data()}; + gsl_permutation_init(&p); int s = 0; // sign of the transformation gsl_linalg_LU_decomp(&rate_matrix_LU_decomp, &p, &s); @@ -696,100 +697,99 @@ auto nltepop_matrix_solve(const int element, const gsl_matrix *rate_matrix, cons if (lumatrix_is_singular(&rate_matrix_LU_decomp, element)) { printout("ERROR: NLTE matrix is singular for element Z=%d!\n", get_atomicnumber(element)); // abort(); - completed_solution = false; - } else { - gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); + return false; + } - // solve matrix equation: rate_matrix * x = balance_vector for x (population vector) - gsl_linalg_LU_solve(&rate_matrix_LU_decomp, &p, balance_vector, &x); + gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); - gsl_set_error_handler(previous_handler); + // solve matrix equation: rate_matrix * x = balance_vector for x (population vector) + gsl_linalg_LU_solve(&rate_matrix_LU_decomp, &p, balance_vector, &x); - // gsl_linalg_HH_solve (&m.matrix, &b.vector, x); + gsl_set_error_handler(previous_handler); - const double TOLERANCE = 1e-40; - THREADLOCALONHOST std::vector vec_work; - vec_work.resize(max_nlte_dimension); - gsl_vector gsl_work_vector = gsl_vector_view_array(vec_work.data(), nlte_dimension).vector; + // gsl_linalg_HH_solve (&m.matrix, &b.vector, x); - double error_best = -1.; + const double TOLERANCE = 1e-40; + THREADLOCALONHOST std::vector vec_work; + vec_work.resize(max_nlte_dimension, 0.); + gsl_vector gsl_work_vector = gsl_vector_view_array(vec_work.data(), nlte_dimension).vector; - // population solution vector with lowest error - THREADLOCALONHOST std::vector vec_x_best; - vec_x_best.resize(max_nlte_dimension); - gsl_vector gsl_x_best = gsl_vector_view_array(vec_x_best.data(), nlte_dimension).vector; + double error_best = -1.; - THREADLOCALONHOST std::vector vec_residual; - vec_residual.resize(max_nlte_dimension); - gsl_vector gsl_vec_residual = gsl_vector_view_array(vec_residual.data(), nlte_dimension).vector; + // population solution vector with lowest error + THREADLOCALONHOST std::vector vec_x_best; + vec_x_best.resize(max_nlte_dimension, 0.); + gsl_vector gsl_x_best = gsl_vector_view_array(vec_x_best.data(), nlte_dimension).vector; - int iteration = 0; - for (iteration = 0; iteration < 10; iteration++) { - if (iteration > 0) { - gsl_linalg_LU_refine(rate_matrix, &rate_matrix_LU_decomp, &p, balance_vector, &x, &gsl_work_vector); - } + THREADLOCALONHOST std::vector vec_residual; + vec_residual.resize(max_nlte_dimension, 0.); + gsl_vector gsl_vec_residual = gsl_vector_view_array(vec_residual.data(), nlte_dimension).vector; - gsl_vector_memcpy(&gsl_vec_residual, balance_vector); - gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, &x, -1.0, &gsl_vec_residual); // calculate Ax - b = residual - const double error = fabs(gsl_vector_get( - &gsl_vec_residual, gsl_blas_idamax(&gsl_vec_residual))); // value of the largest absolute residual - - if (error < error_best || error_best < 0.) { - gsl_vector_memcpy(&gsl_x_best, &x); - error_best = error; - } - // printout("Linear algebra solver iteration %d has a maximum residual of %g\n",iteration,error); - if (error < TOLERANCE) { - break; - } + int iteration = 0; + for (iteration = 0; iteration < 10; iteration++) { + if (iteration > 0) { + gsl_linalg_LU_refine(rate_matrix, &rate_matrix_LU_decomp, &p, balance_vector, &x, &gsl_work_vector); } - if (error_best >= 0.) { - // printout(" NLTE solver matrix LU_refine: After %d iterations, keeping solution vector with a max residual of - // %g\n",iteration,error_best); - if (error_best > 1e-10) { - printout( - " NLTE solver matrix LU_refine: After %d iterations, best solution vector has a max residual of %g " - "(WARNING!)\n", - iteration, error_best); - } - gsl_vector_memcpy(&x, &gsl_x_best); + gsl_vector_memcpy(&gsl_vec_residual, balance_vector); + gsl_blas_dgemv(CblasNoTrans, 1.0, rate_matrix, &x, -1.0, &gsl_vec_residual); // calculate Ax - b = residual + const double error = fabs(gsl_vector_get( + &gsl_vec_residual, gsl_blas_idamax(&gsl_vec_residual))); // value of the largest absolute residual + + if (error < error_best || error_best < 0.) { + gsl_vector_memcpy(&gsl_x_best, &x); + error_best = error; + } + // printout("Linear algebra solver iteration %d has a maximum residual of %g\n",iteration,error); + if (error < TOLERANCE) { + break; + } + } + if (error_best >= 0.) { + // printout(" NLTE solver matrix LU_refine: After %d iterations, keeping solution vector with a max residual of + // %g\n",iteration,error_best); + if (error_best > 1e-10) { + printout( + " NLTE solver matrix LU_refine: After %d iterations, best solution vector has a max residual of %g " + "(WARNING!)\n", + iteration, error_best); } - // get the real populations using the x vector and the normalisation factors - gsl_vector_memcpy(popvec, &x); - gsl_vector_mul(popvec, pop_normfactor_vec); - // popvec will be used contains the real population densities + gsl_vector_memcpy(&x, &gsl_x_best); + } - for (size_t row = 0; row < nlte_dimension; row++) { - double recovered_balance_vector_elem = 0.; - gsl_vector_const_view row_view = gsl_matrix_const_row(rate_matrix, row); - gsl_blas_ddot(&row_view.vector, &x, &recovered_balance_vector_elem); + // get the real populations using the x vector and the normalisation factors + gsl_vector_memcpy(popvec, &x); + gsl_vector_mul(popvec, pop_normfactor_vec); + // popvec will be used contains the real population densities - const auto [ion, level] = get_ion_level_of_nlte_vector_index(row, element); + for (size_t row = 0; row < nlte_dimension; row++) { + double recovered_balance_vector_elem = 0.; + gsl_vector_const_view row_view = gsl_matrix_const_row(rate_matrix, row); + gsl_blas_ddot(&row_view.vector, &x, &recovered_balance_vector_elem); - // printout("index %4d (ionstage %d level%4d): residual %+.2e recovered balance: %+.2e normed pop %.2e pop %.2e - // departure ratio %.4f\n", - // row,get_ionstage(element,ion),level, gsl_vector_get(residual_vector,row), - // recovered_balance_vector_elem, gsl_vector_get(x,row), - // gsl_vector_get(popvec, row), - // gsl_vector_get(x, row) / gsl_vector_get(x,get_nlte_vector_index(element,ion,0))); + const auto [ion, level] = get_ion_level_of_nlte_vector_index(row, element); - if (gsl_vector_get(popvec, row) < 0.0) { - printout( - " WARNING: NLTE solver gave negative population to index %zud (Z=%d ionstage %d level %d), pop = %g. " - "Replacing with LTE pop of %g\n", - row, get_atomicnumber(element), get_ionstage(element, ion), level, - gsl_vector_get(&x, row) * gsl_vector_get(pop_normfactor_vec, row), gsl_vector_get(pop_normfactor_vec, row)); - gsl_vector_set(popvec, row, gsl_vector_get(pop_normfactor_vec, row)); - } - } + // printout("index %4d (ionstage %d level%4d): residual %+.2e recovered balance: %+.2e normed pop %.2e pop %.2e + // departure ratio %.4f\n", + // row,get_ionstage(element,ion),level, gsl_vector_get(residual_vector,row), + // recovered_balance_vector_elem, gsl_vector_get(x,row), + // gsl_vector_get(popvec, row), + // gsl_vector_get(x, row) / gsl_vector_get(x,get_nlte_vector_index(element,ion,0))); - completed_solution = true; + if (gsl_vector_get(popvec, row) < 0.0) { + printout( + " WARNING: NLTE solver gave negative population to index %zud (Z=%d ionstage %d level %d), pop = %g. " + "Replacing with LTE pop of %g\n", + row, get_atomicnumber(element), get_ionstage(element, ion), level, + gsl_vector_get(&x, row) * gsl_vector_get(pop_normfactor_vec, row), gsl_vector_get(pop_normfactor_vec, row)); + gsl_vector_set(popvec, row, gsl_vector_get(pop_normfactor_vec, row)); + } } - return completed_solution; + return true; } + } // anonymous namespace void solve_nlte_pops_element(const int element, const int modelgridindex, const int timestep, const int nlte_iter) @@ -836,7 +836,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const auto max_nlte_dimension = get_max_nlte_dimension(); THREADLOCALONHOST std::vector vec_rate_matrix; - vec_rate_matrix.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix.resize(max_nlte_dimension * max_nlte_dimension, 0.); auto rate_matrix = gsl_matrix_view_array(vec_rate_matrix.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix, 0.); @@ -853,34 +853,34 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const THREADLOCALONHOST std::vector vec_rate_matrix_rad_bf; THREADLOCALONHOST std::vector vec_rate_matrix_coll_bf; THREADLOCALONHOST std::vector vec_rate_matrix_ntcoll_bf; - if constexpr (individual_process_matricies) { - vec_rate_matrix_rad_bb.resize(max_nlte_dimension * max_nlte_dimension); + if constexpr (individual_process_matrices) { + vec_rate_matrix_rad_bb.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_rad_bb = gsl_matrix_view_array(vec_rate_matrix_rad_bb.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_rad_bb, 0.); - vec_rate_matrix_coll_bb.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_coll_bb.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_coll_bb = gsl_matrix_view_array(vec_rate_matrix_coll_bb.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_coll_bb, 0.); - vec_rate_matrix_ntcoll_bb.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_ntcoll_bb.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_ntcoll_bb = gsl_matrix_view_array(vec_rate_matrix_ntcoll_bb.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_ntcoll_bb, 0.); - vec_rate_matrix_rad_bf.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_rad_bf.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_rad_bf = gsl_matrix_view_array(vec_rate_matrix_rad_bf.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_rad_bf, 0.); - vec_rate_matrix_coll_bf.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_coll_bf.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_coll_bf = gsl_matrix_view_array(vec_rate_matrix_coll_bf.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_coll_bf, 0.); - vec_rate_matrix_ntcoll_bf.resize(max_nlte_dimension * max_nlte_dimension); + vec_rate_matrix_ntcoll_bf.resize(max_nlte_dimension * max_nlte_dimension, 0.); rate_matrix_ntcoll_bf = gsl_matrix_view_array(vec_rate_matrix_ntcoll_bf.data(), nlte_dimension, nlte_dimension).matrix; gsl_matrix_set_all(&rate_matrix_ntcoll_bf, 0.); } else { - // if not individual_process_matricies, alias a single matrix for all transition types + // if not individual_process_matrices, alias a single matrix for all transition types // the "gsl_matrix" structs are independent, but the data is shared rate_matrix_rad_bb = rate_matrix; rate_matrix_coll_bb = rate_matrix; @@ -918,8 +918,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } // printout("\n"); - if (individual_process_matricies) { - // sum the matricies for each transition type to get a total rate matrix + if (individual_process_matrices) { + // sum the matrices for each transition type to get a total rate matrix gsl_matrix_add(&rate_matrix, &rate_matrix_rad_bb); gsl_matrix_add(&rate_matrix, &rate_matrix_coll_bb); gsl_matrix_add(&rate_matrix, &rate_matrix_ntcoll_bb); @@ -934,7 +934,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const gsl_vector_set_all(&first_row_view.vector, 1.0); THREADLOCALONHOST std::vector vec_balance_vector; - vec_balance_vector.resize(max_nlte_dimension); + vec_balance_vector.resize(max_nlte_dimension, 0.); auto balance_vector = gsl_vector_view_array(vec_balance_vector.data(), nlte_dimension).vector; gsl_vector_set_all(&balance_vector, 0.); // set first balance vector entry to the element population (all other entries will be zero) @@ -962,7 +962,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // calculate the normalisation factors and apply them to the matrix // columns and balance vector elements THREADLOCALONHOST std::vector vec_pop_norm_factor_vec; - vec_pop_norm_factor_vec.resize(max_nlte_dimension); + vec_pop_norm_factor_vec.resize(max_nlte_dimension, 0.); auto pop_norm_factor_vec = gsl_vector_view_array(vec_pop_norm_factor_vec.data(), nlte_dimension).vector; gsl_vector_set_all(&pop_norm_factor_vec, 1.0); @@ -990,7 +990,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // the true population densities THREADLOCALONHOST std::vector vec_pop; - vec_pop.resize(max_nlte_dimension); + vec_pop.resize(max_nlte_dimension, 0.); auto popvec = gsl_vector_view_array(vec_pop.data(), nlte_dimension).vector; const bool matrix_solve_success = @@ -1056,7 +1056,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const set_element_pops_lte(modelgridindex, element); } - if (individual_process_matricies && (timestep % 5 == 0) && + if (individual_process_matrices && (timestep % 5 == 0) && (nlte_iter == 0)) // output NLTE stats every nth timestep for the first NLTE iteration only { print_element_rates_summary(element, modelgridindex, timestep, nlte_iter, &popvec, &rate_matrix_rad_bb, @@ -1071,7 +1071,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // print_detailed_level_stats = true; // } - if (individual_process_matricies && print_detailed_level_stats) { + if (individual_process_matrices && print_detailed_level_stats) { const int ionstage = 2; const int ion = ionstage - get_ionstage(element, 0); diff --git a/nonthermal.cc b/nonthermal.cc index 80e5f29a4..fe107e256 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -110,6 +110,7 @@ std::vector colliondata; FILE *nonthermalfile{}; bool nonthermal_initialized = false; +static_assert(SF_EMIN > 0.); constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); // energy grid on which solution is sampled @@ -274,8 +275,15 @@ void read_shell_configs() { } void read_binding_energies() { - const bool binding_en_newformat = std::filesystem::exists("binding_energies_lotz_tab1and2.txt") || - std::filesystem::exists("data/binding_energies_lotz_tab1and2.txt"); + const bool binding_en_newformat_local = std::filesystem::exists("binding_energies_lotz_tab1and2.txt") || + std::filesystem::exists("data/binding_energies_lotz_tab1and2.txt"); +#ifdef MPI_ON + bool binding_en_newformat = binding_en_newformat_local; + // just in case the file system was faulty and the ranks disagree on the existence of the files + MPI_Allreduce(MPI_IN_PLACE, &binding_en_newformat, 1, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD); +#else + const bool binding_en_newformat = binding_en_newformat_local; +#endif int nshells = 0; // number of shell in binding energy file int n_z_binding = 0; // number of elements in binding energy file @@ -293,10 +301,11 @@ void read_binding_energies() { for (int elemindex = 0; elemindex < n_z_binding; elemindex++) { assert_always(get_noncommentline(binding_energies_file, line)); std::istringstream ssline(line); - int z_element = elemindex + 1; // new file as an atomic number column if (binding_en_newformat) { + int z_element{-1}; ssline >> z_element; + assert_always(z_element == (elemindex + 1)); } for (int shell = 0; shell < nshells; shell++) { float bindingenergy = 0.; @@ -579,13 +588,7 @@ void zero_all_effionpot(const int modelgridindex) { { const int index = std::floor((energy_ev - SF_EMIN) / DELTA_E); - if (index < 0) { - return 0; - } - if (index > SFPTS - 1) { - return SFPTS - 1; - } - return index; + return std::clamp(index, 0, SFPTS - 1); } [[nodiscard]] constexpr auto get_energyindex_ev_gteq(const double energy_ev) -> int @@ -593,13 +596,7 @@ void zero_all_effionpot(const int modelgridindex) { { const int index = std::ceil((energy_ev - SF_EMIN) / DELTA_E); - if (index < 0) { - return 0; - } - if (index > SFPTS - 1) { - return SFPTS - 1; - } - return index; + return std::clamp(index, 0, SFPTS - 1); } // interpolate the y flux values to get the value at a given energy @@ -786,7 +783,7 @@ constexpr auto electron_loss_rate(const double energy, const double nne) -> doub // impact ionization cross section in cm^2 // energy and ionization_potential should be in eV -// fitting forumula of Younger 1981 +// fitting formula of Younger 1981 // called Q_i(E) in KF92 equation 7 constexpr auto xs_impactionization(const double energy_ev, const collionrow &colliondata_ion) -> double { const double ionpot_ev = colliondata_ion.ionpot_ev; @@ -907,11 +904,11 @@ auto calculate_frac_heating(const int modelgridindex, const std::array(std::ceil(SF_EMIN / DELTA_E) * 10); - assert_always(nsteps > 0); - const double delta_endash = SF_EMIN / nsteps; - for (int j = 0; j < nsteps; j++) { - const double endash = SF_EMIN * j / nsteps; + constexpr int nsteps = (static_cast(SF_EMIN / DELTA_E) + 1) * 10; + static_assert(nsteps > 0); + constexpr double delta_endash = SF_EMIN / nsteps; + for (int j = 1; j < nsteps; j++) { + const double endash = delta_endash * j; N_e_contrib += N_e(modelgridindex, endash * EV, yfunc) * endash * delta_endash; } frac_heating_Einit += N_e_contrib; @@ -1127,7 +1124,7 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme const int ionstage = get_ionstage(element, ion); double ionpot_valence = -1; - for (auto &collionrow : colliondata) { + for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { get_xs_ionization_vector(cross_section_vec, collionrow); @@ -1185,7 +1182,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen double eta_sum = 0.; double ionpot_valence = -1; int matching_nlsubshell_count = 0; - for (auto &collionrow : colliondata) { + for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { matching_nlsubshell_count++; const double frac_ionization_shell = @@ -1205,7 +1202,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen eta_over_ionpot_sum += eta_over_ionpot; - for (size_t a = 0; a < eta_nauger_ionize_sum.size(); a++) { + for (ptrdiff_t a = 0; a < std::ssize(eta_nauger_ionize_sum); a++) { eta_nauger_ionize_over_ionpot_sum[a] += eta_over_ionpot * collionrow.prob_num_auger[a]; eta_nauger_ionize_sum[a] += frac_ionization_shell * collionrow.prob_num_auger[a]; } @@ -1294,7 +1291,8 @@ auto get_xs_excitation_vector(const int element, const int ion, const int lower, const double statweight_lower, const double epsilon_trans) -> std::tuple, int> { std::array xs_excitation_vec{}; - const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; + const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; + const double coll_strength = uptr.coll_str; if (coll_strength >= 0) { // collision strength is available, so use it // Li et al. 2012 equation 11 @@ -1310,10 +1308,9 @@ auto get_xs_excitation_vector(const int element, const int ion, const int lower, } return {xs_excitation_vec, en_startindex}; } - const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; + const bool forbidden = uptr.forbidden; if (!forbidden) { - const double trans_osc_strength = - globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; + const double trans_osc_strength = uptr.osc_strength; // permitted E1 electric dipole transitions // constexpr double g_bar = 0.2; @@ -1422,7 +1419,7 @@ auto select_nt_ionization(const int modelgridindex) -> std::tuple { const double ratetotal = get_ntion_energyrate(modelgridindex); - // select based on the calcuated energy going to ionisation for each ion + // select based on the calculated energy going to ionisation for each ion double ratesum = 0.; for (int ielement = 0; ielement < get_nelements(); ielement++) { const int nions = get_nions(ielement); @@ -1484,7 +1481,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo calculate_eff_ionpot_auger_rates(modelgridindex, element, ion, yfunc); int matching_nlsubshell_count = 0; - for (auto &collionrow : colliondata) { + for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double frac_ionization_ion_shell = calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); @@ -1768,7 +1765,7 @@ void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, // add the ionization terms to the Spencer-Fano matrix { std::array vec_xs_ionization{}; - for (auto &collionrow : colliondata) { + for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double ionpot_ev = collionrow.ionpot_ev; const double en_auger_ev = collionrow.en_auger_ev; @@ -1781,6 +1778,7 @@ void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, // Z, ionstage, colliondata[n].n, colliondata[n].l, ionpot_ev); const int xsstartindex = get_xs_ionization_vector(vec_xs_ionization, collionrow); + assert_always(xsstartindex >= 0); // Luke Shingles: the use of min and max on the epsilon limits keeps energies // from becoming unphysical. This insight came from reading the // CMFGEN Fortran source code (Li, Dessart, Hillier 2012, doi:10.1111/j.1365-2966.2012.21198.x) @@ -1851,7 +1849,7 @@ void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, for (int i = 0; i < augerstopindex; i++) { const int rowoffset = uppertriangular(i, 0); const double en = engrid(i); - const int jstart = i > xsstartindex ? i : xsstartindex; + const int jstart = std::max(i, xsstartindex); for (int j = jstart; j < SFPTS; j++) { const double xs = vec_xs_ionization[j]; if constexpr (SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN) { @@ -2037,9 +2035,9 @@ void init(const int my_rank, const int ndo_nonempty) { if (grid::get_numassociatedcells(modelgridindex) > 0) { nt_solution[modelgridindex].allions = - static_cast(calloc(get_includedions(), sizeof(NonThermalSolutionIon))); + static_cast(malloc(get_includedions() * sizeof(NonThermalSolutionIon))); - const size_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); nt_solution[modelgridindex].frac_excitations_list = NT_EXCITATION_ON ? &excitations_list_all_cells[nonemptymgi * nt_excitations_stored] : nullptr; @@ -2454,8 +2452,6 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i "%d (nne=%g e-/cm^3)\n", SFPTS, SF_EMIN, SF_EMAX, modelgridindex, timestep, iteration, nne); - assert_always(SF_EMIN > 0.); - nt_solution[modelgridindex].nneperion_when_solved = nne_per_ion; nt_solution[modelgridindex].timestep_last_solved = timestep; @@ -2653,9 +2649,7 @@ void read_restart_data(FILE *gridsave_file) { int frac_excitations_list_size_in = 0; assert_always(fscanf(gridsave_file, "%d\n", &frac_excitations_list_size_in) == 1); - if (nt_solution[modelgridindex].frac_excitations_list_size != frac_excitations_list_size_in) { - nt_solution[modelgridindex].frac_excitations_list_size = frac_excitations_list_size_in; - } + nt_solution[modelgridindex].frac_excitations_list_size = frac_excitations_list_size_in; for (int excitationindex = 0; excitationindex < frac_excitations_list_size_in; excitationindex++) { assert_always(fscanf(gridsave_file, "%la %la %d\n", diff --git a/packet.cc b/packet.cc index 6b7234a53..12d8a4768 100644 --- a/packet.cc +++ b/packet.cc @@ -54,10 +54,8 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac // use equal area probability distribution to select radius const double rcyl_rand = std::sqrt((zrand * std::pow(rcyl_inner, 2)) + ((1. - zrand) * std::pow(rcyl_outer, 2))); const double theta_rand = rng_uniform() * 2 * PI; - pkt.pos[0] = std::cos(theta_rand) * rcyl_rand; - pkt.pos[1] = std::sin(theta_rand) * rcyl_rand; - - pkt.pos[2] = grid::get_cellcoordmin(cellindex, 1) + (rng_uniform_pos() * grid::wid_init(cellindex, 1)); + pkt.pos = {std::cos(theta_rand) * rcyl_rand, std::sin(theta_rand) * rcyl_rand, + grid::get_cellcoordmin(cellindex, 1) + (rng_uniform_pos() * grid::wid_init(cellindex, 1))}; } else if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { for (int axis = 0; axis < 3; axis++) { @@ -79,7 +77,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac // pellet packet is moving with the homologous flow, so dir is proportional to pos pkt.dir = vec_norm(pkt.pos); // assign dir = pos / vec_len(pos) - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.e_rf = pkt.e_cmf / dopplerfactor; pkt.trueemissiontype = EMTYPE_NOTSET; diff --git a/packet.h b/packet.h index 0685c7dec..621cf794b 100644 --- a/packet.h +++ b/packet.h @@ -80,7 +80,7 @@ struct Packet { int pellet_nucindex{-1}; // nuclide index of the decaying species float trueemissionvelocity{-1}; - inline auto operator==(const Packet &rhs) -> bool { + inline auto operator==(const Packet &rhs) const -> bool { return (number == rhs.number && type == rhs.type && (em_pos[0] == rhs.em_pos[0] && em_pos[1] == rhs.em_pos[1] && em_pos[2] == rhs.em_pos[2]) && nu_cmf == rhs.nu_cmf && where == rhs.where && prop_time == rhs.prop_time && tdecay == rhs.tdecay && diff --git a/radfield.cc b/radfield.cc index aa8635771..1b0076d0f 100644 --- a/radfield.cc +++ b/radfield.cc @@ -42,7 +42,7 @@ struct RadFieldBinSolution { }; struct RadFieldBin { - double J_raw; // value needs to be multipled by J_normfactor to get the true value + double J_raw; // value needs to be multiplied by J_normfactor to get the true value double nuJ_raw; int contribcount; }; @@ -1036,22 +1036,28 @@ void normalise_J(const int modelgridindex, const double estimator_normfactor_ove } void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, const double deltat) { - if (nts != globals::timestep_initial || titer != 0) { - for (int mgi = 0; mgi < grid::get_npts_model(); mgi++) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); - if (!globals::lte_iteration && grid::modelgrid[mgi].thick != 1) { - const int assoc_cells = grid::get_numassociatedcells(mgi); - if (assoc_cells > 0) { - const double deltaV = - grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); - const double estimator_normfactor = 1 / deltaV / deltat / globals::nprocs; - assert_always(nonemptymgi >= 0); - for (int i = 0; i < globals::bfestimcount; i++) { - const auto mgibfindex = (nonemptymgi * globals::bfestimcount) + i; - prev_bfrate_normed[mgibfindex] = bfrate_raw[mgibfindex] * (estimator_normfactor / H); - } - } - } + if (globals::rank_in_node != 0) { + return; + } + if (globals::lte_iteration) { + return; + } + if (nts == globals::timestep_initial && titer == 0) { + return; + } + const auto bfestimcount = globals::bfestimcount; + const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < nonempty_npts_model; nonemptymgi++) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); + if (grid::modelgrid[mgi].thick == 1) { + continue; + } + const double deltaV = + grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); + const double estimator_normfactor = 1 / deltaV / deltat / globals::nprocs; + for (int i = 0; i < bfestimcount; i++) { + const auto mgibfindex = (nonemptymgi * bfestimcount) + i; + prev_bfrate_normed[mgibfindex] = bfrate_raw[mgibfindex] * (estimator_normfactor / H); } } } diff --git a/ratecoeff.cc b/ratecoeff.cc index d808ce35b..d66176d3b 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -252,8 +252,8 @@ void write_ratecoeff_dat() { const int bflutindex = get_bflutindex(iter, element, ion, level, phixstargetindex); fprintf(ratecoeff_file, "%la %la %la %la\n", spontrecombcoeffs[bflutindex], bfcooling_coeffs[bflutindex], - !USE_LUT_PHOTOION ? -1 : corrphotoioncoeffs[bflutindex], - !USE_LUT_BFHEATING ? -1 : globals::bfheating_coeff[bflutindex]); + USE_LUT_PHOTOION ? corrphotoioncoeffs[bflutindex] : -1, + USE_LUT_BFHEATING ? globals::bfheating_coeff[bflutindex] : -1); } } } @@ -387,14 +387,12 @@ void precalculate_rate_coefficient_integrals() { const double sfac = calculate_sahafact(element, ion, level, upperlevel, T_e, E_threshold); - assert_always(globals::elements[element].ions[ion].levels[level].photoion_xs != nullptr); + assert_always(get_phixs_table(element, ion, level) != nullptr); // the threshold of the first target gives nu of the first phixstable point const GSLIntegrationParas intparas = { - .nu_edge = nu_threshold, - .T = T_e, - .photoion_xs = globals::elements[element].ions[ion].levels[level].photoion_xs}; + .nu_edge = nu_threshold, .T = T_e, .photoion_xs = get_phixs_table(element, ion, level)}; - // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field + // Spontaneous recombination and bf-cooling coefficient don't depend on the radiation field double alpha_sp = 0.; status = @@ -482,24 +480,30 @@ void precalculate_rate_coefficient_integrals() { void scale_level_phixs(const int element, const int ion, const int level, const double factor) { // if we store the data in node shared memory, then only one rank should update it if (globals::rank_in_node == 0) { + const int nphixstargets = get_nphixstargets(element, ion, level); + if (nphixstargets == 0) { + return; + } + + auto *phixstable = get_phixs_table(element, ion, level); for (int n = 0; n < globals::NPHIXSPOINTS; n++) { - globals::elements[element].ions[ion].levels[level].photoion_xs[n] *= factor; + phixstable[n] *= factor; } - const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { for (int iter = 0; iter < TABLESIZE; iter++) { - spontrecombcoeffs[get_bflutindex(iter, element, ion, level, phixstargetindex)] *= factor; + const auto bflutindex = get_bflutindex(iter, element, ion, level, phixstargetindex); + spontrecombcoeffs[bflutindex] *= factor; if constexpr (USE_LUT_PHOTOION) { - corrphotoioncoeffs[get_bflutindex(iter, element, ion, level, phixstargetindex)] *= factor; + corrphotoioncoeffs[bflutindex] *= factor; } if constexpr (USE_LUT_BFHEATING) { - globals::bfheating_coeff[get_bflutindex(iter, element, ion, level, phixstargetindex)] *= factor; + globals::bfheating_coeff[bflutindex] *= factor; } - bfcooling_coeffs[get_bflutindex(iter, element, ion, level, phixstargetindex)] *= factor; + bfcooling_coeffs[bflutindex] *= factor; } } } @@ -645,21 +649,23 @@ void read_recombrate_file() { } void precalculate_ion_alpha_sp() { + globals::ion_alpha_sp.resize(get_includedions() * TABLESIZE); for (int iter = 0; iter < TABLESIZE; iter++) { const float T_e = MINTEMP * exp(iter * T_step_log); for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element) - 1; for (int ion = 0; ion < nions; ion++) { - const int nlevels = get_ionisinglevels(element, ion); + const auto uniqueionindex = get_uniqueionindex(element, ion); + const int nionisinglevels = get_ionisinglevels(element, ion); double zeta = 0.; - for (int level = 0; level < nlevels; level++) { + for (int level = 0; level < nionisinglevels; level++) { const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const double zeta_level = get_spontrecombcoeff(element, ion, level, phixstargetindex, T_e); zeta += zeta_level; } } - globals::elements[element].ions[ion].Alpha_sp[iter] = zeta; + globals::ion_alpha_sp[(uniqueionindex * TABLESIZE) + iter] = zeta; } } } @@ -690,7 +696,7 @@ auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, c const auto T_e = grid::get_Te(modelgridindex); const auto intparas = gsl_integral_paras_gammacorr{ .nu_edge = nu_threshold, - .photoion_xs = globals::elements[element].ions[lowerion].levels[level].photoion_xs, + .photoion_xs = get_phixs_table(element, lowerion, level), .T_e = T_e, .modelgridindex = modelgridindex, }; @@ -777,7 +783,7 @@ auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int const auto intparas = gsl_integral_paras_gammacorr{ .nu_edge = nu_threshold, .departure_ratio = departure_ratio, - .photoion_xs = globals::elements[element].ions[ion].levels[level].photoion_xs, + .photoion_xs = get_phixs_table(element, ion, level), .T_e = T_e, .modelgridindex = modelgridindex, }; @@ -851,60 +857,57 @@ auto get_nlevels_important(const int modelgridindex, const int element, const in } // anonymous namespace void setup_photoion_luts() { + assert_always(globals::nbfcontinua > 0); size_t mem_usage_photoionluts = 2 * TABLESIZE * globals::nbfcontinua * sizeof(double); - if (globals::nbfcontinua > 0) { #ifdef MPI_ON - MPI_Win win = MPI_WIN_NULL; - MPI_Aint size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &spontrecombcoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &spontrecombcoeffs) == MPI_SUCCESS); + MPI_Win win = MPI_WIN_NULL; + MPI_Aint size = + (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + int disp_unit = sizeof(double); + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &spontrecombcoeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &spontrecombcoeffs) == MPI_SUCCESS); #else - spontrecombcoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); + spontrecombcoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); #endif - assert_always(spontrecombcoeffs != nullptr); + assert_always(spontrecombcoeffs != nullptr); - if constexpr (USE_LUT_PHOTOION) { + if constexpr (USE_LUT_PHOTOION) { #ifdef MPI_ON - size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &corrphotoioncoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &corrphotoioncoeffs) == MPI_SUCCESS); + size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &corrphotoioncoeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &corrphotoioncoeffs) == MPI_SUCCESS); #else - corrphotoioncoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); + corrphotoioncoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); #endif - assert_always(corrphotoioncoeffs != nullptr); - mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); - } + assert_always(corrphotoioncoeffs != nullptr); + mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); + } - if constexpr (USE_LUT_BFHEATING) { + if constexpr (USE_LUT_BFHEATING) { #ifdef MPI_ON - size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &globals::bfheating_coeff, &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &globals::bfheating_coeff) == MPI_SUCCESS); + size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &globals::bfheating_coeff, &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &globals::bfheating_coeff) == MPI_SUCCESS); #else - globals::bfheating_coeff = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); + globals::bfheating_coeff = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); #endif - assert_always(globals::bfheating_coeff != nullptr); - mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); - } + assert_always(globals::bfheating_coeff != nullptr); + mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); + } #ifdef MPI_ON - size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &bfcooling_coeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &bfcooling_coeffs) == MPI_SUCCESS); + size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &bfcooling_coeffs, + &win) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &bfcooling_coeffs) == MPI_SUCCESS); #else - bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); + bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); #endif - assert_always(bfcooling_coeffs != nullptr); - } + assert_always(bfcooling_coeffs != nullptr); printout( "[info] mem_usage: lookup tables derived from photoionisation (spontrecombcoeff, bfcooling and " @@ -923,9 +926,7 @@ __host__ __device__ auto select_continuum_nu(int element, const int lowerion, co const int npieces = globals::NPHIXSPOINTS; const GSLIntegrationParas intparas = { - .nu_edge = nu_threshold, - .T = T_e, - .photoion_xs = globals::elements[element].ions[lowerion].levels[lower].photoion_xs}; + .nu_edge = nu_threshold, .T = T_e, .photoion_xs = get_phixs_table(element, lowerion, lower)}; const double zrand = 1. - rng_uniform(); // Make sure that 0 < zrand <= 1 @@ -948,7 +949,7 @@ __host__ __device__ auto select_continuum_nu(int element, const int lowerion, co alpha_sp_old = alpha_sp; const double xlow = nu_threshold + (i * deltanu); - // Spontaneous recombination and bf-cooling coefficient don't depend on the cutted radiation field + // Spontaneous recombination and bf-cooling coefficient don't depend on the radiation field integrator(intparas, xlow, nu_max_phixs, 0, CONTINUUM_NU_INTEGRAL_ACCURACY, GSL_INTEG_GAUSS31, &alpha_sp, &error); @@ -1100,7 +1101,7 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i // T_e = T_R for this precalculation. void ratecoefficients_init() { printout("time before tabulation of rate coefficients %ld\n", std::time(nullptr)); - // Determine the temperture grids gridsize + // Determine the temperature grids gridsize T_step_log = (log(MAXTEMP) - log(MINTEMP)) / (TABLESIZE - 1.); md5_file("adata.txt", adatafile_hash); diff --git a/rpkt.cc b/rpkt.cc index 0f321e558..508bf9045 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -50,7 +50,7 @@ MPI_Win win_expansionopacity_planck_cumulative = MPI_WIN_NULL; // get the frequency change per distance travelled assuming linear change to the abort distance // this is done is two parts to get identical results to do_rpkt_step() -auto get_nu_cmf_abort(const std::array pos, const std::array dir, const double prop_time, +auto get_nu_cmf_abort(const std::array &pos, const std::array &dir, const double prop_time, const double nu_rf, const double abort_dist) -> double { const auto half_abort_dist = abort_dist / 2.; const auto abort_time = prop_time + (half_abort_dist / CLIGHT_PROP) + (half_abort_dist / CLIGHT_PROP); @@ -59,19 +59,19 @@ auto get_nu_cmf_abort(const std::array pos, const std::array double { +constexpr auto get_expopac_bin_nu_upper(const ptrdiff_t binindex) -> double { const auto lambda_lower = expopac_lambdamin + (binindex * expopac_deltalambda); return 1e8 * CLIGHT / lambda_lower; } -constexpr auto get_expopac_bin_nu_lower(const size_t binindex) -> double { +constexpr auto get_expopac_bin_nu_lower(const ptrdiff_t binindex) -> double { const auto lambda_upper = expopac_lambdamin + ((binindex + 1) * expopac_deltalambda); return 1e8 * CLIGHT / lambda_upper; } @@ -342,7 +342,7 @@ void electron_scatter_rpkt(Packet &pkt) { p = (mu + 1) + (mu - 1) * (cos(2 * phisc) * Qi + sin(2 * phisc) * Ui); // generate a number between 0 and the maximum of the previous function (2) - x = 2 * rng_uniform(); + x = 2. * rng_uniform(); }; } else { // Assume isotropic scattering @@ -365,13 +365,7 @@ void electron_scatter_rpkt(Packet &pkt) { old_dir_cmf[1] * cos(tsc); new_dir_cmf[2] = sin(tsc) * cos(phisc) * sqrt(1 - pow(old_dir_cmf[2], 2.)) + old_dir_cmf[2] * cos(tsc); } else { - new_dir_cmf[0] = sin(tsc) * cos(phisc); - new_dir_cmf[1] = sin(tsc) * sin(phisc); - if (old_dir_cmf[2] > 0) { - new_dir_cmf[2] = cos(tsc); - } else { - new_dir_cmf[2] = -cos(tsc); - } + new_dir_cmf = {sin(tsc) * cos(phisc), sin(tsc) * sin(phisc), (old_dir_cmf[2] > 0) ? cos(tsc) : -cos(tsc)}; } // Need to rotate Stokes Parameters in the scattering plane @@ -423,7 +417,7 @@ void electron_scatter_rpkt(Packet &pkt) { // Finally we want to put in the rest frame energy and frequency. // And record that it's now a r-pkt. - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; pkt.e_rf = pkt.e_cmf / dopplerfactor; } @@ -431,7 +425,7 @@ void electron_scatter_rpkt(Packet &pkt) { void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const int modelgridindex) { const double nu = pkt.nu_cmf; - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); const double chi_cont = chi_rpkt_cont.total * dopplerfactor; const double chi_escatter = chi_rpkt_cont.ffescat * dopplerfactor; const double chi_ff = chi_rpkt_cont.ffheat * dopplerfactor; @@ -546,9 +540,7 @@ void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const pkt.absorptiontype = pktmastate.activatingline; pkt.absorptionfreq = pkt.nu_rf; - pkt.absorptiondir[0] = pkt.dir[0]; - pkt.absorptiondir[1] = pkt.dir[1]; - pkt.absorptiondir[2] = pkt.dir[2]; + pkt.absorptiondir = pkt.dir; pkt.type = TYPE_MA; if constexpr (TRACK_ION_STATS) { @@ -716,7 +708,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { // At present there is no scattering/destruction process so all that needs to // happen is that we determine whether the packet reaches the boundary during the timestep. - // Find how far it can travel during the time inverval. + // Find how far it can travel during the time interval. const double tdist = (t2 - pkt.prop_time) * CLIGHT_PROP; @@ -735,8 +727,8 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { } else if (thickcell) [[unlikely]] { // In the case of optically thick cells, we treat the packets in grey approximation to speed up the calculation - const double chi_grey = - grid::get_kappagrey(mgi) * grid::get_rho(mgi) * doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double chi_grey = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * + calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); edist = tau_next / chi_grey; pkt.next_trans = -1; @@ -748,7 +740,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { const auto nu_cmf_abort = get_nu_cmf_abort(pkt.pos, pkt.dir, pkt.prop_time, pkt.nu_rf, abort_dist); const auto d_nu_on_d_l = (nu_cmf_abort - pkt.nu_cmf) / abort_dist; - const auto doppler = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const auto doppler = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); if constexpr (EXPANSIONOPACITIES_ON) { std::tie(edist, pkt.next_trans, event_is_boundbound) = get_event_expansion_opacity( @@ -876,8 +868,10 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix assert_always(!USECELLHISTANDUPDATEPHIXSLIST || phixslist != nullptr); double chi_bf_sum = 0.; - if constexpr (USECELLHISTANDUPDATEPHIXSLIST && (USE_LUT_PHOTOION || USE_LUT_BFHEATING)) { - std::ranges::fill(phixslist->groundcont_gamma_contr, 0.); + if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { + if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { + std::ranges::fill(phixslist->groundcont_gamma_contr, 0.); + } } const auto T_e = grid::get_Te(modelgridindex); @@ -921,17 +915,21 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix const int element = globals::allcont[i].element; const int ion = globals::allcont[i].ion; const int level = globals::allcont[i].level; - const auto bfestimindex = globals::allcont[i].bfestimindex; + const auto bfestimindex = + (USECELLHISTANDUPDATEPHIXSLIST && DETAILED_BF_ESTIMATORS_ON) ? globals::allcont[i].bfestimindex : -1; + double sigma_contr = 0.; + // The bf process happens only if the current cell contains // the involved atomic species + const bool should_keep_this_cont = USECELLHISTANDUPDATEPHIXSLIST + ? globals::cellcache[cellcacheslotid].ch_keep_this_cont[i] + : keep_this_cont(element, ion, level, modelgridindex, nnetot); - if ((DETAILED_BF_ESTIMATORS_ON && grid::get_elem_abundance(modelgridindex, element) > 0) || - (!DETAILED_BF_ESTIMATORS_ON && ((get_nnion(modelgridindex, element, ion) / nnetot > 1.e-6) || (level == 0)))) - [[likely]] { + if (should_keep_this_cont) [[likely]] { const double nnlevel = USECELLHISTANDUPDATEPHIXSLIST ? globals::cellcache[cellcacheslotid].ch_allcont_nnlevel[i] : calculate_levelpop(modelgridindex, element, ion, level); - if (nnlevel > 0) { + if (USECELLHISTANDUPDATEPHIXSLIST || nnlevel > 0) { const double nu_edge = globals::allcont[i].nu_edge; const double sigma_bf = photoionization_crosssection_fromtable(globals::allcont[i].photoion_xs, nu_edge, nu); @@ -954,39 +952,22 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix corrfactor = std::max(0., 1 - stimfactor); // photoionisation minus stimulated recombination } - const double sigma_contr = sigma_bf * globals::allcont[i].probability * corrfactor; + sigma_contr = sigma_bf * globals::allcont[i].probability * corrfactor; - if constexpr (USECELLHISTANDUPDATEPHIXSLIST && (USE_LUT_PHOTOION || USE_LUT_BFHEATING)) { - if (level == 0 && globals::allcont[i].phixstargetindex == 0) { + if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { + if ((USE_LUT_PHOTOION || USE_LUT_BFHEATING) && level == 0 && globals::allcont[i].phixstargetindex == 0) { phixslist->groundcont_gamma_contr[globals::allcont[i].index_in_groundphixslist] = sigma_contr; } } - if constexpr (USECELLHISTANDUPDATEPHIXSLIST && DETAILED_BF_ESTIMATORS_ON) { - if (bfestimindex >= 0) { - phixslist->gamma_contr[bfestimindex] = sigma_contr; - } - } - chi_bf_sum += nnlevel * sigma_contr; - if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { - phixslist->chi_bf_sum[i] = chi_bf_sum; - } - } else if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { - // ignore this particular process - phixslist->chi_bf_sum[i] = chi_bf_sum; - if constexpr (DETAILED_BF_ESTIMATORS_ON) { - if (bfestimindex >= 0) { - phixslist->gamma_contr[bfestimindex] = 0.; - } - } } - } else if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { - // no element present or not an important level + } + if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { phixslist->chi_bf_sum[i] = chi_bf_sum; if constexpr (DETAILED_BF_ESTIMATORS_ON) { if (bfestimindex >= 0) { - phixslist->gamma_contr[bfestimindex] = 0.; + phixslist->gamma_contr[bfestimindex] = sigma_contr; } } } @@ -1121,7 +1102,7 @@ __host__ __device__ void emit_rpkt(Packet &pkt) { const auto dir_cmf = get_rand_isotropic_unitvec(); // This direction is in the cmf - we want to convert it to the rest - // frame - use aberation of angles. We want to convert from cmf to + // frame - use aberration of angles. We want to convert from cmf to // rest so need -ve velocity. const auto vel_vec = get_velocity(pkt.pos, -1. * pkt.prop_time); // negative time since we want the backwards transformation here @@ -1132,14 +1113,12 @@ __host__ __device__ void emit_rpkt(Packet &pkt) { // Finally we want to put in the rest frame energy and frequency. And record // that it's now a r-pkt. - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); pkt.nu_rf = pkt.nu_cmf / dopplerfactor; pkt.e_rf = pkt.e_cmf / dopplerfactor; // Reset polarization information - pkt.stokes[0] = 1.; - pkt.stokes[1] = 0.; - pkt.stokes[2] = 0.; + pkt.stokes = {1., 0., 0.}; pkt.pol_dir = cross_prod(pkt.dir, std::array{0., 0., 1.}); @@ -1244,13 +1223,13 @@ void calculate_expansion_opacities(const int modelgridindex) { // find the first line with nu below the upper limit of the first bin int lineindex = static_cast( - std::lower_bound(&globals::linelist[0], &globals::linelist[globals::nlines], get_expopac_bin_nu_upper(0), + std::lower_bound(globals::linelist, globals::linelist + globals::nlines, get_expopac_bin_nu_upper(0), [](const auto &line, const double nu_cmf) -> bool { return line.nu > nu_cmf; }) - globals::linelist); double kappa_planck_cumulative = 0.; - for (size_t binindex = 0; binindex < expopac_nbins; binindex++) { + for (ptrdiff_t binindex = 0; binindex < expopac_nbins; binindex++) { double bin_linesum = 0.; const auto nu_upper = get_expopac_bin_nu_upper(binindex); diff --git a/rpkt.h b/rpkt.h index 723d25911..88bb0aa4c 100644 --- a/rpkt.h +++ b/rpkt.h @@ -69,4 +69,12 @@ void MPI_Bcast_binned_opacities(int modelgridindex, int root_node_id); return nonemptymgi * globals::nbfcontinua_ground + groundcontindex; } +inline auto keep_this_cont(int element, const int ion, const int level, const int modelgridindex, + const float nnetot) -> bool { + if constexpr (DETAILED_BF_ESTIMATORS_ON) { + return grid::get_elem_abundance(modelgridindex, element) > 0; + } + return ((get_nnion(modelgridindex, element, ion) / nnetot > 1.e-6) || (level == 0)); +} + #endif // RPKT_H diff --git a/sn3d.cc b/sn3d.cc index a2f8907dd..4ed7b98bc 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -191,9 +191,9 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c const double total_dep = (globals::timesteps[i].gamma_dep + globals::timesteps[i].positron_dep + globals::timesteps[i].electron_dep + globals::timesteps[i].alpha_dep); - const double epsilon = (globals::timesteps[i].gamma_emission + globals::timesteps[i].positron_emission + - globals::timesteps[i].electron_emission + globals::timesteps[i].alpha_emission) / - mtot / t_width; + const double epsilon_tot = (globals::timesteps[i].gamma_emission + globals::timesteps[i].positron_emission + + globals::timesteps[i].electron_emission + globals::timesteps[i].alpha_emission) / + mtot / t_width; fprintf(dep_file, "%d %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n", i, t_mid / DAY, t_mid, total_dep / t_width / LSUN, globals::timesteps[i].gamma_dep_discrete / t_width / LSUN, @@ -203,7 +203,7 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c globals::timesteps[i].eps_electron_ana_power / LSUN, globals::timesteps[i].alpha_dep / t_width / LSUN, globals::timesteps[i].alpha_emission / t_width / LSUN, globals::timesteps[i].eps_alpha_ana_power / LSUN, globals::timesteps[i].gamma_emission / t_width / LSUN, globals::timesteps[i].qdot_betaminus / mtot, - globals::timesteps[i].qdot_alpha / mtot, epsilon, globals::timesteps[i].qdot_total / mtot, + globals::timesteps[i].qdot_alpha / mtot, epsilon_tot, globals::timesteps[i].qdot_total / mtot, globals::timesteps[i].positron_dep_discrete / t_width / LSUN, globals::timesteps[i].electron_dep_discrete / t_width / LSUN, globals::timesteps[i].alpha_dep_discrete / t_width / LSUN); @@ -455,7 +455,7 @@ void write_temp_packetsfile(const int timestep, const int my_rank, const Packet printout("Writing %s...", filename); FILE *packets_file = fopen(filename, "wb"); if (packets_file == nullptr) { - printout("ERROR: Could not open file '%s' for mode 'wb'. \n", filename); + printout("ERROR: Could not open file '%s' for mode 'wb'.\n", filename); write_success = false; } else { write_success = @@ -532,8 +532,8 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe MPI_Barrier(MPI_COMM_WORLD); #endif - bool write_verified_sucess = false; - while (!write_verified_sucess) { + bool write_verified_success = false; + while (!write_verified_success) { const auto time_write_packets_file_start = std::time(nullptr); printout("time before write temporary packets file %ld\n", time_write_packets_file_start); @@ -561,7 +561,7 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe printout("reading back temporary packets file to check validity...\n"); // read packets file back to check that the disk write didn't fail - write_verified_sucess = verify_temp_packetsfile(nts, my_rank, packets); + write_verified_success = verify_temp_packetsfile(nts, my_rank, packets); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); @@ -734,7 +734,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns std::time(nullptr), std::time(nullptr) - time_communicate_estimators_start); #endif - // The estimators have been summed across all proceses and distributed. + // The estimators have been summed across all processes and distributed. // They will now be normalised independently on all processes. normalise_deposition_estimators(nts); @@ -747,11 +747,11 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns globals::timesteps[nts].pellet_decays, globals::nesc, globals::timesteps[nts].mid / DAY); if (VPKT_ON) { - printout("During timestep %d on MPI process %d, %d virtual packets were generated and %d escaped. \n", nts, + printout("During timestep %d on MPI process %d, %d virtual packets were generated and %d escaped.\n", nts, my_rank, nvpkt, nvpkt_esc1 + nvpkt_esc2 + nvpkt_esc3); printout( "%d virtual packets came from an electron scattering event, %d from a kpkt deactivation and %d from a " - "macroatom deactivation. \n", + "macroatom deactivation.\n", nvpkt_esc1, nvpkt_esc2, nvpkt_esc3); nvpkt = 0; diff --git a/sn3d.h b/sn3d.h index fcffeefae..ddd785109 100644 --- a/sn3d.h +++ b/sn3d.h @@ -1,4 +1,5 @@ #pragma once +#include #ifndef SN3D_H #define SN3D_H @@ -81,12 +82,10 @@ inline tm timebuf{}; #define USE_SIMPSON_INTEGRATOR false #endif -inline void nop(gsl_integration_workspace *w) {}; - inline thread_local auto gslworkspace = std::unique_ptr{ USE_SIMPSON_INTEGRATOR ? nullptr : gsl_integration_workspace_alloc(GSLWSIZE), - USE_SIMPSON_INTEGRATOR ? nop : gsl_integration_workspace_free}; + USE_SIMPSON_INTEGRATOR ? [](gsl_integration_workspace *const w) {} : gsl_integration_workspace_free}; #ifdef _OPENMP @@ -315,16 +314,19 @@ inline void check_already_running() { #endif } -template - requires std::is_integral::value -constexpr auto get_range_chunk(const T size, const auto nchunks_in, const auto nchunk_in) -> std::tuple { - const auto nchunks = static_cast(nchunks_in); - const auto nchunk = static_cast(nchunk_in); +constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, + const ptrdiff_t nchunk) -> std::tuple { + assert_always(size >= 0); + assert_always(nchunks >= 0); + assert_always(nchunk >= 0); const auto minchunksize = size / nchunks; // integer division, minimum non-empty cells per process const auto n_remainder = size % nchunks; const auto nstart = (minchunksize + 1) * std::min(n_remainder, nchunk) + - minchunksize * std::max(static_cast(0), nchunk - n_remainder); + minchunksize * std::max(static_cast(0), nchunk - n_remainder); const auto nsize = (nchunk < n_remainder) ? minchunksize + 1 : minchunksize; + assert_testmodeonly(nstart >= 0); + assert_testmodeonly(nsize >= 0); + assert_testmodeonly((nstart + nsize) <= size); return std::tuple{nstart, nsize}; } diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 79ae146b5..e9806807b 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -1,14 +1,14 @@ #include "spectrum_lightcurve.h" -#ifdef MPI_ON -#include -#endif - #include #include +#include #include #include #include +#ifdef MPI_ON +#include +#endif #include #include #include @@ -417,7 +417,7 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss const int proccount = get_proccount(); const int ioncount = get_nelements() * get_max_nions(); assert_always(stokes_i->lower_freq.size() == stokes_i->delta_freq.size()); - for (size_t m = 0; m < stokes_i->lower_freq.size(); m++) { + for (ptrdiff_t m = 0; m < std::ssize(stokes_i->lower_freq); m++) { fprintf(specpol_file, "%g ", ((stokes_i->lower_freq[m] + (stokes_i->delta_freq[m] / 2)))); // Stokes I @@ -513,7 +513,7 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co spectra.lower_freq.resize(MNUBINS); spectra.delta_freq.resize(spectra.lower_freq.size()); - for (size_t nnu = 0; nnu < spectra.lower_freq.size(); nnu++) { + for (ptrdiff_t nnu = 0; nnu < std::ssize(spectra.lower_freq); nnu++) { spectra.lower_freq[nnu] = exp(log(nu_min) + (nnu * (dlognu))); spectra.delta_freq[nnu] = exp(log(nu_min) + ((nnu + 1) * (dlognu))) - spectra.lower_freq[nnu]; } @@ -546,7 +546,7 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co std::ranges::fill(spectra.emissionalltimesteps, 0.0); std::ranges::fill(spectra.trueemissionalltimesteps, 0.0); - for (size_t nts = 0; nts < spectra.timesteps.size(); nts++) { + for (ptrdiff_t nts = 0; nts < std::ssize(spectra.timesteps); nts++) { spectra.timesteps[nts].absorption = &spectra.absorptionalltimesteps[nts * MNUBINS * get_nelements() * get_max_nions()]; spectra.timesteps[nts].emission = &spectra.emissionalltimesteps[nts * MNUBINS * proccount]; diff --git a/thermalbalance.cc b/thermalbalance.cc index be99d0966..8e3dab343 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -76,11 +76,10 @@ auto calculate_bfheatingcoeff(const int element, const int ion, const int level, // const double sf_Te = calculate_sahafact(element,ion,level,upperionlevel,T_e,E_threshold); // const double sf_TR = calculate_sahafact(element,ion,level,upperionlevel,T_R,E_threshold); - const gsl_integral_paras_bfheating intparas = { - .nu_edge = nu_threshold, - .modelgridindex = modelgridindex, - .T_R = grid::get_TR(modelgridindex), - .photoion_xs = globals::elements[element].ions[ion].levels[level].photoion_xs}; + const gsl_integral_paras_bfheating intparas = {.nu_edge = nu_threshold, + .modelgridindex = modelgridindex, + .T_R = grid::get_TR(modelgridindex), + .photoion_xs = get_phixs_table(element, ion, level)}; // intparas.Te_TR_factor = sqrt(T_e/T_R) * sf_Te / sf_TR; diff --git a/update_grid.cc b/update_grid.cc index a42c49131..9a7fb3226 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -688,7 +688,7 @@ void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, cons calculate_bfheatingcoeffs(mgi, bfheatingcoeffs); printout("took %ld seconds\n", std::time(nullptr) - sys_time_start_calculate_bfheatingcoeffs); - const double covergence_tolerance = 0.04; + const double convergence_tolerance = 0.04; for (int nlte_iter = 0; nlte_iter <= NLTEITER; nlte_iter++) { const auto sys_time_start_spencerfano = std::time(nullptr); if (NT_ON && NT_SOLVE_SPENCERFANO) { @@ -760,11 +760,11 @@ void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, cons "%g, new nne is %g, fracdiff %g, prev T_e %g new T_e %g fracdiff %g\n", mgi, nts, nlte_iter, nne_prev, grid::get_nne(mgi), fracdiff_nne, prev_T_e, grid::get_Te(mgi), fracdiff_T_e); - if (fracdiff_nne <= covergence_tolerance && fracdiff_T_e <= covergence_tolerance) { + if (fracdiff_nne <= convergence_tolerance && fracdiff_T_e <= convergence_tolerance) { printout( "NLTE (Spencer-Fano/Te/pops) solver nne converged to tolerance %g <= %g and T_e to " "tolerance %g <= %g after %d iterations.\n", - fracdiff_nne, covergence_tolerance, fracdiff_T_e, covergence_tolerance, nlte_iter + 1); + fracdiff_nne, convergence_tolerance, fracdiff_T_e, convergence_tolerance, nlte_iter + 1); break; } if (nlte_iter == NLTEITER) { @@ -1160,11 +1160,11 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const } // end OpenMP parallel section - // Now after all the relevant taks of update_grid have been finished activate + // Now after all the relevant tasks of update_grid have been finished activate // the use of the cellcache for all OpenMP tasks, in what follows (update_packets) use_cellcache = true; - // alterative way to write out estimators. this keeps the modelgrid cells in order but + // alternative way to write out estimators. this keeps the modelgrid cells in order but // heatingrates are not valid. #ifdef _OPENMP for (int n = nstart; n < nstart+nblock; n++) // { // write_to_estimators_file(n,nts); @@ -1242,11 +1242,14 @@ void cellcache_change_cell(const int modelgridindex) { if (modelgridindex >= 0) { std::ranges::fill(cacheslot.ch_allcont_departureratios, -1.); + const auto nnetot = grid::get_nnetot(modelgridindex); for (int i = 0; i < globals::nbfcontinua; i++) { const int element = globals::allcont[i].element; const int ion = globals::allcont[i].ion; const int level = globals::allcont[i].level; - cacheslot.ch_allcont_nnlevel[i] = get_levelpop(modelgridindex, element, ion, level); + const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); + cacheslot.ch_allcont_nnlevel[i] = nnlevel; + cacheslot.ch_keep_this_cont[i] = nnlevel > 0 && keep_this_cont(element, ion, level, modelgridindex, nnetot); } } } diff --git a/update_packets.cc b/update_packets.cc index 196eb706d..f1af51f1f 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -44,7 +44,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double prefactor = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 7.74 : 7.4; const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * std::pow((0.2 * 29979200000) / v_ej, 3. / 2.); - const double f_p = std::log(1 + (2. * ts * ts / tau_ineff / tau_ineff)) / (2. * ts * ts / tau_ineff / tau_ineff); + const double f_p = std::log1p(2. * ts * ts / tau_ineff / tau_ineff) / (2. * ts * ts / tau_ineff / tau_ineff); assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { @@ -60,7 +60,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double aux_term = 2 * A / (ts * grid::get_rho(mgi)); // In Bulla 2023 (arXiv:2211.14348), the following line contains (<-> eq. 7) contains a typo. The way implemented // here is the original from Wollaeger paper without the typo - const double f_p = std::log(1. + aux_term) / aux_term; + const double f_p = std::log1p(aux_term) / aux_term; assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { @@ -80,14 +80,10 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const double particle_en = H * pkt.nu_cmf; // energy of the particles in the packet - // for endot independent of energy, the next line is trival (for E dependent endot, an integral would be needed) + // for endot independent of energy, the next line is trivial (for E dependent endot, an integral would be needed) const double t_enzero = ts + (particle_en / endot); // time at which zero energy is reached - if (t_enzero > t2) { - en_deposited = pkt.e_cmf * (t2 - ts) / (particle_en / endot); - } else { - en_deposited = pkt.e_cmf * (t_enzero - ts) / (particle_en / endot); - } + en_deposited = pkt.e_cmf * (std::min(t2, t_enzero) - ts) / (particle_en / endot); // A discrete absorption event should occur somewhere along the // continuous track from initial kinetic energy to zero KE. diff --git a/vectors.h b/vectors.h index 5486046b4..378ba8a0f 100644 --- a/vectors.h +++ b/vectors.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "constants.h" @@ -16,14 +15,14 @@ // return the the magnitude of a vector template -[[nodiscard]] [[gnu::const]] constexpr auto vec_len(const std::array vec) -> double { +[[nodiscard]] constexpr auto vec_len(const std::array &vec) -> double { const double squaredlen = std::accumulate(vec.begin(), vec.end(), 0., [](auto a, auto b) { return a + b * b; }); return std::sqrt(squaredlen); } // get a normalized copy of vec_in -[[nodiscard]] [[gnu::const]] constexpr auto vec_norm(const std::array vec_in) { +[[nodiscard]] constexpr auto vec_norm(const std::array &vec_in) { const double magnitude = vec_len(vec_in); const std::array vec_out{vec_in[0] / magnitude, vec_in[1] / magnitude, vec_in[2] / magnitude}; @@ -33,35 +32,32 @@ template // vector dot product template -[[nodiscard]] [[gnu::const]] constexpr auto dot(const std::array x, - const std::array y) -> double { +[[nodiscard]] constexpr auto dot(const std::array &x, const std::array &y) -> double { // if len(x) < len(y), the extra elements of y are ignored return std::inner_product(x.begin(), x.end(), y.begin(), 0.); } // Get velocity vector of the flow at a position with homologous expansion. -[[nodiscard]] [[gnu::pure]] constexpr auto get_velocity(std::span x, - const double t) -> std::array { +[[nodiscard]] constexpr auto get_velocity(const std::array &x, const double t) -> std::array { return std::array{x[0] / t, x[1] / t, x[2] / t}; } -[[nodiscard]] [[gnu::const]] constexpr auto cross_prod(const std::array vec_a, - const std::array vec_b) { +[[nodiscard]] constexpr auto cross_prod(const std::array &vec_a, const std::array &vec_b) { return std::array{(vec_a[1] * vec_b[2]) - (vec_b[1] * vec_a[2]), (vec_a[2] * vec_b[0]) - (vec_b[2] * vec_a[0]), (vec_a[0] * vec_b[1]) - (vec_b[0] * vec_a[1])}; } -[[nodiscard]] [[gnu::const]] constexpr auto vec_scale(const std::array vec, const double scalefactor) { +[[nodiscard]] constexpr auto vec_scale(const std::array &vec, const double scalefactor) { return std::array{vec[0] * scalefactor, vec[1] * scalefactor, vec[2] * scalefactor}; } -// aberation of angles in special relativity +// aberration of angles in special relativity // dir1: direction unit vector in frame1 // vel: velocity of frame2 relative to frame1 // dir2: direction vector in frame2 -[[nodiscard]] [[gnu::const]] constexpr auto angle_ab(const std::array dir1, - const std::array vel) -> std::array { +[[nodiscard]] constexpr auto angle_ab(const std::array &dir1, + const std::array &vel) -> std::array { const double vsqr = dot(vel, vel) / CLIGHTSQUARED; const double gamma_rel = 1. / std::sqrt(1 - vsqr); @@ -75,44 +71,15 @@ template return vec_norm(dir2); } -// Doppler factor -// arguments: -// dir_rf: the rest frame direction (unit vector) of light propagation -// vel_rf: velocity of the comoving frame relative to the rest frame -// returns: the ratio f = nu_cmf / nu_rf -[[gnu::const]] [[nodiscard]] constexpr auto doppler_nucmf_on_nurf(const std::array dir_rf, - const std::array vel_rf) -> double { - assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED >= 0.); - assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED < 1.); - - const double ndotv = dot(dir_rf, vel_rf); - double dopplerfactor = 1. - (ndotv / CLIGHT); - - if (USE_RELATIVISTIC_DOPPLER_SHIFT) { - const double betasq = dot(vel_rf, vel_rf) / CLIGHTSQUARED; - assert_testmodeonly(betasq >= 0.); // v < c - assert_testmodeonly(betasq < 1.); // v < c - dopplerfactor = dopplerfactor / std::sqrt(1 - betasq); - } - - assert_testmodeonly(std::isfinite(dopplerfactor)); - assert_testmodeonly(dopplerfactor > 0); - - return dopplerfactor; -} - -[[gnu::const]] [[nodiscard]] constexpr auto doppler_squared_nucmf_on_nurf(const std::array &pos_rf, - const std::array dir_rf, - const double prop_time) -> double -// Doppler factor squared, either to first order v/c or fully relativisitic -// depending on USE_RELATIVISTIC_DOPPLER_SHIFT -// -// arguments: +// Doppler factor squared, either to first order v/c or fully relativisitic depending on USE_RELATIVISTIC_DOPPLER_SHIFT +// Arguments: // pos_rf: the rest frame position of the packet // dir_rf: the rest frame direction (unit vector) of light propagation // prop_time: the propagation time of the packet // returns: the ratio f = (nu_cmf / nu_rf) ^ 2 -{ +[[nodiscard]] constexpr auto doppler_squared_nucmf_on_nurf(const std::array &pos_rf, + const std::array &dir_rf, + const double prop_time) -> double { // velocity of the comoving frame relative to the rest frame const auto vel_rf = get_velocity(pos_rf, prop_time); @@ -130,14 +97,39 @@ template return dopplerfactorsq; } -[[gnu::pure]] [[nodiscard]] constexpr auto doppler_packet_nucmf_on_nurf(const std::span pos_rf, - const std::array dir_rf, - const double prop_time) -> double { - return doppler_nucmf_on_nurf(dir_rf, get_velocity(pos_rf, prop_time)); +// Doppler factor either to first order v/c or fully relativisitic depending on USE_RELATIVISTIC_DOPPLER_SHIFT +// Arguments: +// pos_rf: the rest frame position of the packet +// dir_rf: the rest frame direction (unit vector) of light propagation +// prop_time: the propagation time of the packet +// returns: the ratio f = nu_cmf / nu_rf +[[nodiscard]] constexpr auto calculate_doppler_nucmf_on_nurf(const std::array &pos_rf, + const std::array &dir_rf, + const double prop_time) -> double { + // velocity of the comoving frame relative to the rest frame + const auto vel_rf = get_velocity(pos_rf, prop_time); + + assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED >= 0.); + assert_testmodeonly(dot(vel_rf, vel_rf) / CLIGHTSQUARED < 1.); + + const double ndotv = dot(dir_rf, vel_rf); + double dopplerfactor = 1. - (ndotv / CLIGHT); + + if (USE_RELATIVISTIC_DOPPLER_SHIFT) { + const double betasq = dot(vel_rf, vel_rf) / CLIGHTSQUARED; + assert_testmodeonly(betasq >= 0.); // v < c + assert_testmodeonly(betasq < 1.); // v < c + dopplerfactor = dopplerfactor / std::sqrt(1 - betasq); + } + + assert_testmodeonly(std::isfinite(dopplerfactor)); + assert_testmodeonly(dopplerfactor > 0); + + return dopplerfactor; } // Move a packet along a straight line (specified by current dir vector). The distance moved is in the rest frame. -constexpr auto move_pkt_withtime(std::array &pos_rf, const std::array dir_rf, double &prop_time, +constexpr auto move_pkt_withtime(std::array &pos_rf, const std::array &dir_rf, double &prop_time, const double nu_rf, double &nu_cmf, const double e_rf, double &e_cmf, const double distance) -> double { assert_always(distance >= 0); @@ -151,7 +143,7 @@ constexpr auto move_pkt_withtime(std::array &pos_rf, const std::array // During motion, rest frame energy and frequency are conserved. // But need to update the co-moving ones. - const double dopplerfactor = doppler_packet_nucmf_on_nurf(pos_rf, dir_rf, prop_time); + const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pos_rf, dir_rf, prop_time); nu_cmf = nu_rf * dopplerfactor; e_cmf = e_rf * dopplerfactor; @@ -167,7 +159,7 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return move_pkt_withtime(pkt.pos, pkt.dir, pkt.prop_time, pkt.nu_rf, pkt.nu_cmf, pkt.e_rf, pkt.e_cmf, distance); } -[[nodiscard]] [[gnu::const]] constexpr auto get_arrive_time(const Packet &pkt) -> double +[[nodiscard]] constexpr auto get_arrive_time(const Packet &pkt) -> double // We know that a packet escaped at "escape_time". However, we have // to allow for travel time. Use the formula in Leon's paper. The extra // distance to be travelled beyond the reference surface is ds = r_ref (1 - mu). @@ -175,8 +167,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return pkt.escape_time - (dot(pkt.pos, pkt.dir) / CLIGHT_PROP); } -[[nodiscard]] [[gnu::const]] constexpr auto get_escapedirectionbin(const std::array dir_in, - const std::array syn_dir) -> int { +[[nodiscard]] constexpr auto get_escapedirectionbin(const std::array &dir_in, + const std::array &syn_dir) -> int { constexpr auto xhat = std::array{1.0, 0.0, 0.0}; // sometimes dir vectors aren't accurately normalised @@ -220,10 +212,9 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { } // Rotation angle from the scattering plane -[[nodiscard]] [[gnu::const]] constexpr auto get_rot_angle(const std::array n1, - const std::array n2, - const std::array ref1, - const std::array ref2) -> double { +[[nodiscard]] constexpr auto get_rot_angle(const std::array &n1, const std::array &n2, + const std::array &ref1, + const std::array &ref2) -> double { // We need to rotate Stokes Parameters to (or from) the scattering plane from (or to) // the meridian frame such that Q=1 is in the scattering plane and along ref1 @@ -256,7 +247,7 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { } // Routine to compute the meridian frame axes ref1 and ref2 -[[nodiscard]] [[gnu::const]] constexpr auto meridian(const std::array n) +[[nodiscard]] constexpr auto meridian(const std::array &n) -> std::tuple, std::array> { // for ref_1 use (from triple product rule) const double n_xylen = std::sqrt(n[0] * n[0] + n[1] * n[1]); @@ -268,8 +259,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return {ref1, ref2}; } -[[nodiscard]] [[gnu::const]] constexpr auto lorentz(const std::array e_rf, const std::array n_rf, - const std::array v) -> std::array { +[[nodiscard]] constexpr auto lorentz(const std::array &e_rf, const std::array &n_rf, + const std::array &v) -> std::array { // Use Lorentz transformations to get e_cmf from e_rf const auto beta = std::array{v[0] / CLIGHT, v[1] / CLIGHT, v[2] / CLIGHT}; @@ -301,8 +292,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { } // Routine to transform the Stokes Parameters from RF to CMF -constexpr auto frame_transform(const std::array n_rf, double *Q, double *U, - const std::array v) -> std::array { +constexpr auto frame_transform(const std::array &n_rf, double *Q, double *U, + const std::array &v) -> std::array { // Meridian frame in the RF const auto [ref1_rf, ref2_rf] = meridian(n_rf); diff --git a/vpkt.cc b/vpkt.cc index 0f32febe1..1f254a989 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -111,8 +111,8 @@ void add_to_vspecpol(const Packet &vpkt, const int obsdirindex, const int opacho } // Routine to add a packet to the outcoming spectrum. -void add_to_vpkt_grid(const Packet &vpkt, const std::array vel, const int wlbin, const int obsdirindex, - const std::array obs) { +void add_to_vpkt_grid(const Packet &vpkt, const std::array &vel, const int wlbin, const int obsdirindex, + const std::array &obs) { double vref1{NAN}; double vref2{NAN}; @@ -160,7 +160,7 @@ void add_to_vpkt_grid(const Packet &vpkt, const std::array vel, const } auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_arrive, const double nu_rf, - const double e_rf, const int obsdirindex, const std::array obsdir, + const double e_rf, const int obsdirindex, const std::array &obsdir, const enum packet_type type_before_rpkt, std::stringstream &vpkt_contrib_row) -> bool { int mgi = 0; @@ -171,7 +171,6 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar vpkt.last_cross = BOUNDARY_NONE; bool end_packet = false; - double ldist = 0; double t_future = t_current; for (int opacindex = 0; opacindex < Nspectra; opacindex++) { @@ -187,7 +186,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar // ------------ SCATTERING EVENT: dipole function -------------------- double pn{NAN}; - double I{NAN}; + constexpr double I = 1.; double Q{NAN}; double U{NAN}; if (type_before_rpkt == TYPE_RPKT) { @@ -218,12 +217,8 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar pn = 3. / (16. * PI) * (1 + pow(mu, 2.) + (pow(mu, 2.) - 1) * Qold); const double Inew = 0.75 * ((mu * mu + 1.0) + Qold * (mu * mu - 1.0)); - double Qnew = 0.75 * ((mu * mu - 1.0) + Qold * (mu * mu + 1.0)); - double Unew = 1.5 * mu * Uold; - - Qnew = Qnew / Inew; - Unew = Unew / Inew; - I = Inew / Inew; + const double Qnew = (0.75 * ((mu * mu - 1.0) + Qold * (mu * mu + 1.0))) / Inew; + const double Unew = (1.5 * mu * Uold) / Inew; // Need to rotate Stokes Parameters out of the scattering plane to the meridian frame @@ -247,7 +242,6 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar } else if (type_before_rpkt == TYPE_KPKT || type_before_rpkt == TYPE_MA) { // MACROATOM and KPKT: isotropic emission - I = 1; Q = 0; U = 0; pn = 1 / (4 * PI); @@ -297,7 +291,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar assert_testmodeonly(nu_cmf_abort <= vpkt.nu_cmf); const double d_nu_on_d_l = (nu_cmf_abort - vpkt.nu_cmf) / sdist; - ldist = 0; + double ldist = 0; while (ldist < sdist) { const int lineindex = closest_transition(vpkt.nu_cmf, vpkt.next_trans); @@ -389,9 +383,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar assert_always(std::isfinite(prob)); - vpkt.stokes[0] = I * prob; - vpkt.stokes[1] = Q * prob; - vpkt.stokes[2] = U * prob; + vpkt.stokes = {I * prob, Q * prob, U * prob}; for (const auto stokeval : vpkt.stokes) { assert_always(std::isfinite(stokeval)); @@ -409,9 +401,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar if (vgrid_on) { const double prob = pn * exp(-tau_vpkt[0]); - vpkt.stokes[0] = I * prob; - vpkt.stokes[1] = Q * prob; - vpkt.stokes[2] = U * prob; + vpkt.stokes = {I * prob, Q * prob, U * prob}; for (int wlbin = 0; wlbin < Nrange_grid; wlbin++) { if (vpkt.nu_rf > nu_grid_min[wlbin] && vpkt.nu_rf < nu_grid_max[wlbin]) { // Frequency selection @@ -425,11 +415,11 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar } void init_vspecpol() { - vspecpol.resize(VMTBINS); + vspecpol.resize(VMTBINS, {}); const int indexmax = Nspectra * Nobs; for (int p = 0; p < VMTBINS; p++) { - vspecpol[p].resize(indexmax); + vspecpol[p].resize(indexmax, {}); } for (int m = 0; m < VMNUBINS; m++) { @@ -602,12 +592,12 @@ void read_vpkt_grid(const int my_rank, const int nts) { } // anonymous namespace void vpkt_remove_temp_file(const int nts, const int my_rank) { - char filenames[3][MAXFILENAMELENGTH]; + std::array filenames{}; snprintf(filenames[0], MAXFILENAMELENGTH, "vspecpol_%.4d_ts%d.tmp", my_rank, nts); snprintf(filenames[1], MAXFILENAMELENGTH, "vpkt_grid_%.4d_ts%d.tmp", my_rank, nts); snprintf(filenames[2], MAXFILENAMELENGTH, "vpackets_%.4d_ts%d.tmp", my_rank, nts); - for (const auto &filename : filenames) { + for (const auto *filename : filenames) { if (std::filesystem::exists(filename)) { std::remove(filename); printout("Deleted %s\n", filename); @@ -744,10 +734,10 @@ void read_parameterfile_vpkt() { } // if dum7=1, vpkt are not created when cell optical depth is larger than cell_is_optically_thick_vpkt - int overrride_thickcell_tau = 0; - assert_always(fscanf(input_file, "%d %lg \n", &overrride_thickcell_tau, &cell_is_optically_thick_vpkt) == 2); + int override_thickcell_tau = 0; + assert_always(fscanf(input_file, "%d %lg \n", &override_thickcell_tau, &cell_is_optically_thick_vpkt) == 2); - if (overrride_thickcell_tau == 1) { + if (override_thickcell_tau == 1) { printout("vpkt.txt: cell_is_optically_thick_vpkt %lg\n", cell_is_optically_thick_vpkt); } else { cell_is_optically_thick_vpkt = globals::cell_is_optically_thick; @@ -903,7 +893,7 @@ void vpkt_init(const int nts, const int my_rank, const bool continued_from_saved } } -auto vpkt_call_estimators(Packet &pkt, const enum packet_type type_before_rpkt) -> void { +auto vpkt_call_estimators(const Packet &pkt, const enum packet_type type_before_rpkt) -> void { if constexpr (!VPKT_ON) { return; } @@ -917,8 +907,6 @@ auto vpkt_call_estimators(Packet &pkt, const enum packet_type type_before_rpkt) const double t_current = pkt.prop_time; - const auto vel_vec = get_velocity(pkt.pos, pkt.prop_time); - std::stringstream vpkt_contrib_row; bool any_dir_escaped = false; @@ -936,7 +924,7 @@ auto vpkt_call_estimators(Packet &pkt, const enum packet_type type_before_rpkt) if (t_arrive >= VSPEC_TIMEMIN_input && t_arrive <= VSPEC_TIMEMAX_input) { // time selection - const double doppler = doppler_nucmf_on_nurf(obsdir, vel_vec); + const double doppler = calculate_doppler_nucmf_on_nurf(pkt.pos, obsdir, pkt.prop_time); const double nu_rf = pkt.nu_cmf / doppler; const double e_rf = pkt.e_cmf / doppler; diff --git a/vpkt.h b/vpkt.h index e78a77dde..a1eb72e43 100644 --- a/vpkt.h +++ b/vpkt.h @@ -7,7 +7,7 @@ void read_parameterfile_vpkt(); void vpkt_init(int nts, int my_rank, bool continued_from_saved); -void vpkt_call_estimators(Packet &pkt, enum packet_type type_before_rpkt); +void vpkt_call_estimators(const Packet &pkt, enum packet_type type_before_rpkt); void vpkt_write_timestep(int nts, int my_rank, bool is_final); void vpkt_remove_temp_file(int nts, int my_rank); From fd797635c58a93d1ff3dd79866e3496ebcb454d1 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 3 Sep 2024 21:11:41 +0100 Subject: [PATCH 037/117] Default off for VERIFY_WRITTEN_PACKETS_FILES (#122) --- sn3d.cc | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/sn3d.cc b/sn3d.cc index 4ed7b98bc..ed1f306ac 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -65,6 +65,7 @@ std::mt19937 stdrng{std::random_device{}()}; std::ofstream output_file; namespace { +constexpr bool VERIFY_WRITTEN_PACKETS_FILES = false; FILE *linestat_file{}; auto real_time_start = -1; @@ -532,8 +533,8 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe MPI_Barrier(MPI_COMM_WORLD); #endif - bool write_verified_success = false; - while (!write_verified_success) { + bool write_successful = false; + while (!write_successful) { const auto time_write_packets_file_start = std::time(nullptr); printout("time before write temporary packets file %ld\n", time_write_packets_file_start); @@ -542,33 +543,38 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe vpkt_write_timestep(nts, my_rank, false); - const auto time_write_packets_file_finished = std::time(nullptr); + const auto time_write_packets_finished_thisrank = std::time(nullptr); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif + const auto timenow = std::time(nullptr); - printout("time after write temporary packets file %ld (took %ld seconds, waited %ld s for other ranks)\n", - std::time(nullptr), time_write_packets_file_finished - time_write_packets_file_start, - std::time(nullptr) - time_write_packets_file_finished); + printout("time after write temporary packets file %ld (took %lds, waited %lds, total %lds)\n", timenow, + time_write_packets_finished_thisrank - time_write_packets_file_start, + timenow - time_write_packets_finished_thisrank, timenow - time_write_packets_file_start); + if constexpr (VERIFY_WRITTEN_PACKETS_FILES) { #ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); + MPI_Barrier(MPI_COMM_WORLD); #endif - const auto time_readback_packets_start = std::time(nullptr); + const auto time_readback_packets_start = std::time(nullptr); - printout("reading back temporary packets file to check validity...\n"); + printout("reading back temporary packets file to check validity...\n"); - // read packets file back to check that the disk write didn't fail - write_verified_success = verify_temp_packetsfile(nts, my_rank, packets); + // read packets file back to check that the disk write didn't fail + write_successful = verify_temp_packetsfile(nts, my_rank, packets); #ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); + MPI_Barrier(MPI_COMM_WORLD); #endif - printout("Verifying packets files for all ranks took %ld seconds.\n", - std::time(nullptr) - time_readback_packets_start); + printout("Verifying packets files for all ranks took %ld seconds.\n", + std::time(nullptr) - time_readback_packets_start); + } else { + write_successful = true; + } } if (my_rank == 0) { From 718f3ee3b8c445097e016bd06dc47f49cd865c5d Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 4 Sep 2024 08:44:29 +0100 Subject: [PATCH 038/117] Disable assertion for duplicate transitions on input (tripped on classic dataset) --- input.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/input.cc b/input.cc index b86106ef0..bcd192f6f 100644 --- a/input.cc +++ b/input.cc @@ -609,14 +609,22 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons const int nupperdowntrans = get_ndowntrans(element, ion, level); auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans]; - assert_always(downtransition.targetlevelindex == lowerlevel); + + // this is what classic did, but it is not quite correct. The downtrans list should be searched to find the + // correct index, not just using the last one. It probably works for the case where the transitions are sorted, + // but the assertion tripped on C IV in the classic dataset. + // assert_always(downtransition.targetlevelindex == lowerlevel); + downtransition.einstein_A += transition.A; downtransition.osc_strength += f_ul; downtransition.coll_str = std::max(downtransition.coll_str, transition.coll_str); const int nloweruptrans = get_nuptrans(element, ion, lowerlevel); auto &uptransition = globals::elements[element].ions[ion].levels[lowerlevel].uptrans[nloweruptrans]; - assert_always(uptransition.targetlevelindex == level); + + // as above, the downtrans list should be searched to find the correct index instead of using the last one. + // assert_always(uptransition.targetlevelindex == level); + uptransition.einstein_A += transition.A; uptransition.osc_strength += f_ul; uptransition.coll_str = std::max(uptransition.coll_str, transition.coll_str); From 29ccf5ad1ba99c269a9685bd8250db364f0587ea Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 4 Sep 2024 08:49:08 +0100 Subject: [PATCH 039/117] Fix clang-tidy 19 warnings --- .clang-tidy | 2 ++ input.cc | 4 ++-- packet.h | 2 +- ratecoeff.h | 4 ++-- rpkt.h | 2 +- sn3d.h | 6 +++--- vectors.h | 23 ++++++++++++----------- 7 files changed, 23 insertions(+), 20 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 5573209cd..4db7639c9 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -12,6 +12,7 @@ Checks: > -bugprone-easily-swappable-parameters, -bugprone-exception-escape, -bugprone-implicit-widening-of-multiplication-result, + -bugprone-multi-level-implicit-pointer-conversion, -bugprone-narrowing-conversions, -boost-use-ranges, -llvmlibc-*, @@ -39,6 +40,7 @@ Checks: > -misc-no-recursion, -misc-non-private-member-variables-in-classes, -modernize-use-ranges, + -performance-enum-size, -readability-identifier-length, -readability-function-cognitive-complexity, -readability-magic-numbers, diff --git a/input.cc b/input.cc index bcd192f6f..fa3d6c0b0 100644 --- a/input.cc +++ b/input.cc @@ -925,8 +925,8 @@ void read_phixs_data() { if (!tmpallphixs.empty()) { assert_always((nbftables * globals::NPHIXSPOINTS) == std::ssize(tmpallphixs)); - // nbftables is not large enough! This is a bug. -// copy the photoionisation tables into one contiguous block of memory + + // copy the photoionisation tables into one contiguous block of memory #ifdef MPI_ON MPI_Win win_allphixsblock = MPI_WIN_NULL; diff --git a/packet.h b/packet.h index 621cf794b..119cad317 100644 --- a/packet.h +++ b/packet.h @@ -80,7 +80,7 @@ struct Packet { int pellet_nucindex{-1}; // nuclide index of the decaying species float trueemissionvelocity{-1}; - inline auto operator==(const Packet &rhs) const -> bool { + auto operator==(const Packet &rhs) const -> bool { return (number == rhs.number && type == rhs.type && (em_pos[0] == rhs.em_pos[0] && em_pos[1] == rhs.em_pos[1] && em_pos[2] == rhs.em_pos[2]) && nu_cmf == rhs.nu_cmf && where == rhs.where && prop_time == rhs.prop_time && tdecay == rhs.tdecay && diff --git a/ratecoeff.h b/ratecoeff.h index 76fd9ce1e..b15eb3bbb 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -66,7 +66,7 @@ constexpr auto simpson_integrator(auto ¶ms, double a, double b, int sampleco weight = 4.; } - const double x = a + deltax * i; + const double x = a + (deltax * i); integral += weight * func_integrand(x, ¶ms) * deltax; } @@ -80,7 +80,7 @@ auto integrator(auto params, double a, double b, double epsabs, double epsrel, i double *abserr) { if constexpr (USE_SIMPSON_INTEGRATOR) { // need an odd number for Simpson rule - const int samplecount = std::max(1, static_cast((b / a) / globals::NPHIXSNUINCREMENT)) * 4 + 1; + const int samplecount = (std::max(1, static_cast((b / a) / globals::NPHIXSNUINCREMENT)) * 4) + 1; *result = simpson_integrator(params, a, b, samplecount); *abserr = 0.; diff --git a/rpkt.h b/rpkt.h index 88bb0aa4c..8960a765d 100644 --- a/rpkt.h +++ b/rpkt.h @@ -66,7 +66,7 @@ void MPI_Bcast_binned_opacities(int modelgridindex, int root_node_id); assert_testmodeonly(ion < get_nions(element) - 1); const int groundcontindex = globals::elements[element].ions[ion].groundcontindex; assert_always(groundcontindex >= 0); - return nonemptymgi * globals::nbfcontinua_ground + groundcontindex; + return (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; } inline auto keep_this_cont(int element, const int ion, const int level, const int modelgridindex, diff --git a/sn3d.h b/sn3d.h index ddd785109..59fc16424 100644 --- a/sn3d.h +++ b/sn3d.h @@ -219,7 +219,7 @@ inline void gsl_error_handler_printout(const char *reason, const char *file, int const int phixstargetindex) -> int { const int contindex = -1 - globals::elements[element].ions[ion].levels[level].cont_index + phixstargetindex; - const int bflutindex = tempindex * globals::nbfcontinua + contindex; + const int bflutindex = (tempindex * globals::nbfcontinua) + contindex; assert_testmodeonly(bflutindex >= 0); assert_testmodeonly(bflutindex <= TABLESIZE * globals::nbfcontinua); return bflutindex; @@ -321,8 +321,8 @@ constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, assert_always(nchunk >= 0); const auto minchunksize = size / nchunks; // integer division, minimum non-empty cells per process const auto n_remainder = size % nchunks; - const auto nstart = (minchunksize + 1) * std::min(n_remainder, nchunk) + - minchunksize * std::max(static_cast(0), nchunk - n_remainder); + const auto nstart = ((minchunksize + 1) * std::min(n_remainder, nchunk)) + + (minchunksize * std::max(static_cast(0), nchunk - n_remainder)); const auto nsize = (nchunk < n_remainder) ? minchunksize + 1 : minchunksize; assert_testmodeonly(nstart >= 0); assert_testmodeonly(nsize >= 0); diff --git a/vectors.h b/vectors.h index 378ba8a0f..18ae136ea 100644 --- a/vectors.h +++ b/vectors.h @@ -16,7 +16,7 @@ // return the the magnitude of a vector template [[nodiscard]] constexpr auto vec_len(const std::array &vec) -> double { - const double squaredlen = std::accumulate(vec.begin(), vec.end(), 0., [](auto a, auto b) { return a + b * b; }); + const double squaredlen = std::accumulate(vec.begin(), vec.end(), 0., [](auto a, auto b) { return a + (b * b); }); return std::sqrt(squaredlen); } @@ -89,7 +89,7 @@ template const double ndotv_on_c = dot(dir_rf, vel_rf) / CLIGHT; const double dopplerfactorsq = USE_RELATIVISTIC_DOPPLER_SHIFT ? std::pow(1. - ndotv_on_c, 2) / (1 - (dot(vel_rf, vel_rf) / CLIGHTSQUARED)) - : (1. - 2 * ndotv_on_c); + : (1. - (2 * ndotv_on_c)); assert_testmodeonly(std::isfinite(dopplerfactorsq)); assert_testmodeonly(dopplerfactorsq > 0); @@ -220,7 +220,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { // ref1_sc is the ref1 axis in the scattering plane ref1 = n1 x ( n1 x n2 ) const double n1_dot_n2 = dot(n1, n2); - auto ref1_sc = std::array{n1[0] * n1_dot_n2 - n2[0], n1[1] * n1_dot_n2 - n2[1], n1[2] * n1_dot_n2 - n2[2]}; + auto ref1_sc = + std::array{(n1[0] * n1_dot_n2) - n2[0], (n1[1] * n1_dot_n2) - n2[1], (n1[2] * n1_dot_n2) - n2[2]}; ref1_sc = vec_norm(ref1_sc); const double cos_stokes_rot_1 = std::clamp(dot(ref1_sc, ref1), -1., 1.); @@ -250,7 +251,7 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { [[nodiscard]] constexpr auto meridian(const std::array &n) -> std::tuple, std::array> { // for ref_1 use (from triple product rule) - const double n_xylen = std::sqrt(n[0] * n[0] + n[1] * n[1]); + const double n_xylen = std::sqrt((n[0] * n[0]) + (n[1] * n[1])); const auto ref1 = std::array{-1. * n[0] * n[2] / n_xylen, -1. * n[1] * n[2] / n_xylen, (1 - (n[2] * n[2])) / n_xylen}; @@ -285,9 +286,9 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { // const double v_cr_e[3] = {beta[1] * e_rf[2] - beta[2] * e_rf[1], beta[2] * e_rf[0] - beta[0] * e_rf[2], // beta[0] * e_rf[1] - beta[1] * e_rf[0]}; - const auto e_cmf = std::array{e_par[0] + gamma_rel * (e_perp[0] + v_cr_b[0]), - e_par[1] + gamma_rel * (e_perp[1] + v_cr_b[1]), - e_par[2] + gamma_rel * (e_perp[2] + v_cr_b[2])}; + const auto e_cmf = std::array{e_par[0] + (gamma_rel * (e_perp[0] + v_cr_b[0])), + e_par[1] + (gamma_rel * (e_perp[1] + v_cr_b[1])), + e_par[2] + (gamma_rel * (e_perp[2] + v_cr_b[2]))}; return vec_norm(e_cmf); } @@ -301,7 +302,7 @@ constexpr auto frame_transform(const std::array &n_rf, double *Q, dou const double U0 = *U; // Compute polarisation (which is invariant) - const double p = sqrt(Q0 * Q0 + U0 * U0); + const double p = sqrt((Q0 * Q0) + (U0 * U0)); // We want to compute the angle between ref1 and the electric field double rot_angle = 0; @@ -334,9 +335,9 @@ constexpr auto frame_transform(const std::array &n_rf, double *Q, dou // Define electric field by linear combination of ref1 and ref2 (using the angle just computed) - const auto elec_rf = std::array{cos(rot_angle) * ref1_rf[0] - sin(rot_angle) * ref2_rf[0], - cos(rot_angle) * ref1_rf[1] - sin(rot_angle) * ref2_rf[1], - cos(rot_angle) * ref1_rf[2] - sin(rot_angle) * ref2_rf[2]}; + const auto elec_rf = std::array{(cos(rot_angle) * ref1_rf[0]) - (sin(rot_angle) * ref2_rf[0]), + (cos(rot_angle) * ref1_rf[1]) - (sin(rot_angle) * ref2_rf[1]), + (cos(rot_angle) * ref1_rf[2]) - (sin(rot_angle) * ref2_rf[2])}; // Aberration const auto n_cmf = angle_ab(n_rf, v); From ec46b7380f7c077cb4c1b57a15ca06ad6d1ac755 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 4 Sep 2024 10:18:21 +0100 Subject: [PATCH 040/117] Remove redundant #pragma once --- artisoptions_christinenonthermal.h | 1 - artisoptions_classic.h | 1 - artisoptions_kilonova_lte.h | 1 - artisoptions_nltenebular.h | 1 - artisoptions_nltewithoutnonthermal.h | 1 - atomic.h | 1 - constants.h | 1 - decay.h | 1 - exspec.h | 1 - gammapkt.h | 1 - globals.h | 1 - grid.h | 1 - input.h | 1 - kpkt.h | 1 - ltepop.h | 1 - macroatom.h | 1 - md5.h | 1 - nltepop.h | 1 - nonthermal.h | 1 - packet.h | 1 - radfield.h | 1 - ratecoeff.h | 1 - rpkt.h | 1 - sn3d.h | 3 +-- spectrum_lightcurve.h | 1 - stats.h | 1 - thermalbalance.h | 1 - update_grid.h | 1 - update_packets.h | 1 - vectors.h | 1 - vpkt.h | 1 - 31 files changed, 1 insertion(+), 32 deletions(-) diff --git a/artisoptions_christinenonthermal.h b/artisoptions_christinenonthermal.h index c648cc0db..77c574bcf 100644 --- a/artisoptions_christinenonthermal.h +++ b/artisoptions_christinenonthermal.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ARTISOPTIONS_H // NOLINT(llvm-header-guard) #define ARTISOPTIONS_H // NOLINTBEGIN(modernize*,misc-unused-parameters) diff --git a/artisoptions_classic.h b/artisoptions_classic.h index f937a2687..0e34b81d8 100644 --- a/artisoptions_classic.h +++ b/artisoptions_classic.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ARTISOPTIONS_H // NOLINT(llvm-header-guard) #define ARTISOPTIONS_H // NOLINTBEGIN(modernize*,misc-unused-parameters) diff --git a/artisoptions_kilonova_lte.h b/artisoptions_kilonova_lte.h index f0be2ea4a..3f35ddf43 100644 --- a/artisoptions_kilonova_lte.h +++ b/artisoptions_kilonova_lte.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ARTISOPTIONS_H // NOLINT(llvm-header-guard) #define ARTISOPTIONS_H // NOLINTBEGIN(modernize*,misc-unused-parameters) diff --git a/artisoptions_nltenebular.h b/artisoptions_nltenebular.h index 276b0d4e2..63e607994 100644 --- a/artisoptions_nltenebular.h +++ b/artisoptions_nltenebular.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ARTISOPTIONS_H // NOLINT(llvm-header-guard) #define ARTISOPTIONS_H // NOLINTBEGIN(modernize*,misc-unused-parameters) diff --git a/artisoptions_nltewithoutnonthermal.h b/artisoptions_nltewithoutnonthermal.h index 475bcaa67..4db1817c7 100644 --- a/artisoptions_nltewithoutnonthermal.h +++ b/artisoptions_nltewithoutnonthermal.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ARTISOPTIONS_H // NOLINT(llvm-header-guard) #define ARTISOPTIONS_H // NOLINTBEGIN(modernize*,misc-unused-parameters) diff --git a/atomic.h b/atomic.h index a3b3993ed..b4b0e1a6d 100644 --- a/atomic.h +++ b/atomic.h @@ -1,4 +1,3 @@ -#pragma once #ifndef ATOMIC_H #define ATOMIC_H diff --git a/constants.h b/constants.h index a605fca95..a38928eb5 100644 --- a/constants.h +++ b/constants.h @@ -1,4 +1,3 @@ -#pragma once #ifndef CONSTANTS_H #define CONSTANTS_H diff --git a/decay.h b/decay.h index 0fbb2d8b9..9e115666b 100644 --- a/decay.h +++ b/decay.h @@ -1,4 +1,3 @@ -#pragma once #ifndef DECAY_H #define DECAY_H diff --git a/exspec.h b/exspec.h index 388c8f8ba..1221a4698 100644 --- a/exspec.h +++ b/exspec.h @@ -1,4 +1,3 @@ -#pragma once #ifndef EXSPEC_H #define EXSPEC_H diff --git a/gammapkt.h b/gammapkt.h index fbe1f50c1..1f360a241 100644 --- a/gammapkt.h +++ b/gammapkt.h @@ -1,4 +1,3 @@ -#pragma once #ifndef GAMMAPKT_H #define GAMMAPKT_H diff --git a/globals.h b/globals.h index e871a9015..db4911180 100644 --- a/globals.h +++ b/globals.h @@ -1,4 +1,3 @@ -#pragma once #include #ifndef GLOBALS_H #define GLOBALS_H diff --git a/grid.h b/grid.h index 3e371ecbb..d0bbc8361 100644 --- a/grid.h +++ b/grid.h @@ -1,4 +1,3 @@ -#pragma once #include #ifndef GRIDINIT_H #define GRIDINIT_H diff --git a/input.h b/input.h index 6807c4ba0..6e53d730c 100644 --- a/input.h +++ b/input.h @@ -1,4 +1,3 @@ -#pragma once #ifndef INPUT_H #define INPUT_H diff --git a/kpkt.h b/kpkt.h index 60bbdc588..3c3a35125 100644 --- a/kpkt.h +++ b/kpkt.h @@ -1,4 +1,3 @@ -#pragma once #ifndef KPKT_H #define KPKT_H diff --git a/ltepop.h b/ltepop.h index 036605101..14a930846 100644 --- a/ltepop.h +++ b/ltepop.h @@ -1,4 +1,3 @@ -#pragma once #ifndef LTEPOP_H #define LTEPOP_H diff --git a/macroatom.h b/macroatom.h index e8cd7f51e..9ebde5e3c 100644 --- a/macroatom.h +++ b/macroatom.h @@ -1,4 +1,3 @@ -#pragma once #ifndef MACROATOM_H #define MACROATOM_H diff --git a/md5.h b/md5.h index 0c3b904a8..4b014a789 100644 --- a/md5.h +++ b/md5.h @@ -6,7 +6,6 @@ * Details: Defines the API for the corresponding MD5 implementation. *********************************************************************/ -#pragma once #ifndef MD5_H #define MD5_H diff --git a/nltepop.h b/nltepop.h index ad0767c3b..f18e155fa 100644 --- a/nltepop.h +++ b/nltepop.h @@ -1,4 +1,3 @@ -#pragma once #ifndef NLTEPOP_H #define NLTEPOP_H diff --git a/nonthermal.h b/nonthermal.h index a73c0faff..37933b9dc 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -1,4 +1,3 @@ -#pragma once #ifndef NONTHERMAL_H #define NONTHERMAL_H diff --git a/packet.h b/packet.h index 119cad317..f2dd8ccd7 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,3 @@ -#pragma once #ifndef PACKET_H #define PACKET_H diff --git a/radfield.h b/radfield.h index a5fa068c3..8a335c1ae 100644 --- a/radfield.h +++ b/radfield.h @@ -1,4 +1,3 @@ -#pragma once #include #ifndef RADFIELD_H #define RADFIELD_H diff --git a/ratecoeff.h b/ratecoeff.h index b15eb3bbb..c53b5264d 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -1,4 +1,3 @@ -#pragma once #ifndef RATECOEFF_H #define RATECOEFF_H diff --git a/rpkt.h b/rpkt.h index 8960a765d..059ea3947 100644 --- a/rpkt.h +++ b/rpkt.h @@ -1,4 +1,3 @@ -#pragma once #ifndef RPKT_H #define RPKT_H diff --git a/sn3d.h b/sn3d.h index 59fc16424..6dfb7cce6 100644 --- a/sn3d.h +++ b/sn3d.h @@ -1,5 +1,3 @@ -#pragma once -#include #ifndef SN3D_H #define SN3D_H @@ -19,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/spectrum_lightcurve.h b/spectrum_lightcurve.h index f753c987d..18f1da7ad 100644 --- a/spectrum_lightcurve.h +++ b/spectrum_lightcurve.h @@ -1,4 +1,3 @@ -#pragma once #ifndef SPECTRUM_H #define SPECTRUM_H diff --git a/stats.h b/stats.h index 3b9497d34..effff2caf 100644 --- a/stats.h +++ b/stats.h @@ -1,4 +1,3 @@ -#pragma once #include #ifndef STATS_H #define STATS_H diff --git a/thermalbalance.h b/thermalbalance.h index d59b369ce..c48997b95 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -1,4 +1,3 @@ -#pragma once #ifndef THERMALBALANCE_H #define THERMALBALANCE_H diff --git a/update_grid.h b/update_grid.h index e6e753171..bfe60a2b5 100644 --- a/update_grid.h +++ b/update_grid.h @@ -1,4 +1,3 @@ -#pragma once #ifndef UPDATE_GRID_H #define UPDATE_GRID_H diff --git a/update_packets.h b/update_packets.h index da9667e4f..88c40f665 100644 --- a/update_packets.h +++ b/update_packets.h @@ -1,4 +1,3 @@ -#pragma once #ifndef UPDATE_PACKETS_H #define UPDATE_PACKETS_H diff --git a/vectors.h b/vectors.h index 18ae136ea..8bee8c776 100644 --- a/vectors.h +++ b/vectors.h @@ -1,4 +1,3 @@ -#pragma once #ifndef VECTORS_H #define VECTORS_H diff --git a/vpkt.h b/vpkt.h index a1eb72e43..ad6787e96 100644 --- a/vpkt.h +++ b/vpkt.h @@ -1,4 +1,3 @@ -#pragma once #ifndef VPKT_H #define VPKT_H From d59dcb56661042bf10ae26a116ff3f6554afac69 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 10 Sep 2024 22:03:05 +0100 Subject: [PATCH 041/117] Replace level transition pointers with indicies (#123) sim2010 classic mode 2-120 days 2e7pkt 960 core JUWELS runtime decreased from 1.18k core hrs (v2024.09) to 1.13k core hours (4.5% faster). --- atomic.h | 23 +++++- globals.h | 39 +++++----- input.cc | 151 +++++++++++++++++++----------------- kpkt.cc | 16 +--- macroatom.cc | 167 +++++++++++++++++++--------------------- macroatom.h | 7 +- nltepop.cc | 16 ++-- nonthermal.cc | 47 ++++++----- radfield.cc | 4 +- ratecoeff.cc | 2 +- ratecoeff.h | 6 +- rpkt.cc | 110 ++++++++------------------ rpkt.h | 45 ++++++++++- scripts/artis-juwels.sh | 4 +- sn3d.h | 2 +- spectrum_lightcurve.cc | 6 +- stats.cc | 9 +-- thermalbalance.cc | 5 +- vpkt.cc | 4 +- 19 files changed, 337 insertions(+), 326 deletions(-) diff --git a/atomic.h b/atomic.h index b4b0e1a6d..b7110d34e 100644 --- a/atomic.h +++ b/atomic.h @@ -94,7 +94,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) assert_testmodeonly(phixstargetindex >= 0); assert_testmodeonly(phixstargetindex < get_nphixstargets(element, ion, level)); - return globals::elements[element].ions[ion].levels[level].phixstargets[phixstargetindex].levelindex; + return globals::allphixstargets[globals::elements[element].ions[ion].levels[level].phixstargetstart + + phixstargetindex] + .levelindex; } // Return the probability of a target state for photoionization of (element,ion,level). @@ -106,7 +108,9 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) assert_testmodeonly(phixstargetindex >= 0); assert_testmodeonly(phixstargetindex < get_nphixstargets(element, ion, level)); - return globals::elements[element].ions[ion].levels[level].phixstargets[phixstargetindex].probability; + return globals::allphixstargets[globals::elements[element].ions[ion].levels[level].phixstargetstart + + phixstargetindex] + .probability; } // Return the statistical weight of (element,ion,level). @@ -360,6 +364,10 @@ inline auto get_includedlevels() -> int { return includedlevels; } return globals::elements[element].ions[ion].levels[level].ndowntrans; } +[[nodiscard]] inline auto get_downtranslist(const int element, const int ion, const int level) -> LevelTransition * { + return globals::alltrans + globals::elements[element].ions[ion].levels[level].alltrans_startdown; +} + // the number of upward bound-bound transitions from the specified level [[nodiscard]] inline auto get_nuptrans(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); @@ -368,6 +376,15 @@ inline auto get_includedlevels() -> int { return includedlevels; } return globals::elements[element].ions[ion].levels[level].nuptrans; } +[[nodiscard]] inline auto get_uptranslist(const int element, const int ion, const int level) -> LevelTransition * { + const auto &levelref = globals::elements[element].ions[ion].levels[level]; + return globals::alltrans + levelref.alltrans_startdown + levelref.ndowntrans; +} + +[[nodiscard]] inline auto get_uptransspan(const int element, const int ion, const int level) { + return std::span(get_uptranslist(element, ion, level), get_nuptrans(element, ion, level)); +} + // the number of downward bound-bound transitions from the specified level inline void set_ndowntrans(const int element, const int ion, const int level, const int ndowntrans) { assert_testmodeonly(element < get_nelements()); @@ -404,7 +421,7 @@ inline void set_nuptrans(const int element, const int ion, const int level, cons [[nodiscard]] inline auto get_emtype_continuum(const int element, const int ion, const int level, const int upperionlevel) -> int { const int phixstargetindex = get_phixtargetindex(element, ion, level, upperionlevel); - return globals::elements[element].ions[ion].levels[level].cont_index - phixstargetindex; + return -1 - globals::elements[element].ions[ion].levels[level].cont_index - phixstargetindex; } // Returns the energy of (element,ion,level). diff --git a/globals.h b/globals.h index db4911180..d46106e78 100644 --- a/globals.h +++ b/globals.h @@ -54,7 +54,7 @@ struct FullPhotoionTransition { int level; int phixstargetindex; int upperlevel; - float *photoion_xs; + const float *photoion_xs; double probability; int index_in_groundphixslist; int bfestimindex; @@ -66,11 +66,6 @@ struct GroundPhotoion { int ion; }; -struct PhotoionTarget { - double probability; // fraction of phixs cross section leading to this final level - int levelindex; // index of upper ion level after photoionisation -}; - struct LevelTransition { int lineindex; int targetlevelindex; @@ -80,18 +75,23 @@ struct LevelTransition { bool forbidden; }; +struct PhotoionTarget { + double probability; // fraction of phixs cross section leading to this final level + int levelindex; // index of upper ion level after photoionisation +}; + struct EnergyLevel { - double epsilon{-1}; // Excitation energy of this level relative to the neutral ground level. - LevelTransition *uptrans{}; // Allowed upward transitions from this level - LevelTransition *downtrans{}; // Allowed downward transitions from this level - int nuptrans{0}; - int ndowntrans{0}; - PhotoionTarget *phixstargets{}; // pointer to table of target states and probabilities - int phixsstart{-1}; // index to start of photoionisation cross-sections table in global::allphixs - int nphixstargets{0}; // length of phixstargets array: - float stat_weight{0.}; // Statistical weight of this level. - - int cont_index{-1}; // Index of the continuum associated to this level. Negative number. + double epsilon{-1}; // Excitation energy of this level relative to the neutral ground level. + int alltrans_startdown{}; // index into globals::alltrans for first down transition from this level + int ndowntrans{0}; // Number of down transitions from this level + int nuptrans{0}; // Number of up transitions to this level + int phixsstart{-1}; // index to start of photoionisation cross-sections table in global::allphixs + int nphixstargets{0}; // number of target levels for photoionisation + float stat_weight{0.}; // statistical weight of this level + int phixstargetstart{}; // index into globals::allphixstargets + int cont_index{-1}; // index of the bound-free continuum (for first target) sorted by + // element/ion/level/phixstargetindex + // (not an index into the nu_edge-sorted allcont list!) int closestgroundlevelcont{-1}; }; @@ -109,7 +109,6 @@ struct Ion { int uniquelevelindexstart; int groundcontindex; double ionpot; // Ionisation threshold to the next ionstage - LevelTransition *alltransitions; }; struct Element { @@ -134,7 +133,7 @@ struct TransitionLine { struct GSLIntegrationParas { double nu_edge; float T; - float *photoion_xs; + const float *photoion_xs; }; template @@ -258,6 +257,8 @@ inline int opacity_case{}; // 0 grey, 1 for Fe-grp dependence. inline std::vector ion_alpha_sp; // alpha_sp for each ion and temperature table value inline float *allphixs{}; +inline LevelTransition *alltrans; +inline std::vector allphixstargets; inline std::vector elements; diff --git a/input.cc b/input.cc index fa3d6c0b0..6967ca33f 100644 --- a/input.cc +++ b/input.cc @@ -22,7 +22,6 @@ #include #include #include -#include #ifndef GPU_ON #include #endif @@ -91,6 +90,9 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input const int lowerion, const int lowerlevel, const int upperion, int upperlevel_in, std::vector &tmpallphixs, size_t *mem_usage_phixs, const int phixs_file_version) { std::string phixsline; + assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargetstart == -1); + globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargetstart = + static_cast(globals::allphixstargets.size()); if (upperlevel_in >= 0) { // file gives photoionisation to a single target state only int upperlevel = upperlevel_in - groundstate_index_in; assert_always(upperlevel >= 0); @@ -98,18 +100,12 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = 1; *mem_usage_phixs += sizeof(PhotoionTarget); - assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets == nullptr); - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(malloc(sizeof(PhotoionTarget))); - assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); - if (single_level_top_ion && (upperion == get_nions(element) - 1)) { // top ion has only one level, so send it to that level upperlevel = 0; } - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].levelindex = upperlevel; - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].probability = 1.; + globals::allphixstargets.push_back({.probability = 1., .levelindex = upperlevel}); } else { // upperlevel < 0, indicating that a table of upper levels and their probabilities will follow int in_nphixstargets = 0; assert_always(get_noncommentline(phixsfile, phixsline)); @@ -121,10 +117,6 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = in_nphixstargets; *mem_usage_phixs += in_nphixstargets * sizeof(PhotoionTarget); - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(malloc(in_nphixstargets * sizeof(PhotoionTarget))); - assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); - double probability_sum = 0.; for (int i = 0; i < in_nphixstargets; i++) { double phixstargetprobability{NAN}; @@ -133,9 +125,8 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input const int upperlevel = upperlevel_in - groundstate_index_in; assert_always(upperlevel >= 0); assert_always(phixstargetprobability > 0); - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[i].levelindex = upperlevel; - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[i].probability = - phixstargetprobability; + globals::allphixstargets.push_back({.probability = phixstargetprobability, .levelindex = upperlevel}); + probability_sum += phixstargetprobability; } if (fabs(probability_sum - 1.0) > 0.01) { @@ -145,17 +136,13 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input } else { // file has table of target states and probabilities but our top ion is limited to one level globals::elements[element].ions[lowerion].levels[lowerlevel].nphixstargets = 1; *mem_usage_phixs += sizeof(PhotoionTarget); - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets = - static_cast(malloc(sizeof(PhotoionTarget))); - assert_always(globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets != nullptr); for (int i = 0; i < in_nphixstargets; i++) { assert_always(get_noncommentline(phixsfile, phixsline)); } // send it to the ground state of the top ion - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].levelindex = 0; - globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargets[0].probability = 1.; + globals::allphixstargets.push_back({.probability = 1., .levelindex = 0}); } } @@ -167,7 +154,10 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input if (lowerion < get_nions(element) - 1) { for (int phixstargetindex = 0; phixstargetindex < get_nphixstargets(element, lowerion, lowerlevel); phixstargetindex++) { - const int upperlevel = get_phixsupperlevel(element, lowerion, lowerlevel, phixstargetindex); + const int upperlevel = + globals::allphixstargets[globals::elements[element].ions[lowerion].levels[lowerlevel].phixstargetstart + + phixstargetindex] + .levelindex; if (upperlevel > get_maxrecombininglevel(element, lowerion + 1)) { globals::elements[element].ions[lowerion + 1].maxrecombininglevel = upperlevel; } @@ -364,7 +354,7 @@ void read_ion_levels(std::fstream &adata, const int element, const int ion, cons const double currentlevelenergy = (energyoffset + levelenergy) * EV; globals::elements[element].ions[ion].levels[level].nphixstargets = 0; globals::elements[element].ions[ion].levels[level].phixsstart = -1; - globals::elements[element].ions[ion].levels[level].phixstargets = nullptr; + globals::elements[element].ions[ion].levels[level].phixstargetstart = -1; globals::elements[element].ions[ion].levels[level].epsilon = currentlevelenergy; globals::elements[element].ions[ion].levels[level].stat_weight = statweight; assert_always(statweight > 0.); @@ -430,7 +420,9 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition const int lower = lower_in - groundstate_index_in; const int upper = upper_in - groundstate_index_in; assert_always(lower >= 0); - assert_always(upper >= 0); + assert_always(upper > lower); + assert_always(lower >= prev_lower); + assert_always(upper >= prev_upper || lower > prev_lower); // this entire block can be removed if we don't want to add in extra collisonal // transitions between levels @@ -477,7 +469,8 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition void add_transitions_to_unsorted_linelist(const int element, const int ion, const int nlevelsmax, const std::vector &transitiontable, std::vector &iondowntranstmplineindicies, int &lineindex, - std::vector &temp_linelist) { + std::vector &temp_linelist, + std::vector &temp_alltranslist) { const int lineindex_initial = lineindex; ptrdiff_t totupdowntrans = 0; // pass 0 to get transition counts of each level @@ -485,29 +478,11 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons for (int pass = 0; pass < 2; pass++) { lineindex = lineindex_initial; if (pass == 1) { - int alltransindex = 0; - auto &ionalltrans = globals::elements[element].ions[ion].alltransitions; - -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); - MPI_Win win_alltransblock = MPI_WIN_NULL; - - const auto [_, noderank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); - - auto size = static_cast(noderank_trans * sizeof(LevelTransition)); - int disp_unit = sizeof(LevelTransition); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &ionalltrans, &win_alltransblock); - - MPI_Win_shared_query(win_alltransblock, 0, &size, &disp_unit, &ionalltrans); -#else - ionalltrans = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); -#endif - + int alltransindex = temp_alltranslist.size(); + temp_alltranslist.resize(temp_alltranslist.size() + totupdowntrans); for (int level = 0; level < nlevelsmax; level++) { - globals::elements[element].ions[ion].levels[level].downtrans = &ionalltrans[alltransindex]; + globals::elements[element].ions[ion].levels[level].alltrans_startdown = alltransindex; alltransindex += get_ndowntrans(element, ion, level); - - globals::elements[element].ions[ion].levels[level].uptrans = &ionalltrans[alltransindex]; alltransindex += get_nuptrans(element, ion, level); set_ndowntrans(element, ion, level, 0); @@ -567,20 +542,21 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons // the line list has not been sorted yet, so the store the level index for now and // the index into the sorted line list will be set later - globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans - 1] = { - .lineindex = -1, - .targetlevelindex = lowerlevel, - .einstein_A = transition.A, - .coll_str = transition.coll_str, - .osc_strength = f_ul, - .forbidden = transition.forbidden}; - globals::elements[element].ions[ion].levels[lowerlevel].uptrans[nloweruptrans - 1] = { - .lineindex = -1, - .targetlevelindex = level, - .einstein_A = transition.A, - .coll_str = transition.coll_str, - .osc_strength = f_ul, - .forbidden = transition.forbidden}; + temp_alltranslist[globals::elements[element].ions[ion].levels[level].alltrans_startdown + nupperdowntrans - + 1] = {.lineindex = -1, + .targetlevelindex = lowerlevel, + .einstein_A = transition.A, + .coll_str = transition.coll_str, + .osc_strength = f_ul, + .forbidden = transition.forbidden}; + const auto lowerstartup = globals::elements[element].ions[ion].levels[lowerlevel].alltrans_startdown + + get_ndowntrans(element, ion, lowerlevel); + temp_alltranslist[lowerstartup + nloweruptrans - 1] = {.lineindex = -1, + .targetlevelindex = level, + .einstein_A = transition.A, + .coll_str = transition.coll_str, + .osc_strength = f_ul, + .forbidden = transition.forbidden}; } } else if (pass == 1 && globals::rank_in_node == 0) { @@ -608,19 +584,19 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons const float f_ul = g_ratio * ME * pow(CLIGHT, 3) / (8 * pow(QE * nu_trans * PI, 2)) * transition.A; const int nupperdowntrans = get_ndowntrans(element, ion, level); - auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[nupperdowntrans]; + auto &downtransition = temp_alltranslist[globals::elements[element].ions[ion].levels[level].alltrans_startdown + + nupperdowntrans - 1]; - // this is what classic did, but it is not quite correct. The downtrans list should be searched to find the - // correct index, not just using the last one. It probably works for the case where the transitions are sorted, - // but the assertion tripped on C IV in the classic dataset. - // assert_always(downtransition.targetlevelindex == lowerlevel); + assert_always(downtransition.targetlevelindex == lowerlevel); downtransition.einstein_A += transition.A; downtransition.osc_strength += f_ul; downtransition.coll_str = std::max(downtransition.coll_str, transition.coll_str); const int nloweruptrans = get_nuptrans(element, ion, lowerlevel); - auto &uptransition = globals::elements[element].ions[ion].levels[lowerlevel].uptrans[nloweruptrans]; + const auto lowerstartup = globals::elements[element].ions[ion].levels[lowerlevel].alltrans_startdown + + get_ndowntrans(element, ion, lowerlevel); + auto &uptransition = temp_alltranslist[lowerstartup + nloweruptrans - 1]; // as above, the downtrans list should be searched to find the correct index instead of using the last one. // assert_always(uptransition.targetlevelindex == level); @@ -859,6 +835,7 @@ void read_phixs_data() { globals::nbfcontinua_ground = 0; globals::nbfcontinua = 0; std::vector tmpallphixs; + globals::allphixstargets.clear(); // read in photoionisation cross sections phixs_file_version_exists[0] = false; @@ -882,7 +859,7 @@ void read_phixs_data() { read_phixs_file(1, tmpallphixs); } - int cont_index = -1; + int cont_index = 0; ptrdiff_t nbftables = 0; for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); @@ -890,9 +867,8 @@ void read_phixs_data() { const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); - globals::elements[element].ions[ion].levels[level].cont_index = - (nphixstargets > 0) ? cont_index : std::numeric_limits::max(); - cont_index -= nphixstargets; + globals::elements[element].ions[ion].levels[level].cont_index = (nphixstargets > 0) ? cont_index : -1; + cont_index += nphixstargets; if (nphixstargets > 0) { nbftables++; } @@ -951,8 +927,13 @@ void read_phixs_data() { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif + tmpallphixs.clear(); + tmpallphixs.shrink_to_fit(); } + globals::allphixstargets.shrink_to_fit(); + assert_always(cont_index == std::ssize(globals::allphixstargets)); + setup_phixs_list(); } @@ -972,6 +953,7 @@ void read_atomicdata_files() { globals::elements.resize(nelements_in); std::vector temp_linelist; + std::vector temp_alltranslist; std::vector iontransitiontable; std::vector iondowntranstmplineindicies; @@ -1145,7 +1127,7 @@ void read_atomicdata_files() { iondowntranstmplineindicies.resize(downtranslevelstart(nlevelsmax)); add_transitions_to_unsorted_linelist(element, ion, nlevelsmax, iontransitiontable, iondowntranstmplineindicies, - lineindex, temp_linelist); + lineindex, temp_linelist, temp_alltranslist); for (int level = 0; level < nlevelsmax; level++) { uniquelevelindex++; @@ -1206,6 +1188,31 @@ void read_atomicdata_files() { } } + { + // create a shared all transitions list and then copy data across, freeing the local copy + const auto totupdowntrans = totaluptrans + totaldowntrans; + assert_always(totupdowntrans == static_cast(temp_alltranslist.size())); +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); + MPI_Win win_alltransblock = MPI_WIN_NULL; + + const auto [_, noderank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); + + auto size = static_cast(noderank_trans * sizeof(LevelTransition)); + int disp_unit = sizeof(LevelTransition); + MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &globals::alltrans, + &win_alltransblock); + + MPI_Win_shared_query(win_alltransblock, 0, &size, &disp_unit, &globals::alltrans); +#else + globals::alltrans = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); +#endif + if (globals::rank_in_node == 0) { + std::copy_n(temp_alltranslist.data(), totupdowntrans, globals::alltrans); + temp_alltranslist.clear(); + } + } + // create a linelist shared on node and then copy data across, freeing the local copy TransitionLine *nonconstlinelist{}; { @@ -1275,7 +1282,7 @@ void read_atomicdata_files() { // so find the first matching the upper and lower transition const int nupperdowntrans = get_ndowntrans(element, ion, upperlevel); - auto &downtranslist = globals::elements[element].ions[ion].levels[upperlevel].downtrans; + auto *downtranslist = get_downtranslist(element, ion, upperlevel); auto *downtransition = std::find_if(downtranslist, downtranslist + nupperdowntrans, [=](const auto &downtrans) { return downtrans.targetlevelindex == lowerlevel; }); @@ -1284,7 +1291,7 @@ void read_atomicdata_files() { downtransition->lineindex = lineindex; const int nloweruptrans = get_nuptrans(element, ion, lowerlevel); - auto &uptranslist = globals::elements[element].ions[ion].levels[lowerlevel].uptrans; + auto *uptranslist = get_uptranslist(element, ion, lowerlevel); auto *uptransition = std::find_if(uptranslist, uptranslist + nloweruptrans, [=](const auto &uptr) { return uptr.targetlevelindex == upperlevel; }); assert_always(uptransition != (uptranslist + nloweruptrans)); diff --git a/kpkt.cc b/kpkt.cc index 1e948d2f2..24a293c84 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -88,8 +88,9 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co const int nuptrans = get_nuptrans(element, ion, level); if (nuptrans > 0) { + const auto *const uptranslist = get_uptranslist(element, ion, level); for (int ii = 0; ii < nuptrans; ii++) { - const int upper = globals::elements[element].ions[ion].levels[level].uptrans[ii].targetlevelindex; + const int upper = uptranslist[ii].targetlevelindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon_current; const double C = nnlevel * col_excitation_ratecoeff(T_e, nne, element, ion, level, ii, epsilon_trans, statweight) * @@ -596,9 +597,9 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { int upper = -1; // excitation to same ionization stage const int nuptrans = get_nuptrans(element, ion, level); - const auto *const uptrans = globals::elements[element].ions[ion].levels[level].uptrans; + const auto *const uptranslist = get_uptranslist(element, ion, level); for (int ii = 0; ii < nuptrans; ii++) { - const int tmpupper = uptrans[ii].targetlevelindex; + const int tmpupper = uptranslist[ii].targetlevelindex; // printout(" excitation to level %d possible\n",upper); const double epsilon_trans = epsilon(element, ion, tmpupper) - epsilon_current; const double C = nnlevel * @@ -611,15 +612,6 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { } } - if (upper < 0) { - printout( - "WARNING: Could not select an upper level. modelgridindex %d i %td element %d ion %d level %d rndcool " - "%g " - "contrib_low %g contrib %g (should match %g) upper %d nuptrans %d\n", - modelgridindex, i, element, ion, level, rndcool_ion_process, contrib_low, contrib, - globals::cellcache[cellcacheslotid].cooling_contrib[i], upper, nuptrans); - std::abort(); - } assert_always(upper >= 0); if constexpr (TRACK_ION_STATS) { diff --git a/macroatom.cc b/macroatom.cc index 9c754d409..4693ce74c 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -34,16 +34,16 @@ constexpr bool LOG_MACROATOM = false; FILE *macroatom_file{}; -void calculate_macroatom_transitionrates(const int modelgridindex, const int element, const int ion, const int level, +auto calculate_macroatom_transitionrates(const int modelgridindex, const int element, const int ion, const int level, const double t_mid, CellCacheLevels &chlevel) { // printout("Calculating transition rates for element %d ion %d level %d\n", element, ion, level); - auto &processrates = chlevel.processrates; + auto processrates = std::array{}; + const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); const double epsilon_current = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); - - const auto &levelref = globals::elements[element].ions[ion].levels[level]; + const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); // Downward transitions within the current ionisation stage: // radiative/collisional deexcitation and internal downward jumps @@ -51,28 +51,26 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele double sum_raddeexc = 0.; double sum_coldeexc = 0.; const int ndowntrans = get_ndowntrans(element, ion, level); + const auto *const leveldowntranslist = get_downtranslist(element, ion, level); + auto *const arr_sum_epstrans_rad_deexc = chlevel.sum_epstrans_rad_deexc; + auto *const arr_sum_internal_down_same = chlevel.sum_internal_down_same; for (int i = 0; i < ndowntrans; i++) { - const auto &downtransition = levelref.downtrans[i]; - const int lower = downtransition.targetlevelindex; - const auto A_ul = downtransition.einstein_A; + const auto &downtrans = leveldowntranslist[i]; + const int lower = downtrans.targetlevelindex; + const auto A_ul = downtrans.einstein_A; const double epsilon_target = epsilon(element, ion, lower); const double epsilon_trans = epsilon_current - epsilon_target; - const double R = - rad_deexcitation_ratecoeff(modelgridindex, element, ion, level, lower, epsilon_trans, A_ul, statweight, t_mid); - const double C = col_deexcitation_ratecoeff(T_e, nne, epsilon_trans, element, ion, level, downtransition); - - const double individ_internal_down_same = (R + C) * epsilon_target; - - const double sum_epstrans_rad_deexc = R * epsilon_trans; - const double individ_col_deexc = C * epsilon_trans; + const double R = rad_deexcitation_ratecoeff(modelgridindex, element, ion, lower, epsilon_trans, A_ul, statweight, + nnlevel, t_mid); + const double C = col_deexcitation_ratecoeff(T_e, nne, epsilon_trans, element, ion, level, downtrans); - sum_raddeexc += sum_epstrans_rad_deexc; - sum_coldeexc += individ_col_deexc; - sum_internal_down_same += individ_internal_down_same; + sum_raddeexc += R * epsilon_trans; + sum_coldeexc += C * epsilon_trans; + sum_internal_down_same += (R + C) * epsilon_target; - chlevel.sum_epstrans_rad_deexc[i] = sum_raddeexc; - chlevel.sum_internal_down_same[i] = sum_internal_down_same; + arr_sum_epstrans_rad_deexc[i] = sum_raddeexc; + arr_sum_internal_down_same[i] = sum_internal_down_same; // printout("checking downtrans %d to level %d: R %g, C %g, epsilon_trans %g\n",i,lower,R,C,epsilon_trans); } @@ -80,6 +78,27 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele processrates[MA_ACTION_COLDEEXC] = sum_coldeexc; processrates[MA_ACTION_INTERNALDOWNSAME] = sum_internal_down_same; + // Calculate sum for upward internal transitions + // transitions within the current ionisation stage + double sum_internal_up_same = 0.; + const int nuptrans = get_nuptrans(element, ion, level); + const auto *const uptranslist = get_uptranslist(element, ion, level); + for (int i = 0; i < nuptrans; i++) { + const auto &uptrans = uptranslist[i]; + const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; + + const double R = rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, nnlevel, + uptrans.lineindex, t_mid); + const double C = col_excitation_ratecoeff(T_e, nne, element, ion, level, i, epsilon_trans, statweight); + const double NT = nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, uptrans.lineindex); + + sum_internal_up_same += (R + C + NT) * epsilon_current; + chlevel.sum_internal_up_same[i] = sum_internal_up_same; + } + processrates[MA_ACTION_INTERNALUPSAME] = sum_internal_up_same; + + assert_always(std::isfinite(processrates[MA_ACTION_INTERNALUPSAME])); + // Downward transitions to lower ionisation stages: // radiative/collisional recombination and internal downward jumps // checks only if there is a lower ion, doesn't make sure that Z(ion)=Z(ion-1)+1 @@ -107,28 +126,6 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele processrates[MA_ACTION_RADRECOMB] = sum_radrecomb; processrates[MA_ACTION_COLRECOMB] = sum_colrecomb; - // Calculate sum for upward internal transitions - // transitions within the current ionisation stage - double sum_internal_up_same = 0.; - const int nuptrans = get_nuptrans(element, ion, level); - for (int i = 0; i < nuptrans; i++) { - const auto &uptrans = levelref.uptrans[i]; - const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; - - const double R = - rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, uptrans.lineindex, t_mid); - const double C = col_excitation_ratecoeff(T_e, nne, element, ion, level, i, epsilon_trans, statweight); - const double NT = nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, uptrans.lineindex); - - const double individ_internal_up_same = (R + C + NT) * epsilon_current; - - sum_internal_up_same += individ_internal_up_same; - chlevel.sum_internal_up_same[i] = sum_internal_up_same; - } - processrates[MA_ACTION_INTERNALUPSAME] = sum_internal_up_same; - - assert_always(std::isfinite(processrates[MA_ACTION_INTERNALUPSAME])); - // Transitions to higher ionisation stages double sum_up_highernt = 0.; double sum_up_higher = 0.; @@ -150,58 +147,57 @@ void calculate_macroatom_transitionrates(const int modelgridindex, const int ele } processrates[MA_ACTION_INTERNALUPHIGHERNT] = sum_up_highernt; processrates[MA_ACTION_INTERNALUPHIGHER] = sum_up_higher; + + return processrates; } -auto do_macroatom_internal_down_same(const int element, const int ion, const int level) -> int { +auto do_macroatom_internal_down_same(const int element, const int ion, const int level, + const CellCacheLevels &chlevel) -> int { const int ndowntrans = get_ndowntrans(element, ion, level); // printout("[debug] do_ma: internal downward jump within current ionstage\n"); - const double *sum_internal_down_same = - globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_down_same; + const double *sum_internal_down_same = chlevel.sum_internal_down_same; // Randomly select the occurring transition const double targetval = rng_uniform() * sum_internal_down_same[ndowntrans - 1]; // first sum_internal_down_same[i] such that sum_internal_down_same[i] > targetval - const double *const upperval = - std::upper_bound(sum_internal_down_same, sum_internal_down_same + ndowntrans, targetval); - const ptrdiff_t downtransindex = upperval - sum_internal_down_same; + const auto downtransindex = + std::upper_bound(sum_internal_down_same, sum_internal_down_same + ndowntrans - 1, targetval) - + sum_internal_down_same; - assert_always(downtransindex < ndowntrans); - const int lower = globals::elements[element].ions[ion].levels[level].downtrans[downtransindex].targetlevelindex; + const int lower = get_downtranslist(element, ion, level)[downtransindex].targetlevelindex; return lower; } // radiative deexcitation void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, const int level, - const int activatingline) { + const int activatingline, const CellCacheLevels &chlevel) { // randomly select which line transitions occurs const int ndowntrans = get_ndowntrans(element, ion, level); - const auto *sum_epstrans_rad_deexc = - globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_epstrans_rad_deexc; + const auto *sum_epstrans_rad_deexc = chlevel.sum_epstrans_rad_deexc; const double targetval = rng_uniform() * sum_epstrans_rad_deexc[ndowntrans - 1]; // first sum_epstrans_rad_deexc[i] such that sum_epstrans_rad_deexc[i] > targetval const auto downtransindex = - std::upper_bound(sum_epstrans_rad_deexc, sum_epstrans_rad_deexc + ndowntrans, targetval) - sum_epstrans_rad_deexc; + std::upper_bound(sum_epstrans_rad_deexc, sum_epstrans_rad_deexc + ndowntrans - 1, targetval) - + sum_epstrans_rad_deexc; - assert_always(downtransindex < ndowntrans); + const auto &downtrans = get_downtranslist(element, ion, level)[downtransindex]; - const auto &selecteddowntrans = globals::elements[element].ions[ion].levels[level].downtrans[downtransindex]; - - if (selecteddowntrans.lineindex == activatingline) { + if (downtrans.lineindex == activatingline) { stats::increment(stats::COUNTER_RESONANCESCATTERINGS); } if constexpr (RECORD_LINESTAT) { - atomicadd(globals::ecounter[selecteddowntrans.lineindex], 1); + atomicadd(globals::ecounter[downtrans.lineindex], 1); } - const double epsilon_trans = epsilon(element, ion, level) - epsilon(element, ion, selecteddowntrans.targetlevelindex); + const double epsilon_trans = epsilon(element, ion, level) - epsilon(element, ion, downtrans.targetlevelindex); const double oldnucmf{(pkt.last_event == 1) ? pkt.nu_cmf : NAN}; pkt.nu_cmf = epsilon_trans / H; @@ -218,8 +214,8 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, emit_rpkt(pkt); // the r-pkt can only interact with lines redder than the current one - pkt.next_trans = selecteddowntrans.lineindex + 1; - pkt.emissiontype = selecteddowntrans.lineindex; + pkt.next_trans = downtrans.lineindex + 1; + pkt.emissiontype = downtrans.lineindex; pkt.em_pos = pkt.pos; pkt.em_time = pkt.prop_time; pkt.nscatterings = 0; @@ -372,7 +368,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // If there are no precalculated rates available then calculate them if (chlevel.processrates[MA_ACTION_INTERNALUPHIGHER] < 0) { - calculate_macroatom_transitionrates(modelgridindex, element, ion, level, t_mid, chlevel); + chlevel.processrates = calculate_macroatom_transitionrates(modelgridindex, element, ion, level, t_mid, chlevel); } } @@ -393,22 +389,19 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // select transition according to probabilities std::array cumulative_transitions{}; - std::partial_sum(processrates.begin(), processrates.end(), cumulative_transitions.begin()); + std::partial_sum(processrates.cbegin(), processrates.cend(), cumulative_transitions.begin()); const double randomrate = rng_uniform() * cumulative_transitions[MA_ACTION_COUNT - 1]; // first cumulative_transitions[i] such that cumulative_transitions[i] > randomrate - const int selected_action = static_cast(std::ranges::upper_bound(cumulative_transitions, randomrate) - - cumulative_transitions.cbegin()); - - assert_always(selected_action < MA_ACTION_COUNT); - assert_always(cumulative_transitions[selected_action] > randomrate); + const auto selected_action = static_cast(std::ranges::upper_bound(cumulative_transitions, randomrate) - + cumulative_transitions.cbegin()); switch (selected_action) { case MA_ACTION_RADDEEXC: { // printout("[debug] do_ma: radiative deexcitation\n"); - do_macroatom_raddeexcitation(pkt, element, ion, level, activatingline); + do_macroatom_raddeexcitation(pkt, element, ion, level, activatingline, chlevel); if constexpr (TRACK_ION_STATS) { stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADDEEXC, pkt.e_cmf); @@ -450,7 +443,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast case MA_ACTION_INTERNALDOWNSAME: { stats::increment(stats::COUNTER_INTERACTIONS); - level = do_macroatom_internal_down_same(element, ion, level); + level = do_macroatom_internal_down_same(element, ion, level, chlevel); break; } @@ -550,18 +543,16 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment(stats::COUNTER_INTERACTIONS); // randomly select the occurring transition - const double *sum_internal_up_same = - globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].sum_internal_up_same; + const double *sum_internal_up_same = chlevel.sum_internal_up_same; const double targetval = rng_uniform() * processrates[MA_ACTION_INTERNALUPSAME]; // first sum_internal_up_same[i] such that sum_internal_up_same[i] > targetval - const double *const upperval = - std::upper_bound(sum_internal_up_same, sum_internal_up_same + nuptrans, targetval); - const ptrdiff_t uptransindex = upperval - sum_internal_up_same; + const auto uptransindex = + std::upper_bound(sum_internal_up_same, sum_internal_up_same + nuptrans - 1, targetval) - + sum_internal_up_same; - assert_always(uptransindex < nuptrans); - const int upper = globals::elements[element].ions[ion].levels[level].uptrans[uptransindex].targetlevelindex; + const int upper = get_uptranslist(element, ion, level)[uptransindex].targetlevelindex; level = upper; break; @@ -657,12 +648,10 @@ void macroatom_close_file() { // radiative deexcitation rate: paperII 3.5.2 // multiply by upper level population to get a rate per second -auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int upper, - const int lower, const double epsilon_trans, const float A_ul, - const double upperstatweight, const double t_current) -> double { - assert_always(upper > lower); - - const double n_u = get_levelpop(modelgridindex, element, ion, upper); +auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, + const double epsilon_trans, const float A_ul, const double upperstatweight, + const double nnlevelupper, const double t_current) -> double { + const auto &n_u = nnlevelupper; const double n_l = get_levelpop(modelgridindex, element, ion, lower); double R = 0.; @@ -703,13 +692,13 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con // radiative excitation rate: paperII 3.5.2 // multiply by lower level population to get a rate per second auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, - const int uptransindex, const double epsilon_trans, const int lineindex, - const double t_current) -> double { - const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; + const int uptransindex, const double epsilon_trans, const double nnlevel_lower, + const int lineindex, const double t_current) -> double { + const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; const int upper = uptr.targetlevelindex; const double n_u = get_levelpop(modelgridindex, element, ion, upper); - const double n_l = get_levelpop(modelgridindex, element, ion, lower); + const auto &n_l = nnlevel_lower; const double nu_trans = epsilon_trans / H; const double A_ul = uptr.einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / std::pow(nu_trans, 3) * A_ul; @@ -917,7 +906,7 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double lowerstatweight) -> double { - const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; + const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; const double coll_strength = uptr.coll_str; const double eoverkt = epsilon_trans / (KB * T_e); diff --git a/macroatom.h b/macroatom.h index 9ebde5e3c..3265012c3 100644 --- a/macroatom.h +++ b/macroatom.h @@ -9,11 +9,12 @@ void macroatom_close_file(); void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate); -[[nodiscard]] auto rad_deexcitation_ratecoeff(int modelgridindex, int element, int ion, int upper, int lower, - double epsilon_trans, float A_ul, double upperstatweight, +[[nodiscard]] auto rad_deexcitation_ratecoeff(int modelgridindex, int element, int ion, int lower, double epsilon_trans, + float A_ul, double upperstatweight, double nnlevelupper, double t_current) -> double; [[nodiscard]] auto rad_excitation_ratecoeff(int modelgridindex, int element, int ion, int lower, int uptransindex, - double epsilon_trans, int lineindex, double t_current) -> double; + double epsilon_trans, double nnlevel_lower, int lineindex, + double t_current) -> double; [[nodiscard]] auto rad_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upperionlevel, int lowerionlevel, int modelgridindex) -> double; [[nodiscard]] auto stim_recombination_ratecoeff(float nne, int element, int upperion, int upper, int lower, diff --git a/nltepop.cc b/nltepop.cc index 073fc1641..8bf3f9048 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -443,18 +443,20 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const int level_index = get_nlte_vector_index(element, ion, level); const double epsilon_level = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); + const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); // de-excitation const int ndowntrans = get_ndowntrans(element, ion, level); + const auto *const leveldowntranslist = get_downtranslist(element, ion, level); for (int i = 0; i < ndowntrans; i++) { - const auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[i]; + const auto &downtransition = leveldowntranslist[i]; const double A_ul = downtransition.einstein_A; const int lower = downtransition.targetlevelindex; const double epsilon_trans = epsilon_level - epsilon(element, ion, lower); - const double R = rad_deexcitation_ratecoeff(modelgridindex, element, ion, level, lower, epsilon_trans, A_ul, - statweight, t_mid) * + const double R = rad_deexcitation_ratecoeff(modelgridindex, element, ion, lower, epsilon_trans, A_ul, statweight, + nnlevel, t_mid) * s_renorm[level]; const double C = col_deexcitation_ratecoeff(T_e, nne, epsilon_trans, element, ion, level, downtransition) * s_renorm[level]; @@ -474,14 +476,14 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, // excitation const int nuptrans = get_nuptrans(element, ion, level); - const auto &leveluptrans = globals::elements[element].ions[ion].levels[level].uptrans; + const auto *const leveluptranslist = get_uptranslist(element, ion, level); for (int i = 0; i < nuptrans; i++) { - const int lineindex = leveluptrans[i].lineindex; - const int upper = leveluptrans[i].targetlevelindex; + const int lineindex = leveluptranslist[i].lineindex; + const int upper = leveluptranslist[i].targetlevelindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon_level; const double R = - rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, lineindex, t_mid) * + rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, nnlevel, lineindex, t_mid) * s_renorm[level]; assert_always(R >= 0); assert_always(std::isfinite(R)); diff --git a/nonthermal.cc b/nonthermal.cc index fe107e256..8b828bb86 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -556,7 +556,7 @@ auto get_possible_nt_excitation_count() -> int { for (int lower = 0; lower < lower_nlevels; lower++) { const int nuptrans = get_nuptrans(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; + const int upper = get_uptranslist(element, ion, lower)[t].targetlevelindex; if (upper < NTEXCITATION_MAXNLEVELS_UPPER) { ntexcitationcount++; } @@ -734,16 +734,13 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, return 0.; } - const double coll_strength = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; - if (coll_strength >= 0) { + const auto &uptrans = get_uptranslist(element, ion, lower)[uptransindex]; + if (uptrans.coll_str >= 0) { // collision strength is available, so use it // Li et al. 2012 equation 11 - return std::pow(H_ionpot / energy, 2) / lowerstatweight * coll_strength * PI * A_naught_squared; + return std::pow(H_ionpot / energy, 2) / lowerstatweight * uptrans.coll_str * PI * A_naught_squared; } - const bool forbidden = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].forbidden; - if (!forbidden) { - const double trans_osc_strength = - globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].osc_strength; + if (!uptrans.forbidden) { // permitted E1 electric dipole transitions const double U = energy / epsilon_trans; @@ -754,7 +751,7 @@ constexpr auto xs_excitation(const int element, const int ion, const int lower, constexpr double prefactor = 45.585750051; // 8 * pi^2/sqrt(3) // Eq 4 of Mewe 1972, possibly from Seaton 1962? - return prefactor * A_naught_squared * std::pow(H_ionpot / epsilon_trans, 2) * trans_osc_strength * g_bar / U; + return prefactor * A_naught_squared * std::pow(H_ionpot / epsilon_trans, 2) * uptrans.osc_strength * g_bar / U; } return 0.; } @@ -829,11 +826,12 @@ auto N_e(const int modelgridindex, const double energy, const std::array= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -1291,12 +1289,11 @@ auto get_xs_excitation_vector(const int element, const int ion, const int lower, const double statweight_lower, const double epsilon_trans) -> std::tuple, int> { std::array xs_excitation_vec{}; - const auto &uptr = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex]; - const double coll_strength = uptr.coll_str; - if (coll_strength >= 0) { + const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; + if (uptr.coll_str >= 0) { // collision strength is available, so use it // Li et al. 2012 equation 11 - const double constantfactor = std::pow(H_ionpot, 2) / statweight_lower * coll_strength * PI * A_naught_squared; + const double constantfactor = std::pow(H_ionpot, 2) / statweight_lower * uptr.coll_str * PI * A_naught_squared; const int en_startindex = get_energyindex_ev_gteq(epsilon_trans / EV); @@ -1308,8 +1305,7 @@ auto get_xs_excitation_vector(const int element, const int ion, const int lower, } return {xs_excitation_vec, en_startindex}; } - const bool forbidden = uptr.forbidden; - if (!forbidden) { + if (!uptr.forbidden) { const double trans_osc_strength = uptr.osc_strength; // permitted E1 electric dipole transitions @@ -1435,8 +1431,9 @@ auto select_nt_ionization(const int modelgridindex) -> std::tuple { auto get_uptransindex(const int element, const int ion, const int lower, const int upper) { const int nuptrans = get_nuptrans(element, ion, lower); + const auto *const leveluptrans = get_uptranslist(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - if (upper == globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex) { + if (upper == leveluptrans[t].targetlevelindex) { return t; } } @@ -1522,11 +1519,12 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo for (int lower = 0; lower < nlevels; lower++) { const double statweight_lower = stat_weight(element, ion, lower); const int nuptrans = get_nuptrans(element, ion, lower); + const auto *const uptranslist = get_uptranslist(element, ion, lower); const double nnlevel = get_levelpop(modelgridindex, element, ion, lower); const double epsilon_lower = epsilon(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; + const int upper = uptranslist[t].targetlevelindex; if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -1545,12 +1543,11 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // if (get_coll_str(lineindex) < 0) // if collision strength is not defined, the rate coefficient is // unreliable // ratecoeffperdeposition = 0.; - const int lineindex = globals::elements[element].ions[ion].levels[lower].uptrans[t].lineindex; tmp_excitation_list.push_back({ .frac_deposition = frac_excitation_thistrans, .ratecoeffperdeposition = ratecoeffperdeposition, - .lineindex = lineindex, + .lineindex = uptranslist[t].lineindex, }); } } // NT_EXCITATION_ON @@ -1645,6 +1642,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const int ion = line.ionindex; const int lower = line.lowerlevelindex; const int upper = line.upperlevelindex; + const auto nnlevel_lower = get_levelpop(modelgridindex, element, ion, lower); const auto uptransindex = get_uptransindex(element, ion, lower, upper); const double epsilon_trans = epsilon(element, ion, upper) - epsilon(element, ion, lower); @@ -1653,13 +1651,13 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double t_mid = globals::timesteps[timestep].mid; const double radexc_ratecoeff = rad_excitation_ratecoeff(modelgridindex, element, ion, lower, uptransindex, - epsilon_trans, lineindex, t_mid); + epsilon_trans, nnlevel_lower, lineindex, t_mid); const double collexc_ratecoeff = col_excitation_ratecoeff(T_e, nne, element, ion, lower, uptransindex, epsilon_trans, stat_weight(element, ion, lower)); const double exc_ratecoeff = radexc_ratecoeff + collexc_ratecoeff + ntcollexc_ratecoeff; - const auto coll_str = globals::elements[element].ions[ion].levels[lower].uptrans[uptransindex].coll_str; + const auto coll_str = get_uptranslist(element, ion, lower)[uptransindex].coll_str; printout( " frac_deposition %.3e Z=%2d ionstage %d lower %4d upper %4d rad_exc %.1e coll_exc %.1e nt_exc %.1e " @@ -1725,8 +1723,9 @@ void sfmatrix_add_excitation(std::vector &sfmatrixuppertri, const int mo const double nnlevel = get_levelpop(modelgridindex, element, ion, lower); const double epsilon_lower = epsilon(element, ion, lower); const int nuptrans = get_nuptrans(element, ion, lower); + const auto *const uptranslist = get_uptranslist(element, ion, lower); for (int t = 0; t < nuptrans; t++) { - const int upper = globals::elements[element].ions[ion].levels[lower].uptrans[t].targetlevelindex; + const int upper = uptranslist[t].targetlevelindex; if (upper >= NTEXCITATION_MAXNLEVELS_UPPER) { continue; } @@ -2274,7 +2273,7 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const if (lowerlevel >= NTEXCITATION_MAXNLEVELS_LOWER) { return 0.; } - const int upperlevel = globals::elements[element].ions[ion].levels[lowerlevel].uptrans[uptransindex].targetlevelindex; + const int upperlevel = get_uptranslist(element, ion, lowerlevel)[uptransindex].targetlevelindex; if (upperlevel >= NTEXCITATION_MAXNLEVELS_UPPER) { return 0.; } diff --git a/radfield.cc b/radfield.cc index 1b0076d0f..a7a3a2b41 100644 --- a/radfield.cc +++ b/radfield.cc @@ -1152,7 +1152,7 @@ void reduce_estimators() for (ptrdiff_t nonemptymgi = 0; nonemptymgi < nonempty_npts_model; nonemptymgi++) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; MPI_Allreduce(MPI_IN_PLACE, &radfieldbins[mgibinindex].J_raw, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &radfieldbins[mgibinindex].nuJ_raw, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &radfieldbins[mgibinindex].contribcount, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); @@ -1194,7 +1194,7 @@ void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = nonemptymgi * RADFIELDBINCOUNT + binindex; + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; if (globals::rank_in_node == 0) { MPI_Bcast(&radfieldbin_solutions[mgibinindex].W, 1, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); MPI_Bcast(&radfieldbin_solutions[mgibinindex].T_R, 1, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); diff --git a/ratecoeff.cc b/ratecoeff.cc index d66176d3b..942c43942 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -43,7 +43,7 @@ double *bfcooling_coeffs{}; struct gsl_integral_paras_gammacorr { double nu_edge; double departure_ratio; - float *photoion_xs; + const float *photoion_xs; float T_e; int modelgridindex; }; diff --git a/ratecoeff.h b/ratecoeff.h index c53b5264d..05aa066bb 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -45,7 +45,7 @@ void setup_photoion_luts(); inline double T_step_log{}; template -constexpr auto simpson_integrator(auto ¶ms, double a, double b, int samplecount) -> double { +constexpr auto simpson_integrator(auto ¶ms, const double a, const double b, const int samplecount) -> double { assert_testmodeonly(samplecount % 2 == 1); const double deltax = (b - a) / samplecount; @@ -75,8 +75,8 @@ constexpr auto simpson_integrator(auto ¶ms, double a, double b, int sampleco } template -auto integrator(auto params, double a, double b, double epsabs, double epsrel, int key, double *result, - double *abserr) { +auto integrator(auto params, const double a, const double b, const double epsabs, const double epsrel, const int key, + double *result, double *abserr) { if constexpr (USE_SIMPSON_INTEGRATOR) { // need an odd number for Simpson rule const int samplecount = (std::max(1, static_cast((b / a) / globals::NPHIXSNUINCREMENT)) * 4) + 1; diff --git a/rpkt.cc b/rpkt.cc index 508bf9045..584a34b14 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -82,14 +82,12 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum MacroAtomState &mastate, const double tau_rnd, // random optical depth until which the packet travels const double abort_dist, // maximal travel distance before packet leaves cell or time step ends - const double nu_cmf_abort, const double d_nu_on_d_l, - const double doppler) -> std::tuple { + const double nu_cmf_abort, const double d_nu_on_d_l, const double doppler, const auto *const linelist, + const int nlines) -> std::tuple { assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); auto pos = pkt.pos; - const auto nu_rf = pkt.nu_rf; auto nu_cmf = pkt.nu_cmf; - const auto e_rf = pkt.e_rf; auto e_cmf = pkt.e_cmf; auto prop_time = pkt.prop_time; int next_trans = pkt.next_trans; @@ -104,10 +102,10 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum // create therefore new variables in packet, which contain next_lowerlevel, ... // returns negative value if nu_cmf > nu_trans - if (const int lineindex = closest_transition(nu_cmf, next_trans); lineindex >= 0) [[likely]] { + if (const int lineindex = closest_transition(nu_cmf, next_trans, nlines, linelist); lineindex >= 0) [[likely]] { // line interaction is possible (nu_cmf > nu_trans) - const double nu_trans = globals::linelist[lineindex].nu; + const double nu_trans = linelist[lineindex].nu; // helper variable to overcome numerical problems after line scattering // further scattering events should be located at lower frequencies to prevent @@ -127,11 +125,11 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum return {std::numeric_limits::max(), next_trans - 1, false}; } - const int element = globals::linelist[lineindex].elementindex; - const int ion = globals::linelist[lineindex].ionindex; - const int upper = globals::linelist[lineindex].upperlevelindex; - const int lower = globals::linelist[lineindex].lowerlevelindex; - const double A_ul = globals::linelist[lineindex].einstein_A; + const int element = linelist[lineindex].elementindex; + const int ion = linelist[lineindex].ionindex; + const int upper = linelist[lineindex].upperlevelindex; + const int lower = linelist[lineindex].lowerlevelindex; + const double A_ul = linelist[lineindex].einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; @@ -154,7 +152,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum tau += tau_cont + tau_line; if constexpr (!USE_RELATIVISTIC_DOPPLER_SHIFT) { - move_pkt_withtime(pos, pkt.dir, prop_time, nu_rf, nu_cmf, e_rf, e_cmf, ldist); + move_pkt_withtime(pos, pkt.dir, prop_time, pkt.nu_rf, nu_cmf, pkt.e_rf, e_cmf, ldist); } else { // avoid move_pkt_withtime() to skip the standard Doppler shift calculation // and use the linear approx instead @@ -175,7 +173,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum mastate = {.element = element, .ion = ion, .level = upper, .activatingline = lineindex}; if constexpr (DETAILED_LINE_ESTIMATORS_ON) { - move_pkt_withtime(pos, pkt.dir, prop_time, nu_rf, nu_cmf, e_rf, e_cmf, ldist); + move_pkt_withtime(pos, pkt.dir, prop_time, pkt.nu_rf, nu_cmf, pkt.e_rf, e_cmf, ldist); radfield::update_lineestimator(modelgridindex, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); } @@ -201,7 +199,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum } // continuum process occurs at edist - return {dist + ((tau_rnd - tau) / chi_cont), globals::nlines + 1, false}; + return {dist + ((tau_rnd - tau) / chi_cont), nlines + 1, false}; } } @@ -267,7 +265,7 @@ auto get_event_expansion_opacity( bool event_is_boundbound = false; std::tie(edist_after_bin, next_trans, event_is_boundbound) = get_event(modelgridindex, pkt_bin_start, chi_rpkt_cont, mastate, tau_rnd - tau, - std::numeric_limits::max(), 0., d_nu_on_d_l, doppler); + std::numeric_limits::max(), 0., d_nu_on_d_l, doppler, globals::linelist, globals::nlines); // assert_always(edist_after_bin <= 1.1 * binedgedist); dist = dist + edist_after_bin; @@ -747,7 +745,8 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { mgi, nonemptymgi, pkt, chi_rpkt_cont, pktmastate, tau_next, nu_cmf_abort, d_nu_on_d_l, doppler); } else { std::tie(edist, pkt.next_trans, event_is_boundbound) = - get_event(mgi, pkt, chi_rpkt_cont, pktmastate, tau_next, abort_dist, nu_cmf_abort, d_nu_on_d_l, doppler); + get_event(mgi, pkt, chi_rpkt_cont, pktmastate, tau_next, abort_dist, nu_cmf_abort, d_nu_on_d_l, doppler, + globals::linelist, globals::nlines); } } assert_always(edist >= 0); @@ -877,6 +876,7 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix const auto T_e = grid::get_Te(modelgridindex); const auto nne = grid::get_nne(modelgridindex); const auto nnetot = grid::get_nnetot(modelgridindex); + const auto &allcont_nu_edge = globals::allcont_nu_edge; // The phixslist is sorted by nu_edge in ascending order (longest to shortest wavelength) // If nu < allcont[i].nu_edge no absorption in any of the following continua @@ -884,19 +884,20 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix // break the list into nu >= nu_edge and the remainder (nu < nu_edge) int i = 0; - const int allcontend = - static_cast(std::ranges::upper_bound(globals::allcont_nu_edge, nu) - globals::allcont_nu_edge.cbegin()); + const int allcontend = static_cast(std::ranges::upper_bound(allcont_nu_edge, nu) - allcont_nu_edge.cbegin()); - const int allcontbegin = - std::lower_bound( - globals::allcont_nu_edge.data(), globals::allcont_nu_edge.data() + allcontend, nu, - [](const double nu_edge, const double nu_cmf) { return nu_edge * last_phixs_nuovernuedge < nu_cmf; }) - - globals::allcont_nu_edge.data(); + const int allcontbegin = std::lower_bound(allcont_nu_edge.data(), allcont_nu_edge.data() + allcontend, nu, + [](const double nu_edge, const double nu_cmf) { + return nu_edge * last_phixs_nuovernuedge < nu_cmf; + }) - + allcont_nu_edge.data(); assert_testmodeonly(allcontbegin >= 0); assert_testmodeonly(allcontend <= globals::nbfcontinua); assert_testmodeonly(allcontbegin <= allcontend); + const auto *const allcont = globals::allcont; + if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { phixslist->allcontbegin = allcontbegin; phixslist->allcontend = allcontend; @@ -912,11 +913,11 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix } for (i = allcontbegin; i < allcontend; i++) { - const int element = globals::allcont[i].element; - const int ion = globals::allcont[i].ion; - const int level = globals::allcont[i].level; + const int element = allcont[i].element; + const int ion = allcont[i].ion; + const int level = allcont[i].level; const auto bfestimindex = - (USECELLHISTANDUPDATEPHIXSLIST && DETAILED_BF_ESTIMATORS_ON) ? globals::allcont[i].bfestimindex : -1; + (USECELLHISTANDUPDATEPHIXSLIST && DETAILED_BF_ESTIMATORS_ON) ? allcont[i].bfestimindex : -1; double sigma_contr = 0.; // The bf process happens only if the current cell contains @@ -930,14 +931,14 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix : calculate_levelpop(modelgridindex, element, ion, level); if (USECELLHISTANDUPDATEPHIXSLIST || nnlevel > 0) { - const double nu_edge = globals::allcont[i].nu_edge; - const double sigma_bf = photoionization_crosssection_fromtable(globals::allcont[i].photoion_xs, nu_edge, nu); + const double nu_edge = allcont[i].nu_edge; + const double sigma_bf = photoionization_crosssection_fromtable(allcont[i].photoion_xs, nu_edge, nu); double corrfactor = 1.; // default to no subtraction of stimulated recombination if constexpr (!SEPARATE_STIMRECOMB) { double departure_ratio = globals::cellcache[cellcacheslotid].ch_allcont_departureratios[i]; if (!USECELLHISTANDUPDATEPHIXSLIST || departure_ratio < 0) { - const int upper = globals::allcont[i].upperlevel; + const int upper = allcont[i].upperlevel; const double nnupperionlevel = USECELLHISTANDUPDATEPHIXSLIST ? get_levelpop(modelgridindex, element, ion + 1, upper) : calculate_levelpop(modelgridindex, element, ion + 1, upper); @@ -952,11 +953,11 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix corrfactor = std::max(0., 1 - stimfactor); // photoionisation minus stimulated recombination } - sigma_contr = sigma_bf * globals::allcont[i].probability * corrfactor; + sigma_contr = sigma_bf * allcont[i].probability * corrfactor; if constexpr (USECELLHISTANDUPDATEPHIXSLIST) { - if ((USE_LUT_PHOTOION || USE_LUT_BFHEATING) && level == 0 && globals::allcont[i].phixstargetindex == 0) { - phixslist->groundcont_gamma_contr[globals::allcont[i].index_in_groundphixslist] = sigma_contr; + if ((USE_LUT_PHOTOION || USE_LUT_BFHEATING) && level == 0 && allcont[i].phixstargetindex == 0) { + phixslist->groundcont_gamma_contr[allcont[i].index_in_groundphixslist] = sigma_contr; } } @@ -1021,49 +1022,6 @@ void allocate_expansionopacities() { expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins); } -__host__ __device__ auto closest_transition(const double nu_cmf, const int next_trans) -> int -// for the propagation through non empty cells -// find the next transition lineindex redder than nu_cmf -// return -1 if no transition can be reached -{ - if (next_trans > (globals::nlines - 1)) { - // packet is tagged as having no more line interactions - return -1; - } - // if nu_cmf is smaller than the lowest frequency in the linelist, - // no line interaction is possible: return negative value as a flag - if (nu_cmf < globals::linelist[globals::nlines - 1].nu) { - return -1; - } - - if (next_trans > 0) [[likely]] { - // if next_trans > 0 we know the next line we should interact with, independent of the packets - // current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors - return next_trans; - } - if (nu_cmf >= globals::linelist[0].nu) { - // if nu_cmf is larger than the highest frequency in the the linelist, - // interaction with the first line occurs - no search - return 0; - } - // otherwise go through the list until nu_cmf is located between two - // entries in the line list and get the index of the closest line - // to lower frequencies - - // will find the highest frequency (lowest index) line with nu_line <= nu_cmf - // lower_bound matches the first element where the comparison function is false - const int matchindex = static_cast( - std::lower_bound(globals::linelist, globals::linelist + globals::nlines, nu_cmf, - [](const auto &line, const double find_nu_cmf) -> bool { return line.nu > find_nu_cmf; }) - - globals::linelist); - - if (matchindex >= globals::nlines) [[unlikely]] { - return -1; - } - - return matchindex; -} - // return a randomly chosen frequency with a distribution of Planck function times the expansion opacity __host__ __device__ auto sample_planck_times_expansion_opacity(const int nonemptymgi) -> double { assert_testmodeonly(RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.); diff --git a/rpkt.h b/rpkt.h index 059ea3947..077bdecf4 100644 --- a/rpkt.h +++ b/rpkt.h @@ -32,7 +32,6 @@ struct Rpkt_continuum_absorptioncoeffs { void do_rpkt(Packet &pkt, double t2); void emit_rpkt(Packet &pkt); -[[nodiscard]] auto closest_transition(double nu_cmf, int next_trans) -> int; void calculate_chi_rpkt_cont(double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, int modelgridindex); [[nodiscard]] auto sample_planck_times_expansion_opacity(int nonemptymgi) -> double; void allocate_expansionopacities(); @@ -59,6 +58,50 @@ void MPI_Bcast_binned_opacities(int modelgridindex, int root_node_id); return CLIGHT * prop_time * (nu_cmf / nu_trans - 1); } +constexpr auto closest_transition(const double nu_cmf, const int next_trans, const int nlines, + const auto *const linelist) -> int +// for the propagation through non empty cells +// find the next transition lineindex redder than nu_cmf +// return -1 if no transition can be reached +{ + if (next_trans > (nlines - 1)) { + // packet is tagged as having no more line interactions + return -1; + } + // if nu_cmf is smaller than the lowest frequency in the linelist, + // no line interaction is possible: return negative value as a flag + if (nu_cmf < linelist[nlines - 1].nu) { + return -1; + } + + if (next_trans > 0) [[likely]] { + // if next_trans > 0 we know the next line we should interact with, independent of the packets + // current nu_cmf which might be smaller than globals::linelist[left].nu due to propagation errors + return next_trans; + } + if (nu_cmf >= linelist[0].nu) { + // if nu_cmf is larger than the highest frequency in the the linelist, + // interaction with the first line occurs - no search + return 0; + } + // otherwise go through the list until nu_cmf is located between two + // entries in the line list and get the index of the closest line + // to lower frequencies + + // will find the highest frequency (lowest index) line with nu_line <= nu_cmf + // lower_bound matches the first element where the comparison function is false + const int matchindex = static_cast( + std::lower_bound(linelist, linelist + nlines, nu_cmf, + [](const auto &line, const double find_nu_cmf) -> bool { return line.nu > find_nu_cmf; }) - + linelist); + + if (matchindex >= nlines) [[unlikely]] { + return -1; + } + + return matchindex; +} + [[nodiscard]] inline auto get_ionestimindex_nonemptymgi(const int nonemptymgi, const int element, const int ion) -> int { assert_testmodeonly(ion >= 0); diff --git a/scripts/artis-juwels.sh b/scripts/artis-juwels.sh index 6b945551c..af48b507d 100755 --- a/scripts/artis-juwels.sh +++ b/scripts/artis-juwels.sh @@ -34,10 +34,10 @@ mkdir ${SLURM_JOB_ID}.slurm if grep -q "RESTART_NEEDED" "output_0-0.txt" then - sbatch ./artis/scripts/artis-juwels.sh + sbatch --job-name="$SLURM_JOB_NAME" ./artis/scripts/artis-juwels.sh # sbatch $SLURM_JOB_NAME fi if [ -f packets00_0000.out ]; then - sbatch ./artis/scripts/exspec-gzip-juwels.sh + sbatch --job-name="exspec_${PWD##*/}" ./artis/scripts/exspec-gzip-juwels.sh fi diff --git a/sn3d.h b/sn3d.h index 6dfb7cce6..458e501c9 100644 --- a/sn3d.h +++ b/sn3d.h @@ -216,7 +216,7 @@ inline void gsl_error_handler_printout(const char *reason, const char *file, int [[nodiscard]] inline auto get_bflutindex(const int tempindex, const int element, const int ion, const int level, const int phixstargetindex) -> int { - const int contindex = -1 - globals::elements[element].ions[ion].levels[level].cont_index + phixstargetindex; + const int contindex = globals::elements[element].ions[ion].levels[level].cont_index + phixstargetindex; const int bflutindex = (tempindex * globals::nbfcontinua) + contindex; assert_testmodeonly(bflutindex >= 0); diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index e9806807b..a5135cef6 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -114,9 +114,9 @@ void printout_tracemission_stats() { const double B_lu = statweight_target / statweight_lower * B_ul; const int nupperdowntrans = get_ndowntrans(element, ion, upper); - auto &downtranslist = globals::elements[element].ions[ion].levels[upper].downtrans; - auto *downtransition = std::find_if(downtranslist, downtranslist + nupperdowntrans, - [=](const auto &downtr) { return downtr.targetlevelindex == lower; }); + const auto *downtranslist = get_downtranslist(element, ion, upper); + const auto *downtransition = std::find_if(downtranslist, downtranslist + nupperdowntrans, + [=](const auto &downtr) { return downtr.targetlevelindex == lower; }); assert_always(downtransition != (downtranslist + nupperdowntrans)); printout("%7.2e (%5.1f%%) %4d %9d %5d %5d %8.1f %8.2e %4d %7.1f %7.1f %7.1e %7.1e\n", encontrib, diff --git a/stats.cc b/stats.cc index a19b96af3..198db4e7b 100644 --- a/stats.cc +++ b/stats.cc @@ -56,8 +56,8 @@ void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridin stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION, n_photons_absorbed); const int et = pkt.emissiontype; - if (et >= 0) // r-packet is from bound-bound emission - { + if (et >= 0) { + // r-packet is from bound-bound emission stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUND, n_photons_absorbed); const int emissionelement = globals::linelist[et].elementindex; const int emissionion = globals::linelist[et].ionindex; @@ -76,9 +76,8 @@ void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridin n_photons_absorbed); } } - } else if (et != EMTYPE_FREEFREE && - et != EMTYPE_NOTSET) // r-pkt is from bound-free emission (not free-free scattering) - { + } else if (et != EMTYPE_FREEFREE && et != EMTYPE_NOTSET) { + // r-pkt is from bound-free emission (not free-free scattering) stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE, n_photons_absorbed); const int bfindex = (-1 * et) - 1; diff --git a/thermalbalance.cc b/thermalbalance.cc index 8e3dab343..eafbf45e2 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -35,7 +35,7 @@ struct gsl_integral_paras_bfheating { double nu_edge; int modelgridindex; float T_R; - float *photoion_xs; + const float *photoion_xs; }; auto integrand_bfheatingcoeff_custom_radfield(const double nu, void *const voidparas) -> double @@ -115,8 +115,9 @@ auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, con // Collisional heating: deexcitation to same ionization stage const int ndowntrans = get_ndowntrans(element, ion, level); + const auto *const leveldowntranslist = get_downtranslist(element, ion, level); for (int i = 0; i < ndowntrans; i++) { - const auto &downtransition = globals::elements[element].ions[ion].levels[level].downtrans[i]; + const auto &downtransition = leveldowntranslist[i]; const int lower = downtransition.targetlevelindex; const double epsilon_trans = epsilon_level - epsilon(element, ion, lower); const double C = nnlevel * diff --git a/vpkt.cc b/vpkt.cc index 1f254a989..d05c418c2 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -293,7 +293,9 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar double ldist = 0; while (ldist < sdist) { - const int lineindex = closest_transition(vpkt.nu_cmf, vpkt.next_trans); + const int lineindex = + closest_transition(vpkt.nu_cmf, vpkt.next_trans, globals::nlines, + globals::linelist); // find the closest transition to the current frequency if (lineindex < 0) { // no more lines below the current frequency From 94b09bf509ada878787fd8e3960a206ad03c2425 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 11 Sep 2024 08:36:35 +0100 Subject: [PATCH 042/117] Move warning for Planck peak outside NU_MIN_R, NU_MAX_R from packet prop to grid update --- grid.cc | 15 ++++++++++++++- kpkt.cc | 4 ---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/grid.cc b/grid.cc index 668c55b7a..8f7d9d346 100644 --- a/grid.cc +++ b/grid.cc @@ -1876,7 +1876,20 @@ void set_nnetot(const int modelgridindex, const float nnetot) { void set_kappagrey(const int modelgridindex, const float kappagrey) { modelgrid[modelgridindex].kappagrey = kappagrey; } -void set_Te(const int modelgridindex, const float Te) { modelgrid[modelgridindex].Te = Te; } +void set_Te(const int modelgridindex, const float Te) { + if (Te > 0.) { + // ignore the zero initialisation value for this check + const double nu_peak = 5.879e10 * Te; + if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { + printout( + "[warning] modelgridindex %d B_planck(Te=%g K) peak at %g Hz is outside frequency range NU_MIN_R %g NU_MAX_R " + "%g\n", + modelgridindex, Te, nu_peak, NU_MIN_R, NU_MAX_R); + } + } + + modelgrid[modelgridindex].Te = Te; +} void set_TR(const int modelgridindex, const float TR) { modelgrid[modelgridindex].TR = TR; } diff --git a/kpkt.cc b/kpkt.cc index 24a293c84..c5df06603 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -242,10 +242,6 @@ auto sample_planck_analytic(const double T) -> double { // return a randomly chosen frequency according to the Planck distribution of temperature T using a Monte Carlo method auto sample_planck_montecarlo(const double T) -> double { const double nu_peak = 5.879e10 * T; - if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { - printout("[warning] sample_planck: intensity peaks outside frequency range\n"); - } - const double B_peak = radfield::dbb(nu_peak, T, 1); while (true) { From 876332269b77fc533c1941a2ef2140ff94daf5f0 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 12 Sep 2024 11:21:41 +0100 Subject: [PATCH 043/117] Fix resetting particle dep estimators (low impact) (#124) Dep estimators for electrons, positrons, and alphas were not being zeroed at each timestep. However, since they were being divided by dV * dT for normalisation, they became close to zero anyway. Also enable save/load of these estimators to get sensible values on first timestep after resume. --- grid.cc | 20 ++++++++++++------- sn3d.cc | 3 +++ .../results_md5_final.txt | 2 +- .../results_md5_job0.txt | 2 +- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 10 +++++----- .../results_md5_final.txt | 8 ++++---- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 10 +++++----- 18 files changed, 82 insertions(+), 73 deletions(-) diff --git a/grid.cc b/grid.cc index 8f7d9d346..84b23a08a 100644 --- a/grid.cc +++ b/grid.cc @@ -1190,10 +1190,12 @@ void read_grid_restart_data(const int timestep) { float W = 0.; float T_J = 0.; int thick = 0; - double dep_estimator_gamma = 0.; - assert_always(fscanf(gridsave_file, "%d %a %a %a %a %d %la %a %a", &mgi_in, &T_R, &T_e, &W, &T_J, &thick, - &dep_estimator_gamma, &modelgrid[mgi].nne, &modelgrid[mgi].nnetot) == 9); + assert_always(fscanf(gridsave_file, "%d %a %a %a %a %d %la %la %la %la %a %a", &mgi_in, &T_R, &T_e, &W, &T_J, + &thick, &globals::dep_estimator_gamma[nonemptymgi], + &globals::dep_estimator_positron[nonemptymgi], &globals::dep_estimator_electron[nonemptymgi], + &globals::dep_estimator_alpha[nonemptymgi], &modelgrid[mgi].nne, + &modelgrid[mgi].nnetot) == 12); if (mgi_in != mgi) { printout("[fatal] read_grid_restart_data: cell mismatch in reading input gridsave.dat ... abort\n"); @@ -1205,14 +1207,16 @@ void read_grid_restart_data(const int timestep) { assert_always(T_e >= 0.); assert_always(W >= 0.); assert_always(T_J >= 0.); - assert_always(dep_estimator_gamma >= 0.); + assert_always(globals::dep_estimator_gamma[nonemptymgi] >= 0.); + assert_always(globals::dep_estimator_positron[nonemptymgi] >= 0.); + assert_always(globals::dep_estimator_electron[nonemptymgi] >= 0.); + assert_always(globals::dep_estimator_alpha[nonemptymgi] >= 0.); set_TR(mgi, T_R); set_Te(mgi, T_e); set_W(mgi, W); set_TJ(mgi, T_J); modelgrid[mgi].thick = thick; - globals::dep_estimator_gamma[nonemptymgi] = dep_estimator_gamma; if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { @@ -2222,8 +2226,10 @@ void write_grid_restart_data(const int timestep) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); assert_always(globals::dep_estimator_gamma[nonemptymgi] >= 0.); - fprintf(gridsave_file, "%d %a %a %a %a %d %la %a %a", mgi, get_TR(mgi), get_Te(mgi), get_W(mgi), get_TJ(mgi), - modelgrid[mgi].thick, globals::dep_estimator_gamma[nonemptymgi], modelgrid[mgi].nne, modelgrid[mgi].nnetot); + fprintf(gridsave_file, "%d %a %a %a %a %d %la %la %la %la %a %a", mgi, get_TR(mgi), get_Te(mgi), get_W(mgi), + get_TJ(mgi), modelgrid[mgi].thick, globals::dep_estimator_gamma[nonemptymgi], + globals::dep_estimator_positron[nonemptymgi], globals::dep_estimator_electron[nonemptymgi], + globals::dep_estimator_alpha[nonemptymgi], modelgrid[mgi].nne, modelgrid[mgi].nnetot); if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { diff --git a/sn3d.cc b/sn3d.cc index ed1f306ac..568fe2733 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -613,6 +613,9 @@ void zero_estimators() { std::ranges::fill(globals::ffheatingestimator, 0.); std::ranges::fill(globals::colheatingestimator, 0.); std::ranges::fill(globals::dep_estimator_gamma, 0.); + std::ranges::fill(globals::dep_estimator_positron, 0.); + std::ranges::fill(globals::dep_estimator_electron, 0.); + std::ranges::fill(globals::dep_estimator_alpha, 0.); if constexpr (USE_LUT_PHOTOION) { if (globals::nbfcontinua_ground > 0) { diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index 34c42bbf9..9f19b66af 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,7 +1,7 @@ 91de44973f7efdb2bbb67e9ebe78f2bf absorption.out 790e8eb2156e27b9bcf4fe4ec9db7c52 absorptionpol.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -ebb29b17b5d4e5cf6d06b0ef9d8a8df2 deposition.out +ece1861557f42d5e68bccc196784b053 deposition.out ad213adf8e24a171b42f872c59a5dae0 emission.out e8865c8b8fb79aeef5de4dfbaa176e58 emissionpol.out 91e674fadcf5a1f38e36a23aaed77cb3 emissiontrue.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index cb1e739c0..488a9570c 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,6 +1,6 @@ 8c114a35dad58a87b8cd8e3a7b776e80 absorption.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -f5c5f8bf0f84d2483cef3ce24bb46f75 deposition.out +5de886016cb306c7ba1c6d9ea93d6b35 deposition.out ccd6033593f1d4f0e47d9aac7a0e3042 emission.out 1139784b02a652a635e211b934c2cfec emissiontrue.out 457efd00d79f5dd32d4649122b9e4b73 gamma_light_curve.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt index d9a7b5d2a..d46120f46 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt @@ -1,6 +1,6 @@ a68ab8919d91afb5c3a4b28bb98b75b8 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -1dd3dd203c508b5f9e5020988a8694c0 deposition.out +f0db52c346ffcba95d1d8812475f8c34 deposition.out 065c01cd760d54a888a939dfe00378c4 emission.out f345c0a8d5ae60ec17b7bfa78d61abb9 emissiontrue.out dd314f8317220adaee8b48aa1b60f2a3 gamma_light_curve.out @@ -16,7 +16,7 @@ b5ca49a6f951391b5083c421501f645d packets00_0002.out 377af72746a6b1d93754130a3ff6f642 packets00_0003.out 5bc66d0e2f639e2cd2d2a8d9a6487c3b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -73aabc4ca257c9ebae6d7565df848e0d job1/estimators_0000.out -8b98deecd085abe3250f53b9b91161ad job1/estimators_0001.out -ae916593c7b194b9378cc51994b439c6 job1/estimators_0002.out -a7141c81f9f07c07b9520f9715ee9edc job1/estimators_0003.out +ea174eff24f41e70b1d28e9775e7dfd3 job1/estimators_0000.out +0690d0264e69496e2a43cfe86bdc9e01 job1/estimators_0001.out +4c2fa51eabca21c4680661d0db01f811 job1/estimators_0002.out +fef640281337a9f404fc72a269a20406 job1/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index 942ff7aaa..cf3e572a9 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -1,6 +1,6 @@ 9b6e08da1a7ff4bb095586408e58c0bc absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -91eab029c292915e999f17b361c01976 deposition.out +a37e9be6c23303199deccfe9a8704b90 deposition.out da000c6330f226464a3fc2ba16eb8beb emission.out 851560ece3b6630497d362ad8c69a127 emissiontrue.out a65c34c5069444d22e04c7efb8bd0d69 gamma_light_curve.out @@ -15,7 +15,7 @@ d2b546c1df9ca44beec2a25fe5cd7a12 packets00_0001.out 209c278c8753e7d57ef1120c4b1e8c59 packets00_0003.out d90011df9b26a1b201891122b690b7e9 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -2692110b12c41e4aff7c3407e0689961 job0/estimators_0000.out -4cc527f6893669a38fca316fbb2a41f0 job0/estimators_0001.out -49b4139ebb6c1401101ec15edef4ccec job0/estimators_0002.out -0be0aadf1444386b1842d90f47a2c4e8 job0/estimators_0003.out +bfe9ac9322ca2fc013e6ed7cd07abe1f job0/estimators_0000.out +ad0d31b74f09fd1e061c403e5e2bd763 job0/estimators_0001.out +41246b97f5a72d7f40123c07729f14e1 job0/estimators_0002.out +69632b392414d12f24cc196ef927f1af job0/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index ff38445c8..725776a8c 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -16,7 +16,7 @@ dfc316731561dde7037c8e8575bc15c2 packets00_0002.out 0a105cb9c97ab225676df616564e7328 packets00_0003.out 5d1b8350c2c7114b1481465644191e68 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -e652bc4aedaa3ac656a223a4243a412b job1/estimators_0000.out -2f66598613edb2fccfa5e6e63852971d job1/estimators_0001.out -1bb8a67807243dfa484fae77e8a84c88 job1/estimators_0002.out -39a87321a11374d56d67575c20026ee4 job1/estimators_0003.out +7854d43ead9a94869c5e37dee11d2e87 job1/estimators_0000.out +703ca8a7850ec8a620152cd970cb9bae job1/estimators_0001.out +11d15f3f9401e030c1087e91986d73a7 job1/estimators_0002.out +0f652a0b60587153c04186d6f762a8ec job1/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index abba9d368..812e20bd6 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ ae937aa10f537a4be5879d2148711c7d packets00_0000.out 4e44ad72a46350ab16c5b4112f5cd44c packets00_0003.out 2d154c74193a57d21c3b2b31c33bee9e spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -d7b0375369454baa750d6d7ab743abba job0/estimators_0000.out -f00f8c1829c964cecaee7efca667efe7 job0/estimators_0001.out -061900c0d8d04634d41befe29dbf74a2 job0/estimators_0002.out -cae5f71cfbd120dcd89270c8d4afc038 job0/estimators_0003.out +3b78eaa535ee03269f6e131ecf4cd9d3 job0/estimators_0000.out +f463d43459034263373f0fe95b4eced7 job0/estimators_0001.out +481b53d39d4ce276fed21a08ddc642dd job0/estimators_0002.out +772cd018b4eaca80edf71d6b51532b3d job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index c17f3aeb4..925f1450f 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -100,7 +100,7 @@ f8efb652b3b62df30d6490bbfdaf42fe absorption_res_95.out e62dba7cbb6826d15f6cb2fdde45c69b absorption_res_98.out eb05e3560a97e99403464e9c79845341 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -f421b46da29529e44e57cb7caeac62db deposition.out +3e606137299da9ff0d407802b98206a2 deposition.out 94e7893f4d16eaedf276ca3bb09408e2 emission.out 802067a4cd06e68099ae5d93d3e29773 emission_res_00.out e885f6a4f62b14a6b45dd9423c20a98a emission_res_01.out @@ -318,7 +318,7 @@ d88772c9f2f982809105433aa1ef43ed packets00_0000.out 2013eb78c14b8ab574b3e7d045ee9f7f spec.out f7aae73b1abecba91128abc65b17f4be spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -00b8474e1bec3df40f2f643d6b34fc4e job1/estimators_0000.out -ad01423a9531a1c364a1901682609112 job1/estimators_0001.out -b630267042391a009fad2f00b0f0ce2f job1/estimators_0002.out -eb8561e04928876e09d70ba46585054a job1/estimators_0003.out +09651e32e7dfb0398c957d377c0e9656 job1/estimators_0000.out +ac9ea61ba5c871f25071c13e5ad1d328 job1/estimators_0001.out +eac3fde83813a6ff3757b509b1561e99 job1/estimators_0002.out +394fbcae7cb9c701a2bda334f1cf7fc6 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 2475bebe2..c81febc13 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -12,7 +12,7 @@ d395efd35c062824dd6ab0104e0867f8 packets00_0002.out e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out 88a0e6320da73f235aec8739d4a123a3 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -76e3af84b3a66c9a282e41a6627dc4e6 job0/estimators_0000.out -0feb35456d8d8e9bbfc6548ffa0ae332 job0/estimators_0001.out -edd1c258e08cac13e09fcae4bac10992 job0/estimators_0002.out -f7550c181706595984aaf71e651a381f job0/estimators_0003.out +29f6ff5e9d574cddb2f90ec4a977199a job0/estimators_0000.out +24af7d8e90d79673d529c958635c0ace job0/estimators_0001.out +7a13aaeb7e5e6df02e21b97a81524e03 job0/estimators_0002.out +b47c9c48232ffe7e7ee813c891df3aaa job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt index 3190c5f58..be0c21093 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt @@ -100,7 +100,7 @@ b65007ef75f1eaf1a242c7b3119086c7 absorption_res_97.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_98.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -eb9a40aba1639c6cbe0fc742e7b226ad deposition.out +36c53a971b39cd7d798471b5f1674ab2 deposition.out ee60e743859c3ea2e0b13bb96718262e emission.out 5b5cbbc33f5a005f5fc164e755e4874c emission_res_00.out f1b90bc2c43c1773ec470d3cd85dde59 emission_res_01.out @@ -318,7 +318,7 @@ d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out 174d35c403e43ae90380d786e591c078 spec.out a35e02bc19e8aed065425582283e9d52 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -d1b5b66e9f018c0a2bfb6ccc4768b23e job1/estimators_0000.out -00f380ea39781e2dbd41ff4c1afd01fc job1/estimators_0001.out -377757486870b7d66850e6dadba11efa job1/estimators_0002.out -e371aba7e0accf2e0f8d56b9a147b7ba job1/estimators_0003.out +894b712119acaf3ce3ae3a9a7b67c333 job1/estimators_0000.out +3fe5acbfaf7a8d0042f85ec30f98bb32 job1/estimators_0001.out +ee5d305bb32b95e5e93adecca6abe78f job1/estimators_0002.out +c688e2fb47e2f4daee8af193fe26b9a7 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index af614a055..ba75e2213 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ e3a069b579947f54e3812795cf9deee0 packets00_0002.out 09eb173dc9f9ab59c8601d6dbdeb1af1 packets00_0003.out ff5a909e77a5ae78b0ff39c51813013d spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -4103663234968a59f86da66cbe7631d7 job0/estimators_0000.out -592a09fba94ba7569276e124bb766886 job0/estimators_0001.out -58d13995e193b8628bd36bdf41291ace job0/estimators_0002.out -b702a59839ee164667ad998047403529 job0/estimators_0003.out +4f120077aafb8ca9afb7eb557d661604 job0/estimators_0000.out +532fc878ee0d2bd269e9eac3fcd10375 job0/estimators_0001.out +3743f638c0a04d2e7094d5ddc61211e9 job0/estimators_0002.out +3afe098ae5c0f49f714ed77025368f63 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt index 2731fa00a..8b1772515 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt @@ -100,7 +100,7 @@ d17be52ec55a01fd542f0d2275afcc3b absorption_res_97.out 6f6402a01ca879f11e76ba9574630dec absorption_res_98.out 1330bb475a0964fd04a664ba765e56d6 absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -077307c9e4a89453ffb3de622c6bcec9 deposition.out +6097e7d015c08926d1a094899b644c90 deposition.out a7334ce70ab45ad1bdc10afafe1c1ae4 emission.out b9b02e1e727a758a78fd67b0f698de51 emission_res_00.out 7ca10b168860e2e62458a4177a7b5eb3 emission_res_01.out @@ -318,7 +318,7 @@ b80d451b7a65caf3e7e358bb2e31e215 packets00_0003.out 75a19500dc039b998f89bdaa549d4840 spec.out fc09caca8a29c0090c5747885cb037aa spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -27a2cc4fd0945df10105078bc2a80f26 job1/estimators_0000.out -9a6b237afdb0c6dd8201e36fb431b1a6 job1/estimators_0001.out -4591e80eeaf5212c242e212a93c32fd5 job1/estimators_0002.out -2aeea9f1649606d3069a8043b4f50c2b job1/estimators_0003.out +75c948225d2fb276096ede730fee51ee job1/estimators_0000.out +85461f2da040db701a7a2a6f53b84ec2 job1/estimators_0001.out +10927255bf1fa8f5974b96dd08e6d2be job1/estimators_0002.out +ccaf7f79f0cf53bc9ee30ae26a672426 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index 620c6bf38..f9630fcb8 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -12,7 +12,7 @@ a6c0fee501b6128a3fdb60ab924aba93 packets00_0002.out 84f08d240ba21f289e94737ca195f160 packets00_0003.out b653a3329cd63cfa1f429ff83c33693b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -a3a985a3091152eb9b5a8865e94f6c8e job0/estimators_0000.out -42db38927e1d95963b9db81422c760ed job0/estimators_0001.out -253fac738196aa1c188200929cdcde62 job0/estimators_0002.out -3c09f9da7bc2046ce27b4a371077b42f job0/estimators_0003.out +deb7a21406d428d9896a081a30acc8c6 job0/estimators_0000.out +a0844e4c057678905a865f8f9837ddd0 job0/estimators_0001.out +515cb50fee5d4be924120483cfa40399 job0/estimators_0002.out +b9a9acf2b79158ea34947b1e2ef4e700 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index 7e0e4cf37..e0cfcb281 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -100,7 +100,7 @@ f04020b3354c482b666e1e353a0ade12 absorption_res_91.out b75385a68294590db24314feb36f21c5 absorption_res_98.out 150efdd908168411b9a358899ea73ed9 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -a3c0bf87b4453de34b3a9341b3b11f5b deposition.out +e2a3add7bf9902def7761af58204df16 deposition.out df2411bf53d9e8a65897b9176011aaf2 emission.out 01350f3129565d1472dc8705cc30fe54 emission_res_00.out a48a26db68581485e30b75773bec9bb9 emission_res_01.out @@ -318,7 +318,7 @@ f3458bdeaf2f5cb207dcbee103dda567 packets00_0002.out bb247a6213ff848ca038d6c7368d9762 spec.out f51cbb087c29f30368ed94046f8080e1 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -1173c9b839971f9bd6de1c47c3c52cfc job1/estimators_0000.out -50405bde5f9f744708e33f9c37838119 job1/estimators_0001.out -68b39af44a830dc018d3b50e617181f5 job1/estimators_0002.out -aa6b1301009d451e0930d801f6409aaa job1/estimators_0003.out +74da084e4d53ed6309a45a460870e39a job1/estimators_0000.out +aac96d617e8d1f4d38dfe8c8d3747358 job1/estimators_0001.out +17a1c6bcc9b4d66864fd278db2601a60 job1/estimators_0002.out +56468257da13a15505bb30f26c25c4be job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index be6fc3902..76389c1ca 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ b3d6d74cd0c4fbe6519294af8e63ebac packets00_0002.out 933be7818c864b6314faca6a2ceafb82 packets00_0003.out bb3e8856c519696a8af781915be05c81 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -f78175259b7d9db94d3dd67f42b17c92 job0/estimators_0000.out -1e7320ea490f461c5f5006fdf30babb5 job0/estimators_0001.out -965159afc4c97de3079614a6ac5a144c job0/estimators_0002.out -e8885682ef93e0104f1779dcf24c1861 job0/estimators_0003.out +678065cde1029b6978a3cc70096630c8 job0/estimators_0000.out +4cb851be2147ee839acc4cec0b57ec74 job0/estimators_0001.out +3b7949c57381229c6414f5d3355ab87f job0/estimators_0002.out +b30151a628196ec72db82d8f8e9c4414 job0/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt index fc3ef3505..9d3c5899b 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt @@ -100,7 +100,7 @@ e5ceee3b7262cb62fb78cdca0ea59fa9 absorption_res_96.out 177d2331a3ff15e7d4e34f6d4574e0f7 absorption_res_98.out f7b68c0636c7ca9bf007c942ad1d812f absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -a89a171795aff4207996405e987df0c8 deposition.out +8b1a781723d7e9bcb2b03cac75dccdd4 deposition.out 3ca46c8cb5ca3f148548262e536aa502 emission.out efb2a97f998b06b7a3ff16a5475405c5 emission_res_00.out a42dabde264a364f813a89253d2b6799 emission_res_01.out @@ -318,7 +318,7 @@ e802497c7ed89464a51eb0884be7b959 packets00_0003.out a1d482542b13466b0b7976654de18bee spec.out 9f902c07f4dd9d8ca3664cab3dea060a spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -077d45790401e79340f2d4493d296a02 job1/estimators_0000.out -7ee333019530ae1ead47c4f23d8568bf job1/estimators_0001.out -b9a8e2f604b7755b02253d9764235b14 job1/estimators_0002.out -3add597d82a32b0855ef078f4b5d169c job1/estimators_0003.out +6c6c02e417fd289811b9a3f1071d974d job1/estimators_0000.out +b9fe9ebe83ed5cea006834f825349bfe job1/estimators_0001.out +b933e40d7f87bf73b8c56bbbdc035037 job1/estimators_0002.out +a494bfcfce9d35ca15cb9633e7b3d7cf job1/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index 714adc155..a7b8f4016 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,5 +1,5 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -5a6a785cacfeed6eba6cd0d871301974 deposition.out +7909ca40a46c503427a3668ec9512c2f deposition.out c657b77e4d00bad2650f40ed0f2ca494 gamma_light_curve.out 2b769145664780d4f90b07f963588536 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out @@ -12,7 +12,7 @@ a154f9a8511bed32dca64634d174f6f0 packets00_0001.out fb1b9057f1e7fc470fce0cf6011d352b packets00_0003.out efeeac5b0345ab0e40d5eab91e7c8b13 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -052d10ff59ce151cd0ddbaf15b2c4ac9 job0/estimators_0000.out -7424d8f6de56afa74fd555d1e46eabcc job0/estimators_0001.out -fbbd2b3c64ee24ab76e967004aa1a0af job0/estimators_0002.out -a7b97f1a19f1cb2a9fb98cc161a08683 job0/estimators_0003.out +8cd8f36c29cea3b0accaf6d6ce43baa4 job0/estimators_0000.out +c2ecda86dc9ece5e65806ef676f5a0f7 job0/estimators_0001.out +f6f5331b0747eec5afb6cedaabed3e17 job0/estimators_0002.out +f0099de9cdf75566b080793174adf821 job0/estimators_0003.out From 7c8cecddbc7d0302c7c1d9dc008d4db50036f83f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 14 Sep 2024 22:40:44 +0100 Subject: [PATCH 044/117] Remove redundant checks in get_nphixstargets() (#126) --- atomic.h | 11 +++++------ input.cc | 15 ++++++++++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/atomic.h b/atomic.h index b7110d34e..f0771228a 100644 --- a/atomic.h +++ b/atomic.h @@ -77,12 +77,11 @@ inline auto get_nlevels(const int element, const int ion) -> int { inline auto get_nphixstargets(const int element, const int ion, const int level) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(level < get_nlevels(element, ion)); - const int nions = get_nions(element); - assert_testmodeonly(ion < nions); - if ((ion < nions - 1) && (level < get_ionisinglevels(element, ion))) { - return globals::elements[element].ions[ion].levels[level].nphixstargets; - } - return 0; + assert_testmodeonly(ion < get_nions(element)); + const auto nphixstargets = globals::elements[element].ions[ion].levels[level].nphixstargets; + assert_testmodeonly(nphixstargets == 0 || + ((ion < (get_nions(element) - 1)) && (level < get_ionisinglevels(element, ion)))); + return nphixstargets; } // Return the level index of a target state for photoionization of (element,ion,level). diff --git a/input.cc b/input.cc index 6967ca33f..20292312e 100644 --- a/input.cc +++ b/input.cc @@ -470,7 +470,8 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons const std::vector &transitiontable, std::vector &iondowntranstmplineindicies, int &lineindex, std::vector &temp_linelist, - std::vector &temp_alltranslist) { + std::vector &temp_alltranslist, + size_t &temp_alltranslist_size) { const int lineindex_initial = lineindex; ptrdiff_t totupdowntrans = 0; // pass 0 to get transition counts of each level @@ -478,8 +479,11 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons for (int pass = 0; pass < 2; pass++) { lineindex = lineindex_initial; if (pass == 1) { - int alltransindex = temp_alltranslist.size(); - temp_alltranslist.resize(temp_alltranslist.size() + totupdowntrans); + int alltransindex = temp_alltranslist_size; + temp_alltranslist_size += totupdowntrans; + if (globals::rank_in_node == 0) { + temp_alltranslist.resize(temp_alltranslist_size); + } for (int level = 0; level < nlevelsmax; level++) { globals::elements[element].ions[ion].levels[level].alltrans_startdown = alltransindex; alltransindex += get_ndowntrans(element, ion, level); @@ -954,6 +958,7 @@ void read_atomicdata_files() { std::vector temp_linelist; std::vector temp_alltranslist; + size_t temp_alltranslist_size = 0; // keep size separate because the vector is only resized on rank_in_node == 0 std::vector iontransitiontable; std::vector iondowntranstmplineindicies; @@ -1127,7 +1132,7 @@ void read_atomicdata_files() { iondowntranstmplineindicies.resize(downtranslevelstart(nlevelsmax)); add_transitions_to_unsorted_linelist(element, ion, nlevelsmax, iontransitiontable, iondowntranstmplineindicies, - lineindex, temp_linelist, temp_alltranslist); + lineindex, temp_linelist, temp_alltranslist, temp_alltranslist_size); for (int level = 0; level < nlevelsmax; level++) { uniquelevelindex++; @@ -1191,7 +1196,7 @@ void read_atomicdata_files() { { // create a shared all transitions list and then copy data across, freeing the local copy const auto totupdowntrans = totaluptrans + totaldowntrans; - assert_always(totupdowntrans == static_cast(temp_alltranslist.size())); + assert_always(totupdowntrans == static_cast(temp_alltranslist_size)); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); MPI_Win win_alltransblock = MPI_WIN_NULL; From c210f2c255c36975ccac2eb1671af3128e1d43b1 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 17 Sep 2024 11:59:52 +0100 Subject: [PATCH 045/117] Add Lotz 1967 citation to comment --- data/binding_energies_lotz_tab1and2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/binding_energies_lotz_tab1and2.txt b/data/binding_energies_lotz_tab1and2.txt index 7fb80d383..f5e13c888 100644 --- a/data/binding_energies_lotz_tab1and2.txt +++ b/data/binding_energies_lotz_tab1and2.txt @@ -1,4 +1,4 @@ -#Binding energies from Lotz tables 1 and 2 +#Binding energies from Lotz tables 1 and 2 of Lotz W., 1967, JOSA, 57, 873. doi:10.1364/JOSA.57.000873. 1967JOSA...57..873L 28 108 #Z K L1 L2 L3 M1 M2 M3 M4 M5 N1 N2 N3 N4 N5 N6 N7 O1 O2 O3 O4 O5 O6 O7 P1 P2 P3 P4 Q1 1 13.600 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 From d6608c2a343279b5beb5598a94961392b4fc4621 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 17 Sep 2024 14:06:35 +0100 Subject: [PATCH 046/117] Treat alpha deposition as pure heating instead of non-thermal lepton ionisation/excitation/heating (#128) If alphas contribute significantly to the ionisation then it might worth making a separate Spencer-Fano calculation. Sending them to k-packet directly probably makes more sense than treating them as non-thermal electron deposition with the wrong cross sections. This will only affect future runs that have both NT_ON and ThermalisationScheme::DETAILED. --- gammapkt.cc | 76 +++++++++++------------------------------------ nonthermal.cc | 13 ++++++-- nonthermal.h | 1 + packet.h | 1 + thermalbalance.cc | 12 +++++--- thermalbalance.h | 2 +- update_grid.cc | 2 +- update_packets.cc | 27 +++++++++++------ 8 files changed, 59 insertions(+), 75 deletions(-) diff --git a/gammapkt.cc b/gammapkt.cc index 720815db4..379d21cc4 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -324,17 +324,11 @@ auto choose_f(const double xx, const double zrand) -> double auto thomson_angle() -> double { const double B_coeff = (8. * rng_uniform()) - 4.; - double t_coeff = sqrt((B_coeff * B_coeff) + 4); - t_coeff = t_coeff - B_coeff; - t_coeff = t_coeff / 2; - t_coeff = cbrt(t_coeff); + const double t_coeff = std::cbrt((std::sqrt((B_coeff * B_coeff) + 4) - B_coeff) / 2); const double mu = (1 / t_coeff) - t_coeff; - if (fabs(mu) > 1) { - printout("Error in Thomson. Abort.\n"); - std::abort(); - } + assert_always(fabs(mu) <= 1); return mu; } @@ -396,23 +390,16 @@ void compton_scatter(Packet &pkt) { // factor by which the energy changes "f" such that // sigma_partial/sigma_tot = zrand - bool stay_gamma = false; - double f{NAN}; - if (xx < THOMSON_LIMIT) { - f = 1.; // no energy loss - stay_gamma = true; - } else { + // initialise with Thomson limit case (no energy loss) + double f = 1.; + bool stay_gamma = true; + if (xx >= THOMSON_LIMIT) { f = choose_f(xx, rng_uniform()); - // Check that f lies between 1.0 and (2xx + 1) - - if ((f < 1) || (f > (2 * xx + 1))) { - printout("Compton f out of bounds. Abort.\n"); - std::abort(); - } + assert_always(f >= 1.); + assert_always(f <= (2 * xx + 1.)); // Prob of keeping gamma ray is... - const double prob_gamma = 1. / f; stay_gamma = (rng_uniform() < prob_gamma); @@ -437,20 +424,8 @@ void compton_scatter(Packet &pkt) { const auto new_dir = scatter_dir(cmf_dir, cos_theta); - const double test = dot(new_dir, new_dir); - if (fabs(1. - test) > 1.e-8) { - printout("Not a unit vector - Compton. Abort. %g %g %g\n", f, xx, test); - printout("new_dir %g %g %g\n", new_dir[0], new_dir[1], new_dir[2]); - printout("cmf_dir %g %g %g\n", cmf_dir[0], cmf_dir[1], cmf_dir[2]); - printout("cos_theta %g", cos_theta); - std::abort(); - } - - const double test2 = dot(new_dir, cmf_dir); - if (fabs(test2 - cos_theta) > 1.e-8) { - printout("Problem with angle - Compton. Abort.\n"); - std::abort(); - } + assert_testmodeonly(fabs(1. - dot(new_dir, new_dir)) < 1e-8); + assert_testmodeonly(fabs(dot(new_dir, cmf_dir) - cos_theta) < 1e-8); // Now convert back again. @@ -571,7 +546,7 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { } // calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame -auto sigma_pair_prod_rf(const Packet &pkt) -> double { +auto get_chi_pair_prod_rf(const Packet &pkt) -> double { const int mgi = grid::get_cell_modelgridindex(pkt.where); const double rho = grid::get_rho(mgi); @@ -662,7 +637,7 @@ void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const const double xx = H * pkt.nu_cmf / ME / CLIGHT / CLIGHT; double heating_cont = ((meanf_sigma(xx) * grid::get_nnetot(mgi)) + get_chi_photo_electric_rf(pkt) + - (sigma_pair_prod_rf(pkt) * (1. - (2.46636e+20 / pkt.nu_cmf)))); + (get_chi_pair_prod_rf(pkt) * (1. - (2.46636e+20 / pkt.nu_cmf)))); heating_cont = heating_cont * pkt.e_rf * dist * doppler_sq; // The terms in the above are for Compton, photoelectric and pair production. The pair production one @@ -689,10 +664,7 @@ void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const void pair_prod(Packet &pkt) { const double prob_gamma = 1.022 * MEV / (H * pkt.nu_cmf); - if (prob_gamma < 0) { - printout("prob_gamma < 0. pair_prod. Abort. %g\n", prob_gamma); - std::abort(); - } + assert_always(prob_gamma >= 0); if (rng_uniform() > prob_gamma) { // Convert it to an e-minus packet - actually it could be positron EK too, but this works @@ -746,7 +718,7 @@ void transport_gamma(Packet &pkt, const double t2) { if (sdist > maxsdist) { printout("Unreasonably large sdist (gamma). Abort. %g %g %g\n", globals::rmax, pkt.prop_time / globals::tmin, sdist); - std::abort(); + assert_always(false); } if (sdist < 0) { @@ -757,7 +729,7 @@ void transport_gamma(Packet &pkt, const double t2) { if (((snext < 0) && (snext != -99)) || (snext >= grid::ngrid)) { printout("Heading for inappropriate grid cell. Abort.\n"); printout("Current cell %d, target cell %d.\n", pkt.where, snext); - std::abort(); + assert_always(false); } if (sdist > globals::max_path_step) { @@ -775,7 +747,7 @@ void transport_gamma(Packet &pkt, const double t2) { } const double chi_photo_electric = get_chi_photo_electric_rf(pkt); - const double chi_pair_prod = sigma_pair_prod_rf(pkt); + const double chi_pair_prod = get_chi_pair_prod_rf(pkt); const double chi_tot = chi_compton + chi_photo_electric + chi_pair_prod; assert_testmodeonly(std::isfinite(chi_compton)); @@ -841,25 +813,13 @@ void transport_gamma(Packet &pkt, const double t2) { pkt.type = TYPE_NTLEPTON_DEPOSITED; pkt.absorptiontype = -4; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); - } else if ((chi_compton + chi_photo_electric + chi_pair_prod) > chi_rnd) { + } else { // It's a pair production pair_prod(pkt); - } else { - printout( - "Failed to identify event. Gamma (1). chi_compton %g chi_photo_electric %g chi_tot %g chi_rnd %g Abort.\n", - chi_compton, chi_photo_electric, chi_tot, chi_rnd); - const int cellindex = pkt.where; - printout( - " globals::cell[pkt.where].rho %g pkt.nu_cmf %g pkt.dir[0] %g pkt.dir[1] %g " - "pkt.dir[2] %g pkt.pos[0] %g pkt.pos[1] %g pkt.pos[2] %g \n", - grid::get_rho(grid::get_cell_modelgridindex(cellindex)), pkt.nu_cmf, pkt.dir[0], pkt.dir[0], pkt.dir[1], - pkt.dir[2], pkt.pos[1], pkt.pos[2]); - - std::abort(); } } else { printout("Failed to identify event. Gamma (2). edist %g, sdist %g, tdist %g Abort.\n", edist, sdist, tdist); - std::abort(); + assert_always(false); } } diff --git a/nonthermal.cc b/nonthermal.cc index 8b828bb86..4a2ccbc1f 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2102,8 +2102,7 @@ void calculate_deposition_rate_density(const int modelgridindex, const int times } deposition_rate_density_all_cells[modelgridindex] = - (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron + - heatingcoolingrates->dep_alpha); + (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron); } __host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double @@ -2294,6 +2293,16 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const return ratecoeffperdeposition * deposition_rate_density; } +__host__ __device__ void do_ntalpha_deposit(Packet &pkt) { + // if ionisation by alpha particles is found to be important for the ionisation state, we could do a separate + // Spencer-Fano solution. For now, just treat alpha deposition as pure heating (even though the alpha deposition rate + // was calculated from the sum of ionisation and plasma heating) + atomicadd(nt_energy_deposited, pkt.e_cmf); + pkt.last_event = 22; + pkt.type = TYPE_KPKT; + stats::increment(stats::COUNTER_NT_STAT_TO_KPKT); +} + __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { atomicadd(nt_energy_deposited, pkt.e_cmf); diff --git a/nonthermal.h b/nonthermal.h index 37933b9dc..d4acf718c 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -20,6 +20,7 @@ void calculate_deposition_rate_density(int modelgridindex, int timestep, Heating [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; [[nodiscard]] auto nt_excitation_ratecoeff(int modelgridindex, int element, int ion, int lowerlevel, int uptransindex, int lineindex) -> double; +void do_ntalpha_deposit(Packet &pkt); void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); diff --git a/packet.h b/packet.h index f2dd8ccd7..6962558a1 100644 --- a/packet.h +++ b/packet.h @@ -15,6 +15,7 @@ enum packet_type : int { TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS = 21, TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS = 22, TYPE_NONTHERMAL_PREDEPOSIT_ALPHA = 23, + TYPE_NTALPHA_DEPOSITED = 24, TYPE_PRE_KPKT = 120, }; diff --git a/thermalbalance.cc b/thermalbalance.cc index eafbf45e2..ce94a8e2b 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -192,7 +192,7 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const int modelgridindex = params->modelgridindex; const double t_current = params->t_current; - auto *heatingcoolingrates = params->heatingcoolingrates; + auto *const heatingcoolingrates = params->heatingcoolingrates; // Set new T_e guess for the current cell and update populations // globals::cell[cellnumber].T_e = T_e; @@ -204,9 +204,13 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { kpkt::calculate_cooling_rates(modelgridindex, heatingcoolingrates); calculate_heating_rates(modelgridindex, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); - heatingcoolingrates->nt_frac_heating = nonthermal::get_nt_frac_heating(modelgridindex); - heatingcoolingrates->heating_dep = - nonthermal::get_deposition_rate_density(modelgridindex) * heatingcoolingrates->nt_frac_heating; + const auto ntlepton_frac_heating = nonthermal::get_nt_frac_heating(modelgridindex); + const auto ntlepton_dep = nonthermal::get_deposition_rate_density(modelgridindex); + const auto ntalpha_frac_heating = 1.; + const auto ntalpha_dep = heatingcoolingrates->dep_alpha; + heatingcoolingrates->heating_dep = ntlepton_dep * ntlepton_frac_heating + ntalpha_dep * ntalpha_frac_heating; + heatingcoolingrates->dep_frac_heating = + (ntalpha_dep > 0) ? heatingcoolingrates->heating_dep / (ntlepton_dep + ntalpha_dep) : ntlepton_frac_heating; // Adiabatic cooling term const double nntot = get_nnion_tot(modelgridindex) + nne; diff --git a/thermalbalance.h b/thermalbalance.h index c48997b95..e99b3b806 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -12,7 +12,7 @@ struct HeatingCoolingRates { double heating_bf{0}; double heating_ff{0}; double heating_dep{0}; - double nt_frac_heating{0}; + double dep_frac_heating{0}; double dep_gamma{0}; double dep_positron{0}; double dep_electron{0}; diff --git a/update_grid.cc b/update_grid.cc index 9a7fb3226..3d375f2ce 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -660,7 +660,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti heatingcoolingrates->dep_alpha); fprintf(estimators_file, "heating: ff %11.5e bf %11.5e coll %11.5e dep %11.5e heating_dep/total_dep %.3f\n", heatingcoolingrates->heating_ff, heatingcoolingrates->heating_bf, heatingcoolingrates->heating_collisional, - heatingcoolingrates->heating_dep, heatingcoolingrates->nt_frac_heating); + heatingcoolingrates->heating_dep, heatingcoolingrates->dep_frac_heating); fprintf(estimators_file, "cooling: ff %11.5e fb %11.5e coll %11.5e adiabatic %11.5e\n", heatingcoolingrates->cooling_ff, heatingcoolingrates->cooling_fb, heatingcoolingrates->cooling_collisional, heatingcoolingrates->cooling_adiabatic); diff --git a/update_packets.cc b/update_packets.cc index f1af51f1f..4623f41d1 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -33,22 +33,24 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const auto nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); const auto priortype = pkt.type; const double ts = pkt.prop_time; + const auto deposit_type = + (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? TYPE_NTALPHA_DEPOSITED : TYPE_NTLEPTON_DEPOSITED; if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::INSTANT) { // absorption happens - pkt.type = TYPE_NTLEPTON_DEPOSITED; + pkt.type = deposit_type; } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::BARNES) { const double E_kin = grid::get_ejecta_kinetic_energy(); const double v_ej = std::sqrt(E_kin * 2 / grid::mtot_input); - const double prefactor = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 7.74 : 7.4; + const double prefactor = (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? 7.74 : 7.4; const double tau_ineff = prefactor * 86400 * std::sqrt(grid::mtot_input / (5.e-3 * 1.989 * 1.e33)) * std::pow((0.2 * 29979200000) / v_ej, 3. / 2.); const double f_p = std::log1p(2. * ts * ts / tau_ineff / tau_ineff) / (2. * ts * ts / tau_ineff / tau_ineff); assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { - pkt.type = TYPE_NTLEPTON_DEPOSITED; + pkt.type = deposit_type; } else { en_deposited = 0.; pkt.type = TYPE_ESCAPE; @@ -56,7 +58,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { } } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::WOLLAEGER) { // particle thermalisation from Wollaeger+2018, similar to Barnes but using a slightly different expression - const double A = (pkt.pellet_decaytype == decay::DECAYTYPE_ALPHA) ? 1.2 * 1.e-11 : 1.3 * 1.e-11; + const double A = (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? 1.2 * 1.e-11 : 1.3 * 1.e-11; const double aux_term = 2 * A / (ts * grid::get_rho(mgi)); // In Bulla 2023 (arXiv:2211.14348), the following line contains (<-> eq. 7) contains a typo. The way implemented // here is the original from Wollaeger paper without the typo @@ -64,7 +66,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { assert_always(f_p >= 0.); assert_always(f_p <= 1.); if (rng_uniform() < f_p) { - pkt.type = TYPE_NTLEPTON_DEPOSITED; + pkt.type = deposit_type; } else { en_deposited = 0.; pkt.type = TYPE_ESCAPE; @@ -100,7 +102,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { const auto t_new = std::min(t_absorb, t2); if (t_absorb <= t2) { - pkt.type = TYPE_NTLEPTON_DEPOSITED; + pkt.type = deposit_type; } else { pkt.nu_cmf = (particle_en - endot * (t_new - ts)) / H; } @@ -109,19 +111,21 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { pkt.prop_time = t_new; } + // contribute to the trajectory integrated deposition estimator + // and if a deposition event occurred, also the discrete Monte Carlo count deposition rate if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS) { atomicadd(globals::dep_estimator_electron[nonemptymgi], en_deposited); - if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + if (pkt.type == deposit_type) { atomicadd(globals::timesteps[nts].electron_dep_discrete, pkt.e_cmf); } } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS) { atomicadd(globals::dep_estimator_positron[nonemptymgi], en_deposited); - if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + if (pkt.type == deposit_type) { atomicadd(globals::timesteps[nts].positron_dep_discrete, pkt.e_cmf); } } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) { atomicadd(globals::dep_estimator_alpha[nonemptymgi], en_deposited); - if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + if (pkt.type == deposit_type) { atomicadd(globals::timesteps[nts].alpha_dep_discrete, pkt.e_cmf); } } @@ -231,6 +235,11 @@ void do_packet(Packet &pkt, const double t2, const int nts) break; } + case TYPE_NTALPHA_DEPOSITED: { + nonthermal::do_ntalpha_deposit(pkt); + break; + } + case TYPE_PRE_KPKT: { kpkt::do_kpkt_blackbody(pkt); break; From 2561efe0f03c453b265c2c94881f4fac97f72cec Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 17 Sep 2024 15:56:54 +0100 Subject: [PATCH 047/117] Update artis-juwels.sh --- scripts/artis-juwels.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/artis-juwels.sh b/scripts/artis-juwels.sh index af48b507d..c19178222 100755 --- a/scripts/artis-juwels.sh +++ b/scripts/artis-juwels.sh @@ -35,9 +35,8 @@ mkdir ${SLURM_JOB_ID}.slurm if grep -q "RESTART_NEEDED" "output_0-0.txt" then sbatch --job-name="$SLURM_JOB_NAME" ./artis/scripts/artis-juwels.sh - # sbatch $SLURM_JOB_NAME fi if [ -f packets00_0000.out ]; then - sbatch --job-name="exspec_${PWD##*/}" ./artis/scripts/exspec-gzip-juwels.sh + sbatch --job-name="exspec_$SLURM_JOB_NAME" ./artis/scripts/exspec-gzip-juwels.sh fi From 1cc5ac70b30333cdbb9b4fa75cb279b6a38f0b8a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 21 Sep 2024 07:32:46 +0100 Subject: [PATCH 048/117] Attempt to fix memory usage spike on startup --- input.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/input.cc b/input.cc index 20292312e..06c56c87b 100644 --- a/input.cc +++ b/input.cc @@ -1163,8 +1163,7 @@ void read_atomicdata_files() { printout("total uptrans %d\n", totaluptrans); printout("total downtrans %d\n", totaldowntrans); - printout("[info] mem_usage: transition lists occupy %.3f MB (this rank) and %.3f MB (shared on node)\n", - 2 * uniquelevelindex * sizeof(LevelTransition *) / 1024. / 1024., + printout("[info] mem_usage: transition lists occupy %.3f MB (shared on node)\n", (totaluptrans + totaldowntrans) * sizeof(LevelTransition) / 1024. / 1024.); if (globals::rank_in_node == 0) { @@ -1214,8 +1213,9 @@ void read_atomicdata_files() { #endif if (globals::rank_in_node == 0) { std::copy_n(temp_alltranslist.data(), totupdowntrans, globals::alltrans); - temp_alltranslist.clear(); } + temp_alltranslist.clear(); + temp_alltranslist.shrink_to_fit(); } // create a linelist shared on node and then copy data across, freeing the local copy @@ -1239,8 +1239,9 @@ void read_atomicdata_files() { if (globals::rank_in_node == 0) { memcpy(static_cast(nonconstlinelist), temp_linelist.data(), globals::nlines * sizeof(TransitionLine)); - temp_linelist.clear(); } + temp_linelist.clear(); + temp_alltranslist.shrink_to_fit(); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); From ef2991f4d72b8aa1234ee4c0f58cc17d55f770ef Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 23 Sep 2024 12:55:12 +0200 Subject: [PATCH 049/117] Reserve before resize to prevent over-allocation --- input.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/input.cc b/input.cc index 06c56c87b..f08ef242d 100644 --- a/input.cc +++ b/input.cc @@ -482,7 +482,10 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons int alltransindex = temp_alltranslist_size; temp_alltranslist_size += totupdowntrans; if (globals::rank_in_node == 0) { + temp_alltranslist.reserve(temp_alltranslist_size); temp_alltranslist.resize(temp_alltranslist_size); + assert_always(temp_alltranslist_size >= temp_linelist.size()); + temp_linelist.reserve(temp_alltranslist_size); } for (int level = 0; level < nlevelsmax; level++) { globals::elements[element].ions[ion].levels[level].alltrans_startdown = alltransindex; @@ -1153,6 +1156,7 @@ void read_atomicdata_files() { printout("nlines %d\n", globals::nlines); if (globals::rank_in_node == 0) { assert_always(globals::nlines == static_cast(temp_linelist.size())); + temp_linelist.shrink_to_fit(); } if (T_preset > 0) { @@ -1376,6 +1380,7 @@ void setup_cellcache() { } } assert_always(chlevelcount > 0); + globals::cellcache[cellcachenum].ch_all_levels.reserve(chlevelcount); globals::cellcache[cellcachenum].ch_all_levels.resize(chlevelcount); chphixstargetsblock = chphixsblocksize > 0 ? static_cast(malloc(chphixsblocksize)) : nullptr; @@ -1433,8 +1438,11 @@ void setup_cellcache() { assert_always(chtransindex == chtransblocksize); assert_always(globals::nbfcontinua >= 0); + globals::cellcache[cellcachenum].ch_allcont_departureratios.reserve(globals::nbfcontinua); globals::cellcache[cellcachenum].ch_allcont_departureratios.resize(globals::nbfcontinua); + globals::cellcache[cellcachenum].ch_allcont_nnlevel.reserve(globals::nbfcontinua); globals::cellcache[cellcachenum].ch_allcont_nnlevel.resize(globals::nbfcontinua); + globals::cellcache[cellcachenum].ch_keep_this_cont.reserve(globals::nbfcontinua); globals::cellcache[cellcachenum].ch_keep_this_cont.resize(globals::nbfcontinua); mem_usage_cellcache += 2 * globals::nbfcontinua * sizeof(double); @@ -1444,6 +1452,7 @@ void setup_cellcache() { } void write_bflist_file() { + globals::bflist.reserve(globals::nbfcontinua); globals::bflist.resize(globals::nbfcontinua); FILE *bflist_file{}; From 0185ae6d732f6eea0d3b4362826233c17ebcb5de Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 23 Sep 2024 14:04:34 +0200 Subject: [PATCH 050/117] Support statically-linking GSL with STATICGSL=ON (#129) --- Makefile | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 051e11682..9d5177d17 100644 --- a/Makefile +++ b/Makefile @@ -184,12 +184,22 @@ else endif # GSL (GNU Scientific Library) -LDFLAGS += $(shell pkg-config --libs gsl) CXXFLAGS += $(shell pkg-config --cflags gsl) -# GSL option 1: Use pkg-config or gsl-config to find GSL -# -# GSL option 2: Use default search paths to find GSL -# LDFLAGS += -lgsl -lgslcblas -lm + +ifeq ($(STATICGSL),) + # default to dynamic linking + STATICGSL := OFF +endif + +ifeq ($(STATICGSL),ON) + gsllibdir := $(shell pkg-config --variable=libdir gsl) + gsl_objects = $(gsllibdir)/libgsl.a $(gsllibdir)/libgslcblas.a + BUILD_DIR := $(BUILD_DIR)_staticgsl +else ifeq ($(STATICGSL),OFF) + LDFLAGS += $(shell pkg-config --libs gsl) +else + $(error bad value for STATICGSL option. Should be ON or OFF) +endif # Use GSL inline functions CXXFLAGS += -DHAVE_INLINE -DGSL_C99_INLINE @@ -288,21 +298,21 @@ check: $(sn3d_files) run-clang-tidy $(sn3d_files) $(BUILD_DIR)/sn3d: $(sn3d_objects) - $(CXX) $(CXXFLAGS) $(sn3d_objects) $(LDFLAGS) -o $(BUILD_DIR)/sn3d + $(CXX) $(CXXFLAGS) $(sn3d_objects) $(gsl_objects) $(LDFLAGS) -o $(BUILD_DIR)/sn3d -include $(sn3d_dep) sn3d: $(BUILD_DIR)/sn3d ln -sf $(BUILD_DIR)/sn3d sn3d $(BUILD_DIR)/sn3dwhole: $(sn3d_files) version.h artisoptions.h Makefile $(BUILD_DIR)/compiler.txt - $(CXX) $(CXXFLAGS) -g $(sn3d_files) $(LDFLAGS) -o $(BUILD_DIR)/sn3dwhole + $(CXX) $(CXXFLAGS) -g $(sn3d_files) $(gsl_objects) $(LDFLAGS) -o $(BUILD_DIR)/sn3dwhole -include $(sn3d_dep) sn3dwhole: $(BUILD_DIR)/sn3dwhole ln -sf $(BUILD_DIR)/sn3dwhole sn3d $(BUILD_DIR)/exspec: $(exspec_objects) - $(CXX) $(CXXFLAGS) $(exspec_objects) $(LDFLAGS) -o $(BUILD_DIR)/exspec + $(CXX) $(CXXFLAGS) $(exspec_objects) $(gsl_objects) $(LDFLAGS) -o $(BUILD_DIR)/exspec -include $(exspec_dep) exspec: $(BUILD_DIR)/exspec From fd4a14452382add845800931a0b82775906019c7 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 25 Sep 2024 08:26:12 +0200 Subject: [PATCH 051/117] Use clang-format v19.1.0 (#130) --- .github/workflows/ci-checks.yml | 9 +++++++-- .pre-commit-config.yaml | 4 ++-- decay.cc | 16 ++++++++-------- decay.h | 3 +-- grid.cc | 22 +++++++++++++--------- ltepop.cc | 4 ++-- ltepop.h | 8 ++++---- macroatom.cc | 8 ++++---- macroatom.h | 8 ++++---- nltepop.cc | 4 ++-- nonthermal.cc | 24 ++++++++++++------------ radfield.cc | 4 ++-- radfield.h | 4 ++-- ratecoeff.cc | 4 ++-- ratecoeff.h | 16 ++++++++-------- rpkt.h | 8 ++++---- sn3d.h | 4 ++-- stats.cc | 4 ++-- thermalbalance.h | 4 ++-- update_grid.cc | 4 +++- vectors.h | 16 ++++++++-------- 21 files changed, 94 insertions(+), 84 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index fa1544e23..d94a312ff 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -29,14 +29,19 @@ jobs: cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: - runs-on: ubuntu-24.04 + runs-on: macos-14 steps: - uses: actions/checkout@v4 + - name: install clang-format + run: | + brew update + brew install clang-format || true + - name: Run clang-format style check uses: jidicula/clang-format-action@v4.13.0 with: - clang-format-version: '18' + clang-format-version: '19' check-path: . clang-tidy: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a082f1615..e5c2f93d9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-added-large-files args: [--maxkb=800] @@ -22,7 +22,7 @@ repos: args: [--fix=lf] - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-clang-format - rev: 'v18.1.8' + rev: 'v19.1.1' hooks: - id: clang-format files: '\.(c|cc|cpp|h|hpp|cxx|hh|inc)$' diff --git a/decay.cc b/decay.cc index 09064e9c1..93efd7f19 100644 --- a/decay.cc +++ b/decay.cc @@ -501,8 +501,8 @@ auto sample_decaytime(const int decaypathindex, const double tdecaymin, const do } constexpr auto calculate_decaychain(const double firstinitabund, const std::vector &lambdas, - const int num_nuclides, const double timediff, - const bool useexpansionfactor) -> double { + const int num_nuclides, const double timediff, const bool useexpansionfactor) + -> double { // calculate final number abundance from multiple decays, e.g., Ni56 -> Co56 -> Fe56 (nuc[0] -> nuc[1] -> nuc[2]) // the top nuclide initial abundance is set and the chain-end abundance is returned (all intermediates nuclides // are assumed to start with zero abundance) @@ -615,8 +615,8 @@ auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const return nuctotal; } -auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const int decaypathindex, - const double time) -> double +auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const int decaypathindex, const double time) + -> double // returns decay energy [erg/g] that would be released from time tstart [s] to time infinity by a given decaypath { // e.g. Ni56 -> Co56, represents the decay of Co56 nuclei @@ -653,8 +653,8 @@ auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const } auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, - const int decaypathindex, - const double tstart) -> double + const int decaypathindex, const double tstart) + -> double // just here as as check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() // this version does an Euler integration { @@ -1112,8 +1112,8 @@ void free_decaypath_energy_per_mass() { } // energy release rate in form of kinetic energy of positrons, electrons, and alpha particles in [erg/s/g] -[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, - const int decaytype) -> double { +[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) + -> double { double dep_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { diff --git a/decay.h b/decay.h index 9e115666b..93e1c38ef 100644 --- a/decay.h +++ b/decay.h @@ -1,9 +1,8 @@ #ifndef DECAY_H #define DECAY_H -// #include - #include +#include #include #include diff --git a/grid.cc b/grid.cc index 84b23a08a..3c5f88c78 100644 --- a/grid.cc +++ b/grid.cc @@ -264,7 +264,9 @@ void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, } // if (globals::rank_in_node == 0) - { modelgrid[mgi].initmassfracuntrackedstable[element] = massfrac_untrackedstable; } + { + modelgrid[mgi].initmassfracuntrackedstable[element] = massfrac_untrackedstable; + } // (isofracsum + massfracstable) might not exactly match elemabundance if we had to boost it to reach isofracsum set_elem_abundance(mgi, element, isofracsum + massfrac_untrackedstable); @@ -1598,11 +1600,12 @@ template return -1.; } -auto get_coordboundary_distances_cylindrical2d( - const std::array &pkt_pos, const std::array &pkt_dir, - const std::array &pktposgridcoord, const std::array &pktvelgridcoord, const int cellindex, - const double tstart, - const std::array &cellcoordmax) -> std::tuple, std::array> { +auto get_coordboundary_distances_cylindrical2d(const std::array &pkt_pos, + const std::array &pkt_dir, + const std::array &pktposgridcoord, + const std::array &pktvelgridcoord, const int cellindex, + const double tstart, const std::array &cellcoordmax) + -> std::tuple, std::array> { // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the // propagation speed set to the xy component of the 3-velocity @@ -2421,9 +2424,10 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } // compute distance to a cell boundary. -[[nodiscard]] __host__ __device__ auto boundary_distance( - const std::array &dir, const std::array &pos, const double tstart, const int cellindex, - enum cell_boundary *pkt_last_cross) -> std::tuple { +[[nodiscard]] __host__ __device__ auto boundary_distance(const std::array &dir, + const std::array &pos, const double tstart, + const int cellindex, enum cell_boundary *pkt_last_cross) + -> std::tuple { if constexpr (FORCE_SPHERICAL_ESCAPE_SURFACE) { if (get_cell_r_inner(cellindex) > globals::vmax * globals::tmin) { return {0., -99}; diff --git a/ltepop.cc b/ltepop.cc index 8cac5b535..022cda193 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -514,8 +514,8 @@ auto calculate_levelpop(const int modelgridindex, const int element, const int i } // Calculate the population of a level from either LTE or NLTE information -__host__ __device__ auto get_levelpop(const int modelgridindex, const int element, const int ion, - const int level) -> double { +__host__ __device__ auto get_levelpop(const int modelgridindex, const int element, const int ion, const int level) + -> double { double nn = 0.; if (use_cellcache) { assert_testmodeonly(modelgridindex == globals::cellcache[cellcacheslotid].cellnumber); diff --git a/ltepop.h b/ltepop.h index 14a930846..1cbdd039c 100644 --- a/ltepop.h +++ b/ltepop.h @@ -7,13 +7,13 @@ [[nodiscard]] auto calculate_levelpop(int modelgridindex, int element, int ion, int level) -> double; [[nodiscard]] auto calculate_levelpop_lte(int modelgridindex, int element, int ion, int level) -> double; [[nodiscard]] auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double; -[[nodiscard]] auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, - double E_threshold) -> double; +[[nodiscard]] auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, double E_threshold) + -> double; [[nodiscard]] auto get_nnion(int modelgridindex, int element, int ion) -> double; void calculate_ion_balance_nne(int modelgridindex); void calculate_cellpartfuncts(int modelgridindex, int element); -[[nodiscard]] auto calculate_ionfractions(int element, int modelgridindex, double nne, - bool use_phi_lte) -> std::vector; +[[nodiscard]] auto calculate_ionfractions(int element, int modelgridindex, double nne, bool use_phi_lte) + -> std::vector; void set_groundlevelpops(int modelgridindex, int element, float nne, bool force_lte); #endif // LTEPOP_H diff --git a/macroatom.cc b/macroatom.cc index 4693ce74c..8e9140a30 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -151,8 +151,8 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele return processrates; } -auto do_macroatom_internal_down_same(const int element, const int ion, const int level, - const CellCacheLevels &chlevel) -> int { +auto do_macroatom_internal_down_same(const int element, const int ion, const int level, const CellCacheLevels &chlevel) + -> int { const int ndowntrans = get_ndowntrans(element, ion, level); // printout("[debug] do_ma: internal downward jump within current ionstage\n"); @@ -904,8 +904,8 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e // multiply by lower level population to get a rate per second auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, - const int uptransindex, const double epsilon_trans, - const double lowerstatweight) -> double { + const int uptransindex, const double epsilon_trans, const double lowerstatweight) + -> double { const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; const double coll_strength = uptr.coll_str; const double eoverkt = epsilon_trans / (KB * T_e); diff --git a/macroatom.h b/macroatom.h index 3265012c3..3b1428a67 100644 --- a/macroatom.h +++ b/macroatom.h @@ -10,11 +10,11 @@ void macroatom_close_file(); void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate); [[nodiscard]] auto rad_deexcitation_ratecoeff(int modelgridindex, int element, int ion, int lower, double epsilon_trans, - float A_ul, double upperstatweight, double nnlevelupper, - double t_current) -> double; + float A_ul, double upperstatweight, double nnlevelupper, double t_current) + -> double; [[nodiscard]] auto rad_excitation_ratecoeff(int modelgridindex, int element, int ion, int lower, int uptransindex, - double epsilon_trans, double nnlevel_lower, int lineindex, - double t_current) -> double; + double epsilon_trans, double nnlevel_lower, int lineindex, double t_current) + -> double; [[nodiscard]] auto rad_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upperionlevel, int lowerionlevel, int modelgridindex) -> double; [[nodiscard]] auto stim_recombination_ratecoeff(float nne, int element, int upperion, int upper, int lower, diff --git a/nltepop.cc b/nltepop.cc index 8bf3f9048..381cd0edb 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -120,8 +120,8 @@ void filter_nlte_matrix(const int element, gsl_matrix *rate_matrix, gsl_vector * } [[nodiscard]] auto get_total_rate(const int index_selected, const gsl_matrix *rate_matrix, const gsl_vector *popvec, - const bool into_level, const bool only_levels_below, - const bool only_levels_above) -> double { + const bool into_level, const bool only_levels_below, const bool only_levels_above) + -> double { double total_rate = 0.; assert_always(!only_levels_below || !only_levels_above); diff --git a/nonthermal.cc b/nonthermal.cc index 4a2ccbc1f..f95db1d01 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -694,8 +694,8 @@ auto get_xs_ionization_vector(std::array &xs_vec, const collionro // distribution of secondary electron energies for primary electron with energy e_p // Opal, Peterson, & Beaty (1971) -[[nodiscard]] constexpr auto Psecondary(const double e_p, const double epsilon, const double I, - const double J) -> double { +[[nodiscard]] constexpr auto Psecondary(const double e_p, const double epsilon, const double I, const double J) + -> double { const double e_s = epsilon - I; if (e_p <= I || e_s < 0.) { @@ -1081,8 +1081,8 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> // the fraction of deposited energy that goes into ionising electrons in a particular shell auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int element, const int ion, - const collionrow &collionrow, - const std::array &yfunc) -> double { + const collionrow &collionrow, const std::array &yfunc) + -> double { const double nnion = get_nnion(modelgridindex, element, ion); const double ionpot_ev = collionrow.ionpot_ev; @@ -1105,8 +1105,8 @@ auto nt_ionization_ratecoeff_wfapprox(const int modelgridindex, const int elemen } auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion, - const bool assumeshellpotentialisvalence, - const std::array &yfunc) -> double + const bool assumeshellpotentialisvalence, const std::array &yfunc) + -> double // Integrate the ionization cross section over the electron degradation function to get the ionization rate coefficient // i.e. multiply this by ion population to get a rate of ionizations per second // Do not call during packet propagation, as the y vector may not be in memory! @@ -1286,8 +1286,8 @@ auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, con // returns the index of the first valid cross section point (en >= epsilon_trans) // all elements below this index are invalid and should not be used auto get_xs_excitation_vector(const int element, const int ion, const int lower, const int uptransindex, - const double statweight_lower, - const double epsilon_trans) -> std::tuple, int> { + const double statweight_lower, const double epsilon_trans) + -> std::tuple, int> { std::array xs_excitation_vec{}; const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; if (uptr.coll_str >= 0) { @@ -1344,8 +1344,8 @@ auto get_xs_excitation_vector(const int element, const int ion, const int lower, // returns the rate coefficient in s^-1 divided by deposition rate density in erg/cm^3/s auto calculate_nt_excitation_ratecoeff_perdeposition(const std::array &yvec, const int element, const int ion, const int lower, const int uptransindex, - const double statweight_lower, - const double epsilon_trans) -> double { + const double statweight_lower, const double epsilon_trans) + -> double { const auto [xs_excitation_vec, xsstartindex] = get_xs_excitation_vector(element, ion, lower, uptransindex, statweight_lower, epsilon_trans); @@ -2264,8 +2264,8 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const } __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, - const int lowerlevel, const int uptransindex, - const int lineindex) -> double { + const int lowerlevel, const int uptransindex, const int lineindex) + -> double { if constexpr (!NT_EXCITATION_ON) { return 0.; } diff --git a/radfield.cc b/radfield.cc index a7a3a2b41..c50324a0d 100644 --- a/radfield.cc +++ b/radfield.cc @@ -905,8 +905,8 @@ __host__ __device__ auto radfield(const double nu, const int modelgridindex) -> // return the integral of nu^3 / (exp(h nu / k T) - 1) from nu_lower to nu_upper // or if times_nu is true, the integral of nu^4 / (exp(h nu / k T) - 1) from nu_lower to nu_upper -auto planck_integral_analytic(const double T_R, const double nu_lower, const double nu_upper, - const bool times_nu) -> double { +auto planck_integral_analytic(const double T_R, const double nu_lower, const double nu_upper, const bool times_nu) + -> double { double integral = 0.; if (times_nu) { diff --git a/radfield.h b/radfield.h index 8a335c1ae..406c785ca 100644 --- a/radfield.h +++ b/radfield.h @@ -34,8 +34,8 @@ void do_MPI_Bcast(int modelgridindex, int root, int root_node_id); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); void normalise_bf_estimators(int nts, int nts_prev, int titer, double deltat); -[[nodiscard]] auto get_bfrate_estimator(int element, int lowerion, int lower, int phixstargetindex, - int modelgridindex) -> double; +[[nodiscard]] auto get_bfrate_estimator(int element, int lowerion, int lower, int phixstargetindex, int modelgridindex) + -> double; void print_bfrate_contributions(int element, int lowerion, int lower, int phixstargetindex, int modelgridindex, double nnlowerlevel, double nnlowerion); void reset_bfrate_contributions(int modelgridindex); diff --git a/ratecoeff.cc b/ratecoeff.cc index 942c43942..f6715a1cd 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -996,8 +996,8 @@ __host__ __device__ auto get_spontrecombcoeff(int element, const int ion, const // multiply by upper ion population (or ground population if per_groundmultipletpop is true) and nne to get a rate auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const int element, const int upperion, const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, - const bool lower_superlevel_only, const bool per_groundmultipletpop, - const bool stimonly) -> double { + const bool lower_superlevel_only, const bool per_groundmultipletpop, const bool stimonly) + -> double { const int lowerion = upperion - 1; if (lowerion < 0) { return 0.; diff --git a/ratecoeff.h b/ratecoeff.h index 05aa066bb..c351b6979 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -17,19 +17,19 @@ void setup_photoion_luts(); [[nodiscard]] auto select_continuum_nu(int element, int lowerion, int lower, int upperionlevel, float T_e) -> double; -[[nodiscard]] auto interpolate_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, - double T) -> double; +[[nodiscard]] auto interpolate_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, double T) + -> double; [[nodiscard]] auto get_spontrecombcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double; -[[nodiscard]] auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetindex, - int modelgridindex) -> double; +[[nodiscard]] auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetindex, int modelgridindex) + -> double; [[nodiscard]] auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double; -[[nodiscard]] auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, - int modelgridindex) -> double; -[[nodiscard]] auto get_corrphotoioncoeff_ana(int element, int ion, int level, int phixstargetindex, - int modelgridindex) -> double; +[[nodiscard]] auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, int modelgridindex) + -> double; +[[nodiscard]] auto get_corrphotoioncoeff_ana(int element, int ion, int level, int phixstargetindex, int modelgridindex) + -> double; [[nodiscard]] auto iongamma_is_zero(int nonemptymgi, int element, int ion) -> bool; diff --git a/rpkt.h b/rpkt.h index 077bdecf4..871bf59ff 100644 --- a/rpkt.h +++ b/rpkt.h @@ -102,8 +102,8 @@ constexpr auto closest_transition(const double nu_cmf, const int next_trans, con return matchindex; } -[[nodiscard]] inline auto get_ionestimindex_nonemptymgi(const int nonemptymgi, const int element, - const int ion) -> int { +[[nodiscard]] inline auto get_ionestimindex_nonemptymgi(const int nonemptymgi, const int element, const int ion) + -> int { assert_testmodeonly(ion >= 0); assert_testmodeonly(ion < get_nions(element) - 1); const int groundcontindex = globals::elements[element].ions[ion].groundcontindex; @@ -111,8 +111,8 @@ constexpr auto closest_transition(const double nu_cmf, const int next_trans, con return (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; } -inline auto keep_this_cont(int element, const int ion, const int level, const int modelgridindex, - const float nnetot) -> bool { +inline auto keep_this_cont(int element, const int ion, const int level, const int modelgridindex, const float nnetot) + -> bool { if constexpr (DETAILED_BF_ESTIMATORS_ON) { return grid::get_elem_abundance(modelgridindex, element) > 0; } diff --git a/sn3d.h b/sn3d.h index 458e501c9..3fbe4a42a 100644 --- a/sn3d.h +++ b/sn3d.h @@ -313,8 +313,8 @@ inline void check_already_running() { #endif } -constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, - const ptrdiff_t nchunk) -> std::tuple { +constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, const ptrdiff_t nchunk) + -> std::tuple { assert_always(size >= 0); assert_always(nchunks >= 0); assert_always(nchunk >= 0); diff --git a/stats.cc b/stats.cc index 198db4e7b..4784986aa 100644 --- a/stats.cc +++ b/stats.cc @@ -111,8 +111,8 @@ void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridin } } -auto get_ion_stats(const int modelgridindex, const int element, const int ion, - enum ionstattypes ionstattype) -> double { +auto get_ion_stats(const int modelgridindex, const int element, const int ion, enum ionstattypes ionstattype) + -> double { assert_always(ion < get_nions(element)); assert_always(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); diff --git a/thermalbalance.h b/thermalbalance.h index e99b3b806..91a44c73d 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -26,8 +26,8 @@ struct HeatingCoolingRates { void call_T_e_finder(int modelgridindex, int timestep, double t_current, double T_min, double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs); -[[nodiscard]] auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, - double W) -> double; +[[nodiscard]] auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, double W) + -> double; void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs); #endif // THERMALBALANCE_H diff --git a/update_grid.cc b/update_grid.cc index 3d375f2ce..502eca330 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1155,7 +1155,9 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #ifdef _OPENMP #pragma omp critical(estimators_file) #endif - { write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates); } + { + write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates); + } } // end parallel for loop over all modelgrid cells } // end OpenMP parallel section diff --git a/vectors.h b/vectors.h index 8bee8c776..68616eca1 100644 --- a/vectors.h +++ b/vectors.h @@ -55,8 +55,8 @@ template // dir1: direction unit vector in frame1 // vel: velocity of frame2 relative to frame1 // dir2: direction vector in frame2 -[[nodiscard]] constexpr auto angle_ab(const std::array &dir1, - const std::array &vel) -> std::array { +[[nodiscard]] constexpr auto angle_ab(const std::array &dir1, const std::array &vel) + -> std::array { const double vsqr = dot(vel, vel) / CLIGHTSQUARED; const double gamma_rel = 1. / std::sqrt(1 - vsqr); @@ -77,8 +77,8 @@ template // prop_time: the propagation time of the packet // returns: the ratio f = (nu_cmf / nu_rf) ^ 2 [[nodiscard]] constexpr auto doppler_squared_nucmf_on_nurf(const std::array &pos_rf, - const std::array &dir_rf, - const double prop_time) -> double { + const std::array &dir_rf, const double prop_time) + -> double { // velocity of the comoving frame relative to the rest frame const auto vel_rf = get_velocity(pos_rf, prop_time); @@ -212,8 +212,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { // Rotation angle from the scattering plane [[nodiscard]] constexpr auto get_rot_angle(const std::array &n1, const std::array &n2, - const std::array &ref1, - const std::array &ref2) -> double { + const std::array &ref1, const std::array &ref2) + -> double { // We need to rotate Stokes Parameters to (or from) the scattering plane from (or to) // the meridian frame such that Q=1 is in the scattering plane and along ref1 @@ -292,8 +292,8 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { } // Routine to transform the Stokes Parameters from RF to CMF -constexpr auto frame_transform(const std::array &n_rf, double *Q, double *U, - const std::array &v) -> std::array { +constexpr auto frame_transform(const std::array &n_rf, double *Q, double *U, const std::array &v) + -> std::array { // Meridian frame in the RF const auto [ref1_rf, ref2_rf] = meridian(n_rf); From 1b8a3c09310f3296880a787426f04a7699824984 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 1 Oct 2024 10:44:20 +0200 Subject: [PATCH 052/117] Optionally apply time-dependent thermalisation to electrons/positrons produced from gamma-rays (#127) Time-dependent thermalisation was only applied to alphas and betas emitted directly by decays. With the DETAILEDWITHGAMMAPRODUCTS thermalisation mode, the time-dependent treatment also applies to the Compton electrons, photoionised ejected electrons, or electron/positrons from pair-production. Their contributions are still called "gamma-ray deposition" and these particles do not contribute to the alpha and beta deposition rates. --- constants.h | 2 +- gammapkt.cc | 45 ++++++++++++++++++++++++++++++++++----------- update_packets.cc | 39 +++++++++++++++++++++++++-------------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/constants.h b/constants.h index a38928eb5..1150fe4d7 100644 --- a/constants.h +++ b/constants.h @@ -59,6 +59,6 @@ constexpr size_t GSLWSIZE = 16384; // GSL integration workspace size enum class TimeStepSizeMethod { LOGARITHMIC, CONSTANT, LOGARITHMIC_THEN_CONSTANT, CONSTANT_THEN_LOGARITHMIC }; -enum class ThermalisationScheme { INSTANT, DETAILED, BARNES, WOLLAEGER, GUTTMAN }; +enum class ThermalisationScheme { INSTANT, DETAILED, DETAILEDWITHGAMMAPRODUCTS, BARNES, WOLLAEGER, GUTTMAN }; #endif diff --git a/gammapkt.cc b/gammapkt.cc index 379d21cc4..594de2336 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -441,8 +441,13 @@ void compton_scatter(Packet &pkt) { pkt.last_cross = BOUNDARY_NONE; // allow it to re-cross a boundary } else { - // It's converted to an e-minus packet. - pkt.type = TYPE_NTLEPTON_DEPOSITED; + // energy loss of the gamma becomes energy of the electron (needed to calculate time-dependent thermalisation rate) + if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + pkt.nu_cmf = pkt.nu_cmf * (1 - 1 / f); + pkt.type = TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS; + } else { + pkt.type = TYPE_NTLEPTON_DEPOSITED; + } pkt.absorptiontype = -3; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } @@ -632,6 +637,9 @@ void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const if (!(dist > 0)) { return; } + if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + return; // don't instantly deposit energy from gamma rays, handle the particles they produce instead + } const double doppler_sq = doppler_squared_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -666,10 +674,16 @@ void pair_prod(Packet &pkt) { assert_always(prob_gamma >= 0); - if (rng_uniform() > prob_gamma) { - // Convert it to an e-minus packet - actually it could be positron EK too, but this works - // for consistency with compton_scatter. - pkt.type = TYPE_NTLEPTON_DEPOSITED; + const auto zrand = rng_uniform(); + if (zrand > prob_gamma) { + if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + // Convert it to an e-minus or positron kinetic energy packet + pkt.type = (rng_uniform() > 0.5) ? TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS : TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS; + } else { + pkt.type = TYPE_NTLEPTON_DEPOSITED; + } + + // nu_cmf stays the same as the gamma energy becomes the kinetic energy of the electron pkt.absorptiontype = -5; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } else { @@ -809,8 +823,15 @@ void transport_gamma(Packet &pkt, const double t2) { // Compton scattering. compton_scatter(pkt); } else if ((chi_compton + chi_photo_electric) > chi_rnd) { - // Photo electric effect - makes it a k-packet for sure. - pkt.type = TYPE_NTLEPTON_DEPOSITED; + // Photo electric effect + if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + pkt.type = TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS; + // nu_cmf stays the same as the gamma-ray energy becomes the kinetic energy of the electron (minus ionisation + // energy but this is neglected here) + } else { + pkt.type = TYPE_NTLEPTON_DEPOSITED; + } + pkt.absorptiontype = -4; stats::increment(stats::COUNTER_NT_STAT_FROM_GAMMA); } else { @@ -818,7 +839,6 @@ void transport_gamma(Packet &pkt, const double t2) { pair_prod(pkt); } } else { - printout("Failed to identify event. Gamma (2). edist %g, sdist %g, tdist %g Abort.\n", edist, sdist, tdist); assert_always(false); } } @@ -1055,9 +1075,12 @@ __host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { } if (pkt.type != TYPE_GAMMA && pkt.type != TYPE_ESCAPE) { - atomicadd(globals::timesteps[nts].gamma_dep_discrete, pkt.e_cmf); + if constexpr (PARTICLE_THERMALISATION_SCHEME != ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + atomicadd(globals::timesteps[nts].gamma_dep_discrete, pkt.e_cmf); + } - if constexpr (GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILED) { + if constexpr (GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILED && + GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { // no transport, so the path-based gamma deposition estimator won't get updated unless we do it here const int mgi = grid::get_cell_modelgridindex(pkt.where); const int nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); diff --git a/update_packets.cc b/update_packets.cc index 4623f41d1..543b4e135 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -73,6 +73,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { grid::change_cell(pkt, -99); } } else { + // ThermalisationScheme::DETAILED or ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS // local, detailed absorption following Shingles+2023 const double rho = grid::get_rho(grid::get_cell_modelgridindex(pkt.where)); @@ -113,20 +114,30 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { // contribute to the trajectory integrated deposition estimator // and if a deposition event occurred, also the discrete Monte Carlo count deposition rate - if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS) { - atomicadd(globals::dep_estimator_electron[nonemptymgi], en_deposited); - if (pkt.type == deposit_type) { - atomicadd(globals::timesteps[nts].electron_dep_discrete, pkt.e_cmf); - } - } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS) { - atomicadd(globals::dep_estimator_positron[nonemptymgi], en_deposited); - if (pkt.type == deposit_type) { - atomicadd(globals::timesteps[nts].positron_dep_discrete, pkt.e_cmf); - } - } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) { - atomicadd(globals::dep_estimator_alpha[nonemptymgi], en_deposited); - if (pkt.type == deposit_type) { - atomicadd(globals::timesteps[nts].alpha_dep_discrete, pkt.e_cmf); + // for DETAILEDWITHGAMMAPRODUCTS, gamma-ray deposition will lead to predeposit beta particles, but they will count + // toward "gamma deposition" not particle deposition + if (pkt.originated_from_particlenotgamma) { + if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAMINUS) { + atomicadd(globals::dep_estimator_electron[nonemptymgi], en_deposited); + if (pkt.type == deposit_type) { + atomicadd(globals::timesteps[nts].electron_dep_discrete, pkt.e_cmf); + } + } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_BETAPLUS) { + atomicadd(globals::dep_estimator_positron[nonemptymgi], en_deposited); + if (pkt.type == deposit_type) { + atomicadd(globals::timesteps[nts].positron_dep_discrete, pkt.e_cmf); + } + } else if (priortype == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) { + atomicadd(globals::dep_estimator_alpha[nonemptymgi], en_deposited); + if (pkt.type == deposit_type) { + atomicadd(globals::timesteps[nts].alpha_dep_discrete, pkt.e_cmf); + } + + } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { + atomicadd(globals::dep_estimator_gamma[nonemptymgi], en_deposited); + if (pkt.type == TYPE_NTLEPTON_DEPOSITED) { + atomicadd(globals::timesteps[nts].gamma_dep_discrete, pkt.e_cmf); + } } } } From c9f29d8c9929f70b89aac010075ac1c47656e093 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 7 Oct 2024 14:12:48 +0100 Subject: [PATCH 053/117] Update nonthermal.cc --- nonthermal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nonthermal.cc b/nonthermal.cc index f95db1d01..4ec4fc981 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -968,7 +968,7 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { } const int num_shells = electron_binding[get_atomicnumber(element) - 1].size(); - auto q = std::array{0}; + auto q = std::array{}; if (!NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { From b871dd0a15696ef38f54d58204719ae8123e5927 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 11 Oct 2024 11:30:17 +0100 Subject: [PATCH 054/117] nonthermal: refactor with new function get_approx_shell_occupancy() --- nonthermal.cc | 120 +++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 4ec4fc981..079576017 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -959,6 +959,62 @@ auto get_nt_frac_excitation(const int modelgridindex) -> float { return frac_excitation; } +auto get_approx_shell_occupancy(const int nbound, const int ioncharge) { + assert_always(nbound > 0); + assert_always(ioncharge >= 0); + auto q = std::array{}; + + for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { + if (q[0] < 2) { + q[0]++; // K 1s + } else if (q[1] < 2) { + q[1]++; // L1 2s + } else if (q[2] < 2) { + q[2]++; // L2 2p[1/2] + } else if (q[3] < 4) { + q[3]++; // L3 2p[3/2] + } else if (q[4] < 2) { + q[4]++; // M1 3s + } else if (q[5] < 2) { + q[5]++; // M2 3p[1/2] + } else if (q[6] < 4) { + q[6]++; // M3 3p[3/2] + } else if (ioncharge == 0) { + if (q[9] < 2) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } else if (ioncharge == 1) { + if (q[9] < 1) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } else if (ioncharge > 1) { + if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } + } + return q; +} + auto get_mean_binding_energy(const int element, const int ion) -> double { const int ioncharge = get_ionstage(element, ion) - 1; const int nbound = get_atomicnumber(element) - ioncharge; // number of bound electrons @@ -968,72 +1024,16 @@ auto get_mean_binding_energy(const int element, const int ion) -> double { } const int num_shells = electron_binding[get_atomicnumber(element) - 1].size(); - auto q = std::array{}; - - if (!NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { - for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { - if (q[0] < 2) { - q[0]++; // K 1s - } else if (q[1] < 2) { - q[1]++; // L1 2s - } else if (q[2] < 2) { - q[2]++; // L2 2p[1/2] - } else if (q[3] < 4) { - q[3]++; // L3 2p[3/2] - } else if (q[4] < 2) { - q[4]++; // M1 3s - } else if (q[5] < 2) { - q[5]++; // M2 3p[1/2] - } else if (q[6] < 4) { - q[6]++; // M3 3p[3/2] - } else if (ioncharge == 0) { - if (q[9] < 2) { - q[9]++; // N1 4s - } else if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } else if (ioncharge == 1) { - if (q[9] < 1) { - q[9]++; // N1 4s - } else if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } else if (ioncharge > 1) { - if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } - } - } - - // printout("For element %d ion %d I got q's of: %d %d %d %d %d %d %d %d %d %d\n", element, ion, q[0], q[1], - // q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9]); - // printout("%g %g %g %g %g %g %g %g %g %g\n", electron_binding[get_atomicnumber(element)-1][0], - // electron_binding[get_atomicnumber(element)-1][1], - // electron_binding[get_atomicnumber(element)-1][2],electron_binding[get_atomicnumber(element)-1][3],electron_binding[get_atomicnumber(element)-1][4],electron_binding[get_atomicnumber(element)-1][5],electron_binding[get_atomicnumber(element)-1][6],electron_binding[get_atomicnumber(element)-1][7],electron_binding[get_atomicnumber(element)-1][8],electron_binding[get_atomicnumber(element)-1][9]); + // get the approximate shell occupancy if we don't have the data file + auto approx_shells_q = get_approx_shell_occupancy(nbound, ioncharge); double total = 0.; for (int shellindex = 0; shellindex < num_shells; shellindex++) { int electronsinshell = 0; if constexpr (NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { electronsinshell = shells_q[get_atomicnumber(element) - 1][shellindex]; - } else if (shellindex < std::ssize(q)) { - electronsinshell = q[shellindex]; + } else if (shellindex < std::ssize(approx_shells_q)) { + electronsinshell = approx_shells_q[shellindex]; } if (electronsinshell <= 0) { From c64cbbca02c76a22a6194c0860186e44025de70e Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 11 Oct 2024 12:10:23 +0100 Subject: [PATCH 055/117] Comment out debug prints for NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE --- nonthermal.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 079576017..312a35d98 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -262,12 +262,12 @@ void read_shell_configs() { int z_element = 0; assert_always(ssline >> z_element); - printout("Reading shells Z=%d\n", z_element); + // printout("Reading shells Z=%d\n", z_element); for (int shell = 0; shell < nshells; shell++) { int q = 0; assert_always(ssline >> q); - printout("q of %d in shell %d element number %d Z=%d\n", q, shell, elementcounter, z_element); + // printout("q of %d in shell %d element number %d Z=%d\n", q, shell, elementcounter, z_element); shells_q[elementcounter][shell] = q; } elementcounter++; @@ -315,6 +315,10 @@ void read_binding_energies() { } if constexpr (NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { + if (!binding_en_newformat) { + printout( + "NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE is true, but could not find binding_energies_lotz_tab1and2.txt\n"); + } assert_always(binding_en_newformat); read_shell_configs(); } From b00b0b91314d787a068270fb158d0a76f185eda8 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 16 Oct 2024 23:49:59 +0100 Subject: [PATCH 056/117] Update .pre-commit-config.yaml --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e5c2f93d9..dd997faef 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--fix=lf] - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-clang-format - rev: 'v19.1.1' + rev: 'v19.1.2' hooks: - id: clang-format files: '\.(c|cc|cpp|h|hpp|cxx|hh|inc)$' From ca0e34e3c6b98e054e85bf33e35021b864c328b8 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 18 Oct 2024 11:44:44 +0100 Subject: [PATCH 057/117] Enable openmp-simd (#134) --- Makefile | 2 +- atomic.h | 1 + macroatom.cc | 9 +++++++++ macroatom.h | 12 ++++++++++-- nonthermal.cc | 1 + nonthermal.h | 1 + radfield.cc | 2 ++ 7 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9d5177d17..f58e1a6b3 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ CXXFLAGS += -std=c++20 -fstrict-aliasing # CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true ifneq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -ftree-vectorize -Wunknown-pragmas -Wunused-macros -Werror -MD -MP + CXXFLAGS += -fopenmp-simd -ftree-vectorize -Wunknown-pragmas -Wunused-macros -Werror -MD -MP # add -ftrivial-auto-var-init=zero when we drop gcc 11 support endif diff --git a/atomic.h b/atomic.h index f0771228a..f3f2cf4f0 100644 --- a/atomic.h +++ b/atomic.h @@ -52,6 +52,7 @@ inline auto get_nlevels(const int element, const int ion) -> int { } // Return the energy of (element,ion,level). +#pragma omp declare simd [[nodiscard]] inline auto epsilon(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); diff --git a/macroatom.cc b/macroatom.cc index 8e9140a30..96f3c8483 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -54,6 +54,7 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const auto *const leveldowntranslist = get_downtranslist(element, ion, level); auto *const arr_sum_epstrans_rad_deexc = chlevel.sum_epstrans_rad_deexc; auto *const arr_sum_internal_down_same = chlevel.sum_internal_down_same; +#pragma omp simd reduction(+ : sum_raddeexc, sum_coldeexc, sum_internal_down_same) for (int i = 0; i < ndowntrans; i++) { const auto &downtrans = leveldowntranslist[i]; const int lower = downtrans.targetlevelindex; @@ -83,6 +84,7 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele double sum_internal_up_same = 0.; const int nuptrans = get_nuptrans(element, ion, level); const auto *const uptranslist = get_uptranslist(element, ion, level); +#pragma omp simd reduction(+ : sum_internal_up_same) for (int i = 0; i < nuptrans; i++) { const auto &uptrans = uptranslist[i]; const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; @@ -648,6 +650,7 @@ void macroatom_close_file() { // radiative deexcitation rate: paperII 3.5.2 // multiply by upper level population to get a rate per second +#pragma omp declare simd auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, const double epsilon_trans, const float A_ul, const double upperstatweight, const double nnlevelupper, const double t_current) -> double { @@ -691,6 +694,7 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con // radiative excitation rate: paperII 3.5.2 // multiply by lower level population to get a rate per second +#pragma omp declare simd auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double nnlevel_lower, const int lineindex, const double t_current) -> double { @@ -732,6 +736,7 @@ auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const // radiative recombination rate: paperII 3.5.2 // multiply by upper level population to get a rate per second +#pragma omp declare simd auto rad_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, const int upperionlevel, const int lowerionlevel, const int modelgridindex) -> double { // it's probably faster to only check this condition outside this function @@ -780,6 +785,7 @@ auto stim_recombination_ratecoeff(const float nne, const int element, const int } // multiply by upper level population to get a rate per second +#pragma omp declare simd auto col_recombination_ratecoeff(const int modelgridindex, const int element, const int upperion, const int upper, const int lower, const double epsilon_trans) -> double { // it's probably faster to only check this condition outside this function @@ -822,6 +828,7 @@ auto col_recombination_ratecoeff(const int modelgridindex, const int element, co // collisional ionization rate: paperII 3.5.1 // multiply by lower level population to get a rate per second +#pragma omp declare simd auto col_ionization_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int phixstargetindex, const double epsilon_trans) -> double { assert_testmodeonly(phixstargetindex >= 0); @@ -853,6 +860,7 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen } // multiply by upper level population to get a rate per second +#pragma omp declare simd auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, const int element, const int ion, const int upper, const LevelTransition &downtransition) -> double { const int lower = downtransition.targetlevelindex; @@ -903,6 +911,7 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e } // multiply by lower level population to get a rate per second +#pragma omp declare simd auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double lowerstatweight) -> double { diff --git a/macroatom.h b/macroatom.h index 3b1428a67..9593987a9 100644 --- a/macroatom.h +++ b/macroatom.h @@ -9,25 +9,33 @@ void macroatom_close_file(); void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate); +#pragma omp declare simd [[nodiscard]] auto rad_deexcitation_ratecoeff(int modelgridindex, int element, int ion, int lower, double epsilon_trans, float A_ul, double upperstatweight, double nnlevelupper, double t_current) -> double; + +#pragma omp declare simd [[nodiscard]] auto rad_excitation_ratecoeff(int modelgridindex, int element, int ion, int lower, int uptransindex, double epsilon_trans, double nnlevel_lower, int lineindex, double t_current) -> double; + +#pragma omp declare simd [[nodiscard]] auto rad_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upperionlevel, int lowerionlevel, int modelgridindex) -> double; +#pragma omp declare simd [[nodiscard]] auto stim_recombination_ratecoeff(float nne, int element, int upperion, int upper, int lower, int modelgridindex) -> double; +#pragma omp declare simd [[nodiscard]] auto col_recombination_ratecoeff(int modelgridindex, int element, int upperion, int upper, int lower, double epsilon_trans) -> double; +#pragma omp declare simd [[nodiscard]] auto col_ionization_ratecoeff(float T_e, float nne, int element, int ion, int lower, int phixstargetindex, double epsilon_trans) -> double; - +#pragma omp declare simd [[nodiscard]] auto col_deexcitation_ratecoeff(float T_e, float nne, double epsilon_trans, int element, int ion, int upper, const LevelTransition &downtransition) -> double; - +#pragma omp declare simd [[nodiscard]] auto col_excitation_ratecoeff(float T_e, float nne, int element, int ion, int lower, int uptransindex, double epsilon_trans, double lowerstatweight) -> double; diff --git a/nonthermal.cc b/nonthermal.cc index 312a35d98..7df6c6246 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2267,6 +2267,7 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const return nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion); } +#pragma omp declare simd __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lowerlevel, const int uptransindex, const int lineindex) -> double { diff --git a/nonthermal.h b/nonthermal.h index d4acf718c..bb14e4549 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -18,6 +18,7 @@ void solve_spencerfano(int modelgridindex, int timestep, int iteration); void calculate_deposition_rate_density(int modelgridindex, int timestep, HeatingCoolingRates *heatingcoolingrates); [[nodiscard]] auto get_deposition_rate_density(int modelgridindex) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; +#pragma omp declare simd [[nodiscard]] auto nt_excitation_ratecoeff(int modelgridindex, int element, int ion, int lowerlevel, int uptransindex, int lineindex) -> double; void do_ntalpha_deposit(Packet &pkt); diff --git a/radfield.cc b/radfield.cc index c50324a0d..08b62977b 100644 --- a/radfield.cc +++ b/radfield.cc @@ -118,6 +118,7 @@ constexpr auto get_bin_nu_lower(const int binindex) -> double { } // find the left-closed bin [nu_lower, nu_upper) that nu belongs to +#pragma omp declare simd constexpr auto select_bin(const double nu) -> int { if (nu < nu_lower_first_initial) { return -2; // out of range, nu lower than lowest bin's lower boundary @@ -266,6 +267,7 @@ void update_bfestimators(const int nonemptymgi, const double distance_e_cmf, con globals::bfestim_nu_edge.data(); const auto bfestimcount = globals::bfestimcount; +#pragma omp simd for (auto bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { atomicadd(bfrate_raw[(nonemptymgi * bfestimcount) + bfestimindex], phixslist.gamma_contr[bfestimindex] * distance_e_cmf_over_nu); From cab287e099e4f2d184f832e83196f60ac1ccefe0 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 18 Oct 2024 13:39:13 +0100 Subject: [PATCH 058/117] Add Lotz approximation for non-thermal ionisation without Arnaud & Rothenflug data (#132) --- artisoptions_classic.h | 1 - atomic.h | 1 + decay.cc | 4 +- ltepop.cc | 6 +- ltepop.h | 3 + macroatom.cc | 2 - nonthermal.cc | 439 ++++++++++++++++++++++++++++------------- spectrum_lightcurve.cc | 8 +- spectrum_lightcurve.h | 5 +- 9 files changed, 314 insertions(+), 155 deletions(-) diff --git a/artisoptions_classic.h b/artisoptions_classic.h index 0e34b81d8..8a6121d35 100644 --- a/artisoptions_classic.h +++ b/artisoptions_classic.h @@ -53,7 +53,6 @@ constexpr bool TRACK_ION_STATS = false; constexpr double MINPOP = 1e-30; constexpr double NU_MIN_R = 1e14; - constexpr double NU_MAX_R = 5e15; constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = true; diff --git a/atomic.h b/atomic.h index f3f2cf4f0..b624ee689 100644 --- a/atomic.h +++ b/atomic.h @@ -114,6 +114,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) } // Return the statistical weight of (element,ion,level). +#pragma omp declare simd [[nodiscard]] inline auto stat_weight(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); diff --git a/decay.cc b/decay.cc index 93efd7f19..113bf1c0e 100644 --- a/decay.cc +++ b/decay.cc @@ -38,7 +38,7 @@ namespace decay { namespace { -constexpr std::array elsymbols{ +const std::array elsymbols{ "n", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", @@ -775,7 +775,7 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode [[nodiscard]] auto get_elname(const int z) -> std::string { assert_testmodeonly(z <= Z_MAX); - return std::string(elsymbols[z]); + return elsymbols[z]; } [[nodiscard]] auto get_nuc_z(const int nucindex) -> int { diff --git a/ltepop.cc b/ltepop.cc index 022cda193..47d999f6d 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -74,11 +74,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const auto T_e = grid::get_Te(modelgridindex); double Gamma = 0.; - if constexpr (USE_LUT_PHOTOION) { - Gamma = globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]; - } else { - Gamma = calculate_iongamma_per_gspop(modelgridindex, element, ion); - } + Gamma = globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]; // Gamma is the photoionization rate per ground level pop const double Gamma_ion = Gamma * stat_weight(element, ion, 0) / partfunc_ion; diff --git a/ltepop.h b/ltepop.h index 1cbdd039c..965245d4b 100644 --- a/ltepop.h +++ b/ltepop.h @@ -4,8 +4,11 @@ #include [[nodiscard]] auto get_groundlevelpop(int modelgridindex, int element, int ion) -> double; +#pragma omp declare simd [[nodiscard]] auto calculate_levelpop(int modelgridindex, int element, int ion, int level) -> double; +#pragma omp declare simd [[nodiscard]] auto calculate_levelpop_lte(int modelgridindex, int element, int ion, int level) -> double; +#pragma omp declare simd [[nodiscard]] auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double; [[nodiscard]] auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, double E_threshold) -> double; diff --git a/macroatom.cc b/macroatom.cc index 96f3c8483..253a5eeb2 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -54,7 +54,6 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const auto *const leveldowntranslist = get_downtranslist(element, ion, level); auto *const arr_sum_epstrans_rad_deexc = chlevel.sum_epstrans_rad_deexc; auto *const arr_sum_internal_down_same = chlevel.sum_internal_down_same; -#pragma omp simd reduction(+ : sum_raddeexc, sum_coldeexc, sum_internal_down_same) for (int i = 0; i < ndowntrans; i++) { const auto &downtrans = leveldowntranslist[i]; const int lower = downtrans.targetlevelindex; @@ -84,7 +83,6 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele double sum_internal_up_same = 0.; const int nuptrans = get_nuptrans(element, ion, level); const auto *const uptranslist = get_uptranslist(element, ion, level); -#pragma omp simd reduction(+ : sum_internal_up_same) for (int i = 0; i < nuptrans; i++) { const auto &uptrans = uptranslist[i]; const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; diff --git a/nonthermal.cc b/nonthermal.cc index 7df6c6246..5c96d113b 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2,6 +2,7 @@ #include #include +#include #ifdef MPI_ON #include @@ -80,29 +81,38 @@ constexpr double MINDEPRATE = 0.; // Bohr radius squared in cm^2 constexpr double A_naught_squared = 2.800285203e-17; -std::vector> electron_binding; -std::vector> shells_q; +const std::array shellnames{"K ", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5", "N1", + "N2", "N3", "N4", "N5", "N6", "N7", "O1", "O2", "O3", "O4", + "O5", "O6", "O7", "P1", "P2", "P3", "P4", "Q1"}; + +std::vector> elements_electron_binding; +std::vector> elements_shells_q; struct collionrow { - int Z; - int ionstage; - int n; - int l; - double ionpot_ev; - double A; - double B; - double C; - double D; + int Z{-1}; + int ionstage{-1}; + int n = -1; + int l = -1; + double ionpot_ev{NAN}; + double A{NAN}; + double B{NAN}; + double C{NAN}; + double D{NAN}; // track the statistical weight represented by the values below, so they can be updated with new g-weighted averaged // values - double auger_g_accumulated; + double auger_g_accumulated = 0.; // probability of 0, 1, ..., NT_MAX_AUGER_ELECTRONS Auger electrons being ejected when the shell is ionised - std::array prob_num_auger; + std::array prob_num_auger{}; // the average kinetic energy released in Auger electrons after making a hole in this shell - float en_auger_ev; - float n_auger_elec_avg; + float en_auger_ev{NAN}; + float n_auger_elec_avg{NAN}; + + collionrow() { + std::ranges::fill(prob_num_auger, 0.); + prob_num_auger[0] = 1.; + } }; std::vector colliondata; @@ -113,7 +123,7 @@ bool nonthermal_initialized = false; static_assert(SF_EMIN > 0.); constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); -// energy grid on which solution is sampled +// energy grid on which solution is sampled [eV] constexpr auto engrid(int index) -> double { return SF_EMIN + (index * DELTA_E); } const auto logengrid = []() { @@ -251,10 +261,10 @@ void read_shell_configs() { std::istringstream(line) >> nshells >> n_z_binding; printout("Reading electron_shell_occupancy.txt with %d elements and %d shells\n", n_z_binding, nshells); - shells_q.resize(n_z_binding, std::vector(nshells, 0.)); + elements_shells_q.resize(n_z_binding, std::vector(nshells, 0.)); - assert_always(shells_q.size() == electron_binding.size()); - assert_always(shells_q[0].size() == electron_binding[0].size()); + assert_always(elements_shells_q.size() == elements_electron_binding.size()); + assert_always(elements_shells_q[0].size() == elements_electron_binding[0].size()); int elementcounter = 0; while (get_noncommentline(shells_file, line)) { @@ -268,7 +278,7 @@ void read_shell_configs() { int q = 0; assert_always(ssline >> q); // printout("q of %d in shell %d element number %d Z=%d\n", q, shell, elementcounter, z_element); - shells_q[elementcounter][shell] = q; + elements_shells_q[elementcounter][shell] = q; } elementcounter++; } @@ -296,7 +306,7 @@ void read_binding_energies() { std::istringstream(line) >> nshells >> n_z_binding; printout("Reading binding energies file '%s' with %d elements and %d shells\n", filename, n_z_binding, nshells); - electron_binding.resize(n_z_binding, std::vector(nshells, 0.)); + elements_electron_binding.resize(n_z_binding, std::vector(nshells, 0.)); for (int elemindex = 0; elemindex < n_z_binding; elemindex++) { assert_always(get_noncommentline(binding_energies_file, line)); @@ -310,7 +320,7 @@ void read_binding_energies() { for (int shell = 0; shell < nshells; shell++) { float bindingenergy = 0.; assert_always(ssline >> bindingenergy); - electron_binding[elemindex][shell] = bindingenergy * EV; + elements_electron_binding[elemindex][shell] = bindingenergy * EV; } } @@ -503,14 +513,142 @@ void read_auger_data() { fclose(augerfile); } +auto get_approx_shell_occupancies(const int nbound, const int ioncharge) { + assert_always(nbound > 0); + assert_always(ioncharge >= 0); + const int Z = nbound + ioncharge; + std::vector q; + q.resize(std::max(static_cast(10), elements_electron_binding[Z - 1].size()), 0); + + for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { + if (q[0] < 2) { + q[0]++; // K 1s + } else if (q[1] < 2) { + q[1]++; // L1 2s + } else if (q[2] < 2) { + q[2]++; // L2 2p[1/2] + } else if (q[3] < 4) { + q[3]++; // L3 2p[3/2] + } else if (q[4] < 2) { + q[4]++; // M1 3s + } else if (q[5] < 2) { + q[5]++; // M2 3p[1/2] + } else if (q[6] < 4) { + q[6]++; // M3 3p[3/2] + } else if (ioncharge == 0) { + if (q[9] < 2) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } else if (ioncharge == 1) { + if (q[9] < 1) { + q[9]++; // N1 4s + } else if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } else if (ioncharge > 1) { + if (q[7] < 4) { + q[7]++; // M4 3d[3/2] + } else if (q[8] < 6) { + q[8]++; // M5 3d[5/2] + } else { + printout("Going beyond the 4s shell in NT calculation. Abort!\n"); + std::abort(); + } + } + } + assert_always(nbound == std::accumulate(q.begin(), q.end(), 0)); + return q; +} + +auto get_shell_occupancies(const int nbound, const int ioncharge) { + assert_always(nbound > 0); + assert_always(ioncharge >= 0); + const int Z = nbound + ioncharge; + + if constexpr (!NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { + return get_approx_shell_occupancies(nbound, ioncharge); + } + + const auto &element_shells_q_neutral = elements_shells_q.at(Z - 1); + const size_t shellcount = std::min(element_shells_q_neutral.size(), elements_electron_binding[Z - 1].size()); + auto element_shells_q = std::vector(shellcount); + + int electron_count = 0; + for (size_t shellindex = 0; shellindex < shellcount; shellindex++) { + const int electronsinshell_neutral = element_shells_q_neutral.at(shellindex); + + int electronsinshell = 0; + if ((electron_count + electronsinshell_neutral) <= nbound) { + electronsinshell = electronsinshell_neutral; + } else { + electronsinshell = nbound - electron_count; + } + assert_always(electronsinshell <= electronsinshell_neutral); + element_shells_q[shellindex] = electronsinshell; + electron_count += electronsinshell; + assert_always(electron_count <= nbound); + } + + return element_shells_q; +} + +auto get_sum_q_over_binding_energy(const int element, const int ion) -> double { + const int ioncharge = get_ionstage(element, ion) - 1; + const int nbound = get_atomicnumber(element) - ioncharge; // number of bound electrons + + if (nbound <= 0) { + return 0.; + } + + // get the approximate shell occupancy if we don't have the data file + const auto shells_q = get_shell_occupancies(nbound, ioncharge); + const auto &binding_energies = elements_electron_binding.at(get_atomicnumber(element) - 1); + + double total = 0.; + for (int shellindex = 0; shellindex < std::ssize(shells_q); shellindex++) { + const int electronsinshell = shells_q[shellindex]; + + if (electronsinshell <= 0) { + continue; + } + double enbinding = binding_energies.at(shellindex); + const double ionpot = globals::elements[element].ions[ion].ionpot; + if (enbinding <= 0) { + enbinding = binding_energies.at(shellindex - 1); + if (shellindex != 8) { + // For some reason in the Lotz data, this is no energy for the M5 shell before Ni. So if the complaint + // is for 8 (corresponding to that shell) then just use the M4 value + printout("Huh? I'm trying to use a binding energy when I have no data. element %d ion %d\n", element, ion); + printout("Z = %d, ionstage = %d\n", get_atomicnumber(element), get_ionstage(element, ion)); + std::abort(); + } + } + total += electronsinshell / std::max(ionpot, enbinding); + } + + return total; +} + void read_collion_data() { - printout("Reading collisional ionization data...\n"); + printout("Reading collisional ionization data from collion.txt...\n"); FILE *cifile = fopen_required("collion.txt", "r"); int colliondatacount = 0; assert_always(fscanf(cifile, "%d", &colliondatacount) == 1); printout("Reading %d collisional transition rows\n", colliondatacount); - assert_always(colliondatacount > 0); + assert_always(colliondatacount >= 0); for (int i = 0; i < colliondatacount; i++) { collionrow collionrow{}; @@ -540,8 +678,72 @@ void read_collion_data() { // printout("ci row: %2d %2d %1d %1d %lg %lg %lg %lg %lg\n", collionrow.Z, collionrow.nelec, collionrow.n, // collionrow.l, collionrow.ionpot_ev, collionrow.A, collionrow.B, collionrow.C, collionrow.D); } - colliondata.shrink_to_fit(); printout("Stored %zu of %d input shell cross sections\n", colliondata.size(), colliondatacount); + for (int element = 0; element < get_nelements(); element++) { + const int Z = get_atomicnumber(element); + for (int ion = 0; ion < get_nions(element) - 1; ion++) { + const int ionstage = get_ionstage(element, ion); + const bool any_data_matched = std::any_of( + colliondata.cbegin(), colliondata.cend(), + [Z, ionstage](const collionrow &collionrow) { return collionrow.Z == Z && collionrow.ionstage == ionstage; }); + if (!any_data_matched) { + const double ionpot_ev = globals::elements[element].ions[ion].ionpot / EV; + printout("No collisional ionisation data for Z=%d ionstage %d. Using Lotz approximation with ionpot = %g eV\n", + Z, ionstage, ionpot_ev); + + const int ioncharge = ionstage - 1; + const int nbound = Z - ioncharge; // number of bound electrons + // get the approximate shell occupancy if we don't have the data file + auto shells_q = get_shell_occupancies(nbound, ioncharge); + int electron_count = 0; + for (int shellindex = 0; shellindex < std::ssize(shells_q); shellindex++) { + const int electronsinshell = shells_q.at(shellindex); + + electron_count += electronsinshell; + + if (electronsinshell <= 0) { + continue; + } + double enbinding = elements_electron_binding.at(Z - 1).at(shellindex); + const double ionpot = ionpot_ev * EV; + if (enbinding <= 0) { + enbinding = elements_electron_binding.at(Z - 1).at(shellindex - 1); + + if (shellindex != 8) { + // For some reason in the Lotz data, this is no energy for the M5 shell before Ni. So if the complaint + // is for 8 (corresponding to that shell) then just use the M4 value + assert_always(shellindex != 9) + } + } + const double p = std::max(ionpot, enbinding); + collionrow collionrow{}; + collionrow.Z = Z; + collionrow.ionstage = ionstage; + collionrow.n = -1; + collionrow.l = -shellindex; + collionrow.ionpot_ev = p / EV; + collionrow.A = -1.; + collionrow.B = -1.; + collionrow.C = -1.; + collionrow.D = -1.; + std::ranges::fill(collionrow.prob_num_auger, 0.); + collionrow.prob_num_auger[0] = 1.; + collionrow.auger_g_accumulated = 0.; + collionrow.en_auger_ev = 0.; + collionrow.n_auger_elec_avg = 0.; + + colliondata.push_back(collionrow); + if (electron_count >= nbound) { + break; + } + } + } + } + } + colliondata.shrink_to_fit(); + std::ranges::stable_sort(colliondata, [](const collionrow &a, const collionrow &b) { + return std::tie(a.Z, a.ionstage, a.ionpot_ev, a.n, a.l) < std::tie(b.Z, b.ionstage, b.ionpot_ev, b.n, b.l); + }); fclose(cifile); @@ -672,15 +874,68 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it #endif } -// xs_vec will be set with impact ionization cross sections for E > ionpot_ev (and zeros below this energy) +auto xs_ionization_lotz(const double en_erg, const collionrow &colliondata_ion) -> double { + const double ionpot_ev = colliondata_ion.ionpot_ev; + if (en_erg < (ionpot_ev * EV)) { + return 0.; + } + // const double gamma = (en_erg / (ME * std::pow(CLIGHT, 2))) + 1; + // const double beta = std::sqrt(1.0 - (1.0 / (std::pow(gamma, 2)))); + const double beta = std::sqrt(2 * en_erg / ME) / CLIGHT; + + const int ioncharge = colliondata_ion.ionstage - 1; + const int nbound = colliondata_ion.Z - ioncharge; // number of bound electrons + + if (nbound <= 0) { + return 0.; + } + + const int shellindex = -colliondata_ion.l; + const int electronsinshell = get_shell_occupancies(nbound, ioncharge)[shellindex]; + + const double p = colliondata_ion.ionpot_ev * EV; + + if (en_erg > p) { + const double part_sigma_shell = (electronsinshell / p * + (std::log(std::pow(beta, 2) * ME * std::pow(CLIGHT, 2) / 2.0 / p) - + std::log10(1 - std::pow(beta, 2)) - std::pow(beta, 2))); + if (part_sigma_shell > 0.) { + constexpr double Aconst = 1.33e-14 * EV * EV; + const double sigma = 2 * Aconst / std::pow(beta, 2) / ME / std::pow(CLIGHT, 2) * part_sigma_shell; + assert_always(sigma >= 0); + return sigma; + } + } + + return 0.; +} + +auto get_xs_ionization_vector_lotz(std::array &xs_vec, const collionrow &colliondata_ion) -> int { + const double ionpot_ev = colliondata_ion.ionpot_ev; + const int startindex = get_energyindex_ev_gteq(ionpot_ev); + + std::fill_n(xs_vec.begin(), startindex, 0.); + + for (int i = startindex; i < SFPTS; i++) { + xs_vec[i] = xs_ionization_lotz(engrid(i) * EV, colliondata_ion); + } + + return startindex; +} + +// xs_vec will be set with impact ionization cross sections [cm2] for E > ionpot_ev (and zeros below this energy) // returns the index of the first energy point >= ionpot_ev auto get_xs_ionization_vector(std::array &xs_vec, const collionrow &colliondata_ion) -> int { + const double A = colliondata_ion.A; + if (A < 0) { + return get_xs_ionization_vector_lotz(xs_vec, colliondata_ion); + } + const double ionpot_ev = colliondata_ion.ionpot_ev; const int startindex = get_energyindex_ev_gteq(ionpot_ev); std::fill_n(xs_vec.begin(), startindex, 0.); - const double A = colliondata_ion.A; const double B = colliondata_ion.B; const double C = colliondata_ion.C; const double D = colliondata_ion.D; @@ -794,6 +1049,10 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col return 0; } const double A = colliondata_ion.A; + if (A < 0) { + return xs_ionization_lotz(energy_ev / EV, colliondata_ion); + } + const double B = colliondata_ion.B; const double C = colliondata_ion.C; const double D = colliondata_ion.D; @@ -963,106 +1222,6 @@ auto get_nt_frac_excitation(const int modelgridindex) -> float { return frac_excitation; } -auto get_approx_shell_occupancy(const int nbound, const int ioncharge) { - assert_always(nbound > 0); - assert_always(ioncharge >= 0); - auto q = std::array{}; - - for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { - if (q[0] < 2) { - q[0]++; // K 1s - } else if (q[1] < 2) { - q[1]++; // L1 2s - } else if (q[2] < 2) { - q[2]++; // L2 2p[1/2] - } else if (q[3] < 4) { - q[3]++; // L3 2p[3/2] - } else if (q[4] < 2) { - q[4]++; // M1 3s - } else if (q[5] < 2) { - q[5]++; // M2 3p[1/2] - } else if (q[6] < 4) { - q[6]++; // M3 3p[3/2] - } else if (ioncharge == 0) { - if (q[9] < 2) { - q[9]++; // N1 4s - } else if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } else if (ioncharge == 1) { - if (q[9] < 1) { - q[9]++; // N1 4s - } else if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } else if (ioncharge > 1) { - if (q[7] < 4) { - q[7]++; // M4 3d[3/2] - } else if (q[8] < 6) { - q[8]++; // M5 3d[5/2] - } else { - printout("Going beyond the 4s shell in NT calculation. Abort!\n"); - std::abort(); - } - } - } - return q; -} - -auto get_mean_binding_energy(const int element, const int ion) -> double { - const int ioncharge = get_ionstage(element, ion) - 1; - const int nbound = get_atomicnumber(element) - ioncharge; // number of bound electrons - - if (nbound <= 0) { - return 0.; - } - - const int num_shells = electron_binding[get_atomicnumber(element) - 1].size(); - // get the approximate shell occupancy if we don't have the data file - auto approx_shells_q = get_approx_shell_occupancy(nbound, ioncharge); - - double total = 0.; - for (int shellindex = 0; shellindex < num_shells; shellindex++) { - int electronsinshell = 0; - if constexpr (NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE) { - electronsinshell = shells_q[get_atomicnumber(element) - 1][shellindex]; - } else if (shellindex < std::ssize(approx_shells_q)) { - electronsinshell = approx_shells_q[shellindex]; - } - - if (electronsinshell <= 0) { - continue; - } - double enbinding = electron_binding[get_atomicnumber(element) - 1][shellindex]; - const double ionpot = globals::elements[element].ions[ion].ionpot; - if (enbinding <= 0) { - enbinding = electron_binding[get_atomicnumber(element) - 1][shellindex - 1]; - // to get total += electronsinshell/electron_binding[get_atomicnumber(element)-1][electron_loop-1]; - // set use3 = 0. - if (shellindex != 8) { - // For some reason in the Lotz data, this is no energy for the M5 shell before Ni. So if the complaint - // is for 8 (corresponding to that shell) then just use the M4 value - printout("Huh? I'm trying to use a binding energy when I have no data. element %d ion %d\n", element, ion); - printout("Z = %d, ionstage = %d\n", get_atomicnumber(element), get_ionstage(element, ion)); - std::abort(); - } - } - total += electronsinshell / std::max(ionpot, enbinding); - } - - return total; -} - // compute the work per ion pair for doing the NT ionization calculation. // Makes use of EXTREMELY SIMPLE approximations - high energy limits only (can be used as an alternative to the // Spencer-Fano solver) @@ -1076,7 +1235,7 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> Zbar += grid::get_elem_abundance(modelgridindex, ielement) * get_atomicnumber(ielement); } - const double binding = get_mean_binding_energy(element, ion); + const double binding = get_sum_q_over_binding_energy(element, ion); constexpr double Aconst = 1.33e-14 * EV * EV; const double oneoverW = Aconst * binding / Zbar / (2 * PI * std::pow(QE, 4)); @@ -1111,11 +1270,10 @@ auto nt_ionization_ratecoeff_wfapprox(const int modelgridindex, const int elemen auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion, const bool assumeshellpotentialisvalence, const std::array &yfunc) -> double -// Integrate the ionization cross section over the electron degradation function to get the ionization rate coefficient -// i.e. multiply this by ion population to get a rate of ionizations per second -// Do not call during packet propagation, as the y vector may not be in memory! -// IMPORTANT: we are dividing by the shell potential, not the valence potential here! -// To change this set assumeshellpotentialisvalence to true +// Integrate the ionization cross section over the electron degradation function to get the ionization rate +// coefficient i.e. multiply this by ion population to get a rate of ionizations per second Do not call during packet +// propagation, as the y vector may not be in memory! IMPORTANT: we are dividing by the shell potential, not the +// valence potential here! To change this set assumeshellpotentialisvalence to true { std::array cross_section_vec{}; auto gsl_cross_section_vec = gsl_vector_view_array(cross_section_vec.data(), SFPTS).vector; @@ -1481,15 +1639,20 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo calculate_eff_ionpot_auger_rates(modelgridindex, element, ion, yfunc); - int matching_nlsubshell_count = 0; + int matching_subshell_count = 0; for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double frac_ionization_ion_shell = calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); frac_ionization_ion += frac_ionization_ion_shell; - matching_nlsubshell_count++; - printout(" shell n %d, l %d, I %5.1f eV: frac_ionization %10.4e", collionrow.n, collionrow.l, - collionrow.ionpot_ev, frac_ionization_ion_shell); + matching_subshell_count++; + printout(" shell "); + if (collionrow.n >= 0) { + printout("n %d, l %d", collionrow.n, collionrow.l); + } else { + printout("%s (Lotz)", shellnames.at(-collionrow.l).c_str()); + } + printout(" I %5.1f eV: frac_ionization %10.4e", collionrow.ionpot_ev, frac_ionization_ion_shell); if (NT_MAX_AUGER_ELECTRONS > 0) { printout(" prob(n Auger elec):"); @@ -1509,7 +1672,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } else { nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion = 0.; } - printout(" frac_ionization: %g (%d subshells)\n", frac_ionization_ion, matching_nlsubshell_count); + printout(" frac_ionization: %g (%d subshells)\n", frac_ionization_ion, matching_subshell_count); // excitation from all levels is very SLOW const int nlevels_all = get_nlevels(element, ion); diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index a5135cef6..08503f97b 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -186,10 +186,10 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co const double nu_min = spectra.nu_min; const double nu_max = spectra.nu_max; + const double dlognu = (log(nu_max) - log(nu_min)) / MNUBINS; const double t_arrive = get_arrive_time(pkt); if (t_arrive > globals::tmin && t_arrive < globals::tmax && pkt.nu_rf > nu_min && pkt.nu_rf < nu_max) { const int nt = get_timestep(t_arrive); - const double dlognu = (log(nu_max) - log(nu_min)) / MNUBINS; const int nnu = static_cast((log(pkt.nu_rf) - log(nu_min)) / dlognu); assert_always(nnu < MNUBINS); @@ -509,11 +509,9 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co spectra.nu_max = nu_max; spectra.do_emission_res = do_emission_res; const bool print_memusage = - (spectra.lower_freq.empty() || (do_emission_res && spectra.absorptionalltimesteps.empty())); + (spectra.timesteps.empty() || (do_emission_res && spectra.absorptionalltimesteps.empty())); - spectra.lower_freq.resize(MNUBINS); - spectra.delta_freq.resize(spectra.lower_freq.size()); - for (ptrdiff_t nnu = 0; nnu < std::ssize(spectra.lower_freq); nnu++) { + for (ptrdiff_t nnu = 0; nnu < MNUBINS; nnu++) { spectra.lower_freq[nnu] = exp(log(nu_min) + (nnu * (dlognu))); spectra.delta_freq[nnu] = exp(log(nu_min) + ((nnu + 1) * (dlognu))) - spectra.lower_freq[nnu]; } diff --git a/spectrum_lightcurve.h b/spectrum_lightcurve.h index 18f1da7ad..3bcc36d44 100644 --- a/spectrum_lightcurve.h +++ b/spectrum_lightcurve.h @@ -4,6 +4,7 @@ #include #include +#include "exspec.h" #include "packet.h" struct TimeStepSpecrum { @@ -16,8 +17,8 @@ struct TimeStepSpecrum { struct Spectra { double nu_min = -1.; double nu_max = -1.; - std::vector lower_freq; - std::vector delta_freq; + std::array lower_freq; + std::array delta_freq; std::vector fluxalltimesteps; std::vector absorptionalltimesteps; std::vector emissionalltimesteps; From 2592f64e96fc5a7e72561e1610ec6dac58364a71 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 18 Oct 2024 14:27:11 +0100 Subject: [PATCH 059/117] Add Lotz shells for top ion stage --- nonthermal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nonthermal.cc b/nonthermal.cc index 5c96d113b..6ab244d52 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -681,7 +681,7 @@ void read_collion_data() { printout("Stored %zu of %d input shell cross sections\n", colliondata.size(), colliondatacount); for (int element = 0; element < get_nelements(); element++) { const int Z = get_atomicnumber(element); - for (int ion = 0; ion < get_nions(element) - 1; ion++) { + for (int ion = 0; ion < get_nions(element); ion++) { const int ionstage = get_ionstage(element, ion); const bool any_data_matched = std::any_of( colliondata.cbegin(), colliondata.cend(), From 9971cc5ba86e3d88dbc26a035639aaba3981108b Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 24 Oct 2024 13:20:15 +0100 Subject: [PATCH 060/117] Handle missing shell binding energies (e.g., N, O, F) --- nonthermal.cc | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 6ab244d52..2423b093f 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -264,23 +264,21 @@ void read_shell_configs() { elements_shells_q.resize(n_z_binding, std::vector(nshells, 0.)); assert_always(elements_shells_q.size() == elements_electron_binding.size()); - assert_always(elements_shells_q[0].size() == elements_electron_binding[0].size()); - int elementcounter = 0; + int zminusone = 0; while (get_noncommentline(shells_file, line)) { std::istringstream ssline(line); int z_element = 0; assert_always(ssline >> z_element); - // printout("Reading shells Z=%d\n", z_element); + assert_always(elements_shells_q[zminusone].size() == elements_electron_binding[zminusone].size()); for (int shell = 0; shell < nshells; shell++) { int q = 0; assert_always(ssline >> q); - // printout("q of %d in shell %d element number %d Z=%d\n", q, shell, elementcounter, z_element); - elements_shells_q[elementcounter][shell] = q; + elements_shells_q.at(zminusone).at(shell) = q; } - elementcounter++; + zminusone++; } } @@ -308,19 +306,19 @@ void read_binding_energies() { elements_electron_binding.resize(n_z_binding, std::vector(nshells, 0.)); - for (int elemindex = 0; elemindex < n_z_binding; elemindex++) { + for (int zminusone = 0; zminusone < n_z_binding; zminusone++) { assert_always(get_noncommentline(binding_energies_file, line)); std::istringstream ssline(line); // new file as an atomic number column if (binding_en_newformat) { int z_element{-1}; ssline >> z_element; - assert_always(z_element == (elemindex + 1)); + assert_always(z_element == (zminusone + 1)); } for (int shell = 0; shell < nshells; shell++) { float bindingenergy = 0.; assert_always(ssline >> bindingenergy); - elements_electron_binding[elemindex][shell] = bindingenergy * EV; + elements_electron_binding.at(zminusone).at(shell) = bindingenergy * EV; } } @@ -626,14 +624,9 @@ auto get_sum_q_over_binding_energy(const int element, const int ion) -> double { double enbinding = binding_energies.at(shellindex); const double ionpot = globals::elements[element].ions[ion].ionpot; if (enbinding <= 0) { + // if we don't have the shell's binding energy, use the previous one enbinding = binding_energies.at(shellindex - 1); - if (shellindex != 8) { - // For some reason in the Lotz data, this is no energy for the M5 shell before Ni. So if the complaint - // is for 8 (corresponding to that shell) then just use the M4 value - printout("Huh? I'm trying to use a binding energy when I have no data. element %d ion %d\n", element, ion); - printout("Z = %d, ionstage = %d\n", get_atomicnumber(element), get_ionstage(element, ion)); - std::abort(); - } + assert_always(enbinding > 0); } total += electronsinshell / std::max(ionpot, enbinding); } @@ -707,13 +700,9 @@ void read_collion_data() { double enbinding = elements_electron_binding.at(Z - 1).at(shellindex); const double ionpot = ionpot_ev * EV; if (enbinding <= 0) { + // if we don't have the shell's binding energy, use the previous one enbinding = elements_electron_binding.at(Z - 1).at(shellindex - 1); - - if (shellindex != 8) { - // For some reason in the Lotz data, this is no energy for the M5 shell before Ni. So if the complaint - // is for 8 (corresponding to that shell) then just use the M4 value - assert_always(shellindex != 9) - } + assert_always(enbinding > 0); } const double p = std::max(ionpot, enbinding); collionrow collionrow{}; From 83271e7026574f10ee043b0ea1c972b2d01f3ff0 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 25 Oct 2024 11:27:40 +0100 Subject: [PATCH 061/117] Update update_grid.cc --- update_grid.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update_grid.cc b/update_grid.cc index 502eca330..0a47d38ee 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -952,7 +952,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } printout("lte_iteration %d\n", globals::lte_iteration ? 1 : 0); - printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, grid::modelgrid[mgi].thick); + printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, static_cast(grid::modelgrid[mgi].thick)); for (int element = 0; element < get_nelements(); element++) { calculate_cellpartfuncts(mgi, element); From 43cf291ad377811aeed2ed7721311d0632ec923d Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 25 Oct 2024 11:43:10 +0100 Subject: [PATCH 062/117] Avoid clang-tidy warning --- input.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/input.cc b/input.cc index f08ef242d..14281fb60 100644 --- a/input.cc +++ b/input.cc @@ -793,15 +793,17 @@ void setup_phixs_list() { assert_always(allcontindex == globals::nbfcontinua); assert_always(globals::nbfcontinua >= 0); // was initialised as -1 before startup + const auto nbfcontinua = + globals::nbfcontinua; // so that clang-tidy doesn't throw errors on the assumption that nbfcontinua is changing globals::bfestimcount = 0; - if (globals::nbfcontinua > 0) { + if (nbfcontinua > 0) { // indicies above were temporary only. continuum index should be to the sorted list - std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, globals::nbfcontinua), std::ranges::less{}, + std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, nbfcontinua), std::ranges::less{}, &FullPhotoionTransition::nu_edge); globals::bfestim_nu_edge.clear(); - for (int i = 0; i < globals::nbfcontinua; i++) { + for (int i = 0; i < nbfcontinua; i++) { auto &cont = nonconstallcont[i]; if (DETAILED_BF_ESTIMATORS_ON && LEVEL_HAS_BFEST(get_atomicnumber(cont.element), get_ionstage(cont.element, cont.ion), cont.level)) { @@ -813,20 +815,17 @@ void setup_phixs_list() { } } - globals::allcont_nu_edge.resize(globals::nbfcontinua, 0.); + globals::allcont_nu_edge.resize(nbfcontinua, 0.); globals::bfestim_nu_edge.shrink_to_fit(); assert_always(globals::bfestimcount == std::ssize(globals::bfestim_nu_edge)); - } - printout("[info] bound-free estimators track bfestimcount %d photoionisation transitions\n", globals::bfestimcount); - if (globals::nbfcontinua > 0) { - for (int i = 0; i < globals::nbfcontinua; i++) { + for (int i = 0; i < nbfcontinua; i++) { globals::allcont_nu_edge[i] = nonconstallcont[i].nu_edge; } setup_photoion_luts(); - for (int i = 0; i < globals::nbfcontinua; i++) { + for (int i = 0; i < nbfcontinua; i++) { const int element = nonconstallcont[i].element; const int ion = nonconstallcont[i].ion; const int level = nonconstallcont[i].level; @@ -834,6 +833,7 @@ void setup_phixs_list() { assert_always(nonconstallcont[i].photoion_xs != nullptr); } } + printout("[info] bound-free estimators track bfestimcount %d photoionisation transitions\n", globals::bfestimcount); globals::allcont = nonconstallcont; nonconstallcont = nullptr; } From 8d584d067f784e8e3f615202373354ad4c881899 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 26 Oct 2024 05:40:00 +0100 Subject: [PATCH 063/117] Update kpkt.cc --- kpkt.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/kpkt.cc b/kpkt.cc index c5df06603..2b84e9b66 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -463,7 +463,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { } const int ilow = get_coolinglistoffset(element, ion); - const int ihigh = ilow + get_ncoolingterms_ion(element, ion) - 1; + const int ncoolingterms_ion = get_ncoolingterms_ion(element, ion); + const int ihigh = ilow + ncoolingterms_ion - 1; double C_ion_procsum = globals::cellcache[cellcacheslotid].cooling_contrib[ihigh]; if (C_ion_procsum < 0.) { @@ -490,17 +491,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { if (i > ihigh) { printout("do_kpkt: error occurred while selecting a cooling channel: low %d, high %d, i %td, rndcool %g\n", ilow, ihigh, i, rndcool_ion_process); - printout("element %d, ion %d, offset %d, terms %d, coolingsum %g\n", element, ion, - get_coolinglistoffset(element, ion), get_ncoolingterms_ion(element, ion), coolingsum); - - printout("lower %g, %g, %g\n", - globals::cellcache[cellcacheslotid].cooling_contrib[get_coolinglistoffset(element, ion) - 1], - globals::cellcache[cellcacheslotid].cooling_contrib[get_coolinglistoffset(element, ion)], - globals::cellcache[cellcacheslotid].cooling_contrib[get_coolinglistoffset(element, ion) + 1]); - const int finalpos = get_coolinglistoffset(element, ion) + get_ncoolingterms_ion(element, ion) - 1; - printout("upper %g, %g, %g\n", globals::cellcache[cellcacheslotid].cooling_contrib[finalpos - 1], - globals::cellcache[cellcacheslotid].cooling_contrib[finalpos], - globals::cellcache[cellcacheslotid].cooling_contrib[finalpos + 1]); + printout("element %d, ion %d, offset %d, terms %d, coolingsum %g\n", element, ion, ilow, ncoolingterms_ion, + coolingsum); } assert_always(i <= ihigh); From c8c27c252c2a186cf5015e0b9e4e8b5fc3fae57f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 26 Oct 2024 06:48:40 +0100 Subject: [PATCH 064/117] Use standard int for modelcell[].thick to avoid potential incompatibilities with MPI_SHORT --- grid.h | 2 +- sn3d.cc | 4 ++-- update_grid.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/grid.h b/grid.h index d0bbc8361..7dc4184e4 100644 --- a/grid.h +++ b/grid.h @@ -44,7 +44,7 @@ struct ModelGridCell { std::span nlte_pops; // Pointer to an array that contains the nlte-level populations for this cell double totalcooling = -1; double *ion_cooling_contribs{}; - uint_fast8_t thick = 0; + int thick = 0; }; consteval auto get_ngriddimensions() -> int { diff --git a/sn3d.cc b/sn3d.cc index 568fe2733..d39cdc044 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -293,7 +293,7 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_COMM_WORLD); MPI_Pack(&grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_SHORT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack(grid::modelgrid[mgi].elem_massfracs, get_nelements(), MPI_FLOAT, mpi_grid_buffer, @@ -341,7 +341,7 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_COMM_WORLD); MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_SHORT, + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_INT, MPI_COMM_WORLD); MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].elem_massfracs, diff --git a/update_grid.cc b/update_grid.cc index 0a47d38ee..502eca330 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -952,7 +952,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } printout("lte_iteration %d\n", globals::lte_iteration ? 1 : 0); - printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, static_cast(grid::modelgrid[mgi].thick)); + printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, grid::modelgrid[mgi].thick); for (int element = 0; element < get_nelements(); element++) { calculate_cellpartfuncts(mgi, element); From ade60a1b4ee117aa2555ce4ad673d6296f4c5765 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 26 Oct 2024 18:00:43 +0100 Subject: [PATCH 065/117] Fix implicit conversion bool to int --- spectrum_lightcurve.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 08503f97b..755073176 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -122,8 +122,8 @@ void printout_tracemission_stats() { printout("%7.2e (%5.1f%%) %4d %9d %5d %5d %8.1f %8.2e %4d %7.1f %7.1f %7.1e %7.1e\n", encontrib, 100 * encontrib / totalenergy, get_atomicnumber(element), get_ionstage(element, ion), globals::linelist[lineindex].upperlevelindex, globals::linelist[lineindex].lowerlevelindex, - downtransition->coll_str, globals::linelist[lineindex].einstein_A, downtransition->forbidden, - linelambda, v_rad, B_lu, B_ul); + downtransition->coll_str, globals::linelist[lineindex].einstein_A, + static_cast(downtransition->forbidden), linelambda, v_rad, B_lu, B_ul); } else { break; } From 671a0abc8d68f19527426c326b58501ca5f159f3 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 27 Oct 2024 14:52:28 +0000 Subject: [PATCH 066/117] Apply -fopenmp-simd unless OPTIMIZE=OFF --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f58e1a6b3..823b35af7 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ CXXFLAGS += -std=c++20 -fstrict-aliasing # CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true ifneq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -fopenmp-simd -ftree-vectorize -Wunknown-pragmas -Wunused-macros -Werror -MD -MP + CXXFLAGS += -ftree-vectorize -Wunknown-pragmas -Wunused-macros -Werror -MD -MP # add -ftrivial-auto-var-init=zero when we drop gcc 11 support endif @@ -241,7 +241,7 @@ else ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -fast else - CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only + CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only -fopenmp-simd endif endif # endif From e018e02b9d9fd36b15c70e57f3f26cce9aed7cc8 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 27 Oct 2024 15:17:21 +0000 Subject: [PATCH 067/117] -Wno-error=unknown-pragmas --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 823b35af7..adb538573 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ CXXFLAGS += -std=c++20 -fstrict-aliasing # CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true ifneq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -ftree-vectorize -Wunknown-pragmas -Wunused-macros -Werror -MD -MP + CXXFLAGS += -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP # add -ftrivial-auto-var-init=zero when we drop gcc 11 support endif From eccb8123ea9c92373a0d5891d74dfd3cea3a396f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 07:51:56 +0000 Subject: [PATCH 068/117] nonthermal: remove unused test code to fix cppcheck error --- nonthermal.cc | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 2423b093f..e89eb06f6 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -47,31 +47,6 @@ namespace nonthermal { namespace { -// THESE OPTIONS ARE USED TO TEST THE SF SOLVER -// Compare to Kozma & Fransson (1992) pure-oxygen plasma, nne = 1e8, x_e = 0.01 -// #define yscalefactoroverride(mgi) (1e10) -// #define get_nnion_tot(x) (1e10) -// #define get_nnion(modelgridindex, element, ion) get_nnion_override(modelgridindex, element, ion) -// #define grid::get_nne(x) (1e8) -// #define SFPTS 10000 // number of energy points in the Spencer-Fano solution vector -// #define SF_EMAX 3000. // eV -// #define SF_EMIN 1. // eV -// -// double get_nnion_override(const int modelgridindex, const int element, const int ion) -// Fake the composition to test the NT solver -// { -// const double nntot = get_nnion_tot(modelgridindex); -// if (get_atomicnumber(element) == 8) -// { -// const int ionstage = get_ionstage(element, ion); -// if (ionstage == 1) -// return 0.99 * nntot; -// else if (ionstage == 2) -// return 0.01 * nntot; -// } -// return 0.; -// } - // minimum number fraction of the total population to include in SF solution constexpr double minionfraction = 1.e-8; @@ -847,11 +822,7 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it } } -#ifndef yscalefactoroverride // manual override can be defined - const double yscalefactor = (get_deposition_rate_density(modelgridindex) / (E_init_ev * EV)); -#else - const double yscalefactor = yscalefactoroverride(modelgridindex); -#endif + const double yscalefactor = get_deposition_rate_density(modelgridindex) / (E_init_ev * EV); for (int s = 0; s < SFPTS; s++) { fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, engrid(s), sourcevec(s), From 4efe042a62a625ff142180da8c611aa87210f655 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 07:55:20 +0000 Subject: [PATCH 069/117] Update ci-checks.yml --- .github/workflows/ci-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index d94a312ff..f27402936 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -26,7 +26,7 @@ jobs: - name: run cppcheck run: | cppcheck --version - cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . + cppcheck --force --error-exitcode=1 --output-format=sarif --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: runs-on: macos-14 From d092a22e8f7559f54e55e9f7c14f6a95615c828c Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 09:34:44 +0000 Subject: [PATCH 070/117] Drop gcc-11 support (#136) --- .github/workflows/ci-checks.yml | 2 -- .github/workflows/ci.yml | 2 -- .python-version | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 .python-version diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index f27402936..beb2b1237 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -79,7 +79,6 @@ jobs: uses: actions/setup-python@v5 with: cache: pip - python-version: '3.12' - name: Generate compile_commands.json run: | @@ -103,7 +102,6 @@ jobs: matrix: compiler: [ - {name: gcc, ver: 11}, {name: gcc, ver: 12}, {name: gcc, ver: 13}, {name: gcc, ver: 14}, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a10ba0385..ebc175052 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -174,8 +174,6 @@ jobs: - name: Set up Python if: always() && matrix.testmode == 'OFF' uses: actions/setup-python@v5 - with: - python-version: '3.12' - name: Install artistools if: always() && matrix.testmode == 'OFF' diff --git a/.python-version b/.python-version new file mode 100644 index 000000000..24ee5b1be --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 From 1bfd0772404a5344fafbfe33df69c2fb98212a55 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 12:27:15 +0000 Subject: [PATCH 071/117] Makefile: set ffp-contract=off in reproducible mode (#137) --- Makefile | 2 +- .../results_md5_final.txt | 54 +++++++++---------- .../results_md5_job0.txt | 46 ++++++++-------- .../results_md5_job0.txt | 2 +- .../results_md5_job0.txt | 8 +-- .../results_md5_final.txt | 32 +++++------ .../results_md5_job0.txt | 30 +++++------ .../results_md5_job0.txt | 8 +-- .../results_md5_job0.txt | 8 +-- .../results_md5_job0.txt | 8 +-- .../results_md5_job0.txt | 8 +-- .../results_md5_job0.txt | 8 +-- .../results_md5_final.txt | 42 +++++++-------- .../results_md5_job0.txt | 40 +++++++------- .../results_md5_final.txt | 42 +++++++-------- .../results_md5_job0.txt | 40 +++++++------- 16 files changed, 189 insertions(+), 189 deletions(-) diff --git a/Makefile b/Makefile index adb538573..7c2ef74f2 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ else endif ifeq ($(REPRODUCIBLE),ON) - CXXFLAGS += -DREPRODUCIBLE=true + CXXFLAGS += -DREPRODUCIBLE=true -ffp-contract=off BUILD_DIR := $(BUILD_DIR)_reproducible else ifeq ($(REPRODUCIBLE),OFF) else ifeq ($(REPRODUCIBLE),) diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index 9f19b66af..9d4e72c45 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,37 +1,37 @@ -91de44973f7efdb2bbb67e9ebe78f2bf absorption.out -790e8eb2156e27b9bcf4fe4ec9db7c52 absorptionpol.out +1d19eb9cd44e1676147e573510cdcea1 absorption.out +d44b40c22d516f547617dde02c945f3c absorptionpol.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -ece1861557f42d5e68bccc196784b053 deposition.out -ad213adf8e24a171b42f872c59a5dae0 emission.out -e8865c8b8fb79aeef5de4dfbaa176e58 emissionpol.out -91e674fadcf5a1f38e36a23aaed77cb3 emissiontrue.out -c22a1fe1065a07ad719688fee38d9b3b gamma_light_curve.out -66aa1260a8d46c287b3158e99799b4cf gamma_spec.out +f837f0157d192bbbb577c8b23cb50ed4 deposition.out +519afdda0e662486dde4a176a115da94 emission.out +bba8bac5a86bddbc398af93d56697d6f emissionpol.out +7d6a7ff76fb74ab0c762c1d7bd41969f emissiontrue.out +ec53538474a3c9eec9d51a350b001d3a gamma_light_curve.out +436a3f2b6ec69cc9e8cb8aea80541882 gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -19b4c6db4900c2e74d507c960cf55ef5 light_curve.out +5e818206372ff62ae5169fdb651106a5 light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -4382e5c02bd5534ba1bffb13eae880c6 packets00_0000.out -79baa7f0db446f2dc0b03434b466075d packets00_0001.out -1eb2657af29e3573eea7f03758a1ac0e packets00_0002.out -b7a810f6843879ea211c64057d0e2e93 packets00_0003.out -47dc8003341536751d4a5fc1042053b7 spec.out -1c34b924847577d008b968827d6f36cc specpol.out +5ef844f385730d21db8d38f3ec342245 packets00_0000.out +37240a677a12c756e8ab376c82cf06a5 packets00_0001.out +e9a40a0e47d3bc0a2330fbe241142329 packets00_0002.out +5ff5f79e130997cfa8e9328e17801cf1 packets00_0003.out +73d1c7f4c7d4e005618a41022554aeaf spec.out +a41ca549452afa07ffe4bbd2aabe91f5 specpol.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -38c0fc1f2aeaa64e46b411e637097d27 vpackets_0000.out -074ad43f9a262b688d49fe1a037f7296 vpackets_0001.out -6e56402b2745c26899907d1fecb51b3a vpackets_0002.out -886d6db822af59198983bc30a4f0493b vpackets_0003.out +931045ea18be6c5b359cdf17dd6b9ef9 vpackets_0000.out +6f07bb74b92abff101f6f65e66287c48 vpackets_0001.out +efd2845000833d995726b5eabf1ad378 vpackets_0002.out +6ac45acfd977dcf18db1aab36f9e0d1b vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -3c910fc4c70dbec8bc6a3298ab24e256 vspecpol_0000.out -447a6fa50e85aee2b2107017b2834407 vspecpol_0001.out -6e2819c669a6f777818ea7d53ad9c45c vspecpol_0002.out -95cc343aacd91999d9608237e2b15e65 vspecpol_0003.out -225e09eb035710ab91de7c07303196ee job1/estimators_0000.out -90185995d5079abbafc4984db90709d7 job1/estimators_0001.out -3b37d3290a9781cd095c6af2d19c9c31 job1/estimators_0002.out -e949621dfbcd945f99c65dde68d4cd11 job1/estimators_0003.out +9e01f3c447fb54ffd459568df1fe45f0 vspecpol_0000.out +74b375a53c8dd18012a28fc99e0e4c81 vspecpol_0001.out +5a942a9b0d19f7cb09cce399b85b587d vspecpol_0002.out +6d5a0fc2026a308aa8828171fe632871 vspecpol_0003.out +e481ca36d367159c20fe7d124646e5d2 job1/estimators_0000.out +b40ca35f2c5b54b16a319c3b2b81b9f6 job1/estimators_0001.out +3c154196b823aa934c54231aade6ae0b job1/estimators_0002.out +808f73c14dcaa0882ebc7776efd53d92 job1/estimators_0003.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index 488a9570c..48a6fbb13 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,33 +1,33 @@ -8c114a35dad58a87b8cd8e3a7b776e80 absorption.out +4fa50b452f08ef4682f6b395336dd1f9 absorption.out c0604236aa7df99cda43e5c7bbe7b6f4 bflist.out -5de886016cb306c7ba1c6d9ea93d6b35 deposition.out -ccd6033593f1d4f0e47d9aac7a0e3042 emission.out -1139784b02a652a635e211b934c2cfec emissiontrue.out -457efd00d79f5dd32d4649122b9e4b73 gamma_light_curve.out +a0e5014007f856bc900792b916853e1a deposition.out +149b794b7b3e37048bb6ab8ee5e2fed2 emission.out +6a48504a422f4b3666989a167b1df25a emissiontrue.out +c532033f860b76b8c5244784da32313b gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out 20bddb22b6f084a7abc105c210366bfd grid.out -b8e0cefe62b6395ee5282537db59a69d light_curve.out +61d5b071cea6e1098030a8cf2fbe14e9 light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -029652c38ebe0a14ecfba46b76af0f28 packets00_0000.out -4c45d523f09576fe1035fa89ed0548b2 packets00_0001.out -381e796cd7d9192661584ea60e6c28dd packets00_0002.out -d6d5190184299f680e41638d67c4977c packets00_0003.out -89adfd1461b00ddbab825fc9abca2b13 spec.out +dc626ea88194714abcdf146723c88d6c packets00_0000.out +39bae205a40145c915daadd3c3b5e1c8 packets00_0001.out +bc5b497552ff03cf4d025f986278da1d packets00_0002.out +11919740e525fc5ceb459416050281b2 packets00_0003.out +2fa32a2e224cca813b38a1387afbe85b spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out -b80b994ca74daf4696751030d26a220f vpackets_0000.out -9fc86726f401c7758a0b0c2441ed6fa3 vpackets_0001.out -d89452752b6175590dd104fe095c6259 vpackets_0002.out -22e6218e5c400595ebd035f1b166a2f1 vpackets_0003.out +d1a1ad1c22e25f94724db515c351e488 vpackets_0000.out +c6203bcae314708954260f61559b3e08 vpackets_0001.out +1dc45e7fba2a0e152fa21b9561766500 vpackets_0002.out +f8d9d667842337a8f1162c076f13e18b vpackets_0003.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0000.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0001.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0002.out d04b04da202515e44b961e6ec9f96c60 vpkt_grid_0003.out -819d3b1ded1e2eb9cce2565c711ba51a vspecpol_0000.out -58f69311579e40139fa7d5f609ef0f8c vspecpol_0001.out -3bec72b5f06389cab1d8259f43ad5dd3 vspecpol_0002.out -d5c9b7d3e0194c1921bcded25308d118 vspecpol_0003.out -41b24af878ddf58986b5ba1e5a104f6a job0/estimators_0000.out -6f5dbce4d8957c98b02559bfe17fa739 job0/estimators_0001.out -7df27f7428d33eb7bc1045e9e8a24a71 job0/estimators_0002.out -700ae0652cb45e12884124bc89acfb80 job0/estimators_0003.out +e23873d93b6a446298ab812a93649766 vspecpol_0000.out +44942d26d5191cf524795eec796119aa vspecpol_0001.out +3e7b30f691e0a5e877995234d7c9261c vspecpol_0002.out +abd4288217b349a05f417935c26770ac vspecpol_0003.out +43a8685992c16f9a4845e6311330d0bf job0/estimators_0000.out +2ef0fbd0fc5e8a6624ad792b8ad51193 job0/estimators_0001.out +61ee10456d6271accc07b9d9e5f9342b job0/estimators_0002.out +5c62d5b3db08baf3c0800dee7ea788e7 job0/estimators_0003.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_job0.txt b/tests/classicmode_3d_inputfiles/results_md5_job0.txt index 907e3f249..946fcb3c2 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_job0.txt @@ -11,7 +11,7 @@ c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out 1e81ef6f94c8332c880d8be2f0ffba5d packets00_0000.out 1e44ed84716f7f2b2de2b445456c4a69 packets00_0001.out -1c7de0c56fdae989ac20c34ee75cf0ae packets00_0002.out +f14d052cf549aec94aa7334a03b71662 packets00_0002.out 8fdf70de6cd92502cd925f66c3824a41 packets00_0003.out 79606abc60e8efc6546ef0844303e152 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index cf3e572a9..f50fc8345 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ d2b546c1df9ca44beec2a25fe5cd7a12 packets00_0001.out 209c278c8753e7d57ef1120c4b1e8c59 packets00_0003.out d90011df9b26a1b201891122b690b7e9 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -bfe9ac9322ca2fc013e6ed7cd07abe1f job0/estimators_0000.out -ad0d31b74f09fd1e061c403e5e2bd763 job0/estimators_0001.out -41246b97f5a72d7f40123c07729f14e1 job0/estimators_0002.out -69632b392414d12f24cc196ef927f1af job0/estimators_0003.out +59b9ddad12a7142035a8a14a66772533 job0/estimators_0000.out +914fb771d6a47c19c2902a35f2b31b8a job0/estimators_0001.out +2fc6ed25172ee06c660042cc2bd4bb79 job0/estimators_0002.out +903bf6890de8671b082f96627469ab5e job0/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index 725776a8c..8268caafe 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -0b8379bbff5216cd6abcba82844b8487 absorption.out +f06170f48efc0e06240668b75fc209ab absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -547a1de3163dec22eeeb454e95a47547 deposition.out -68213044ca74286c2aa953c5c5743a11 emission.out -a706d0f17dbbbeb6fd110b07fe6e4c6e emissiontrue.out -79d2e235c3f3c1e9d1b28bdbc5becf63 gamma_light_curve.out -f02c3fa27c869ecdfa683b3f322e4c97 gamma_spec.out +b0408ab41fc6af31a67b83db2d30995a deposition.out +8809f7f9b0de8b9f340bbfcfd74c8971 emission.out +99b1de21168c8370d1f503eaf46ba252 emissiontrue.out +7d05408c2969bcf5e2776f3b51716ef1 gamma_light_curve.out +ea2528ae1d42dce5f7c8eef94b948c86 gamma_spec.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -2c58924b06fa661e845332174146b70b light_curve.out +c61ea3b7b9fc33359366cb32edf7ad74 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -bbcda55b0e73fc6e59fe4af09174a9b3 packets00_0000.out -dc26f3f4662cbfa1952c414176e5ce13 packets00_0001.out -dfc316731561dde7037c8e8575bc15c2 packets00_0002.out -0a105cb9c97ab225676df616564e7328 packets00_0003.out -5d1b8350c2c7114b1481465644191e68 spec.out +41c15e45e9bcc526fa7b93afaa922048 packets00_0000.out +cb5dfa67343136b93267bf3555e13ecd packets00_0001.out +292f4caa6eb687c34d12fe9b01aa9aa4 packets00_0002.out +3c7ca4b9ccd45c820f424c1d4a4e597b packets00_0003.out +dbb89cf92f157e3519a95ee53a28320f spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -7854d43ead9a94869c5e37dee11d2e87 job1/estimators_0000.out -703ca8a7850ec8a620152cd970cb9bae job1/estimators_0001.out -11d15f3f9401e030c1087e91986d73a7 job1/estimators_0002.out -0f652a0b60587153c04186d6f762a8ec job1/estimators_0003.out +bb94370d18931aa66b2679ca2f9d0a68 job1/estimators_0000.out +b3a3eb895f42b0d30e6defe5b82a50b3 job1/estimators_0001.out +a99083e8902291ec9eaa8762c5d185de job1/estimators_0002.out +adbe958740bf9170186c9b9a325353cc job1/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index 812e20bd6..112d23508 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -888fe6d988b6fd0d9b59cf3b55b5a575 absorption.out +5cc44fdb5a61e3462dbdbc69df162192 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -ed7c357f88e63609dea1a4ae6401adc1 deposition.out -75bb459780e3ed4ee46ec1448027da7c emission.out -dd986a6d56658cd9bc80406bc4c56030 emissiontrue.out -7724afce818c73150db50ce7232d1a5e gamma_light_curve.out +2f58b4c57f01595ff2039430f6b93e7c deposition.out +ac5639d46649923f4d6962a640ca309f emission.out +682041787c0270df66edc5aa01a9a7dc emissiontrue.out +5099680a2dd8f2b9b0054fa4316dd6cb gamma_light_curve.out 4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -00f1a6e50058ff026ce3ed0511ea7ce7 light_curve.out +c4e3d0aa48ca1a45d08d6b06c4087666 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -ae937aa10f537a4be5879d2148711c7d packets00_0000.out -242f927ab741ee4fa4cdab11c057e675 packets00_0001.out -7fdac7c300f071bfa1015ee244ca7d7c packets00_0002.out -4e44ad72a46350ab16c5b4112f5cd44c packets00_0003.out -2d154c74193a57d21c3b2b31c33bee9e spec.out +db70f134991145ac721669fa501d8a3c packets00_0000.out +dbbcc00ad6de0a91ac579ac6380547ca packets00_0001.out +78ddc8d30e4af6a61f209a645dbe4455 packets00_0002.out +8e92340c3acf00e67508154c253256c8 packets00_0003.out +2ebdb99d551f71d619b45c09bdd354cb spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -3b78eaa535ee03269f6e131ecf4cd9d3 job0/estimators_0000.out -f463d43459034263373f0fe95b4eced7 job0/estimators_0001.out -481b53d39d4ce276fed21a08ddc642dd job0/estimators_0002.out -772cd018b4eaca80edf71d6b51532b3d job0/estimators_0003.out +2889a013b8d2c36925d8e5d96f486703 job0/estimators_0000.out +78abe66049a2de616aae8947d708077a job0/estimators_0001.out +610f067f46a2e965dc439051379c6f40 job0/estimators_0002.out +a917473083f7d971dfc6277426369d4d job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index c81febc13..7484339b6 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -12,7 +12,7 @@ d395efd35c062824dd6ab0104e0867f8 packets00_0002.out e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out 88a0e6320da73f235aec8739d4a123a3 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -29f6ff5e9d574cddb2f90ec4a977199a job0/estimators_0000.out -24af7d8e90d79673d529c958635c0ace job0/estimators_0001.out -7a13aaeb7e5e6df02e21b97a81524e03 job0/estimators_0002.out -b47c9c48232ffe7e7ee813c891df3aaa job0/estimators_0003.out +9978501c2017ce329a24e54daffab148 job0/estimators_0000.out +93677b669e99a50f2e2af2814ac45d38 job0/estimators_0001.out +86a9ed26919747b91ef687add9752d7a job0/estimators_0002.out +209d5a8c2f888d5cefecbe77c1156e46 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index ba75e2213..e84792a17 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ e3a069b579947f54e3812795cf9deee0 packets00_0002.out 09eb173dc9f9ab59c8601d6dbdeb1af1 packets00_0003.out ff5a909e77a5ae78b0ff39c51813013d spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -4f120077aafb8ca9afb7eb557d661604 job0/estimators_0000.out -532fc878ee0d2bd269e9eac3fcd10375 job0/estimators_0001.out -3743f638c0a04d2e7094d5ddc61211e9 job0/estimators_0002.out -3afe098ae5c0f49f714ed77025368f63 job0/estimators_0003.out +0b45d96ce750f8d1d1f14b6fc47bebee job0/estimators_0000.out +c4cd5a51c5e2e4d3bb802cd9ab1ea77e job0/estimators_0001.out +2826b779993334c54235dea711d48428 job0/estimators_0002.out +9f8cf88d1a42ac2d5bbfdf7c327ba9d0 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index f9630fcb8..b1824fdab 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -12,7 +12,7 @@ a6c0fee501b6128a3fdb60ab924aba93 packets00_0002.out 84f08d240ba21f289e94737ca195f160 packets00_0003.out b653a3329cd63cfa1f429ff83c33693b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -deb7a21406d428d9896a081a30acc8c6 job0/estimators_0000.out -a0844e4c057678905a865f8f9837ddd0 job0/estimators_0001.out -515cb50fee5d4be924120483cfa40399 job0/estimators_0002.out -b9a9acf2b79158ea34947b1e2ef4e700 job0/estimators_0003.out +3a92706d94b2a4dfb4eb12b375c09bea job0/estimators_0000.out +a4bcb8cf8684bfd118fea9ebbcdc6021 job0/estimators_0001.out +1243ebd40d52270f3c272a87f1c2344a job0/estimators_0002.out +43676cd3885a88ed6cd81ade39494090 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index 76389c1ca..3e00d7055 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -15,7 +15,7 @@ b3d6d74cd0c4fbe6519294af8e63ebac packets00_0002.out 933be7818c864b6314faca6a2ceafb82 packets00_0003.out bb3e8856c519696a8af781915be05c81 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -678065cde1029b6978a3cc70096630c8 job0/estimators_0000.out -4cb851be2147ee839acc4cec0b57ec74 job0/estimators_0001.out -3b7949c57381229c6414f5d3355ab87f job0/estimators_0002.out -b30151a628196ec72db82d8f8e9c4414 job0/estimators_0003.out +0a029585f75d28b146493a4ad8e072c9 job0/estimators_0000.out +8c285d9ee87777ac585a1afd2e1ea568 job0/estimators_0001.out +f2fccf596e474acc5e0ab17aee2e3b12 job0/estimators_0002.out +ead312ccff0e5916f5004e32beae8559 job0/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index a7b8f4016..8cabb1390 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -12,7 +12,7 @@ a154f9a8511bed32dca64634d174f6f0 packets00_0001.out fb1b9057f1e7fc470fce0cf6011d352b packets00_0003.out efeeac5b0345ab0e40d5eab91e7c8b13 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -8cd8f36c29cea3b0accaf6d6ce43baa4 job0/estimators_0000.out -c2ecda86dc9ece5e65806ef676f5a0f7 job0/estimators_0001.out -f6f5331b0747eec5afb6cedaabed3e17 job0/estimators_0002.out -f0099de9cdf75566b080793174adf821 job0/estimators_0003.out +62783f048fc6a50fd8eec41d80a98cca job0/estimators_0000.out +2be2d54a38f9d5c0136a0c74bf023983 job0/estimators_0001.out +1a223ba1b090edeb6c14d4450878a1d1 job0/estimators_0002.out +55044a8a50537fa2fbac942f95112038 job0/estimators_0003.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 6b9eb8215..0f162034a 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -1a45b3c04b542f49ae27d4d54e9688c7 absorption.out +fae457639b1c328f6d8cad9d320d8cfa absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -57ac877a8c87629fbd11739e54c67daf deposition.out -1c02b034e6c568c158be8b34230c040d emission.out -2de88edda4f95630136d81deb821ec84 emissiontrue.out -2a636a749f5313433bcbcb67d48317ea gamma_light_curve.out -c3ad1c8e879c9f24318d604edb33ce11 gamma_spec.out +8000f1cd86ea8fc929e3956e373dc418 deposition.out +54d2f4656656ef3b6ec01e0ada76df6f emission.out +66111439a28421109a0780d80c2857c6 emissiontrue.out +35a93274bf6497a395edd6ad3bf4d288 gamma_light_curve.out +91b4b9296b54b92bafa3be7c0fac6e7d gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -35cef386fee0b62db5f858ee0d0e2425 light_curve.out +d164a3f16763d00efb6c5fb77c7cc28d light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -c1a6cec53ad08507a3d33d26da81f5a0 packets00_0000.out -cd7bb6d7cfe495b7406ef294bcbf8aa5 packets00_0001.out -c991bc240721279875b2936204a3bfc4 packets00_0002.out -1f3dfaafc02a8cbb47a3e62ba1f5f577 packets00_0003.out -5ebe9a852e9975574a6c946396b2a493 spec.out +f96c3ee5226174b4b8ec96f28891fb3a packets00_0000.out +15d85a7a462122bcedd7e062cbe87a13 packets00_0001.out +c6553cfa275d7233c01483bb0d76fd6f packets00_0002.out +fe3bd5e02b6bd99c9952bd6844ee6511 packets00_0003.out +016f17fa70a9c4f51370e93ae1726178 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -41a368446a406a721a6f9e8ba501f688 job1/estimators_0000.out -d4944478ee048e90c97b36d446da524d job1/estimators_0001.out -5e017495cce2903b6562ee5898ae700c job1/estimators_0002.out -68bc097a9846683d70a6ea4c05409b6c job1/nlte_0000.out -1f42a41c734a379c43c9831282e01a3b job1/nlte_0001.out -a503160f8b2ab0daafd1a327155c89d9 job1/nlte_0002.out +da485f04616e55614c596aa7da71a56e job1/estimators_0000.out +fb7cd3f5a650f7fd327bb881fa309e56 job1/estimators_0001.out +346c52212207801f6b016ee463f90bdb job1/estimators_0002.out +7c7f8384eb6ffdc73439d8255444761b job1/nlte_0000.out +2955bcccd9ff1744d5cc635463f92f74 job1/nlte_0001.out +f6dfc69e1ecbe5e4838160c94eae4390 job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -0373cda8e4acd2b1c49d343de9212f2f job1/radfield_0000.out -84376d4c46df0c412ab15509b55f94e9 job1/radfield_0001.out -6d4f5acbd6cc5c2d28fe336dbc4c944d job1/radfield_0002.out +6cefe0c0f4f344ae0fe215479ff702c0 job1/radfield_0000.out +3ac6a500599048c09861ae54d838d551 job1/radfield_0001.out +0ae4c4599d3caf162e94e1c81ba6f47c job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index 0ed2709df..b137463bd 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -4bdbc3fce442065843b75ccba8eb743c absorption.out +3d4761043871ca377db5577773fc9fa9 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -51e6ebef8f4a7ef46a6a07fdb4d629a1 deposition.out -664c267df1eebce02213cea5de6c07d3 emission.out -3738629c1d3d5ad08aa3ec2e47aac010 emissiontrue.out -13c9966c51be68d7e8b1f3429b9b2e3b gamma_light_curve.out +ca7aba5bcf922df1a215f9a430c62d6e deposition.out +b572b3b0eb158c2f5708aea54bf5a8d2 emission.out +d94f3c8e88cf2c3e8d9402b8eda53d57 emissiontrue.out +bb161073d8675c66989191fa8904955c gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -b2550978a93cc4b3e90784b845f03e03 light_curve.out +f532725fe559290335a353905f17a1f1 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -193f160d32272bceded94c3947b515db packets00_0000.out -3f7dff609efc917105d94844cb174449 packets00_0001.out -13ff1a6dd1731a2afcde09d70bc08c31 packets00_0002.out -51e103a37a3af8019e6eeba00688f4cc packets00_0003.out -90898a3ef561472bdcedd584014c63ef spec.out +51e228322c99a96c271ad2ab0f51d5e3 packets00_0000.out +51b23be79eb9ecd9bdede2cdfdeb7b6d packets00_0001.out +dc7f0380146827e0c0349758328182b2 packets00_0002.out +da9f5a7e9ea5a5994035f8cfb9312f89 packets00_0003.out +5b1fcce42483fdd04a03b0d378cf92ca spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -d5be89a8d1af7fd6be5c43872e445d6f job0/estimators_0000.out -c10f74a61fbd197aad25725bb48c5168 job0/estimators_0001.out -4f4c606953b350605dc8b8b03a169bac job0/estimators_0002.out -784108881cb7cd2ab9f880ba22105f1c job0/nlte_0000.out -8d081daafb63005388d675bb5a09bd7e job0/nlte_0001.out -cd0456b8df5b41aca5f930a26cfb6c32 job0/nlte_0002.out +34ddd0a2d79e19640f06fabbfebdb8fe job0/estimators_0000.out +13594569496e944cbe64d8ad73d07549 job0/estimators_0001.out +945dcd2dca1fe7610ba5218a519afdb5 job0/estimators_0002.out +db7b6f001f5b1115a36a9e5e99a7b8d1 job0/nlte_0000.out +065e80e98b641952bce2db500aa8f8c0 job0/nlte_0001.out +38f8a173a5c4e2acb4c6dc18fe6c2aac job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -7e9eeae2662e50b8cdacea0e48b17a2f job0/radfield_0000.out -557988c63e95c5fd7c1afe44facdb6b0 job0/radfield_0001.out -23af1dc66920467d2dfae6f70272029f job0/radfield_0002.out +3eb872041047a946222d9e8896a3140f job0/radfield_0000.out +d364314ae61b485d9a05907342706167 job0/radfield_0001.out +d33aa4018ec2f1adda99e9891562f002 job0/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 3ba8339ec..1f0342343 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -1,30 +1,30 @@ -16a7f8ef6a92defc1b5481963e5de5c2 absorption.out +1f4e225a396fb48cab9538fb5744a2f0 absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -cc0a6fd9e6f9ad648b3390d4b44b8354 deposition.out -587660bdb3b97f6b66d7317aabce2022 emission.out -613e3769666b9d43690aa370f2327b64 emissiontrue.out -707ad83631c3818fd5ed337022eebac6 gamma_light_curve.out -58abd1e96234d7897c4ebd1714b17625 gamma_spec.out +02896e17c793f7c4f9558593a9b97bed deposition.out +6b91303cd34a8086ee7ef47ecaa295f9 emission.out +1a55d5fa025bb295189ccf86602e21e8 emissiontrue.out +dfbe046f234e2e0d9ecc6392e0e4a218 gamma_light_curve.out +47139752760e082c05b536f1352431cb gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -2fbe87a317801b68d8097d3d0083fc1f light_curve.out +f656ff0ddbfe87bd1aea03d0e6599d6e light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -3dfe8799a8e5604d417d2660e7c3d527 packets00_0000.out -125289b175cfdc79c07f96c460d51622 packets00_0001.out -e8247a5cf14742233c9c4e00a9d6b9f2 packets00_0002.out -9b1bfec708d8a15bed0ac2526fed4b09 packets00_0003.out -c794b14a31f6c47464b0bbe72c5ce0fb spec.out +613664768e148c3d54add5bfa4fdf1ba packets00_0000.out +1a5db35d4a44ebcdf9d6b7098a58933d packets00_0001.out +f70e961d53307f25a044855caa6f2224 packets00_0002.out +21e4c0508130eedb1a196138efa59d9f packets00_0003.out +7f27bc271891a2effb367040cd4d3d6f spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -cd82cf5f2a867ec6f1ee328533c3db31 job1/estimators_0000.out -8da02f394fbaff90ae7f5d42902dca19 job1/estimators_0001.out -85938a7cf404d6a321fc213a953a64b6 job1/estimators_0002.out -7a77628812bcc3817cf521249cce7197 job1/nlte_0000.out -6c51dd67dc33038823e674710e862faa job1/nlte_0001.out -e61ba5b8b4780b62ee05076ff45268a6 job1/nlte_0002.out +b723d2ef8df8da5f337f5197bfaa7a00 job1/estimators_0000.out +9500e52d5135e642c62da310c046bcb1 job1/estimators_0001.out +abb88431c718b2898e817ad76e8a099b job1/estimators_0002.out +7fad386c6c6ad93e558954325e0a3b27 job1/nlte_0000.out +af22d7b135926c5ddecab95db3be05c6 job1/nlte_0001.out +6ddb80fd4753109834df1ac4ea15f44b job1/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out -79737c6717a49beec528fd4d6bb7fca1 job1/radfield_0000.out -5281dd710252b0c2c08ed50355ba3987 job1/radfield_0001.out -14c3f5bd88492c3b863e075a305b77e5 job1/radfield_0002.out +9b775cd0c4a0ec68188ba6eb9395766e job1/radfield_0000.out +2f140f78ac85f4eca187c713c6a9b120 job1/radfield_0001.out +966a4ad7b86bd21abc07064dde2a337c job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index 39ac20ea1..f7daff3f0 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -1,29 +1,29 @@ -dbad535e3a31ab55a0e3bd7eff082468 absorption.out +3027a661f0775894011d1ef853fc253e absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out -cacc8737b397653578dc03be41d5629f deposition.out -9b1deaf1cae7c7e75e6a8c9c0578e361 emission.out -2bea2f08ea2c1591360c69be60a96f5a emissiontrue.out -4ded7840283c11cbc6571fa429522bb9 gamma_light_curve.out +841ee5678b194cfc99520ebd0bd972cf deposition.out +f2697775a593aab14d9b52d3045a9e21 emission.out +edda83a44919d8cc91a921edc0e35494 emissiontrue.out +168c2509292f23440ceaded4a46ad52c gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out -a0593185f1a88664c8df5ca8db65160f light_curve.out +1532ef4bc0e11d420a6af982a0c6c8ff light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -0657a2cde6aa10cab3afd3f4f0793a58 packets00_0000.out -45de6bcc5f0280c42cff5a82f88edf26 packets00_0001.out -78aff0b4f5a6cc7992e0f695e34807bc packets00_0002.out -584cbfce883f9fd38f1e7f15b96612c7 packets00_0003.out -4bb17284dbfe23d42f9eaecd7c9cdb44 spec.out +842123db7fcab69910f2af297a5062ba packets00_0000.out +7a4ef901a8a17cab8815ecda9dbc6440 packets00_0001.out +42fe7c0b3942b799722f4f2d252cf5ba packets00_0002.out +80e286700a4286bae24bcc4b5c2ca66f packets00_0003.out +b0fe20f352168bb11db76f98b428dbb5 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out -e831f0a4a820c3932f54196718e229e4 job0/estimators_0000.out -340dc15b95391780cc400bfef074f00c job0/estimators_0001.out -c25cbbd7255fe4af2c6eb604877ca190 job0/estimators_0002.out -e5ace14c553cf3740bee1df94fde209d job0/nlte_0000.out -7c46469ea1f9675cc7a33c9004d989e5 job0/nlte_0001.out -ebc341a405730478997b4987bb76b9c1 job0/nlte_0002.out +448519eae825ada3ebfbe280ebf7ef65 job0/estimators_0000.out +bc6393b0fa989162a19cb6a8e45d369f job0/estimators_0001.out +260b0cd55fd2cb7e4ae4f076d952440f job0/estimators_0002.out +293a0481beead6b266c51ef55813abd4 job0/nlte_0000.out +212fd9d5a9a09c0da30be8fd54584e48 job0/nlte_0001.out +22f4dfabcb46ecfb742e43d66e9d7c8e job0/nlte_0002.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out 098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out -c5b81a79d8ae799c09c588b41f1e3a2f job0/radfield_0000.out -ab52b0e6955ad389c85125df8cc064f6 job0/radfield_0001.out -fdeb82c6b0b35791d1f28d2b56a86259 job0/radfield_0002.out +82c5527878531c8cd0ed309ac4e6411b job0/radfield_0000.out +714469b7b7094e4847ddea178529a378 job0/radfield_0001.out +f81c683aeee7965f09b112d398c77b15 job0/radfield_0002.out From 8cd920b8bd4917bde615a111a78e75828db18d89 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 16:42:28 +0000 Subject: [PATCH 072/117] Initialise packets (#139) No change to observables (uninitialised fields are not valid or accessed except to write to packets*.out) , but affects the reproducibility of results on the CI system. --- .github/workflows/ci.yml | 4 ++-- Makefile | 3 +-- packet.cc | 6 +----- sn3d.cc | 4 ++-- .../results_md5_final.txt | 8 ++++---- .../results_md5_job0.txt | 8 ++++---- tests/classicmode_3d_inputfiles/results_md5_final.txt | 8 ++++---- tests/classicmode_3d_inputfiles/results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../results_md5_job0.txt | 8 ++++---- .../results_md5_final.txt | 8 ++++---- .../kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt | 8 ++++---- .../nebular_1d_3dgrid_inputfiles/results_md5_final.txt | 10 +++++----- .../nebular_1d_3dgrid_inputfiles/results_md5_job0.txt | 10 +++++----- .../results_md5_final.txt | 10 +++++----- .../results_md5_job0.txt | 10 +++++----- 26 files changed, 98 insertions(+), 103 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebc175052..bfbc5a1b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,7 +140,7 @@ jobs: - name: Checksum job0 output files #if: always() - if: always() && matrix.testmode == 'OFF' + if: always() working-directory: tests/${{ matrix.testname }}_testrun run: | md5sum *.out job0/*.out | tee ../${{ matrix.testname }}_inputfiles/results_md5_job0.txt @@ -205,7 +205,7 @@ jobs: - name: Checksum job1 output files #if: always() - if: always() && matrix.testmode == 'OFF' + if: always() working-directory: tests/${{ matrix.testname }}_testrun run: | md5sum *.out job1/*.out | tee ../${{ matrix.testname }}_inputfiles/results_md5_final.txt diff --git a/Makefile b/Makefile index 7c2ef74f2..ee8e21865 100644 --- a/Makefile +++ b/Makefile @@ -62,8 +62,7 @@ CXXFLAGS += -std=c++20 -fstrict-aliasing # CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true ifneq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP - # add -ftrivial-auto-var-init=zero when we drop gcc 11 support + CXXFLAGS += -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP -ftrivial-auto-var-init=pattern endif # profile-guided optimisation diff --git a/packet.cc b/packet.cc index 12d8a4768..822eb11c2 100644 --- a/packet.cc +++ b/packet.cc @@ -133,14 +133,10 @@ void packet_init(Packet *pkt) // Now place the pellets in the ejecta and decide at what time they will decay. - if (globals::npkts > MPKTS) { - printout("Too many packets. Abort.\n"); - std::abort(); - } - printout("Placing pellets...\n"); auto allpkts = std::ranges::iota_view{0, globals::npkts}; std::ranges::for_each(allpkts, [&, norm, e0](const int n) { + pkt[n] = Packet{}; const double targetval = rng_uniform() * norm; // first i such that en_cumulative[i] > targetval diff --git a/sn3d.cc b/sn3d.cc index d39cdc044..ea0945cfe 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -883,7 +883,7 @@ auto main(int argc, char *argv[]) -> int { } } - auto *const packets = static_cast(malloc(MPKTS * sizeof(Packet))); + auto *const packets = static_cast(malloc(globals::npkts * sizeof(Packet))); assert_always(packets != nullptr); @@ -965,7 +965,7 @@ auto main(int argc, char *argv[]) -> int { printout("Simulation propagates %g packets per process (total %g with nprocs %d)\n", 1. * globals::npkts, 1. * globals::npkts * globals::nprocs, globals::nprocs); - printout("[info] mem_usage: packets occupy %.3f MB\n", MPKTS * sizeof(Packet) / 1024. / 1024.); + printout("[info] mem_usage: packets occupy %.3f MB\n", globals::npkts * sizeof(Packet) / 1024. / 1024.); if (!globals::simulation_continued_from_saved) { std::remove("deposition.out"); diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt index 9d4e72c45..fb85b66c4 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_final.txt @@ -12,10 +12,10 @@ ec53538474a3c9eec9d51a350b001d3a gamma_light_curve.out 5e818206372ff62ae5169fdb651106a5 light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -5ef844f385730d21db8d38f3ec342245 packets00_0000.out -37240a677a12c756e8ab376c82cf06a5 packets00_0001.out -e9a40a0e47d3bc0a2330fbe241142329 packets00_0002.out -5ff5f79e130997cfa8e9328e17801cf1 packets00_0003.out +c5f4648200998cf8a12a8bc4247d00f4 packets00_0000.out +f2e4cf2ce9f04a7159a539004d207a79 packets00_0001.out +992116649007c727a6ffb33f6badb7aa packets00_0002.out +49a84d0bccf30eaaf440ebe023baed44 packets00_0003.out 73d1c7f4c7d4e005618a41022554aeaf spec.out a41ca549452afa07ffe4bbd2aabe91f5 specpol.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out diff --git a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt index 48a6fbb13..6d47d1e2f 100644 --- a/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ c532033f860b76b8c5244784da32313b gamma_light_curve.out 61d5b071cea6e1098030a8cf2fbe14e9 light_curve.out 87aa0a1a8eebc5b15f95c5c7ba6325a3 linestat.out 41a1c375110d8edbf421edca3fc426e8 modelgridrankassignments.out -dc626ea88194714abcdf146723c88d6c packets00_0000.out -39bae205a40145c915daadd3c3b5e1c8 packets00_0001.out -bc5b497552ff03cf4d025f986278da1d packets00_0002.out -11919740e525fc5ceb459416050281b2 packets00_0003.out +7c30c238fe6c85290ebe07c4fdd14afa packets00_0000.out +928f9c63f5dce2ab016f8eb5f53ad6a4 packets00_0001.out +d7e94b3bd5866621da4c7809ea02dd9e packets00_0002.out +035a4d719c778d0d7b12e1c1a0be5381 packets00_0003.out 2fa32a2e224cca813b38a1387afbe85b spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out d1a1ad1c22e25f94724db515c351e488 vpackets_0000.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_final.txt b/tests/classicmode_3d_inputfiles/results_md5_final.txt index eaef465a3..777d3d0a3 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_final.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_final.txt @@ -513,10 +513,10 @@ b55e935340c11d93c28cf583701f0c89 light_curve.out c8a8b908bcdbf00c2d57592c03e23dd3 light_curve_res.out c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -d4bd9d264f25c09fff92bf56870c262d packets00_0000.out -96713f8399f5fdb12b1e05b8b936d2f6 packets00_0001.out -5360849c3c59fd884cfbfb7013a4da10 packets00_0002.out -a112392101bd80542cb30df0c9650e35 packets00_0003.out +209eb2ef47ba2ac5e7613b194d14727c packets00_0000.out +0833ce88598ab839bf6fecf39c39e1bf packets00_0001.out +37f4993f675845597277236e6892276b packets00_0002.out +e4dedb262fd4d1dd233a13608fc36b45 packets00_0003.out 8c7c79fbc346b83861ae26c8386177a1 spec.out d675f9c16c776141b7fc58067b682021 spec_res.out c137d2b84f03c7dd06718fef347dbd15 specpol.out diff --git a/tests/classicmode_3d_inputfiles/results_md5_job0.txt b/tests/classicmode_3d_inputfiles/results_md5_job0.txt index 946fcb3c2..ede748600 100644 --- a/tests/classicmode_3d_inputfiles/results_md5_job0.txt +++ b/tests/classicmode_3d_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ e08bbb965fac36412810b8769a13ab9d grid.out 076e72bd1967d1baf52db88300446693 light_curve.out c0138ff7e4fab0ee2bcabb2ca6c2f6b9 linestat.out 0edca801bc9867f17f0208399cf9ebd3 modelgridrankassignments.out -1e81ef6f94c8332c880d8be2f0ffba5d packets00_0000.out -1e44ed84716f7f2b2de2b445456c4a69 packets00_0001.out -f14d052cf549aec94aa7334a03b71662 packets00_0002.out -8fdf70de6cd92502cd925f66c3824a41 packets00_0003.out +b5e22d82616bb0a13d9e346356c154e3 packets00_0000.out +0a99f4670e404536a8e615be9bc2a271 packets00_0001.out +f5f1a898dde29898a08fd4bed7aa8865 packets00_0002.out +f8d231a78d88bffd1d023e6a77d60448 packets00_0003.out 79606abc60e8efc6546ef0844303e152 spec.out bc01f046eab9bf3802149e0ff63d5069 timesteps.out d301fc9a5830434377ebc654a613205b job0/estimators_0000.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt index d46120f46..5c2d18786 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt @@ -10,10 +10,10 @@ dd314f8317220adaee8b48aa1b60f2a3 gamma_light_curve.out f0b726a4dfbbbe17d71e182cfc251e72 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -4c54bcd871084746f43ad26453c039eb packets00_0000.out -0c872ac2a44f70d6d3fc9ffaf9c64338 packets00_0001.out -b5ca49a6f951391b5083c421501f645d packets00_0002.out -377af72746a6b1d93754130a3ff6f642 packets00_0003.out +8c3d21a3d8646afef626a7adeb0feee8 packets00_0000.out +67239f5faf43336b8bd4a175553763ee packets00_0001.out +b4828c6463ba397ce993bf75488a2a33 packets00_0002.out +ddfded7dcd44bb1469432977052eca4b packets00_0003.out 5bc66d0e2f639e2cd2d2a8d9a6487c3b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out ea174eff24f41e70b1d28e9775e7dfd3 job1/estimators_0000.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index f50fc8345..f6525158b 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ a65c34c5069444d22e04c7efb8bd0d69 gamma_light_curve.out ba3d39bcb52c8f2f4bb30666cec29607 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -c028370406b2659f1e2cc8f7b476305f packets00_0000.out -d2b546c1df9ca44beec2a25fe5cd7a12 packets00_0001.out -37dd64d999dff9f764006b75b37c2627 packets00_0002.out -209c278c8753e7d57ef1120c4b1e8c59 packets00_0003.out +f267baafef20bacbaf44ac66b4de90d5 packets00_0000.out +01c4d1d02b822f05d6a0b1a19ae0f6aa packets00_0001.out +04fca0a55fde00a2a3b31cf49d611a9b packets00_0002.out +54a3b60f3de31e59d9d046f1e133d7ef packets00_0003.out d90011df9b26a1b201891122b690b7e9 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 59b9ddad12a7142035a8a14a66772533 job0/estimators_0000.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index 8268caafe..d5471ecb5 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -10,10 +10,10 @@ ea2528ae1d42dce5f7c8eef94b948c86 gamma_spec.out c61ea3b7b9fc33359366cb32edf7ad74 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -41c15e45e9bcc526fa7b93afaa922048 packets00_0000.out -cb5dfa67343136b93267bf3555e13ecd packets00_0001.out -292f4caa6eb687c34d12fe9b01aa9aa4 packets00_0002.out -3c7ca4b9ccd45c820f424c1d4a4e597b packets00_0003.out +7e330e3a09784fdf8026ef2b81efc0d9 packets00_0000.out +59947bdab37695bb5c41b233e9644a59 packets00_0001.out +08ea133f3dd4ef8b99fd51aa7a23eb01 packets00_0002.out +7ae9a0fe5fc4b76b418fd95e41659f35 packets00_0003.out dbb89cf92f157e3519a95ee53a28320f spec.out a351f1711fecd60c023d0ba7332092db timesteps.out bb94370d18931aa66b2679ca2f9d0a68 job1/estimators_0000.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index 112d23508..1b868dbd6 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ ac5639d46649923f4d6962a640ca309f emission.out c4e3d0aa48ca1a45d08d6b06c4087666 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -db70f134991145ac721669fa501d8a3c packets00_0000.out -dbbcc00ad6de0a91ac579ac6380547ca packets00_0001.out -78ddc8d30e4af6a61f209a645dbe4455 packets00_0002.out -8e92340c3acf00e67508154c253256c8 packets00_0003.out +3dca38a2a4a7610f384725664209a2f6 packets00_0000.out +2c29214bc02476969918f550375e613d packets00_0001.out +08a3134596ed9a4bf7eed265acdf3d1d packets00_0002.out +6cb7f23fe871e1e174e941850084f3bb packets00_0003.out 2ebdb99d551f71d619b45c09bdd354cb spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 2889a013b8d2c36925d8e5d96f486703 job0/estimators_0000.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index 925f1450f..92881013c 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -311,10 +311,10 @@ b1e9d6e1b0460ddb425ebe296ef0eaee light_curve.out c4376a7fa8ea4fc8a0345dc0c3231889 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d88772c9f2f982809105433aa1ef43ed packets00_0000.out -8b2b12f83be94c74e6b452ed629a01e6 packets00_0001.out -8eda58f172cdcb88a86e018a286ee9f2 packets00_0002.out -3492c21b7da16033c832dbbb53e23c04 packets00_0003.out +1338bf7d672024f42b380d8d0f080038 packets00_0000.out +0c819dfd660bd1129ec869f14b8935dd packets00_0001.out +d197dc03276447c2ce703bbb3cd6e5ff packets00_0002.out +d1c0b59a25497a262c3668b515c42369 packets00_0003.out 2013eb78c14b8ab574b3e7d045ee9f7f spec.out f7aae73b1abecba91128abc65b17f4be spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 7484339b6..7748a2486 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -6,10 +6,10 @@ afe66f023087001ce7a9fff264f87b2b gamma_light_curve.out c167f0a32585932e22e6265b0c9ebbbb light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -c5d9f0d8d6ea6137782e7f73cceb2a99 packets00_0000.out -2f157c26d84a5002e5f88f1ffe881654 packets00_0001.out -d395efd35c062824dd6ab0104e0867f8 packets00_0002.out -e51e447e54bfe2d3f609ece1e8699cad packets00_0003.out +90053e981acde88f38e4a7614acd2cca packets00_0000.out +7f3cb2ff61dcf6693258fb12a8d4a2de packets00_0001.out +e3d4d90c60c5ffd0d7beae8dddd8cacf packets00_0002.out +04e3c8228a973338ecde2f6b90bc40bf packets00_0003.out 88a0e6320da73f235aec8739d4a123a3 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 9978501c2017ce329a24e54daffab148 job0/estimators_0000.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt index be0c21093..5bedf5372 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt @@ -311,10 +311,10 @@ ee190b2ade0bbeb40a257d10ab7f1a34 gamma_spec.out 789a5fa6f1c64c8b08062c61854f4b47 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -6da8a73c53bf054878e8d385dad5b24c packets00_0000.out -45df3063a9a76a9c0f926e10d29f772e packets00_0001.out -01bf4b44c6efd342d5dc62fbecd04990 packets00_0002.out -5c9f70d461efb06a3627dca6aab5b2d9 packets00_0003.out +0d5fb0c7428d958910c037a7658af3b4 packets00_0000.out +b07e99459b2eaae02f5b45a719019248 packets00_0001.out +52c38efc594cb6fd7f96b2722df4197b packets00_0002.out +245600dfb88eeebea106755dcc4b07ad packets00_0003.out 174d35c403e43ae90380d786e591c078 spec.out a35e02bc19e8aed065425582283e9d52 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index e84792a17..596f4e1e6 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ f3658f06dcf3f3cb59f2af794051dd09 gamma_light_curve.out 79ada276fd59c2e1321109afd258fb59 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -c2735ac629f244ca65ed93c9a68f804e packets00_0000.out -97ee84db14d194468fe7c8cc3748213c packets00_0001.out -e3a069b579947f54e3812795cf9deee0 packets00_0002.out -09eb173dc9f9ab59c8601d6dbdeb1af1 packets00_0003.out +5fa7e1c5ff3a497bded048dba65ea86b packets00_0000.out +83a9c67696d72ebd6eed3da323030e10 packets00_0001.out +61fa8c163469dade9ced584a19edb6ca packets00_0002.out +36075e4eb01b10e9213f54a6594b01eb packets00_0003.out ff5a909e77a5ae78b0ff39c51813013d spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 0b45d96ce750f8d1d1f14b6fc47bebee job0/estimators_0000.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt index 8b1772515..23b277cbf 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt @@ -311,10 +311,10 @@ c418bd488a88758b8998799fb0e85f56 light_curve.out dc87afe89962c6cc982654d6b51fe6d4 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d657a1b558b3d8f5ef12ffc2fe97af0c packets00_0000.out -5607b49884bd2a64e7546e79e9beb5b5 packets00_0001.out -6d750b33c47adb3ab9e147cc7f226ef5 packets00_0002.out -b80d451b7a65caf3e7e358bb2e31e215 packets00_0003.out +d874fa90ab0cd656db374027c4d84263 packets00_0000.out +c42b25777b701b4bafbbe678ab9cb553 packets00_0001.out +4189f86a3de001dc02082a24da06459f packets00_0002.out +5f80eab7dae548e5b2033d039c81806f packets00_0003.out 75a19500dc039b998f89bdaa549d4840 spec.out fc09caca8a29c0090c5747885cb037aa spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index b1824fdab..383d9c49c 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -6,10 +6,10 @@ dcde6c7de036fea5e230d1d09e8bf708 gamma_light_curve.out f0c53ee7bd627cdffa79a78172ae55b0 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -69f7ff7b95a98965ba7470e7a56aa00e packets00_0000.out -6f81cdc308ab997a2aae42e9aad3b5ce packets00_0001.out -a6c0fee501b6128a3fdb60ab924aba93 packets00_0002.out -84f08d240ba21f289e94737ca195f160 packets00_0003.out +66841da450aa382ffb1bc89f4a2a5ab3 packets00_0000.out +0ed4bdd8a029f59a5274448a1afab0e5 packets00_0001.out +332651698a9ce00b998de24435e3f424 packets00_0002.out +273f83e24133d8984219f4afe187c397 packets00_0003.out b653a3329cd63cfa1f429ff83c33693b spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 3a92706d94b2a4dfb4eb12b375c09bea job0/estimators_0000.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index e0cfcb281..f37031da7 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -311,10 +311,10 @@ c7d59db7e83a3c394a2e3fc9479eba6d emissiontrue_res_97.out 45367bb87fbb87d83a989dd396432059 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -5f4673ed07b99575ce686a3dd9c0d9ad packets00_0000.out -67104d4b06c8170db6a487091f826506 packets00_0001.out -f3458bdeaf2f5cb207dcbee103dda567 packets00_0002.out -945a661db635f34f23b10ed8e800586b packets00_0003.out +40f77198c2de368bdc98ef21639b1ecf packets00_0000.out +63f250cb7df583bc3ecb9393b550834b packets00_0001.out +1981cc7eb1a690d599e7927af9f34201 packets00_0002.out +2d7648f5c9a62b28ecbfd764fd148702 packets00_0003.out bb247a6213ff848ca038d6c7368d9762 spec.out f51cbb087c29f30368ed94046f8080e1 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index 3e00d7055..b35aea5a4 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -9,10 +9,10 @@ ecb663d454dac15eb2ff74b4ca4c581d absorption.out 5e36aef9929f8ab61fa35cba5969663b light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -18756de76903d456aac7a3ae3f1068ca packets00_0000.out -6cfdd8a322075d58586bc3a8548f5040 packets00_0001.out -b3d6d74cd0c4fbe6519294af8e63ebac packets00_0002.out -933be7818c864b6314faca6a2ceafb82 packets00_0003.out +d7c33a4fc48a35472da38bd58bd7a66e packets00_0000.out +4e3fcb685c790aac6ba82d4ac4fb42e7 packets00_0001.out +58ebb999b4e2e9d4dfa0763f06ce88cf packets00_0002.out +71f446d85027c652e0a0ae80327b1e0f packets00_0003.out bb3e8856c519696a8af781915be05c81 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 0a029585f75d28b146493a4ad8e072c9 job0/estimators_0000.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt index 9d3c5899b..fb6833053 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt @@ -311,10 +311,10 @@ b72b67aae10074c2b0915aaad7d9ccbc grid.out 7e4a49bf389bf336c0745b602e21468f light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -ca0cad54b337590f4d881ca2ec7542d2 packets00_0000.out -e58ede787afe0fb5fc82d49b071586c3 packets00_0001.out -ec98e6641906656d97ca0d82335436fb packets00_0002.out -e802497c7ed89464a51eb0884be7b959 packets00_0003.out +9ac2e742736a386964564a7a03f426db packets00_0000.out +5ff366aa042aca37c22e262e97876ef1 packets00_0001.out +6ae2565142cbf1ae6c652342468d3d67 packets00_0002.out +7d9cbc99445626402d07bd66f0556aeb packets00_0003.out a1d482542b13466b0b7976654de18bee spec.out 9f902c07f4dd9d8ca3664cab3dea060a spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index 8cabb1390..81be18378 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -6,10 +6,10 @@ b72b67aae10074c2b0915aaad7d9ccbc grid.out 2c912821e702307536768d4a714fd680 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -c5fcded63551749abec1a322748e9f6d packets00_0000.out -a154f9a8511bed32dca64634d174f6f0 packets00_0001.out -7554b0d216037e2fd5bfd993681a329d packets00_0002.out -fb1b9057f1e7fc470fce0cf6011d352b packets00_0003.out +4f87a99a2945c219881086c9ef1e0304 packets00_0000.out +cf6d2847ed627f6018794964232f3e60 packets00_0001.out +2d6fe04c6e5b997d2b1ae1f28833a7fb packets00_0002.out +f8a58f999a95e3dd96ef3797c04a8f1a packets00_0003.out efeeac5b0345ab0e40d5eab91e7c8b13 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out 62783f048fc6a50fd8eec41d80a98cca job0/estimators_0000.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 0f162034a..379a55f10 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -2,7 +2,7 @@ fae457639b1c328f6d8cad9d320d8cfa absorption.out aff44ecad68d986f04fcd6110331ba8b bflist.out 8000f1cd86ea8fc929e3956e373dc418 deposition.out 54d2f4656656ef3b6ec01e0ada76df6f emission.out -66111439a28421109a0780d80c2857c6 emissiontrue.out +9c3cff5bedc024da8e6d0eb55236348e emissiontrue.out 35a93274bf6497a395edd6ad3bf4d288 gamma_light_curve.out 91b4b9296b54b92bafa3be7c0fac6e7d gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out @@ -10,10 +10,10 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out d164a3f16763d00efb6c5fb77c7cc28d light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -f96c3ee5226174b4b8ec96f28891fb3a packets00_0000.out -15d85a7a462122bcedd7e062cbe87a13 packets00_0001.out -c6553cfa275d7233c01483bb0d76fd6f packets00_0002.out -fe3bd5e02b6bd99c9952bd6844ee6511 packets00_0003.out +401401c222866521c21bbc4fc434cd07 packets00_0000.out +e4d1c9201d97eedae8cc1873e663f2e1 packets00_0001.out +8fd002442cc49845bd39644195a02d9f packets00_0002.out +cb58820a9bd90883f848b84a1f271c6c packets00_0003.out 016f17fa70a9c4f51370e93ae1726178 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out da485f04616e55614c596aa7da71a56e job1/estimators_0000.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index b137463bd..aede92c2c 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -2,17 +2,17 @@ aff44ecad68d986f04fcd6110331ba8b bflist.out ca7aba5bcf922df1a215f9a430c62d6e deposition.out b572b3b0eb158c2f5708aea54bf5a8d2 emission.out -d94f3c8e88cf2c3e8d9402b8eda53d57 emissiontrue.out +38378dd5d9ea9bc666aad4f8760021bb emissiontrue.out bb161073d8675c66989191fa8904955c gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out f532725fe559290335a353905f17a1f1 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -51e228322c99a96c271ad2ab0f51d5e3 packets00_0000.out -51b23be79eb9ecd9bdede2cdfdeb7b6d packets00_0001.out -dc7f0380146827e0c0349758328182b2 packets00_0002.out -da9f5a7e9ea5a5994035f8cfb9312f89 packets00_0003.out +aa62adbfd7880c712dd9665a24ff3bdb packets00_0000.out +874c58560800a3f2270dbe2361e92f2c packets00_0001.out +e04f37851cbde644a4589dc73ffe36e2 packets00_0002.out +ce6db00706ebfd0ffd47a42b06dd63f9 packets00_0003.out 5b1fcce42483fdd04a03b0d378cf92ca spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out 34ddd0a2d79e19640f06fabbfebdb8fe job0/estimators_0000.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 1f0342343..1fbcbbc01 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -2,7 +2,7 @@ aff44ecad68d986f04fcd6110331ba8b bflist.out 02896e17c793f7c4f9558593a9b97bed deposition.out 6b91303cd34a8086ee7ef47ecaa295f9 emission.out -1a55d5fa025bb295189ccf86602e21e8 emissiontrue.out +52ee035d0e8bb20cb4e553b2048739db emissiontrue.out dfbe046f234e2e0d9ecc6392e0e4a218 gamma_light_curve.out 47139752760e082c05b536f1352431cb gamma_spec.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out @@ -10,10 +10,10 @@ a3e3cf9b6adeac882d182c06011c63e8 grid.out f656ff0ddbfe87bd1aea03d0e6599d6e light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -613664768e148c3d54add5bfa4fdf1ba packets00_0000.out -1a5db35d4a44ebcdf9d6b7098a58933d packets00_0001.out -f70e961d53307f25a044855caa6f2224 packets00_0002.out -21e4c0508130eedb1a196138efa59d9f packets00_0003.out +f4803e42c4a9b480f3388cac951ca47e packets00_0000.out +765e1c4746919376f9f15052ce818ee8 packets00_0001.out +639efb02cd996f17cf2a159c0efe10e4 packets00_0002.out +ff8dc64a3c6a40e62c76613e991ec6a5 packets00_0003.out 7f27bc271891a2effb367040cd4d3d6f spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out b723d2ef8df8da5f337f5197bfaa7a00 job1/estimators_0000.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index f7daff3f0..2cc983afc 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -2,17 +2,17 @@ aff44ecad68d986f04fcd6110331ba8b bflist.out 841ee5678b194cfc99520ebd0bd972cf deposition.out f2697775a593aab14d9b52d3045a9e21 emission.out -edda83a44919d8cc91a921edc0e35494 emissiontrue.out +f23e456ba844d7fa8eb277ac3de4ddfe emissiontrue.out 168c2509292f23440ceaded4a46ad52c gamma_light_curve.out 057b226c371f3819cba5e04bfea3d114 gammalinelist.out a3e3cf9b6adeac882d182c06011c63e8 grid.out 1532ef4bc0e11d420a6af982a0c6c8ff light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out 25a9dd224aa09e3ac10e091ad673223d modelgridrankassignments.out -842123db7fcab69910f2af297a5062ba packets00_0000.out -7a4ef901a8a17cab8815ecda9dbc6440 packets00_0001.out -42fe7c0b3942b799722f4f2d252cf5ba packets00_0002.out -80e286700a4286bae24bcc4b5c2ca66f packets00_0003.out +436a38243559287bc8c780d04b327788 packets00_0000.out +db2ed6f09cef9f73f87802eb692d6ba8 packets00_0001.out +eefba1fd91ef031a71bad0c97c728ed9 packets00_0002.out +436e0674576a9efa66d7f370a01728ad packets00_0003.out b0fe20f352168bb11db76f98b428dbb5 spec.out 8e7163982f1aa938dc1505478b8c60d1 timesteps.out 448519eae825ada3ebfbe280ebf7ef65 job0/estimators_0000.out From 4a02324a5bc160fbe86d65399373dd4f59e73341 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 17:36:40 +0000 Subject: [PATCH 073/117] Replace printout macro with function (to prepare for C++23 std::format) (#138) --- .clang-tidy | 1 + atomic.h | 3 --- decay.cc | 3 --- exspec.cc | 1 - gammapkt.cc | 8 -------- grid.cc | 15 --------------- input.cc | 11 ----------- ltepop.cc | 4 ---- macroatom.cc | 4 ++-- nltepop.cc | 5 ----- nonthermal.cc | 35 +++++------------------------------ radfield.cc | 8 -------- ratecoeff.cc | 7 ------- sn3d.cc | 2 +- sn3d.h | 20 ++++++++++++-------- thermalbalance.cc | 4 ---- update_grid.cc | 5 ----- update_packets.cc | 5 ----- vpkt.cc | 1 - 19 files changed, 21 insertions(+), 121 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 4db7639c9..b927c18ce 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -16,6 +16,7 @@ Checks: > -bugprone-narrowing-conversions, -boost-use-ranges, -llvmlibc-*, + -cert-dcl50-cpp, -cert-err33-c, -cert-err34-c, -cert-err58-cpp, diff --git a/atomic.h b/atomic.h index b624ee689..dcd9e4dcd 100644 --- a/atomic.h +++ b/atomic.h @@ -230,9 +230,6 @@ inline auto get_elementindex(const int Z) -> int { return static_cast(elem - globals::elements.begin()); } - // printout("[debug] get_elementindex: element Z=%d was not found in atomic data ... skip readin of cross sections - // for this element\n",Z); printout("[fatal] get_elementindex: element Z=%d was not found in atomic data ... - // abort\n"); abort();; return -100; } diff --git a/decay.cc b/decay.cc index 113bf1c0e..909a44831 100644 --- a/decay.cc +++ b/decay.cc @@ -973,9 +973,6 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector nuclides[alphanucindex].endecay_q[DECAYTYPE_BETAMINUS] = Q_total_betadec * MEV; nuclides[alphanucindex].branchprobs[DECAYTYPE_ALPHA] = branch_alpha; nuclides[alphanucindex].endecay_q[DECAYTYPE_ALPHA] = Q_total_alphadec * MEV; - - // printout("alphadecay file: Adding (Z=%d)%s%d endecay_alpha %g endecay_gamma %g tau_s %g\n", - // z, get_elname(z), a, e_alpha_mev, e_gamma_mev, tau_sec); } } } diff --git a/exspec.cc b/exspec.cc index a877b3a0d..3b1b44c48 100644 --- a/exspec.cc +++ b/exspec.cc @@ -82,7 +82,6 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra int nesc_gamma = 0; int nesc_rpkt = 0; for (int ii = 0; ii < globals::npkts; ii++) { - // printout("packet %d escape_type %d type %d", ii, pkts[ii].escape_type, pkts[ii].type); if (pkts_start[ii].type == TYPE_ESCAPE) { nesc_tot++; if (pkts_start[ii].escape_type == TYPE_RPKT) { diff --git a/gammapkt.cc b/gammapkt.cc index 594de2336..95b5a4c40 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -296,13 +296,10 @@ auto choose_f(const double xx, const double zrand) -> double int count = 0; double err = 1e20; - // printout("new\n"); - double ftry = (f_max + f_min) / 2; while ((err > 1.e-4) && (count < 1000)) { ftry = (f_max + f_min) / 2; const double sigma_try = sigma_compton_partial(xx, ftry); - // printout("ftry %g %g %g %g %g\n",ftry, f_min, f_max, try, norm); if (sigma_try > norm) { f_max = ftry; err = (sigma_try - norm) / norm; @@ -780,8 +777,6 @@ void transport_gamma(Packet &pkt, const double t2) { assert_always(tdist >= 0); - // printout("sdist, tdist, edist %g %g %g\n",sdist, tdist, edist); - if ((sdist < tdist) && (sdist < edist)) { move_pkt_withtime(pkt, sdist / 2.); @@ -1056,9 +1051,6 @@ __host__ __device__ void pellet_gamma_decay(Packet &pkt) { } pkt.pol_dir = vec_norm(pkt.pol_dir); - // printout("initialise pol state of packet %g, %g, %g, %g, - // %g\n",pkt.stokes_qu[0],pkt.stokes_qu[1],pkt.pol_dir[0],pkt.pol_dir[1],pkt.pol_dir[2]); - // printout("pkt direction %g, %g, %g\n",pkt.dir[0],pkt.dir[1],pkt.dir[2]); } __host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { diff --git a/grid.cc b/grid.cc index 3c5f88c78..69c7ccf7a 100644 --- a/grid.cc +++ b/grid.cc @@ -111,9 +111,6 @@ void read_possible_yefile() { const int mgi = mgiplusone - 1; if (mgi >= 0 && mgi < get_npts_model()) { set_initelectronfrac(mgi, initelecfrac); - // printout("Ye.txt: setting mgi %d init_ye %g\n", mgi, initelecfrac); - } else { - // printout("Ye.txt: ignoring mgi %d init_ye %g\n", mgi, initelecfrac); } } fclose(filein); @@ -1021,8 +1018,6 @@ void read_3d_model() { std::istringstream ssline(line); assert_always(ssline >> cellnumberin >> cellpos_in[0] >> cellpos_in[1] >> cellpos_in[2] >> rho_model); - // printout("cell %d, posz %g, posy %g, posx %g, rho %g, rho_init %g\n",dum1,dum3,dum4,dum5,rho_model,rho_model* - // pow( (t_model/globals::tmin), 3.)); if (mgi == 0) { first_cellindex = cellnumberin; @@ -2379,7 +2374,6 @@ void grid_init(const int my_rank) { if (totmassradionuclide_actual > 0.) { const double ratio = totmassradionuclide[nucindex] / totmassradionuclide_actual; - // printout("nuclide %d ratio %g\n", nucindex, ratio); for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double prev_abund = get_modelinitnucmassfrac(mgi, nucindex); @@ -2470,7 +2464,6 @@ auto get_totmassradionuclide(const int z, const int a) -> double { const auto negdirections = std::array{COORD0_MIN, COORD1_MIN, COORD2_MIN}; const auto posdirections = std::array{COORD0_MAX, COORD1_MAX, COORD2_MAX}; - // printout("checking inside cell boundary\n"); for (int d = 0; d < ndim; d++) { // flip is either zero or one to indicate +ve and -ve boundaries along the selected axis for (int flip = 0; flip < 2; flip++) { @@ -2526,14 +2519,6 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } } - // printout("pkt.number %d\n", pkt.number); - // printout("delta1x %g delta2x %g\n", (initpos[0] * globals::tmin/tstart)-grid::get_cellcoordmin(cellindex, 0), - // cellcoordmax[0] - (initpos[0] * globals::tmin/tstart)); printout("delta1y %g delta2y %g\n", (initpos[1] * - // globals::tmin/tstart)-grid::get_cellcoordmin(cellindex, 1), cellcoordmax[1] - (initpos[1] * - // globals::tmin/tstart)); printout("delta1z %g delta2z %g\n", (initpos[2] * - // globals::tmin/tstart)-grid::get_cellcoordmin(cellindex, 2), cellcoordmax[2] - (initpos[2] * - // globals::tmin/tstart)); printout("dir [%g, %g, %g]\n", dir[0],dir[1],dir[2]); - // distance to reach the cell's upper boundary on each coordinate auto d_coordmaxboundary = std::array{-1}; diff --git a/input.cc b/input.cc index 14281fb60..9dfcda442 100644 --- a/input.cc +++ b/input.cc @@ -219,12 +219,9 @@ void read_phixs_data_table(std::fstream &phixsfile, const int nphixspoints_input // the photoionisation cross-sections in the database are given in Mbarn = 1e6 * 1e-28m^2 // to convert to cgs units multiply by 1e-18 levelphixstable[i] = phixs * 1e-18; - // fprintf(database_file,"%g %g\n", nutable[i], phixstable[i]); } } - // nbfcontinua++; - // printout("[debug] element %d, ion %d, level %d: phixs exists %g\n",element,lowerion,lowerlevel,phixs*1e-18); globals::nbfcontinua += get_nphixstargets(element, lowerion, lowerlevel); if (lowerlevel == 0 && get_nphixstargets(element, lowerion, lowerlevel) > 0) { globals::nbfcontinua_ground++; @@ -446,8 +443,6 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition if (tmplevel == prev_lower) { continue; } - // printout("+adding transition index %d Z=%02d ionstage %d lower %d upper %d\n", i, Z, ionstage, prev_lower, - // tmplevel); tottransitions++; assert_always(tmplevel >= 0); iontransitiontable.push_back( @@ -457,9 +452,6 @@ void read_ion_transitions(std::fstream &ftransitiondata, const int tottransition iontransitiontable.push_back( {.lower = lower, .upper = upper, .A = A, .coll_str = coll_str, .forbidden = (intforbidden == 1)}); - // printout("index %d, lower %d, upper %d, A %g\n",transitionindex,lower,upper,A); - // printout("reading transition index %d lower %d upper %d\n", i, transitiontable[i].lower, - // transitiontable[i].upper); prev_lower = lower; prev_upper = upper; } @@ -1017,7 +1009,6 @@ void read_atomicdata_files() { double ionpot = 0.; for (int ion = 0; ion < nions; ion++) { int nlevelsmax = nlevelsmax_readin; - // printout("element %d ion %d\n", element, ion); // calculate the current levels ground level energy assert_always(ionpot >= 0); energyoffset += ionpot; @@ -1646,8 +1637,6 @@ void input(int rank) { auto get_noncommentline(std::fstream &input, std::string &line) -> bool { while (true) { const bool linefound = !(!std::getline(input, line)); - // printout("LINE: >%s< linefound: %s commentonly: %s \n", line.c_str(), linefound ? "true" : "false", - // lineiscommentonly(line) ? "true" : "false"); if (!linefound) { return false; } diff --git a/ltepop.cc b/ltepop.cc index 47d999f6d..06b2178b6 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -185,7 +185,6 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co // Case for when no NLTE level information is available yet nn = calculate_levelpop_lte(modelgridindex, element, ion, level); } else { - // printout("Using an nlte population!\n"); nn = nltepop_over_rho * grid::get_rho(modelgridindex); if (!std::isfinite(nn)) { printout("[fatal] NLTE population failure.\n"); @@ -209,7 +208,6 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co // Case for when no NLTE level information is available yet nn = calculate_levelpop_lte(modelgridindex, element, ion, level); } else { - // printout("Using a superlevel population!\n"); nn = superlevelpop_over_rho * grid::get_rho(modelgridindex) * superlevel_boltzmann(modelgridindex, element, ion, level); if (!std::isfinite(nn)) { @@ -544,8 +542,6 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co const double g_lower = stat_weight(element, ion, level); const double g_upper = stat_weight(element, ion + 1, upperionlevel); const double sf = SAHACONST * g_lower / g_upper * pow(T, -1.5) * exp(E_threshold / KB / T); - // printout("element %d, ion %d, level %d, T, %g, E %g has sf %g (g_l %g g_u %g)\n", element, ion, level, T, - // E_threshold, sf,stat_weight(element,ion,level),stat_weight(element,ion+1,0) ); if (sf < 0) { printout( "[fatal] calculate_sahafact: Negative Saha factor. sfac %g element %d ion %d level %d upperionlevel %d " diff --git a/macroatom.cc b/macroatom.cc index 253a5eeb2..e1642e998 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -682,8 +682,8 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con } // printout("[debug] rad_rates_down: Z=%d, ionstage %d, upper %d, lower %d\n", get_atomicnumber(element), - // get_ionstage(element, ion), upper, lower); printout("[debug] rad_deexc: A_ul %g, tau_sobolev %g, n_u %g\n", A_ul, - // tau_sobolev, n_u); + // get_ionstage(element, ion), upper, lower); printout("[debug] rad_deexc: A_ul %g, tau_sobolev %g, n_u %g\n", + // A_ul, tau_sobolev, n_u); assert_testmodeonly(std::isfinite(R)); } diff --git a/nltepop.cc b/nltepop.cc index 381cd0edb..208081672 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -1175,11 +1175,6 @@ void nltepop_write_to_file(const int modelgridindex, const int timestep) { } nnlevelnlte = slpopfactor * superlevel_partfunc; - - // printout("nltepop_write_to_file: The Z=%d ionstage %d superlevel population is %g with rho %g and - // superlevel_partfunc %g Te %g scaled pop stored as %g\n", get_atomicnumber(element), get_ionstage(element, - // ion), nnlevelnlte, grid::modelgrid[modelgridindex].rho, superlevel_partfunc, grid::get_Te(modelgridindex), - // grid::modelgrid[modelgridindex].nlte_pops[ion_first_nlte + nlevels_nlte]); } const double ion_popfrac = nnlevelnlte / get_nnion(modelgridindex, element, ion); diff --git a/nonthermal.cc b/nonthermal.cc index e89eb06f6..c4c476265 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -452,7 +452,6 @@ void read_auger_data() { assert_always(fabs(prob_sum - 1.0) < 0.001); printout("\n"); - // printout("ionpot %g %g, g %d\n", colliondata[i].ionpot_ev, ionpot_ev, g); const bool found_existing_data = (collionrow.auger_g_accumulated > 0.); // keep existing data but update according to statistical weight represented by existing and new data @@ -642,9 +641,6 @@ void read_collion_data() { collionrow.n_auger_elec_avg = 0.; colliondata.push_back(collionrow); - - // printout("ci row: %2d %2d %1d %1d %lg %lg %lg %lg %lg\n", collionrow.Z, collionrow.nelec, collionrow.n, - // collionrow.l, collionrow.ionpot_ev, collionrow.A, collionrow.B, collionrow.C, collionrow.D); } printout("Stored %zu of %d input shell cross sections\n", colliondata.size(), colliondatacount); for (int element = 0; element < get_nelements(); element++) { @@ -1900,9 +1896,6 @@ void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, assert_always(ionpot_ev >= SF_EMIN); - // printout("Z=%2d ionstage %d n %d l %d ionpot %g eV\n", - // Z, ionstage, colliondata[n].n, colliondata[n].l, ionpot_ev); - const int xsstartindex = get_xs_ionization_vector(vec_xs_ionization, collionrow); assert_always(xsstartindex >= 0); // Luke Shingles: the use of min and max on the epsilon limits keeps energies @@ -2012,7 +2005,6 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array sfmatrix_LU{}; // auto gsl_sfmatrix_LU = gsl_matrix_view_array(sfmatrix_LU.data(), SFPTS, SFPTS).matrix; @@ -2020,8 +2012,6 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array yvec_arr{}; auto gsl_yvec = gsl_vector_view_array(yvec_arr.data(), SFPTS).vector; @@ -2029,7 +2019,8 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array yvec_best{}; @@ -2057,7 +2048,7 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array= 0.) { if (error_best > 1e-10) { @@ -2370,9 +2361,6 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const // probably because eff_ionpot = 0 because the solver hasn't been run yet, or no impact ionization cross sections // exist const double Y_nt_wfapprox = nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion); - // printout("Warning: Spencer-Fano solver gives non-finite ionization rate (%g) for element %d ionstage %d for - // cell %d. Using WF approx instead = %g\n", - // Y_nt, get_atomicnumber(element), get_ionstage(element, ion), modelgridindex, Y_nt_wfapprox); return Y_nt_wfapprox; } if (Y_nt <= 0) { @@ -2474,9 +2462,6 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { pkt.e_cmf); } - // printout("NTLEPTON packet in cell %d selected ionization of Z=%d ionstage %d to %d\n", - // modelgridindex, get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, - // upperion)); do_macroatom(pkt, {.element = element, .ion = upperion, .level = 0, .activatingline = -99}); return; } @@ -2506,9 +2491,6 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { stats::increment(stats::COUNTER_NT_STAT_TO_EXCITATION); - // printout("NTLEPTON packet selected in cell %d excitation of Z=%d ionstage %d level %d upperlevel %d\n", - // modelgridindex, get_atomicnumber(element), get_ionstage(element, ion), lower, upper); - do_macroatom(pkt, {.element = element, .ion = ion, .level = upper, .activatingline = -99}); return; } @@ -2664,10 +2646,8 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i } // printout("SF matrix | RHS vector:\n"); - // for (int row = 0; row < 10; row++) - // { - // for (int column = 0; column < 10; column++) - // { + // for (int row = 0; row < 10; row++) { + // for (int column = 0; column < 10; column++) { // char str[15]; // snprintf(str, 15, "%+.1e ", gsl_matrix_get(sfmatrix, row, column)); // printout(str); @@ -2803,11 +2783,6 @@ void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ return; } - // printout("nonthermal_MPI_Bcast cell %d before: ratecoeff(Z=%d ionstage %d): %g, eff_ionpot %g eV\n", - // modelgridindex, logged_element_z, logged_ionstage, - // nt_ionization_ratecoeff_sf(modelgridindex, logged_element_index, logged_ion_index), - // get_eff_ionpot(modelgridindex, logged_element_index, logged_ion_index) / EV); - MPI_Bcast(&deposition_rate_density_all_cells[modelgridindex], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); if (NT_ON && NT_SOLVE_SPENCERFANO) { diff --git a/radfield.cc b/radfield.cc index 08b62977b..69092f99f 100644 --- a/radfield.cc +++ b/radfield.cc @@ -187,7 +187,6 @@ void add_detailed_line(const int lineindex) { } detailed_lineindicies[detailed_linecount] = lineindex; detailed_linecount++; - // printout("Added Jblue estimator for lineindex %d count %d\n", lineindex, detailed_linecount); } // get the normalised J_nu @@ -688,13 +687,6 @@ auto get_Jblueindex(const int lineindex) -> int { } } - // const int element = linelist[lineindex].elementindex; - // const int ion = linelist[lineindex].ionindex; - // const int lower = linelist[lineindex].lowerlevelindex; - // const int upper = linelist[lineindex].upperlevelindex; - // printout("Could not find lineindex %d among %d items (Z=%02d ionstage %d lower %d upper %d)\n", - // lineindex, detailed_linecount, get_atomicnumber(element), get_ionstage(element, ion), lower, upper); - return -1; } diff --git a/ratecoeff.cc b/ratecoeff.cc index f6715a1cd..efd51c8c6 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -536,8 +536,6 @@ void read_recombrate_file() { int tablerows = 0; while (fscanf(recombrate_file, "%d %d %d\n", &atomicnumber, &upperionstage, &tablerows) > 0) { - // printout("%d %d %d\n", atomicnumber, upperionstage, tablerows); - RRCRow T_highestbelow = {.log_Te = 0, .rrc_low_n = 0, .rrc_total = 0}; RRCRow T_lowestabove = {.log_Te = 0, .rrc_low_n = 0, .rrc_total = 0}; T_highestbelow.log_Te = -1; @@ -984,8 +982,6 @@ __host__ __device__ auto get_spontrecombcoeff(int element, const int ion, const const double f_upper = spontrecombcoeffs[get_bflutindex(upperindex, element, ion, level, phixstargetindex)]; const double f_lower = spontrecombcoeffs[get_bflutindex(lowerindex, element, ion, level, phixstargetindex)]; - // printout("interpolate_spontrecombcoeff element %d, ion %d, level %d, upper %g, lower %g\n", - // element,ion,level,f_upper,f_lower); Alpha_sp = (f_lower + (f_upper - f_lower) / (T_upper - T_lower) * (T_e - T_lower)); } else { Alpha_sp = spontrecombcoeffs[get_bflutindex(TABLESIZE - 1, element, ion, level, phixstargetindex)]; @@ -1310,7 +1306,6 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - } const double epsilon_trans = epsilon(element, ion + 1, upperlevel) - epsilon(element, ion, level); - // printout("%g %g %g\n", get_levelpop(n,element,ion,level),col_ionization(n,0,epsilon_trans),epsilon_trans); if (nnlevel * col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans) > 0) { return false; @@ -1348,8 +1343,6 @@ auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, c Col_ion += nnlevel * col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); } } - // printout("element %d ion %d: col/gamma %g Te %g ne %g\n", element, ion, Col_ion/Gamma, grid::get_Te(n), - // grid::get_nne(n)); Gamma += Col_ion; Gamma /= get_groundlevelpop(modelgridindex, element, ion); return Gamma; diff --git a/sn3d.cc b/sn3d.cc index ea0945cfe..ae4364298 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -965,7 +965,7 @@ auto main(int argc, char *argv[]) -> int { printout("Simulation propagates %g packets per process (total %g with nprocs %d)\n", 1. * globals::npkts, 1. * globals::npkts * globals::nprocs, globals::nprocs); - printout("[info] mem_usage: packets occupy %.3f MB\n", globals::npkts * sizeof(Packet) / 1024. / 1024.); + printout("[info] mem_usage: packets occupy %.3f MB\n", MPKTS * sizeof(Packet) / 1024. / 1024.); if (!globals::simulation_continued_from_saved) { std::remove("deposition.out"); diff --git a/sn3d.h b/sn3d.h index 3fbe4a42a..701803ad5 100644 --- a/sn3d.h +++ b/sn3d.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -112,14 +113,17 @@ inline void print_line_start() { } } -#define printout(...) \ - { \ - print_line_start(); \ - snprintf(outputlinebuf, sizeof(outputlinebuf), __VA_ARGS__); \ - outputstartofline = (outputlinebuf[strlen(outputlinebuf) - 1] == '\n'); \ - output_file << outputlinebuf; \ - output_file.flush(); \ - } +__attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *format, ...) -> void { + print_line_start(); + va_list args{}; + va_start(args, format); + vsnprintf(outputlinebuf, sizeof(outputlinebuf), format, args); + va_end(args); + + outputstartofline = (outputlinebuf[strlen(outputlinebuf) - 1] == '\n'); + output_file << outputlinebuf; + output_file.flush(); +} #define __artis_assert(e) \ { \ diff --git a/thermalbalance.cc b/thermalbalance.cc index ce94a8e2b..caefa03d3 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -126,9 +126,6 @@ auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, con C_deexc += C; } } - // const double nnion = get_nnion(modelgridindex, element, ion); - // printout("ion_col_deexc_heating: T_e %g nne %g Z=%d ionstage %d nnion %g heating_contrib %g contrib/nnion %g\n", - // T_e, nne, get_atomicnumber(element), get_ionstage(element, ion), nnion, C_deexc, C_deexc / nnion); return C_deexc; } @@ -218,7 +215,6 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const double volumetmin = grid::get_modelcell_assocvolume_tmin(modelgridindex); const double dV = 3 * volumetmin / pow(globals::tmin, 3) * pow(t_current, 2); // really dV/dt const double V = volumetmin * pow(t_current / globals::tmin, 3); - // printout("nntot %g, p %g, dV %g, V %g\n",nntot,p,dV,V); heatingcoolingrates->cooling_adiabatic = p * dV / V; const double total_heating_rate = heatingcoolingrates->heating_ff + heatingcoolingrates->heating_bf + diff --git a/update_grid.cc b/update_grid.cc index 502eca330..5bcd685e8 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -920,7 +920,6 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in grid::modelgrid[mgi].thick = 1; if (globals::opacity_case == 3) { - // printout("update_grid: opacity_case 3 ... updating globals::cell[n].chi_grey"); //MK if (grid::get_rho(mgi) > globals::rho_crit) { grid::set_kappagrey(mgi, globals::opcase3_normal * (0.9 * grid::get_ffegrp(mgi) + 0.1) * globals::rho_crit / grid::get_rho(mgi)); @@ -1108,7 +1107,6 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const printout("timestep %d: time before update grid %ld (tstart + %ld) simtime ts_mid %g days\n", nts, sys_time_start_update_grid, sys_time_start_update_grid - real_time_start, globals::timesteps[nts].mid / DAY); - // printout("[debug] update_grid: starting update for timestep %d...\n",m); const double tratmid = globals::timesteps[nts].mid / globals::tmin; // Calculate the critical opacity at which opacity_case 3 switches from a @@ -1124,9 +1122,6 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const // nts_prev is the previous timestep, unless this is timestep zero const double deltat = globals::timesteps[nts_prev].width; - // printout("timestep %d, titer %d\n", nts, titer); - // printout("deltat %g\n", deltat); - cellcache_change_cell(-99); // Do not use values which are saved in the cellcache within update_grid diff --git a/update_packets.cc b/update_packets.cc index 543b4e135..5f893e748 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -201,7 +201,6 @@ void update_pellet(Packet &pkt, const int nts, const double t2) { pkt.absorptiontype = -7; stats::increment(stats::COUNTER_K_STAT_FROM_EARLIERDECAY); - // printout("already decayed packets and propagation by packet_prop\n"); pkt.prop_time = globals::tmin; } else if constexpr (TESTMODE) { printout("ERROR: Something wrong with decaying pellets. tdecay %g ts %g (ts + tw) %g\n", tdecay, ts, t2); @@ -373,12 +372,8 @@ void update_packets(const int my_rank, const int nts, std::span packets) while (!timestepcomplete) { const auto sys_time_start_pass = std::time(nullptr); - // printout("sorting packets..."); - std::ranges::SORT_OR_STABLE_SORT(packets, std_compare_packets_bymodelgriddensity); - // printout("took %lds\n", std::time(nullptr) - sys_time_start_pass); - printout(" update_packets timestep %d pass %3d: started at %ld\n", nts, passnumber, sys_time_start_pass); const int count_pktupdates = static_cast(std::ranges::count_if( diff --git a/vpkt.cc b/vpkt.cc index d05c418c2..3dadcea56 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -313,7 +313,6 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar // the excluded line vpkt.next_trans -= 1; - // printout("ldist > sdist : line in the next cell\n"); break; } From bdc695912e4d2575241144c05b6328b40f3db16a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 28 Oct 2024 18:32:12 +0000 Subject: [PATCH 074/117] Improve hybrid NLTE performance (#133) Total ion photoionisation rate was being recalculated at every iteration of the T_e and nne for ions of elements without NLTE levels, which caused major slowdowns (4x runtime for simple one-zone). The total ion photoionisation rate coefficient for ions of elements without NLTE levels is now calculated only once per T_e change. --- atomic.h | 4 +-- grid.cc | 3 +- input.cc | 65 +++++++++++++++++----------------- kpkt.cc | 6 ++-- ltepop.cc | 16 ++++----- macroatom.cc | 12 +++---- nltepop.cc | 2 +- ratecoeff.cc | 29 ++++++++------- rpkt.cc | 1 - thermalbalance.cc | 19 ++++++++-- update_grid.cc | 89 ++++++++++++++++++++--------------------------- 11 files changed, 119 insertions(+), 127 deletions(-) diff --git a/atomic.h b/atomic.h index dcd9e4dcd..4bc22848c 100644 --- a/atomic.h +++ b/atomic.h @@ -68,7 +68,7 @@ inline auto get_nlevels(const int element, const int ion) -> int { } // Return the number of levels associated with an ion that have energies below the ionisation threshold. -[[nodiscard]] inline auto get_ionisinglevels(const int element, const int ion) -> int { +[[nodiscard]] inline auto get_nlevels_ionising(const int element, const int ion) -> int { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); return globals::elements[element].ions[ion].ionisinglevels; @@ -81,7 +81,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) assert_testmodeonly(ion < get_nions(element)); const auto nphixstargets = globals::elements[element].ions[ion].levels[level].nphixstargets; assert_testmodeonly(nphixstargets == 0 || - ((ion < (get_nions(element) - 1)) && (level < get_ionisinglevels(element, ion)))); + ((ion < (get_nions(element) - 1)) && (level < get_nlevels_ionising(element, ion)))); return nphixstargets; } diff --git a/grid.cc b/grid.cc index 69c7ccf7a..b4265a75c 100644 --- a/grid.cc +++ b/grid.cc @@ -451,7 +451,7 @@ void allocate_nonemptymodelcells() { const auto ionestimcount = nonempty_npts_model * globals::nbfcontinua_ground; const auto ionestimsize = ionestimcount * sizeof(double); - if (USE_LUT_PHOTOION && ionestimsize > 0) { + if (ionestimsize > 0) { #ifdef MPI_ON const auto [_, noderank_nonemptycellcount] = get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); @@ -1385,7 +1385,6 @@ void setup_grid_cartesian_3d() { for (int axis = 0; axis < 3; axis++) { assert_always(nxyz[axis] == get_cellcoordpointnum(n, axis)); cell[n].pos_min[axis] = -globals::rmax + (2 * nxyz[axis] * globals::rmax / ncoordgrid[axis]); - // cell[n].xyz[axis] = nxyz[axis]; } assert_always(n == nxyz[2] * ncoordgrid[1] * ncoordgrid[2] + nxyz[1] * ncoordgrid[0] + nxyz[0]); diff --git a/input.cc b/input.cc index 9dfcda442..f3d0a1d6a 100644 --- a/input.cc +++ b/input.cc @@ -294,7 +294,7 @@ void read_phixs_file(const int phixs_file_version, std::vector &tmpallphi assert_always(lowerlevel >= 0); // store only photoionization crosssections for ions that are part of the current model atom - if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_ionisinglevels(element, lowerion)) { + if (lowerion >= 0 && upperion < get_nions(element) && lowerlevel < get_nlevels_ionising(element, lowerion)) { read_phixs_data_table(phixsfile, nphixspoints_inputtable, element, lowerion, lowerlevel, upperion, upperlevel_in, tmpallphixs, &mem_usage_phixs, phixs_file_version); @@ -710,30 +710,28 @@ void setup_phixs_list() { printout("[info] read_atomicdata: number of bfcontinua %d\n", globals::nbfcontinua); printout("[info] read_atomicdata: number of ground-level bfcontinua %d\n", globals::nbfcontinua_ground); - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::groundcont.resize(globals::nbfcontinua_ground); + globals::groundcont.resize(globals::nbfcontinua_ground); - int groundcontindex = 0; - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - const int level = 0; - const int nphixstargets = get_nphixstargets(element, ion, level); - if (nphixstargets == 0) { - continue; - } - const double E_threshold = get_phixs_threshold(element, ion, level, 0); - const double nu_edge = E_threshold / H; - assert_always(groundcontindex < globals::nbfcontinua_ground); + int nextgroundcontindex = 0; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + const int level = 0; + const int nphixstargets = get_nphixstargets(element, ion, level); + if (nphixstargets == 0) { + continue; + } + const double E_threshold = get_phixs_threshold(element, ion, level, 0); + const double nu_edge = E_threshold / H; + assert_always(nextgroundcontindex < globals::nbfcontinua_ground); - globals::groundcont[groundcontindex] = {.nu_edge = nu_edge, .element = element, .ion = ion}; + globals::groundcont[nextgroundcontindex] = {.nu_edge = nu_edge, .element = element, .ion = ion}; - groundcontindex++; - } + nextgroundcontindex++; } - assert_always(groundcontindex == globals::nbfcontinua_ground); - std::ranges::SORT_OR_STABLE_SORT(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); } + assert_always(nextgroundcontindex == globals::nbfcontinua_ground); + std::ranges::SORT_OR_STABLE_SORT(globals::groundcont, std::ranges::less{}, &GroundPhotoion::nu_edge); auto *nonconstallcont = static_cast(malloc(globals::nbfcontinua * sizeof(FullPhotoionTransition))); @@ -743,18 +741,16 @@ void setup_phixs_list() { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions - 1; ion++) { - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - globals::elements[element].ions[ion].groundcontindex = - static_cast(std::ranges::find_if(globals::groundcont, - [=](const auto &groundcont) { - return (groundcont.element == element) && (groundcont.ion == ion); - }) - - globals::groundcont.begin()); - if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { - globals::elements[element].ions[ion].groundcontindex = -1; - } + globals::elements[element].ions[ion].groundcontindex = + static_cast(std::ranges::find_if(globals::groundcont, + [=](const auto &groundcont) { + return (groundcont.element == element) && (groundcont.ion == ion); + }) - + globals::groundcont.begin()); + if (globals::elements[element].ions[ion].groundcontindex >= globals::nbfcontinua_ground) { + globals::elements[element].ions[ion].groundcontindex = -1; } - const int nlevels = get_ionisinglevels(element, ion); + const int nlevels = get_nlevels_ionising(element, ion); for (int level = 0; level < nlevels; level++) { const int nphixstargets = get_nphixstargets(element, ion, level); @@ -1455,7 +1451,7 @@ void write_bflist_file() { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - const int nlevels = get_ionisinglevels(element, ion); + const int nlevels = get_nlevels_ionising(element, ion); for (int level = 0; level < nlevels; level++) { const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { @@ -1572,9 +1568,10 @@ void read_atomicdata() { "[input] ionstage %d: %4d levels (%d in groundterm, %4d ionising) %7d lines %6d bf transitions " "(epsilon_ground: %7.2f eV)\n", get_ionstage(element, ion), get_nlevels(element, ion), get_nlevels_groundterm(element, ion), - get_ionisinglevels(element, ion), ion_bbtransitions, ion_photoiontransitions, epsilon(element, ion, 0) / EV); + get_nlevels_ionising(element, ion), ion_bbtransitions, ion_photoiontransitions, + epsilon(element, ion, 0) / EV); - includedionisinglevels += get_ionisinglevels(element, ion); + includedionisinglevels += get_nlevels_ionising(element, ion); includedphotoiontransitions += ion_photoiontransitions; includedboundboundtransitions += ion_bbtransitions; } diff --git a/kpkt.cc b/kpkt.cc index 2b84e9b66..1f8b8a99e 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -57,7 +57,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co double C_ion = 0.; int i = indexionstart; // NOLINT(misc-const-correctness) - const int nionisinglevels = get_ionisinglevels(element, ion); + const int nionisinglevels = get_nlevels_ionising(element, ion); const double nncurrention = get_nnion(modelgridindex, element, ion); // ff creation of rpkt @@ -192,7 +192,7 @@ void set_ncoolingterms() { // All the levels add number of col excitations const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { - // if (ion < nions - 1) and (level < get_ionisinglevels(element,ion)) + // if (ion < nions - 1) and (level < get_nlevels_ionising(element,ion)) if (ion < nions - 1) { ionterms += 2 * get_nphixstargets(element, ion, level); } @@ -309,7 +309,7 @@ void setup_coolinglist() { for (int ion = 0; ion < nions; ion++) { const int nlevels_currention = get_nlevels(element, ion); - const int nionisinglevels = get_ionisinglevels(element, ion); + const int nionisinglevels = get_nlevels_ionising(element, ion); // ff creation of rpkt // ------------------- diff --git a/ltepop.cc b/ltepop.cc index 06b2178b6..ae7b414dc 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -73,19 +73,12 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const auto T_e = grid::get_Te(modelgridindex); - double Gamma = 0.; - Gamma = globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]; + // photoionisation plus collisional ionisation rate coefficient per ground level pop + const double Gamma = globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]; // Gamma is the photoionization rate per ground level pop const double Gamma_ion = Gamma * stat_weight(element, ion, 0) / partfunc_ion; - if (Gamma == 0. && (!NT_ON || (globals::dep_estimator_gamma[nonemptymgi] == 0. && - grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(24, 48)) == 0. && - grid::get_modelinitnucmassfrac(modelgridindex, decay::get_nucindex(28, 56)) == 0.))) { - printout("Fatal: Gamma = 0 for element %d, ion %d in phi ... abort\n", element, ion); - std::abort(); - } - const double Alpha_sp = interpolate_ions_spontrecombcoeff(uniqueionindex, T_e); // const double Col_rec = calculate_ionrecombcoeff(modelgridindex, T_e, element, ion + 1, false, true, false, false, @@ -94,6 +87,11 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const double gamma_nt = NT_ON ? nonthermal::nt_ionization_ratecoeff(modelgridindex, element, ion) : 0.; + if ((Gamma + gamma_nt) == 0) { + printout("Fatal: Gamma = 0 for element %d, ion %d in phi ... abort\n", element, ion); + std::abort(); + } + const double phi = (Alpha_sp + Col_rec) / (Gamma_ion + gamma_nt); // Y_nt should generally be higher than the Gamma term for nebular epoch diff --git a/macroatom.cc b/macroatom.cc index e1642e998..5528ed0b1 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -106,9 +106,7 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele double sum_radrecomb = 0.; double sum_colrecomb = 0.; if (ion > 0 && level <= get_maxrecombininglevel(element, ion)) { - // nlevels = get_nlevels(element,ion-1); - const int nlevels = get_ionisinglevels(element, ion - 1); - // nlevels = get_ionisinglevels(element,ion-1); + const int nlevels = get_nlevels_ionising(element, ion - 1); for (int lower = 0; lower < nlevels; lower++) { const double epsilon_target = epsilon(element, ion - 1, lower); const double epsilon_trans = epsilon_current - epsilon_target; @@ -129,7 +127,7 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele // Transitions to higher ionisation stages double sum_up_highernt = 0.; double sum_up_higher = 0.; - const int ionisinglevels = get_ionisinglevels(element, ion); + const int ionisinglevels = get_nlevels_ionising(element, ion); if (ion < get_nions(element) - 1 && level < ionisinglevels) { if (NT_ON) { sum_up_highernt = nonthermal::nt_ionization_ratecoeff(modelgridindex, element, ion) * epsilon_current; @@ -231,7 +229,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, // Randomly select a continuum const double targetval = rng_uniform() * rad_recomb; double rate = 0; - const int nlevels = get_ionisinglevels(element, upperion - 1); + const int nlevels = get_nlevels_ionising(element, upperion - 1); int lowerionlevel = 0; for (lowerionlevel = 0; lowerionlevel < nlevels; lowerionlevel++) { const double epsilon_trans = epsilon_current - epsilon(element, upperion - 1, lowerionlevel); @@ -496,8 +494,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast double rate = 0.; // nlevels = get_nlevels(element,ion-1); - const int nlevels = get_ionisinglevels(element, ion - 1); - // nlevels = get_ionisinglevels(element,ion-1); + const int nlevels = get_nlevels_ionising(element, ion - 1); + // nlevels = get_nlevels_ionising(element,ion-1); int lower = 0; for (lower = 0; lower < nlevels; lower++) { const double epsilon_target = epsilon(element, ion - 1, lower); diff --git a/nltepop.cc b/nltepop.cc index 208081672..e330c28df 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -519,7 +519,7 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, assert_always(ion + 1 < get_nions(element)); // can't ionise the top ion const auto T_e = grid::get_Te(modelgridindex); const float nne = grid::get_nne(modelgridindex); - const int nionisinglevels = get_ionisinglevels(element, ion); + const int nionisinglevels = get_nlevels_ionising(element, ion); const int maxrecombininglevel = get_maxrecombininglevel(element, ion + 1); for (int level = 0; level < nionisinglevels; level++) { diff --git a/ratecoeff.cc b/ratecoeff.cc index efd51c8c6..d1605cf48 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -151,7 +151,7 @@ auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool assert_always( fscanf(ratecoeff_file, "%d %d %d %d\n", &in_element, &in_ionstage, &in_levels, &in_ionisinglevels) == 4); const int nlevels = get_nlevels(element, ion); - const int ionisinglevels = get_ionisinglevels(element, ion); + const int ionisinglevels = get_nlevels_ionising(element, ion); if (get_atomicnumber(element) != in_element || get_ionstage(element, ion) != in_ionstage || nlevels != in_levels || ionisinglevels != in_ionisinglevels) { printout( @@ -169,9 +169,7 @@ auto read_ratecoeff_dat(FILE *ratecoeff_file) -> bool const int nions = get_nions(element) - 1; for (int ion = 0; ion < nions; ion++) { // nlevels = get_nlevels(element,ion); - const int nlevels = get_ionisinglevels(element, ion); // number of ionising levels associated with current ion - // int nbfcont = get_ionisinglevels(element,ion); // number of ionising levels of the current ion which - // are used in the simulation + const int nlevels = get_nlevels_ionising(element, ion); // number of ionising levels associated with current ion for (int level = 0; level < nlevels; level++) { // Loop over the phixs target states const int nphixstargets = get_nphixstargets(element, ion, level); @@ -234,7 +232,7 @@ void write_ratecoeff_dat() { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { fprintf(ratecoeff_file, "%d %d %d %d\n", get_atomicnumber(element), get_ionstage(element, ion), - get_nlevels(element, ion), get_ionisinglevels(element, ion)); + get_nlevels(element, ion), get_nlevels_ionising(element, ion)); } } @@ -242,7 +240,7 @@ void write_ratecoeff_dat() { const int nions = get_nions(element) - 1; for (int ion = 0; ion < nions; ion++) { // nlevels = get_nlevels(element,ion); - const int nlevels = get_ionisinglevels(element, ion); + const int nlevels = get_nlevels_ionising(element, ion); for (int level = 0; level < nlevels; level++) { // Loop over the phixs targets const auto nphixstargets = get_nphixstargets(element, ion, level); @@ -353,7 +351,7 @@ void precalculate_rate_coefficient_integrals() { for (int ion = 0; ion < nions; ion++) { const int atomic_number = get_atomicnumber(element); const int ionstage = get_ionstage(element, ion); - const int nlevels = get_ionisinglevels(element, ion); + const int nlevels = get_nlevels_ionising(element, ion); printout("Performing rate integrals for Z = %d, ionstage %d...\n", atomic_number, ionstage); gsl_error_handler_t *previous_handler = gsl_set_error_handler(gsl_error_handler_printout); @@ -563,7 +561,7 @@ void read_recombrate_file() { assert_always(T_highestbelow.log_Te > 0); assert_always(T_lowestabove.log_Te > 0); - const int nlevels = get_ionisinglevels(element, ion - 1); + const int nlevels = get_nlevels_ionising(element, ion - 1); const double x = (log_Te_estimate - T_highestbelow.log_Te) / (T_lowestabove.log_Te - T_highestbelow.log_Te); const double input_rrc_low_n = (x * T_highestbelow.rrc_low_n) + ((1 - x) * T_lowestabove.rrc_low_n); @@ -654,7 +652,7 @@ void precalculate_ion_alpha_sp() { const int nions = get_nions(element) - 1; for (int ion = 0; ion < nions; ion++) { const auto uniqueionindex = get_uniqueionindex(element, ion); - const int nionisinglevels = get_ionisinglevels(element, ion); + const int nionisinglevels = get_nlevels_ionising(element, ion); double zeta = 0.; for (int level = 0; level < nionisinglevels; level++) { const auto nphixstargets = get_nphixstargets(element, ion, level); @@ -824,15 +822,13 @@ auto get_nlevels_important(const int modelgridindex, const int element, const in } double nnlevelsum = 0.; - int nlevels_important = get_ionisinglevels(element, ion); // levels needed to get majority of ion pop + int nlevels_important = get_nlevels_ionising(element, ion); // levels needed to get majority of ion pop // debug: treat all ionising levels as important // *nnlevelsum_out = nnion_real; // return nlevels_important; - for (int lower = 0; - (nnlevelsum / nnion_real < IONGAMMA_POPFRAC_LEVELS_INCLUDED) && (lower < get_ionisinglevels(element, ion)); - lower++) { + for (int lower = 0; lower < get_nlevels_ionising(element, ion); lower++) { double nnlowerlevel{NAN}; if (assume_lte) { const double T_exc = T_e; // remember, other parts of the code in LTE mode use TJ, not T_e @@ -847,6 +843,9 @@ auto get_nlevels_important(const int modelgridindex, const int element, const in } nnlevelsum += nnlowerlevel; nlevels_important = lower + 1; + if ((nnlevelsum / nnion_real) >= IONGAMMA_POPFRAC_LEVELS_INCLUDED) { + break; + } } assert_always(nlevels_important <= get_nlevels(element, ion)); return {nlevels_important, nnlevelsum}; @@ -1285,7 +1284,7 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - } const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - if constexpr (USE_LUT_PHOTOION) { + if (USE_LUT_PHOTOION || !elem_has_nlte_levels(element)) { return (globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] == 0); } @@ -1331,7 +1330,7 @@ auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, c double Col_ion = 0.; for (int level = 0; level < nlevels_important; level++) { - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = calculate_levelpop(modelgridindex, element, ion, level); const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upperlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); diff --git a/rpkt.cc b/rpkt.cc index 584a34b14..33a6f258a 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -1116,7 +1116,6 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff } else { // in the other cases chi_grey is an mass absorption coefficient // therefore use the mass density - // sigma = globals::cell[pkt.where].chi_grey * globals::cell[pkt.where].rho; // sigma = SIGMA_T * nne; chi_escat = 0.; diff --git a/thermalbalance.cc b/thermalbalance.cc index caefa03d3..ca5b907bb 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -20,6 +20,7 @@ #include "nonthermal.h" #include "radfield.h" #include "ratecoeff.h" +#include "rpkt.h" #include "sn3d.h" namespace { @@ -159,7 +160,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d // are not included in the model atom. for (int ion = 0; ion < nions - 1; ion++) { - const int nbflevels = get_ionisinglevels(element, ion); + const int nbflevels = get_nlevels_ionising(element, ion); for (int level = 0; level < nbflevels; level++) { const double nnlevel = get_levelpop(modelgridindex, element, ion, level); bfheating += nnlevel * bfheatingcoeffs[get_uniquelevelindex(element, ion, level)]; @@ -192,8 +193,22 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { auto *const heatingcoolingrates = params->heatingcoolingrates; // Set new T_e guess for the current cell and update populations - // globals::cell[cellnumber].T_e = T_e; grid::set_Te(modelgridindex, T_e); + + if constexpr (!USE_LUT_PHOTOION && !LTEPOP_EXCITATION_USE_TJ) { + const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + for (int element = 0; element < get_nelements(); element++) { + if (!elem_has_nlte_levels(element)) { + // recalculate the Gammas using the current population estimates + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] = + calculate_iongamma_per_gspop(modelgridindex, element, ion); + } + } + } + } + calculate_ion_balance_nne(modelgridindex); const auto nne = grid::get_nne(modelgridindex); diff --git a/update_grid.cc b/update_grid.cc index 5bcd685e8..dea7db065 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -675,8 +675,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } } -void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, const int titer, - HeatingCoolingRates *heatingcoolingrates) +void solve_Te_nltepops(const int mgi, const int nts, const int titer, HeatingCoolingRates *heatingcoolingrates) // nts is the timestep number { // bfheating coefficients are needed for the T_e solver, but @@ -701,13 +700,6 @@ void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, cons for (int element = 0; element < get_nelements(); element++) { if (!elem_has_nlte_levels(element)) { calculate_cellpartfuncts(mgi, element); - } else if (USE_LUT_PHOTOION && (nlte_iter != 0)) { - // recalculate the Gammas using the current population estimates - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] = - calculate_iongamma_per_gspop(mgi, element, ion); - } } } const int duration_solve_partfuncs_or_gamma = std::time(nullptr) - sys_time_start_partfuncs_or_gamma; @@ -777,7 +769,6 @@ void solve_Te_nltepops(const int mgi, const int nonemptymgi, const int nts, cons } void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const double estimator_normfactor) { - assert_always(USE_LUT_PHOTOION || USE_LUT_BFHEATING); const int nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); if constexpr (USE_LUT_PHOTOION) { for (int element = 0; element < get_nelements(); element++) { @@ -818,47 +809,45 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d // photoionsation rate! } } - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - for (int element = 0; element < get_nelements(); element++) { - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - // Reuse the gammaestimator array as temporary storage of the Gamma values during - // the remaining part of the update_grid phase. Afterwards it is reset to record - // the next timesteps gamma estimators. - const int groundcontindex = globals::elements[element].ions[ion].groundcontindex; - if (groundcontindex < 0) { - continue; - } - const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; + for (int element = 0; element < get_nelements(); element++) { + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + // Reuse the gammaestimator array as temporary storage of the Gamma values during + // the remaining part of the update_grid phase. Afterwards it is reset to record + // the next timesteps gamma estimators. + const int groundcontindex = globals::elements[element].ions[ion].groundcontindex; + if (groundcontindex < 0) { + continue; + } + const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; - if constexpr (USE_LUT_PHOTOION) { - globals::gammaestimator[ionestimindex] = calculate_iongamma_per_gspop(mgi, element, ion); - } + if (!elem_has_nlte_levels(element)) { + globals::gammaestimator[ionestimindex] = calculate_iongamma_per_gspop(mgi, element, ion); + } - if constexpr (USE_LUT_BFHEATING) { - globals::bfheatingestimator[ionestimindex] *= estimator_normfactor; + if constexpr (USE_LUT_BFHEATING) { + globals::bfheatingestimator[ionestimindex] *= estimator_normfactor; #ifdef DO_TITER - if (bfheatingestimator_save[ionestimindex] >= 0) { - globals::bfheatingestimator[ionestimindex] = - (globals::bfheatingestimator[ionestimindex] + bfheatingestimator_save[ionestimindex]) / 2; - } - bfheatingestimator_save[ionestimindex] = globals::bfheatingestimator[ionestimindex]; + if (bfheatingestimator_save[ionestimindex] >= 0) { + globals::bfheatingestimator[ionestimindex] = + (globals::bfheatingestimator[ionestimindex] + bfheatingestimator_save[ionestimindex]) / 2; + } + bfheatingestimator_save[ionestimindex] = globals::bfheatingestimator[ionestimindex]; #endif - // Now convert bfheatingestimator into the bfheating renormalisation coefficient used in - // get_bfheating in the remaining part of update_grid. Later on it's reset and new - // contributions are added up. - - const double bfheatingcoeff_ana = - get_bfheatingcoeff_ana(element, ion, 0, 0, grid::get_TR(mgi), grid::get_W(mgi)); - globals::bfheatingestimator[ionestimindex] = globals::bfheatingestimator[ionestimindex] / bfheatingcoeff_ana; - - if (!std::isfinite(globals::bfheatingestimator[ionestimindex])) { - printout( - "[fatal] about to set bfheatingestimator = NaN = bfheatingestimator / " - "get_bfheatingcoeff_ana(%d,%d,%d,%d,%d)=%g/%g", - element, ion, 0, 0, mgi, globals::bfheatingestimator[ionestimindex], bfheatingcoeff_ana); - std::abort(); - } + // Now convert bfheatingestimator into the bfheating renormalisation coefficient used in + // get_bfheating in the remaining part of update_grid. Later on it's reset and new + // contributions are added up. + + const double bfheatingcoeff_ana = + get_bfheatingcoeff_ana(element, ion, 0, 0, grid::get_TR(mgi), grid::get_W(mgi)); + globals::bfheatingestimator[ionestimindex] = globals::bfheatingestimator[ionestimindex] / bfheatingcoeff_ana; + + if (!std::isfinite(globals::bfheatingestimator[ionestimindex])) { + printout( + "[fatal] about to set bfheatingestimator = NaN = bfheatingestimator / " + "get_bfheatingcoeff_ana(%d,%d,%d,%d,%d)=%g/%g", + element, ion, 0, 0, mgi, globals::bfheatingestimator[ionestimindex], bfheatingcoeff_ana); + std::abort(); } } } @@ -1015,15 +1004,13 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in titer_average_estimators(mgi); #endif - if constexpr (USE_LUT_PHOTOION || USE_LUT_BFHEATING) { - update_gamma_corrphotoionrenorm_bfheating_estimators(mgi, estimator_normfactor); - } + update_gamma_corrphotoionrenorm_bfheating_estimators(mgi, estimator_normfactor); // Get radiation field parameters (T_J, T_R, W, and bins if enabled) out of the // full-spectrum and binned J and nuJ estimators radfield::fit_parameters(mgi, nts); - solve_Te_nltepops(mgi, nonemptymgi, nts, titer, heatingcoolingrates); + solve_Te_nltepops(mgi, nts, titer, heatingcoolingrates); } printout("Temperature/NLTE solution for cell %d timestep %d took %ld seconds\n", mgi, nts, std::time(nullptr) - sys_time_start_temperature_corrections); From cb565d54892a4a581fe382e0829fe2841ebf13fc Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 30 Oct 2024 12:36:16 +0000 Subject: [PATCH 075/117] Use more nonemptymgi indicies and remove more pointers from ModelGridCell (#140) --- .github/workflows/ci-checks.yml | 2 +- .github/workflows/ci.yml | 21 +- decay.cc | 61 +++--- decay.h | 16 +- exspec.cc | 10 +- gammapkt.cc | 11 +- globals.h | 13 +- grid.cc | 190 ++++++++++-------- grid.h | 44 ++--- input.cc | 8 +- kpkt.cc | 2 +- ltepop.cc | 15 +- macroatom.cc | 2 +- nltepop.cc | 58 ++++-- nltepop.h | 4 + nonthermal.cc | 23 +-- nonthermal.h | 4 +- packet.cc | 6 +- radfield.cc | 48 +++-- radfield.h | 2 +- ratecoeff.cc | 4 +- rpkt.cc | 7 +- rpkt.h | 3 +- sn3d.cc | 332 +++++++++++++++----------------- sn3d.h | 8 +- thermalbalance.cc | 13 +- thermalbalance.h | 2 +- update_grid.cc | 27 +-- update_grid.h | 3 +- update_packets.cc | 6 +- update_packets.h | 2 +- 31 files changed, 491 insertions(+), 456 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index beb2b1237..1a3058714 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -26,7 +26,7 @@ jobs: - name: run cppcheck run: | cppcheck --version - cppcheck --force --error-exitcode=1 --output-format=sarif --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . + cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: runs-on: macos-14 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfbc5a1b7..bb24e52de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -171,21 +171,10 @@ jobs: working-directory: tests/${{ matrix.testname }}_testrun/ run: cat job1/output_0-0.txt - - name: Set up Python - if: always() && matrix.testmode == 'OFF' - uses: actions/setup-python@v5 - - - name: Install artistools - if: always() && matrix.testmode == 'OFF' - run: | - python3 -m pip install --upgrade pip uv - uv pip install --system -U artistools - - name: show deposition.out if: always() && matrix.testmode == 'OFF' working-directory: tests/${{ matrix.testname }}_testrun/ run: | - echo -e "import artistools as at; import polars as pl;\nwith pl.Config(tbl_rows=-1,tbl_cols=-1,tbl_width_chars=300,tbl_formatting='NOTHING'):\n df = at.get_deposition('.')\n print(df.select(['timestep', 'tmid_days'] + [c for c in sorted(df.columns, key=lambda x: x.lower().lstrip('eps_')) if c not in ['timestep', 'tmid_days', 'tmid_s']]))" | python3 - cat deposition.out - name: Run exspec @@ -232,6 +221,16 @@ jobs: name: ${{ matrix.testname }}_inputfiles path: tests/${{ matrix.testname }}_inputfiles/results_md5* + - name: Set up Python + if: always() && matrix.testmode == 'OFF' + uses: actions/setup-python@v5 + + - name: Install artistools + if: always() && matrix.testmode == 'OFF' + run: | + python3 -m pip install --upgrade pip uv + uv pip install --system -U artistools + - name: Plot light curve if: always() && matrix.testmode == 'OFF' working-directory: tests/ diff --git a/decay.cc b/decay.cc index 909a44831..c3f7a0d89 100644 --- a/decay.cc +++ b/decay.cc @@ -652,12 +652,11 @@ auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const return endecay; } -auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int modelgridindex, +// Simple Euler integration as a check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() +auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int nonemptymgi, const int decaypathindex, const double tstart) - -> double -// just here as as check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() -// this version does an Euler integration -{ + -> double { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double min_meanlife = -1; for (int i = 0; i < get_decaypathlength(decaypathindex); i++) { const double meanlife = get_meanlife(decaypaths[decaypathindex].nucindex[i]); @@ -665,9 +664,9 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const i min_meanlife = meanlife; } } + // min steps across the meanlifetime + const int nsteps = static_cast(ceil((tstart - grid::get_t_model()) / min_meanlife) * 100000); - const int nsteps = static_cast(ceil((tstart - grid::get_t_model()) / min_meanlife) * - 100000); // min steps across the meanlifetime double chain_endecay = 0.; double last_chain_endecay = -1.; double last_t = -1.; @@ -722,10 +721,9 @@ auto calculate_simtime_endecay_per_ejectamass(const int mgi, const int decaypath } } -auto get_simtime_endecay_per_ejectamass(const int mgi, const int decaypathindex) -> double +auto get_simtime_endecay_per_ejectamass(const int nonemptymgi, const int decaypathindex) -> double // get the decay energy released during the simulation time per unit mass [erg/g] { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); const double chainendecay = decaypath_energy_per_mass[(nonemptymgi * get_num_decaypaths()) + decaypathindex]; assert_testmodeonly(chainendecay >= 0.); assert_testmodeonly(std::isfinite(chainendecay)); @@ -771,7 +769,7 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode } } // anonymous namespace -[[nodiscard]] auto get_num_nuclides() -> int { return static_cast(nuclides.size()); } +[[nodiscard]] auto get_num_nuclides() -> ptrdiff_t { return std::ssize(nuclides); } [[nodiscard]] auto get_elname(const int z) -> std::string { assert_testmodeonly(z <= Z_MAX); @@ -987,11 +985,11 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector } } - printout("Number of nuclides before filtering: %d\n", get_num_nuclides()); + printout("Number of nuclides before filtering: %td\n", get_num_nuclides()); find_decaypaths(custom_zlist, custom_alist, standard_nuclides); filter_unused_nuclides(custom_zlist, custom_alist, standard_nuclides); - printout("Number of nuclides: %d\n", get_num_nuclides()); + printout("Number of nuclides: %td\n", get_num_nuclides()); const int maxdecaypathlength = std::accumulate( decaypaths.cbegin(), decaypaths.cend(), 0, @@ -1015,7 +1013,8 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector // calculate the decay energy per unit mass [erg/g] released from time t_model to tstart, accounting for // the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) -auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridindex, const double tstart) -> double { +auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int nonemptymgi, const double tstart) -> double { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double tot_endecay = 0.; for (const auto &decaypath : decaypaths) { const int decaypathlength = get_decaypathlength(decaypath); @@ -1038,10 +1037,10 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int modelgridinde } // get the density at time tmin of decay energy that will be released during the simulation time range [erg/cm3] -auto get_modelcell_simtime_endecay_per_mass(const int mgi) -> double { +auto get_modelcell_simtime_endecay_per_mass(const int nonemptymgi) -> double { double endecay_per_mass = 0.; for (int decaypathindex = 0; decaypathindex < get_num_decaypaths(); decaypathindex++) { - endecay_per_mass += get_simtime_endecay_per_ejectamass(mgi, decaypathindex); + endecay_per_mass += get_simtime_endecay_per_ejectamass(nonemptymgi, decaypathindex); } return endecay_per_mass; } @@ -1109,8 +1108,8 @@ void free_decaypath_energy_per_mass() { } // energy release rate in form of kinetic energy of positrons, electrons, and alpha particles in [erg/s/g] -[[nodiscard]] auto get_particle_injection_rate(const int modelgridindex, const double t, const int decaytype) - -> double { +[[nodiscard]] auto get_particle_injection_rate(const int nonemptymgi, const double t, const int decaytype) -> double { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double dep_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1135,7 +1134,8 @@ void free_decaypath_energy_per_mass() { } // energy release rate in form of gamma-rays in [erg/s/g] -[[nodiscard]] auto get_gamma_emission_rate(const int modelgridindex, const double t) -> double { +[[nodiscard]] auto get_gamma_emission_rate(const int nonemptymgi, const double t) -> double { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double eps_gamma_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1159,8 +1159,9 @@ void free_decaypath_energy_per_mass() { } // energy release rate [erg/s/g] including everything (even neutrinos that are ignored elsewhere) -[[nodiscard]] auto get_qdot_modelcell(const int modelgridindex, const double t, const int decaytype) -> double { +[[nodiscard]] auto get_qdot_modelcell(const int nonemptymgi, const double t, const int decaytype) -> double { double qdot = 0.; + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { const auto [z, a] = get_nuc_z_a(nucindex); @@ -1194,7 +1195,8 @@ auto get_global_etot_t0_tinf() -> double { } // Update the mass fractions of elements using the current abundances of nuclides -void update_abundances(const int modelgridindex, const int timestep, const double t_current) { +void update_abundances(const int nonemptymgi, const int timestep, const double t_current) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout("update_abundances for cell %d timestep %d\n", modelgridindex, timestep); for (int element = get_nelements() - 1; element >= 0; element--) { @@ -1243,16 +1245,16 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl isomassfrac_on_nucmass_sum += nuc_massfrac / nucmass(2, 4); } - const double stable_init_massfrac = grid::get_stable_initabund(modelgridindex, element); + const double stable_init_massfrac = grid::get_stable_initabund(nonemptymgi, element); isomassfracsum += stable_init_massfrac; isomassfrac_on_nucmass_sum += stable_init_massfrac / globals::elements[element].initstablemeannucmass; - grid::set_elem_abundance(modelgridindex, element, isomassfracsum); + grid::set_elem_abundance(nonemptymgi, element, isomassfracsum); if (isomassfrac_on_nucmass_sum > 0.) { - grid::set_element_meanweight(modelgridindex, element, isomassfracsum / isomassfrac_on_nucmass_sum); + grid::set_element_meanweight(nonemptymgi, element, isomassfracsum / isomassfrac_on_nucmass_sum); } else { // avoid a divide by zero - grid::set_element_meanweight(modelgridindex, element, globals::elements[element].initstablemeannucmass); + grid::set_element_meanweight(nonemptymgi, element, globals::elements[element].initstablemeannucmass); } } @@ -1298,7 +1300,8 @@ void update_abundances(const int modelgridindex, const int timestep, const doubl // assert_always(fabs(nucfracsum - initnucfracsum) < 0.001); // decays shouldn't change nuclear mass fraction sum } -void fprint_nuc_abundances(FILE *estimators_file, const int modelgridindex, const double t_current, const int element) { +void fprint_nuc_abundances(FILE *estimators_file, const int nonemptmgi, const double t_current, const int element) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptmgi); const double rho = grid::get_rho(modelgridindex); const int atomic_number = get_atomicnumber(element); @@ -1338,7 +1341,7 @@ void fprint_nuc_abundances(FILE *estimators_file, const int modelgridindex, cons } // factor to convert convert mass fraction to number density - const double otherstablemassfrac = grid::get_stable_initabund(modelgridindex, element); + const double otherstablemassfrac = grid::get_stable_initabund(nonemptmgi, element); if (otherstablemassfrac > 0) { const double meannucmass = globals::elements[element].initstablemeannucmass; const double otherstable_numberdens = otherstablemassfrac / meannucmass * grid::get_rho(modelgridindex); @@ -1348,6 +1351,7 @@ void fprint_nuc_abundances(FILE *estimators_file, const int modelgridindex, cons } void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const int num_decaypaths = get_num_decaypaths(); // decay channels include all radioactive decay paths, and possibly also an initial cell energy channel @@ -1358,7 +1362,7 @@ void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { // add the radioactive decay paths for (int decaypathindex = 0; decaypathindex < num_decaypaths; decaypathindex++) { - energysum += get_simtime_endecay_per_ejectamass(mgi, decaypathindex); + energysum += get_simtime_endecay_per_ejectamass(nonemptymgi, decaypathindex); cumulative_en_sum[decaypathindex] = energysum; } @@ -1414,7 +1418,8 @@ void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { // we need to scale the packet energy up or down according to decay rate at the randomly selected time. // e0 is the average energy per packet for this cell and decaypath, so we scale this up or down // according to: decay power at this time relative to the average decay power - const double avgpower = get_simtime_endecay_per_ejectamass(mgi, decaypathindex) / (globals::tmax - tdecaymin); + const double avgpower = + get_simtime_endecay_per_ejectamass(nonemptymgi, decaypathindex) / (globals::tmax - tdecaymin); assert_always(avgpower > 0.); assert_always(std::isfinite(avgpower)); pkt.e_cmf = e0 * get_decaypath_power_per_ejectamass(decaypathindex, mgi, pkt.tdecay) / avgpower; diff --git a/decay.h b/decay.h index 93e1c38ef..71ef0ee6a 100644 --- a/decay.h +++ b/decay.h @@ -26,7 +26,7 @@ constexpr std::array all_decaytypes = { void init_nuclides(const std::vector &custom_zlist, const std::vector &custom_alist); [[nodiscard]] auto get_nucstring_z(const std::string &strnuc) -> int; [[nodiscard]] auto get_nucstring_a(const std::string &strnuc) -> int; -[[nodiscard]] auto get_num_nuclides() -> int; +[[nodiscard]] auto get_num_nuclides() -> ptrdiff_t; [[nodiscard]] auto get_elname(int z) -> std::string; [[nodiscard]] auto get_nuc_z(int nucindex) -> int; [[nodiscard]] auto get_nuc_a(int nucindex) -> int; @@ -35,16 +35,16 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector [[nodiscard]] auto nucdecayenergygamma(int nucindex) -> double; [[nodiscard]] auto nucdecayenergygamma(int z, int a) -> double; void set_nucdecayenergygamma(int nucindex, double value); -void update_abundances(int modelgridindex, int timestep, double t_current); -[[nodiscard]] auto get_endecay_per_ejectamass_t0_to_time_withexpansion(int modelgridindex, double tstart) -> double; -[[nodiscard]] auto get_modelcell_simtime_endecay_per_mass(int mgi) -> double; +void update_abundances(int nonemptymgi, int timestep, double t_current); +[[nodiscard]] auto get_endecay_per_ejectamass_t0_to_time_withexpansion(int nonemptymgi, double tstart) -> double; +[[nodiscard]] auto get_modelcell_simtime_endecay_per_mass(int nonemptymgi) -> double; void setup_decaypath_energy_per_mass(); void free_decaypath_energy_per_mass(); -[[nodiscard]] auto get_qdot_modelcell(int modelgridindex, double t, int decaytype) -> double; -[[nodiscard]] auto get_particle_injection_rate(int modelgridindex, double t, int decaytype) -> double; -[[nodiscard]] auto get_gamma_emission_rate(int modelgridindex, double t) -> double; +[[nodiscard]] auto get_qdot_modelcell(int nonemptymgi, double t, int decaytype) -> double; +[[nodiscard]] auto get_particle_injection_rate(int nonemptymgi, double t, int decaytype) -> double; +[[nodiscard]] auto get_gamma_emission_rate(int nonemptymgi, double t) -> double; [[nodiscard]] auto get_global_etot_t0_tinf() -> double; -void fprint_nuc_abundances(FILE *estimators_file, int modelgridindex, double t_current, int element); +void fprint_nuc_abundances(FILE *estimators_file, int nonemptmgi, double t_current, int element); void setup_radioactive_pellet(double e0, int mgi, Packet &pkt); void cleanup(); diff --git a/exspec.cc b/exspec.cc index 3b1b44c48..21d186877 100644 --- a/exspec.cc +++ b/exspec.cc @@ -73,7 +73,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra MPI_Barrier(MPI_COMM_WORLD); #endif - if (p % globals::nprocs != globals::rank_global) { + if (p % globals::nprocs != globals::my_rank) { printout("skipping packets file %d %d\n", p + 1, globals::nprocs); continue; } @@ -173,7 +173,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) check_already_running(); char filename[MAXFILENAMELENGTH]; - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { snprintf(filename, MAXFILENAMELENGTH, "exspec.txt"); output_file = std::ofstream(filename); assert_always(output_file.is_open()); @@ -194,7 +194,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) #ifdef MPI_ON printout("process id (pid): %d\n", getpid()); printout("MPI enabled:\n"); - printout(" rank_global %d of [0..%d] in MPI_COMM_WORLD\n", globals::rank_global, globals::nprocs - 1); + printout(" rank_global %d of [0..%d] in MPI_COMM_WORLD\n", globals::my_rank, globals::nprocs - 1); printout(" rank_in_node %d of [0..%d] in node %d of [0..%d]\n", globals::rank_in_node, globals::node_nprocs - 1, globals::node_id, globals::node_count - 1); #else @@ -202,14 +202,14 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) #endif // single rank only for now - assert_always(globals::rank_global == 0); + assert_always(globals::my_rank == 0); assert_always(globals::nprocs == 1); printout("Beginning exspec.\n"); // Get input stuff printout("time before input %ld\n", std::time(nullptr)); - input(globals::rank_global); + input(globals::my_rank); printout("time after input %ld\n", std::time(nullptr)); // nprocs_exspec is the number of rank output files to process with expec diff --git a/gammapkt.cc b/gammapkt.cc index 95b5a4c40..458742b68 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -274,7 +274,8 @@ auto get_chi_compton_rf(const Packet &pkt) -> double { const double sigma_cmf = (xx < THOMSON_LIMIT) ? SIGMA_T : sigma_compton_partial(xx, 1 + (2 * xx)); // Now need to multiply by the electron number density. - const double chi_cmf = sigma_cmf * grid::get_nnetot(grid::get_cell_modelgridindex(pkt.where)); + const auto mgi = grid::get_cell_modelgridindex(pkt.where); + const double chi_cmf = sigma_cmf * grid::get_nnetot(mgi); // convert between frames const double chi_rf = chi_cmf * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -782,7 +783,7 @@ void transport_gamma(Packet &pkt, const double t2) { // Move it into the new cell. const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_modelcell_nonemptymgi(mgi) : -1; + const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; if (chi_tot > 0 && nonemptymgi >= 0) { update_gamma_dep(pkt, sdist, mgi, nonemptymgi); } @@ -796,7 +797,7 @@ void transport_gamma(Packet &pkt, const double t2) { // Doesn't reach boundary. move_pkt_withtime(pkt, tdist / 2.); const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_modelcell_nonemptymgi(mgi) : -1; + const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; if (chi_tot > 0 && nonemptymgi >= 0) { update_gamma_dep(pkt, tdist, mgi, nonemptymgi); @@ -806,7 +807,7 @@ void transport_gamma(Packet &pkt, const double t2) { } else if ((edist < sdist) && (edist < tdist)) { move_pkt_withtime(pkt, edist / 2.); const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_modelcell_nonemptymgi(mgi) : -1; + const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; if (chi_tot > 0 && nonemptymgi >= 0) { update_gamma_dep(pkt, edist, mgi, nonemptymgi); } @@ -1075,7 +1076,7 @@ __host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { // no transport, so the path-based gamma deposition estimator won't get updated unless we do it here const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); atomicadd(globals::dep_estimator_gamma[nonemptymgi], pkt.e_cmf); } } diff --git a/globals.h b/globals.h index d46106e78..b61b38159 100644 --- a/globals.h +++ b/globals.h @@ -289,7 +289,7 @@ inline MPI_Comm mpi_comm_internode{MPI_COMM_NULL}; #endif inline int nprocs{-1}; -inline int rank_global{-1}; +inline int my_rank{-1}; inline int node_nprocs{-1}; inline int rank_in_node{-1}; @@ -328,12 +328,11 @@ inline std::deque mutex_cellcachemacroatom; inline void setup_mpi_vars() { #ifdef MPI_ON - MPI_Comm_rank(MPI_COMM_WORLD, &globals::rank_global); + MPI_Comm_rank(MPI_COMM_WORLD, &globals::my_rank); MPI_Comm_size(MPI_COMM_WORLD, &globals::nprocs); // make an intra-node communicator (group ranks that can share memory) - MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, globals::rank_global, MPI_INFO_NULL, - &globals::mpi_comm_node); + MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, globals::my_rank, MPI_INFO_NULL, &globals::mpi_comm_node); // get the local rank within this node MPI_Comm_rank(globals::mpi_comm_node, &globals::rank_in_node); @@ -346,7 +345,7 @@ inline void setup_mpi_vars() { #ifdef MAX_NODE_SIZE if (MAX_NODE_SIZE > 0 && globals::node_nprocs > MAX_NODE_SIZE) { // limit the number of ranks that can share memory - MPI_Comm_split(globals::mpi_comm_node, globals::rank_in_node / MAX_NODE_SIZE, globals::rank_global, + MPI_Comm_split(globals::mpi_comm_node, globals::rank_in_node / MAX_NODE_SIZE, globals::my_rank, &globals::mpi_comm_node); MPI_Comm_rank(globals::mpi_comm_node, &globals::rank_in_node); @@ -357,7 +356,7 @@ inline void setup_mpi_vars() { #endif // make an inter-node communicator (using local rank as the key for group membership) - MPI_Comm_split(MPI_COMM_WORLD, globals::rank_in_node, globals::rank_global, &globals::mpi_comm_internode); + MPI_Comm_split(MPI_COMM_WORLD, globals::rank_in_node, globals::my_rank, &globals::mpi_comm_internode); // take the node id from the local rank 0 (node master) and broadcast it if (globals::rank_in_node == 0) { @@ -369,7 +368,7 @@ inline void setup_mpi_vars() { MPI_Bcast(&globals::node_count, 1, MPI_INT, 0, globals::mpi_comm_node); #else - globals::rank_global = 0; + globals::my_rank = 0; globals::nprocs = 1; globals::rank_in_node = 0; globals::node_nprocs = 1; diff --git a/grid.cc b/grid.cc index b4265a75c..52d80c705 100644 --- a/grid.cc +++ b/grid.cc @@ -72,8 +72,6 @@ std::vector mgi_of_nonemptymgi; std::span totmassradionuclide{}; // total mass of each radionuclide in the ejecta -double *nltepops_allcells{}; - #ifdef MPI_ON MPI_Win win_nltepops_allcells = MPI_WIN_NULL; MPI_Win win_initnucmassfrac_allcells = MPI_WIN_NULL; @@ -81,9 +79,10 @@ MPI_Win win_initnucmassfrac_allcells = MPI_WIN_NULL; float *initnucmassfrac_allcells{}; float *initmassfracuntrackedstable_allcells{}; -float *elem_meanweight_allcells{}; +int *elements_uppermost_ion_allcells{}; // Highest ion index that has a significant population std::vector ranks_nstart; +std::vector ranks_nstart_nonempty; std::vector ranks_ndo; std::vector ranks_ndo_nonempty; int maxndo = -1; @@ -156,11 +155,8 @@ void allocate_initradiobund() { assert_always(initnucmassfrac_allcells != nullptr); for (ptrdiff_t mgi = 0; mgi < (npts_model + 1); mgi++) { - modelgrid[mgi].initnucmassfrac = &initnucmassfrac_allcells[mgi * num_nuclides]; if (mgi % static_cast(globals::node_nprocs) == globals::rank_in_node) { - for (int i = 0; i < decay::get_num_nuclides(); i++) { - modelgrid[mgi].initnucmassfrac[i] = 0.; - } + std::fill_n(&initnucmassfrac_allcells[mgi * num_nuclides], num_nuclides, 0.); } } #ifdef MPI_ON @@ -221,21 +217,22 @@ void set_modelinitnucmassfrac(const int modelgridindex, const int nucindex, floa assert_always(abund >= 0.); assert_always(abund <= 1.); + const ptrdiff_t num_nuclides = decay::get_num_nuclides(); - assert_always(modelgrid[modelgridindex].initnucmassfrac != nullptr); - modelgrid[modelgridindex].initnucmassfrac[nucindex] = abund; + initnucmassfrac_allcells[(modelgridindex * num_nuclides) + nucindex] = abund; } void set_initenergyq(const int modelgridindex, const double initenergyq) { modelgrid[modelgridindex].initenergyq = initenergyq; } -void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, const float elemabundance) { +void set_elem_untrackedstable_abund_from_total(const int nonemptymgi, const int element, const float elemabundance) { // set the stable mass fraction of an element from the total element mass fraction // by subtracting the abundances of radioactive isotopes. // if the element Z=anumber has no specific stable abundance variable then the function does nothing const int atomic_number = get_atomicnumber(element); + const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); double isofracsum = 0.; // mass fraction sum of radioactive isotopes for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { @@ -255,31 +252,32 @@ void set_elem_untrackedstable_abund_from_total(const int mgi, const int element, printout(" massfrac(Z) %g massfrac_radioisotopes(Z) %g\n", elemabundance, isofracsum); printout(" increasing elemental abundance to %g and setting stable isotopic abundance to zero\n", isofracsum); } - assert_always(massfrac_untrackedstable >= - -1e-2); // result is allowed to be slightly negative due to roundoff error + // result is allowed to be slightly negative due to roundoff error + assert_always(massfrac_untrackedstable >= -1e-2); massfrac_untrackedstable = 0.; // bring up to zero if negative } // if (globals::rank_in_node == 0) { - modelgrid[mgi].initmassfracuntrackedstable[element] = massfrac_untrackedstable; + initmassfracuntrackedstable_allcells[(nonemptymgi * get_nelements()) + element] = massfrac_untrackedstable; } // (isofracsum + massfracstable) might not exactly match elemabundance if we had to boost it to reach isofracsum - set_elem_abundance(mgi, element, isofracsum + massfrac_untrackedstable); + set_elem_abundance(nonemptymgi, element, isofracsum + massfrac_untrackedstable); } void allocate_nonemptycells_composition_cooling() // Initialise composition dependent cell data for the given cell { const ptrdiff_t npts_nonempty = get_nonempty_npts_model(); + const auto nelements = get_nelements(); #ifdef MPI_ON const auto [_, noderank_nonemptycellcount] = get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); { - auto size = static_cast(noderank_nonemptycellcount * get_nelements() * sizeof(float)); + auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); int disp_unit = sizeof(float); MPI_Win mpiwin = MPI_WIN_NULL; assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, @@ -289,7 +287,7 @@ void allocate_nonemptycells_composition_cooling() } { - auto size = static_cast(noderank_nonemptycellcount * get_nelements() * sizeof(float)); + auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); int disp_unit = sizeof(float); MPI_Win mpiwin = MPI_WIN_NULL; @@ -298,9 +296,33 @@ void allocate_nonemptycells_composition_cooling() assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_meanweight_allcells) == MPI_SUCCESS); MPI_Barrier(globals::mpi_comm_node); } + + { + auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(int)); + int disp_unit = sizeof(int); + MPI_Win mpiwin = MPI_WIN_NULL; + + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &elements_uppermost_ion_allcells, &mpiwin) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elements_uppermost_ion_allcells) == MPI_SUCCESS); + MPI_Barrier(globals::mpi_comm_node); + } + + { + auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); + int disp_unit = sizeof(float); + MPI_Win mpiwin = MPI_WIN_NULL; + + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, + &elem_massfracs_allcells, &mpiwin) == MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_massfracs_allcells) == MPI_SUCCESS); + MPI_Barrier(globals::mpi_comm_node); + } #else - initmassfracuntrackedstable_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); - elem_meanweight_allcells = static_cast(malloc(npts_nonempty * get_nelements() * sizeof(float))); + initmassfracuntrackedstable_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); + elem_meanweight_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); + elements_uppermost_ion_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(int))); + elem_massfracs_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); #endif if (globals::total_nlte_levels > 0) { @@ -322,36 +344,13 @@ void allocate_nonemptycells_composition_cooling() for (ptrdiff_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - modelgrid[modelgridindex].elements_uppermost_ion = static_cast(malloc(get_nelements() * sizeof(int))); - - assert_always(modelgrid[modelgridindex].elements_uppermost_ion != nullptr); - - modelgrid[modelgridindex].elem_massfracs = static_cast(malloc(get_nelements() * sizeof(float))); - - if (modelgrid[modelgridindex].elem_massfracs == nullptr) { - printout("[fatal] input: not enough memory to initialize compositionlist for cell %d... abort\n", modelgridindex); - std::abort(); - } - - modelgrid[modelgridindex].initmassfracuntrackedstable = - &initmassfracuntrackedstable_allcells[nonemptymgi * get_nelements()]; - - assert_always(modelgrid[modelgridindex].initmassfracuntrackedstable != nullptr); - - modelgrid[modelgridindex].elem_meanweight = &elem_meanweight_allcells[nonemptymgi * get_nelements()]; - - assert_always(modelgrid[modelgridindex].elem_meanweight != nullptr); - if (globals::total_nlte_levels > 0) { - modelgrid[modelgridindex].nlte_pops = - std::span(&nltepops_allcells[nonemptymgi * globals::total_nlte_levels], globals::total_nlte_levels); - assert_always(modelgrid[modelgridindex].nlte_pops.data() != nullptr); - // -1 indicates that there is currently no information on the nlte populations - std::ranges::fill(modelgrid[modelgridindex].nlte_pops, -1.); + std::ranges::fill_n(&grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels)], + globals::total_nlte_levels, -1.); } - std::fill_n(modelgrid[modelgridindex].elem_massfracs, get_nelements(), -1.); + std::fill_n(&elem_massfracs_allcells[nonemptymgi * nelements], nelements, -1.); modelgrid[modelgridindex].ion_groundlevelpops = static_cast(calloc(get_includedions(), sizeof(float))); if (modelgrid[modelgridindex].ion_groundlevelpops == nullptr) { @@ -429,10 +428,8 @@ void allocate_nonemptymodelcells() { nonemptymgi_of_mgi[mgi] = -1; set_rho_tmin(mgi, 0.); set_rho(mgi, 0.); - if (modelgrid[mgi].initnucmassfrac != nullptr) { - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - set_modelinitnucmassfrac(mgi, nucindex, 0.); - } + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + set_modelinitnucmassfrac(mgi, nucindex, 0.); } } } @@ -625,6 +622,7 @@ void abundances_read() { if (threedimensional || normfactor <= 0.) { normfactor = 1.; } + const int nonemptymgi = get_nonemptymgi_of_mgi(mgi); for (int element = 0; element < get_nelements(); element++) { // now set the abundances (by mass) of included elements, i.e. @@ -634,7 +632,7 @@ void abundances_read() { assert_always(elemabundance >= 0.); // radioactive nuclide abundances should have already been set by read_??_model - set_elem_untrackedstable_abund_from_total(mgi, element, elemabundance); + set_elem_untrackedstable_abund_from_total(nonemptymgi, element, elemabundance); } } } @@ -1253,7 +1251,7 @@ void assign_initial_temperatures() { for (int nonempymgi = 0; nonempymgi < get_nonempty_npts_model(); nonempymgi++) { const int mgi = get_mgi_of_nonemptymgi(nonempymgi); - double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(mgi, tstart); + double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(nonempymgi, tstart); if constexpr (INITIAL_PACKETS_ON && USE_MODEL_INITIAL_ENERGY) { decayedenergy_per_mass += get_initenergyq(mgi); } @@ -1285,6 +1283,16 @@ void assign_initial_temperatures() { printout(" cells above MAXTEMP %g: %d\n", MAXTEMP, cells_above_maxtemp); } +// start at mgi_start and find the next non-empty cell, or return -1 if none found +[[nodiscard]] auto get_next_nonemptymgi(const int mgi_start) -> int { + for (int mgi = mgi_start; mgi < get_npts_model(); mgi++) { + if (get_numassociatedcells(mgi) > 0) { + return nonemptymgi_of_mgi[mgi]; + } + } + return -1; +} + void setup_nstart_ndo() { const int nprocesses = globals::nprocs; const int npts_nonempty = get_nonempty_npts_model(); @@ -1293,23 +1301,26 @@ void setup_nstart_ndo() { maxndo = 0; ranks_nstart.resize(nprocesses, -1); + ranks_nstart_nonempty.resize(nprocesses, -1); ranks_ndo.resize(nprocesses, 0); ranks_ndo_nonempty.resize(nprocesses, 0); // begin with no cell assignments std::ranges::fill(ranks_nstart, 0); + std::ranges::fill(ranks_nstart_nonempty, 0); std::ranges::fill(ranks_ndo, 0); std::ranges::fill(ranks_ndo_nonempty, 0); if (nprocesses >= get_npts_model()) { // for convenience, rank == mgi when there is at least one rank per cell maxndo = 1; - for (int r = 0; r < nprocesses; r++) { - if (r < get_npts_model()) { - const int mgi = r; - ranks_nstart[r] = mgi; - ranks_ndo[r] = 1; - ranks_ndo_nonempty[r] = (get_numassociatedcells(mgi) > 0) ? 1 : 0; + for (int rank = 0; rank < nprocesses; rank++) { + if (rank < get_npts_model()) { + const int mgi = rank; + ranks_nstart[rank] = mgi; + ranks_ndo[rank] = 1; + ranks_nstart_nonempty[rank] = (get_numassociatedcells(mgi) > 0) ? get_nonemptymgi_of_mgi(mgi) : 0; + ranks_ndo_nonempty[rank] = (get_numassociatedcells(mgi) > 0) ? 1 : 0; } } } else { @@ -1322,6 +1333,8 @@ void setup_nstart_ndo() { // current rank has enough non-empty cells, so start assigning cells to the next rank rank++; ranks_nstart[rank] = mgi; + ranks_nstart_nonempty[rank] = get_next_nonemptymgi(mgi); + assert_always(ranks_nstart_nonempty[rank] >= 0); } ranks_ndo[rank]++; @@ -1341,7 +1354,7 @@ void setup_nstart_ndo() { assert_always(npts_assigned == get_npts_model()); assert_always(npts_nonempty_assigned == get_nonempty_npts_model()); - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { auto fileout = std::ofstream("modelgridrankassignments.out"); assert_always(fileout.is_open()); fileout << "#rank nstart ndo ndo_nonempty\n"; @@ -1816,14 +1829,24 @@ __host__ __device__ auto get_nnetot(const int modelgridindex) -> float { __host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } +auto get_elem_abundance(int modelgridindex, int element) -> float // mass fraction of an element (all isotopes combined) -void set_elem_abundance(const int modelgridindex, const int element, const float newabundance) { - modelgrid[modelgridindex].elem_massfracs[element] = newabundance; +{ + const int nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); + const auto massfrac = elem_massfracs_allcells[(static_cast(nonemptymgi) * get_nelements()) + element]; + assert_testmodeonly(massfrac >= 0.0); + return massfrac; +} + +// mass fraction of an element (all isotopes combined) +void set_elem_abundance(const int nonemptymgi, const int element, const float newabundance) { + elem_massfracs_allcells[(static_cast(nonemptymgi) * get_nelements()) + element] = newabundance; } // mass fraction of an element (all isotopes combined) __host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double { - const double elem_meanweight = grid::get_element_meanweight(modelgridindex, element); + const auto nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); + const double elem_meanweight = grid::get_element_meanweight(nonemptymgi, element); return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); } @@ -1937,7 +1960,7 @@ __host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int } // get the index in the list of non-empty cells for a given model grid cell -__host__ __device__ auto get_modelcell_nonemptymgi(const int mgi) -> int { +__host__ __device__ auto get_nonemptymgi_of_mgi(const int mgi) -> int { assert_testmodeonly(get_nonempty_npts_model() > 0); assert_testmodeonly(mgi < get_npts_model()); @@ -1965,20 +1988,20 @@ __host__ __device__ auto get_mgi_of_nonemptymgi(const int nonemptymgi) -> int { // get the mass fraction of a nuclide in a model grid cell at t=t_model by nuclide index auto get_modelinitnucmassfrac(const int modelgridindex, const int nucindex) -> float { - assert_testmodeonly(modelgrid[modelgridindex].initnucmassfrac != nullptr); - return modelgrid[modelgridindex].initnucmassfrac[nucindex]; + const ptrdiff_t num_nuclides = decay::get_num_nuclides(); + + return initnucmassfrac_allcells[(modelgridindex * num_nuclides) + nucindex]; } -auto get_stable_initabund(const int mgi, const int element) -> float { - assert_testmodeonly(modelgrid[mgi].initmassfracuntrackedstable != nullptr); - return modelgrid[mgi].initmassfracuntrackedstable[element]; +auto get_stable_initabund(const int nonemptymgi, const int element) -> float { + return initmassfracuntrackedstable_allcells[(static_cast(nonemptymgi) * get_nelements()) + element]; } -auto get_element_meanweight(const int mgi, const int element) -> float +auto get_element_meanweight(const int nonemptymgi, const int element) -> float // weight is in grams { if (USE_CALCULATED_MEANATOMICWEIGHT) { - const double mu = modelgrid[mgi].elem_meanweight[element]; + const double mu = elem_meanweight_allcells[(nonemptymgi * get_nelements()) + element]; if (mu > 0) { return mu; } @@ -1987,26 +2010,24 @@ auto get_element_meanweight(const int mgi, const int element) -> float } // set element weight in grams -void set_element_meanweight(const int mgi, const int element, const float meanweight) { +void set_element_meanweight(const int nonemptymgi, const int element, const float meanweight) { assert_always(meanweight > 0.); - modelgrid[mgi].elem_meanweight[element] = meanweight; + elem_meanweight_allcells[(static_cast(nonemptymgi) * get_nelements()) + element] = meanweight; } auto get_electronfrac(const int modelgridindex) -> double { + const auto nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); double nucleondens = 0.; for (int element = 0; element < get_nelements(); element++) { - nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(modelgridindex, element) / MH; + nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(nonemptymgi, element) / MH; } return get_nnetot(modelgridindex) / nucleondens; } auto get_initelectronfrac(const int modelgridindex) -> double { return modelgrid[modelgridindex].initelectronfrac; } -auto get_initenergyq(const int modelgridindex) -> double { - // q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] - - return modelgrid[modelgridindex].initenergyq; -} +// q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] +auto get_initenergyq(const int modelgridindex) -> double { return modelgrid[modelgridindex].initenergyq; } // get the radial distance from the origin to the centre of the cell at time tmin auto get_cellradialposmid(const int cellindex) -> double { @@ -2034,12 +2055,14 @@ auto get_cellradialposmid(const int cellindex) -> double { return vec_len(dcen); } -auto get_elements_uppermost_ion(const int modelgridindex, const int element) -> int { - return modelgrid[modelgridindex].elements_uppermost_ion[element]; +[[nodiscard]] auto get_elements_uppermost_ion(const int modelgridindex, const int element) -> int { + const ptrdiff_t nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); + return elements_uppermost_ion_allcells[(nonemptymgi * get_nelements()) + element]; } void set_elements_uppermost_ion(const int modelgridindex, const int element, const int newvalue) { - modelgrid[modelgridindex].elements_uppermost_ion[element] = newvalue; + const ptrdiff_t nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); + elements_uppermost_ion_allcells[(nonemptymgi * get_nelements()) + element] = newvalue; } void calculate_kappagrey() { @@ -2260,6 +2283,13 @@ auto get_nstart(const int rank) -> int { return ranks_nstart[rank]; } +auto get_nstart_nonempty(const int rank) -> int { + if (ranks_ndo.empty()) { + setup_nstart_ndo(); + } + return ranks_nstart_nonempty[rank]; +} + auto get_ndo(const int rank) -> int { if (ranks_ndo.empty()) { setup_nstart_ndo(); @@ -2326,7 +2356,7 @@ void grid_init(const int my_rank) { std::abort(); } - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { FILE *grid_file = fopen_required("grid.out", "w"); for (int n = 0; n < ngrid; n++) { const int mgi = get_cell_modelgridindex(n); diff --git a/grid.h b/grid.h index 7dc4184e4..c8bd2ed84 100644 --- a/grid.h +++ b/grid.h @@ -1,4 +1,6 @@ +#include #include + #ifndef GRIDINIT_H #define GRIDINIT_H @@ -23,25 +25,16 @@ struct ModelGridCell { float rhoinit = -1.; float rho = -1.; // modelgrid nn_tot - float nnetot = -1.; // total electron density (free + bound). - float *initnucmassfrac{}; - float *initmassfracuntrackedstable{}; - float *elem_meanweight{}; + float nnetot = -1.; // total electron density (free + bound). float initelectronfrac = -1; // Ye: electrons (or protons) per nucleon float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] float ffegrp = 0.; float kappagrey = 0.; - float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell - // This is only stored to print it outside the OpenMP loop in update_grid to the - // estimatorsfile so there is no need to communicate it via MPI so far! - int *elements_uppermost_ion{}; // Highest ionisation stage which has a decent population for a particular - // element in a given cell. - float *elem_massfracs{}; // Pointer to an array which contains the time dependent - // abundances of all included elements and all the groundlevel - + float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell + // This is only stored to print it outside the OpenMP loop in update_grid to the + // estimatorsfile so there is no need to communicate it via MPI so far! float *ion_groundlevelpops{}; // groundlevel populations of all included ions float *ion_partfuncts{}; // partition functions for all included ions - std::span nlte_pops; // Pointer to an array that contains the nlte-level populations for this cell double totalcooling = -1; double *ion_cooling_contribs{}; int thick = 0; @@ -67,6 +60,11 @@ inline int ngrid{0}; inline double mtot_input{0.}; +inline float *elem_meanweight_allcells{}; +inline float *elem_massfracs_allcells; // mass fractions of elements in each cell for the current timestep + +inline double *nltepops_allcells{}; + [[nodiscard]] auto get_elements_uppermost_ion(int modelgridindex, int element) -> int; void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); [[nodiscard]] auto wid_init(int cellindex, int axis) -> double; @@ -82,7 +80,7 @@ void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); [[nodiscard]] auto get_nne(int modelgridindex) -> float; [[nodiscard]] auto get_nnetot(int modelgridindex) -> float; [[nodiscard]] auto get_ffegrp(int modelgridindex) -> float; -void set_elem_abundance(int modelgridindex, int element, float newabundance); +void set_elem_abundance(int nonemptymgi, int element, float newabundance); [[nodiscard]] auto get_elem_numberdens(int modelgridindex, int element) -> double; [[nodiscard]] auto get_initelectronfrac(int modelgridindex) -> double; [[nodiscard]] auto get_initenergyq(int modelgridindex) -> double; @@ -101,12 +99,13 @@ void set_TJ(int modelgridindex, float TJ); void set_W(int modelgridindex, float W); void grid_init(int my_rank); [[nodiscard]] auto get_modelinitnucmassfrac(int modelgridindex, int nucindex) -> float; -[[nodiscard]] auto get_stable_initabund(int mgi, int element) -> float; -[[nodiscard]] auto get_element_meanweight(int mgi, int element) -> float; -void set_element_meanweight(int mgi, int element, float meanweight); +[[nodiscard]] auto get_stable_initabund(int nonemptymgi, int element) -> float; +[[nodiscard]] auto get_element_meanweight(int nonemptymgi, int element) -> float; +[[nodiscard]] auto get_elem_abundance(int modelgridindex, int element) -> float; +void set_element_meanweight(int nonemptymgi, int element, float meanweight); [[nodiscard]] auto get_electronfrac(int modelgridindex) -> double; [[nodiscard]] auto get_numassociatedcells(int modelgridindex) -> int; -[[nodiscard]] auto get_modelcell_nonemptymgi(int mgi) -> int; +[[nodiscard]] auto get_nonemptymgi_of_mgi(int mgi) -> int; [[nodiscard]] auto get_mgi_of_nonemptymgi(int nonemptymgi) -> int; [[nodiscard]] auto get_model_type() -> GridType; void set_model_type(GridType model_type_value); @@ -119,20 +118,13 @@ void read_ejecta_model(); void write_grid_restart_data(int timestep); [[nodiscard]] auto get_maxndo() -> int; [[nodiscard]] auto get_nstart(int rank) -> int; +[[nodiscard]] auto get_nstart_nonempty(int rank) -> int; [[nodiscard]] auto get_ndo(int rank) -> int; [[nodiscard]] auto get_ndo_nonempty(int rank) -> int; [[nodiscard]] auto get_totmassradionuclide(int z, int a) -> double; [[nodiscard]] auto boundary_distance(const std::array &dir, const std::array &pos, double tstart, int cellindex, enum cell_boundary *pkt_last_cross) -> std::tuple; -[[nodiscard]] inline auto get_elem_abundance(int modelgridindex, int element) -> float -// mass fraction of an element (all isotopes combined) -{ - const auto massfrac = modelgrid[modelgridindex].elem_massfracs[element]; - assert_testmodeonly(massfrac >= 0.0); - return massfrac; -} - void calculate_kappagrey(); inline void change_cell(Packet &pkt, const int snext) diff --git a/input.cc b/input.cc index f3d0a1d6a..b0c34c793 100644 --- a/input.cc +++ b/input.cc @@ -1443,7 +1443,7 @@ void write_bflist_file() { globals::bflist.resize(globals::nbfcontinua); FILE *bflist_file{}; - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { bflist_file = fopen_required("bflist.out", "w"); fprintf(bflist_file, "%d\n", globals::nbfcontinua); } @@ -1461,7 +1461,7 @@ void write_bflist_file() { globals::bflist[i].levelindex = level; globals::bflist[i].phixstargetindex = phixstargetindex; - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { fprintf(bflist_file, "%d %d %d %d %d\n", i, element, ion, level, upperionlevel); } @@ -1479,7 +1479,7 @@ void write_bflist_file() { } } assert_always(i == globals::nbfcontinua); - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { fclose(bflist_file); } } @@ -1867,7 +1867,7 @@ void read_parameterfile(int rank) { void update_parameterfile(int nts) // Subroutine to read in input parameters from input.txt. { - assert_always(globals::rank_global == 0); + assert_always(globals::my_rank == 0); if (nts >= 0) { printout("Update input.txt for restart at timestep %d...", nts); } else { diff --git a/kpkt.cc b/kpkt.cc index 1f8b8a99e..5efcc5d5a 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -373,7 +373,7 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); if (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0. && grid::modelgrid[modelgridindex].thick != 1) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); pkt.nu_cmf = sample_planck_times_expansion_opacity(nonemptymgi); } else { pkt.nu_cmf = sample_planck_montecarlo(grid::get_Te(modelgridindex)); diff --git a/ltepop.cc b/ltepop.cc index ae7b414dc..3206d5215 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -177,8 +177,7 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co } else if (elem_has_nlte_levels(element)) { if (is_nlte(element, ion, level)) { // first_nlte refers to the first excited state (level=1) - const double nltepop_over_rho = - grid::modelgrid[modelgridindex].nlte_pops[globals::elements[element].ions[ion].first_nlte + level - 1]; + const double nltepop_over_rho = get_nlte_levelpop_over_rho(modelgridindex, element, ion, level); if (nltepop_over_rho < -0.9) { // Case for when no NLTE level information is available yet nn = calculate_levelpop_lte(modelgridindex, element, ion, level); @@ -198,9 +197,7 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co // level is in the superlevel assert_testmodeonly(level_isinsuperlevel(element, ion, level)); - const int sl_nlte_index = globals::elements[element].ions[ion].first_nlte + get_nlevels_nlte(element, ion); - - const double superlevelpop_over_rho = grid::modelgrid[modelgridindex].nlte_pops[sl_nlte_index]; + const double superlevelpop_over_rho = get_nlte_superlevelpop_over_rho(modelgridindex, element, ion); if (superlevelpop_over_rho < -0.9) // TODO: should change this to less than zero? { // Case for when no NLTE level information is available yet @@ -283,7 +280,7 @@ auto find_uppermost_ion(const int modelgridindex, const int element, const doubl if (!force_lte && elem_has_nlte_levels(element)) { return nions - 1; } - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const bool use_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); int uppermost_ion = 0; @@ -378,8 +375,8 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc if constexpr (USE_LUT_PHOTOION) { for (int ion = 0; ion <= grid::get_elements_uppermost_ion(modelgridindex, element); ion++) { printout("element %d, ion %d, gammaionest %g\n", element, ion, - globals::gammaestimator[get_ionestimindex_nonemptymgi( - grid::get_modelcell_nonemptymgi(modelgridindex), element, ion)]); + globals::gammaestimator[get_ionestimindex_nonemptymgi(grid::get_nonemptymgi_of_mgi(modelgridindex), + element, ion)]); } } } @@ -423,7 +420,7 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(uppermost_ion <= std::max(0, get_nions(element) - 1)); - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if (uppermost_ion < 0) { return {}; diff --git a/macroatom.cc b/macroatom.cc index 5528ed0b1..1f50ccf57 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -307,7 +307,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, // handle activated macro atoms __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) { const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_testmodeonly(nonemptymgi >= 0); const auto T_e = grid::get_Te(modelgridindex); diff --git a/nltepop.cc b/nltepop.cc index e330c28df..aa6d30022 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -383,10 +384,10 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e } void nltepop_reset_element(const int modelgridindex, const int element) { + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - const int nlte_start = globals::elements[element].ions[ion].first_nlte; - std::fill_n(&grid::modelgrid[modelgridindex].nlte_pops[nlte_start], + std::fill_n(&grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels)], get_nlevels_nlte(element, ion) + (ion_has_superlevel(element, ion) ? 1 : 0), -1.); } } @@ -1023,12 +1024,11 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // gsl_vector_get(x, index_gs), gsl_vector_get(pop_norm_factor_vec, index_gs)); // store the NLTE level populations - const int nlte_start = globals::elements[element].ions[ion].first_nlte; // double solution_ion_pop = 0.; for (int level = 1; level <= nlevels_nlte; level++) { const int index = get_nlte_vector_index(element, ion, level); - grid::modelgrid[modelgridindex].nlte_pops[nlte_start + level - 1] = - gsl_vector_get(&popvec, index) / grid::get_rho(modelgridindex); + set_nlte_levelpop_over_rho(modelgridindex, element, ion, level, + gsl_vector_get(&popvec, index) / grid::get_rho(modelgridindex)); // solution_ion_pop += gsl_vector_get(popvec, index); } @@ -1036,8 +1036,9 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const if (ion_has_superlevel(element, ion)) // a superlevel exists { const int index_sl = get_nlte_vector_index(element, ion, nlevels_nlte + 1); - grid::modelgrid[modelgridindex].nlte_pops[nlte_start + nlevels_nlte] = - (gsl_vector_get(&popvec, index_sl) / grid::modelgrid[modelgridindex].rho / superlevel_partfunc[ion]); + set_nlte_superlevelpop_over_rho( + modelgridindex, element, ion, + gsl_vector_get(&popvec, index_sl) / grid::get_rho(modelgridindex) / superlevel_partfunc[ion]); } // store the ground level population @@ -1142,7 +1143,6 @@ void nltepop_write_to_file(const int modelgridindex, const int timestep) { for (int ion = 0; ion < nions; ion++) { const int nlevels_nlte = get_nlevels_nlte(element, ion); - const int ion_first_nlte = globals::elements[element].ions[ion].first_nlte; const int ionstage = get_ionstage(element, ion); const int nsuperlevels = ion_has_superlevel(element, ion) ? 1 : 0; @@ -1158,13 +1158,13 @@ void nltepop_write_to_file(const int modelgridindex, const int timestep) { if (level == 0) { nnlevelnlte = get_groundlevelpop(modelgridindex, element, ion); } else { - nnlevelnlte = (grid::modelgrid[modelgridindex].nlte_pops[ion_first_nlte + level - 1] * - grid::modelgrid[modelgridindex].rho); + nnlevelnlte = + get_nlte_levelpop_over_rho(modelgridindex, element, ion, level) * grid::modelgrid[modelgridindex].rho; } } else { // superlevel, so add the populations of all other levels in the superlevel - const double slpopfactor = (grid::modelgrid[modelgridindex].nlte_pops[ion_first_nlte + nlevels_nlte] * - grid::modelgrid[modelgridindex].rho); + const double slpopfactor = + get_nlte_superlevelpop_over_rho(modelgridindex, element, ion) * grid::modelgrid[modelgridindex].rho; nnlevellte = 0; double superlevel_partfunc = 0; @@ -1207,7 +1207,7 @@ void nltepop_write_restart_data(FILE *restart_file) { } } for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { - fprintf(restart_file, "%la ", grid::modelgrid[modelgridindex].nlte_pops[nlteindex]); + fprintf(restart_file, "%la ", grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + nlteindex]); } } } @@ -1260,7 +1260,37 @@ void nltepop_read_restart_data(FILE *restart_file) { assert_always(fscanf(restart_file, "%*a ") == 0); // discard value (master rank of this node will set it) } else #endif - assert_always(fscanf(restart_file, "%la ", &grid::modelgrid[modelgridindex].nlte_pops[nlteindex]) == 1); + assert_always(fscanf(restart_file, "%la ", + &grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + nlteindex]) == 1); } } } + +auto get_nlte_levelpop_over_rho(const int modelgridindex, const int element, const int ion, const int level) -> double { + assert_testmodeonly(level <= get_nlevels_nlte(element, ion)); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + return grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + + globals::elements[element].ions[ion].first_nlte + level - 1]; +} + +auto get_nlte_superlevelpop_over_rho(const int modelgridindex, const int element, const int ion) -> double { + assert_testmodeonly(ion_has_superlevel(element, ion)); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const int sl_nlte_index = globals::elements[element].ions[ion].first_nlte + get_nlevels_nlte(element, ion); + return grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + sl_nlte_index]; +} + +void set_nlte_levelpop_over_rho(const int modelgridindex, const int element, const int ion, const int level, + const double value) { + assert_testmodeonly(level <= get_nlevels_nlte(element, ion)); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + globals::elements[element].ions[ion].first_nlte + + level - 1] = value; +} + +void set_nlte_superlevelpop_over_rho(const int modelgridindex, const int element, const int ion, const double value) { + assert_testmodeonly(ion_has_superlevel(element, ion)); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const int sl_nlte_index = globals::elements[element].ions[ion].first_nlte + get_nlevels_nlte(element, ion); + grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + sl_nlte_index] = value; +} diff --git a/nltepop.h b/nltepop.h index f18e155fa..4d2cd18c8 100644 --- a/nltepop.h +++ b/nltepop.h @@ -5,6 +5,10 @@ void solve_nlte_pops_element(int element, int modelgridindex, int timestep, int nlte_iter); [[nodiscard]] auto superlevel_boltzmann(int modelgridindex, int element, int ion, int level) -> double; +[[nodiscard]] auto get_nlte_levelpop_over_rho(int modelgridindex, int element, int ion, int level) -> double; +[[nodiscard]] auto get_nlte_superlevelpop_over_rho(int modelgridindex, int element, int ion) -> double; +void set_nlte_levelpop_over_rho(int modelgridindex, int element, int ion, int level, double value); +void set_nlte_superlevelpop_over_rho(int modelgridindex, int element, int ion, double value); void nltepop_write_to_file(int modelgridindex, int timestep); void nltepop_open_file(int my_rank); void nltepop_close_file(); diff --git a/nonthermal.cc b/nonthermal.cc index c4c476265..a48b5a965 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2154,7 +2154,7 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[modelgridindex].allions = static_cast(malloc(get_includedions() * sizeof(NonThermalSolutionIon))); - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); nt_solution[modelgridindex].frac_excitations_list = NT_EXCITATION_ON ? &excitations_list_all_cells[nonemptymgi * nt_excitations_stored] : nullptr; @@ -2185,9 +2185,9 @@ void init(const int my_rank, const int ndo_nonempty) { // set total non-thermal deposition rate from individual gamma/positron/electron/alpha rates. This should be called // after packet propagation is finished for this timestep and normalise_deposition_estimators() has been done -void calculate_deposition_rate_density(const int modelgridindex, const int timestep, +void calculate_deposition_rate_density(const int nonemptymgi, const int timestep, HeatingCoolingRates *heatingcoolingrates) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); heatingcoolingrates->dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; const double tmid = globals::timesteps[timestep].mid; @@ -2198,16 +2198,16 @@ void calculate_deposition_rate_density(const int modelgridindex, const int times // with time-dependent deposition, we don't have an analytic rate, so we use the Monte Carlo rate assert_always(heatingcoolingrates != nullptr); - heatingcoolingrates->eps_gamma_ana = rho * decay::get_gamma_emission_rate(modelgridindex, tmid); + heatingcoolingrates->eps_gamma_ana = rho * decay::get_gamma_emission_rate(nonemptymgi, tmid); heatingcoolingrates->eps_positron_ana = - rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_BETAPLUS); + rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_BETAPLUS); heatingcoolingrates->eps_electron_ana = - (rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_BETAMINUS)); + (rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_BETAMINUS)); heatingcoolingrates->eps_alpha_ana = - rho * decay::get_particle_injection_rate(modelgridindex, tmid, decay::DECAYTYPE_ALPHA); + rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_ALPHA); if (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::INSTANT) { heatingcoolingrates->dep_positron = heatingcoolingrates->eps_positron_ana; @@ -2223,9 +2223,8 @@ void calculate_deposition_rate_density(const int modelgridindex, const int times (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron); } -__host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double // get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() -{ +__host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double { assert_always(deposition_rate_density_all_cells[modelgridindex] >= 0); return deposition_rate_density_all_cells[modelgridindex]; } @@ -2778,10 +2777,8 @@ void read_restart_data(FILE *gridsave_file) { } #ifdef MPI_ON -void nt_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) { - if (grid::get_numassociatedcells(modelgridindex) == 0) { - return; - } +void nt_MPI_Bcast(const int nonemptymgi, const int root, const int root_node_id) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); MPI_Bcast(&deposition_rate_density_all_cells[modelgridindex], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); diff --git a/nonthermal.h b/nonthermal.h index bb14e4549..f137c9274 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -15,7 +15,7 @@ void solve_spencerfano(int modelgridindex, int timestep, int iteration); bool energyweighted) -> double; [[nodiscard]] auto nt_ionisation_maxupperion(int element, int lowerion) -> int; [[nodiscard]] auto nt_random_upperion(int modelgridindex, int element, int lowerion, bool energyweighted) -> int; -void calculate_deposition_rate_density(int modelgridindex, int timestep, HeatingCoolingRates *heatingcoolingrates); +void calculate_deposition_rate_density(int nonemptymgi, int timestep, HeatingCoolingRates *heatingcoolingrates); [[nodiscard]] auto get_deposition_rate_density(int modelgridindex) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; #pragma omp declare simd @@ -25,7 +25,7 @@ void do_ntalpha_deposit(Packet &pkt); void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); -void nt_MPI_Bcast(int modelgridindex, int root, int root_node_id); +void nt_MPI_Bcast(int nonemptymgi, int root, int root_node_id); void nt_reset_stats(); void nt_print_stats(double modelvolume, double deltat); } // namespace nonthermal diff --git a/packet.cc b/packet.cc index 822eb11c2..2b1e7cd06 100644 --- a/packet.cc +++ b/packet.cc @@ -111,9 +111,11 @@ void packet_init(Packet *pkt) double norm = 0.; for (int m = 0; m < grid::ngrid; m++) { - if (const int mgi = grid::get_cell_modelgridindex(m); mgi < grid::get_npts_model()) // some grid cells are empty + const int mgi = grid::get_cell_modelgridindex(m); + if (mgi < grid::get_npts_model() && grid::get_numassociatedcells(mgi) > 0) // some grid cells are empty { - double q = decay::get_modelcell_simtime_endecay_per_mass(mgi); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + double q = decay::get_modelcell_simtime_endecay_per_mass(nonemptymgi); if constexpr (INITIAL_PACKETS_ON && USE_MODEL_INITIAL_ENERGY) { q += grid::get_initenergyq(mgi); } diff --git a/radfield.cc b/radfield.cc index 69092f99f..3361996dc 100644 --- a/radfield.cc +++ b/radfield.cc @@ -191,7 +191,7 @@ void add_detailed_line(const int lineindex) { // get the normalised J_nu auto get_bin_J(const int modelgridindex, const int binindex) -> double { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); @@ -200,7 +200,7 @@ auto get_bin_J(const int modelgridindex, const int binindex) -> double { } auto get_bin_nuJ(const int modelgridindex, const int binindex) -> double { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); @@ -216,17 +216,17 @@ auto get_bin_nu_bar(const int modelgridindex, const int binindex) -> double { } auto get_bin_contribcount(const int modelgridindex, const int binindex) -> int { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].contribcount; } auto get_bin_W(const int modelgridindex, const int binindex) -> float { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].W; } auto get_bin_T_R(const int modelgridindex, const int binindex) -> float { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].T_R; } @@ -409,7 +409,7 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { } // namespace radfield void set_params_fullspec(const int modelgridindex, const int timestep) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const double nubar = nuJ[nonemptymgi] / J[nonemptymgi]; if (!std::isfinite(nubar) || nubar == 0.) { printout("[warning] T_R estimator infinite in cell %d, keep T_R, T_J, W of last timestep. J = %g. nuJ = %g\n", @@ -646,7 +646,7 @@ void init(const int my_rank, const int ndo_nonempty) { void initialise_prev_titer_photoionestimators() { #ifdef DO_TITER for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); globals::ffheatingestimator_save[nonemptymgi] = -1.; globals::colheatingestimator_save[nonemptymgi] = -1.; J_reduced_save[nonemptymgi] = -1.; @@ -704,7 +704,7 @@ auto get_Jb_lu_contribcount(const int modelgridindex, const int jblueindex) -> i void write_to_file(const int modelgridindex, const int timestep) { assert_always(MULTIBIN_RADFIELD_MODEL_ON); - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); #ifdef _OPENMP #pragma omp critical(out_file) { @@ -881,7 +881,7 @@ __host__ __device__ auto radfield(const double nu, const int modelgridindex) -> const int binindex = select_bin(nu); if (binindex >= 0) { const auto &bin = - radfieldbin_solutions[(grid::get_modelcell_nonemptymgi(modelgridindex) * RADFIELDBINCOUNT) + binindex]; + radfieldbin_solutions[(grid::get_nonemptymgi_of_mgi(modelgridindex) * RADFIELDBINCOUNT) + binindex]; if (bin.W >= 0.) { const double J_nu = dbb(nu, bin.T_R, bin.W); return J_nu; @@ -939,7 +939,7 @@ auto planck_integral_analytic(const double T_R, const double nu_lower, const dou void fit_parameters(const int modelgridindex, const int timestep) { set_params_fullspec(modelgridindex, timestep); - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { if (J_normfactor[nonemptymgi] <= 0) { @@ -1020,7 +1020,7 @@ void fit_parameters(const int modelgridindex, const int timestep) { void set_J_normfactor(const int nonemptymgi, const double normfactor) { J_normfactor[nonemptymgi] = normfactor; } void normalise_J(const int modelgridindex, const double estimator_normfactor_over4pi) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_always(std::isfinite(J[nonemptymgi])); J[nonemptymgi] *= estimator_normfactor_over4pi; for (int i = 0; i < detailed_linecount; i++) { @@ -1063,7 +1063,7 @@ auto get_bfrate_estimator(const int element, const int lowerion, const int lower if (allcontindex >= 0) { const auto bfestimindex = globals::allcont[allcontindex].bfestimindex; if (bfestimindex >= 0) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); return prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + bfestimindex]; } } @@ -1073,13 +1073,13 @@ auto get_bfrate_estimator(const int element, const int lowerion, const int lower } void normalise_nuJ(const int modelgridindex, const double estimator_normfactor_over4pi) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_always(std::isfinite(nuJ[nonemptymgi])); nuJ[nonemptymgi] *= estimator_normfactor_over4pi; } auto get_T_J_from_J(const int modelgridindex) -> double { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const double T_J = pow(J[nonemptymgi] * PI / STEBO, 1. / 4.); if (!std::isfinite(T_J)) { // keep old value of T_J @@ -1101,7 +1101,7 @@ auto get_T_J_from_J(const int modelgridindex) -> double { #ifdef DO_TITER void titer_J(const int modelgridindex) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if (J_reduced_save[nonemptymgi] >= 0) { J[nonemptymgi] = (J[nonemptymgi] + J_reduced_save[nonemptymgi]) / 2; } @@ -1109,7 +1109,7 @@ void titer_J(const int modelgridindex) { } void titer_nuJ(const int modelgridindex) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if (nuJ_reduced_save[nonemptymgi] >= 0) { nuJ[nonemptymgi] = (nuJ[nonemptymgi] + nuJ_reduced_save[nonemptymgi]) / 2; } @@ -1178,12 +1178,7 @@ void reduce_estimators() // broadcast computed radfield results including parameters // from the cells belonging to root process to all processes -void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_id) { - if (grid::get_numassociatedcells(modelgridindex) == 0) { - return; - } - - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); +void do_MPI_Bcast(const ptrdiff_t nonemptymgi, const int root, const int root_node_id) { MPI_Bcast(&J_normfactor[nonemptymgi], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { @@ -1197,6 +1192,7 @@ void do_MPI_Bcast(const int modelgridindex, const int root, const int root_node_ } if constexpr (DETAILED_LINE_ESTIMATORS_ON) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { MPI_Bcast(&prev_Jb_lu_normed[modelgridindex][jblueindex].value, 1, MPI_DOUBLE, root, MPI_COMM_WORLD); MPI_Bcast(&prev_Jb_lu_normed[modelgridindex][jblueindex].contribcount, 1, MPI_INT, root, MPI_COMM_WORLD); @@ -1230,7 +1226,7 @@ void write_restart_data(FILE *gridsave_file) { for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); fprintf(gridsave_file, "%d\n", modelgridindex); for (int i = 0; i < bfestimcount; i++) { fprintf(gridsave_file, "%a ", prev_bfrate_normed[(nonemptymgi * bfestimcount) + i]); @@ -1249,7 +1245,7 @@ void write_restart_data(FILE *gridsave_file) { for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_testmodeonly(nonemptymgi >= 0); fprintf(gridsave_file, "%d %la\n", modelgridindex, J_normfactor[nonemptymgi]); @@ -1333,7 +1329,7 @@ void read_restart_data(FILE *gridsave_file) { for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); int mgi_in = 0; assert_always(fscanf(gridsave_file, "%d\n", &mgi_in) == 1); assert_always(mgi_in == modelgridindex); @@ -1366,7 +1362,7 @@ void read_restart_data(FILE *gridsave_file) { for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { if (grid::get_numassociatedcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); int mgi_in = 0; assert_always(fscanf(gridsave_file, "%d %la\n", &mgi_in, &J_normfactor[nonemptymgi]) == 2); if (mgi_in != modelgridindex) { diff --git a/radfield.h b/radfield.h index 406c785ca..e0ad0c20f 100644 --- a/radfield.h +++ b/radfield.h @@ -30,7 +30,7 @@ void normalise_nuJ(int modelgridindex, double estimator_normfactor_over4pi); void titer_J(int modelgridindex); void titer_nuJ(int modelgridindex); void reduce_estimators(); -void do_MPI_Bcast(int modelgridindex, int root, int root_node_id); +void do_MPI_Bcast(ptrdiff_t nonemptymgi, int root, int root_node_id); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); void normalise_bf_estimators(int nts, int nts_prev, int titer, double deltat); diff --git a/ratecoeff.cc b/ratecoeff.cc index d1605cf48..10f5ab164 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -1135,7 +1135,7 @@ void ratecoefficients_init() { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { write_ratecoeff_dat(); } } @@ -1253,7 +1253,7 @@ __host__ __device__ auto get_corrphotoioncoeff(const int element, const int ion, } else { const double W = grid::get_W(modelgridindex); const double T_R = grid::get_TR(modelgridindex); - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); gammacorr = W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); const int index_in_groundlevelcontestimator = diff --git a/rpkt.cc b/rpkt.cc index 33a6f258a..43ac93d0f 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -625,7 +625,7 @@ void update_estimators(const double e_cmf, const double nu_cmf, const double dis auto do_rpkt_step(Packet &pkt, const double t2) -> bool { const int cellindex = pkt.where; const int mgi = grid::get_cell_modelgridindex(cellindex); - const int nonemptymgi = (mgi != grid::get_npts_model()) ? grid::get_modelcell_nonemptymgi(mgi) : -1; + const int nonemptymgi = (mgi != grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; MacroAtomState pktmastate{}; @@ -1150,10 +1150,9 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff } #ifdef MPI_ON -void MPI_Bcast_binned_opacities(const int modelgridindex, const int root_node_id) { +void MPI_Bcast_binned_opacities(const ptrdiff_t nonemptymgi, const int root_node_id) { if constexpr (EXPANSIONOPACITIES_ON) { if (globals::rank_in_node == 0) { - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); assert_always(nonemptymgi >= 0); MPI_Bcast(&expansionopacities[nonemptymgi * expopac_nbins], expopac_nbins, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); @@ -1168,7 +1167,7 @@ void MPI_Bcast_binned_opacities(const int modelgridindex, const int root_node_id #endif void calculate_expansion_opacities(const int modelgridindex) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const auto rho = grid::get_rho(modelgridindex); const auto sys_time_start_calc = std::time(nullptr); diff --git a/rpkt.h b/rpkt.h index 871bf59ff..634a0e14a 100644 --- a/rpkt.h +++ b/rpkt.h @@ -1,6 +1,7 @@ #ifndef RPKT_H #define RPKT_H +#include #include #include #include @@ -36,7 +37,7 @@ void calculate_chi_rpkt_cont(double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi [[nodiscard]] auto sample_planck_times_expansion_opacity(int nonemptymgi) -> double; void allocate_expansionopacities(); void calculate_expansion_opacities(int modelgridindex); -void MPI_Bcast_binned_opacities(int modelgridindex, int root_node_id); +void MPI_Bcast_binned_opacities(ptrdiff_t nonemptymgi, int root_node_id); [[nodiscard]] constexpr auto get_linedistance(const double prop_time, const double nu_cmf, const double nu_trans, const double d_nu_on_d_l) -> double { diff --git a/sn3d.cc b/sn3d.cc index ae4364298..e4c091132 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -113,65 +113,60 @@ void initialise_linestat_file() { fflush(linestat_file); } -void write_deposition_file(const int nts, const int my_rank, const int nstart, const int ndo) { +void write_deposition_file() { + const int my_rank = globals::my_rank; + const int nts = globals::timestep; printout("Calculating deposition rates...\n"); auto const time_write_deposition_file_start = std::time(nullptr); double mtot = 0.; + const int nstart_nonempty = grid::get_nstart_nonempty(my_rank); + const int ndo_nonempty = grid::get_ndo_nonempty(my_rank); // calculate analytical decay rates - // for (int i = 0; i <= nts; i++) - { - const int i = nts; - const double t_mid = globals::timesteps[i].mid; - - // power in [erg/s] - globals::timesteps[i].eps_positron_ana_power = 0.; - globals::timesteps[i].eps_electron_ana_power = 0.; - globals::timesteps[i].eps_alpha_ana_power = 0.; - globals::timesteps[i].qdot_betaminus = 0.; - globals::timesteps[i].qdot_alpha = 0.; - globals::timesteps[i].qdot_total = 0.; - - for (int mgi = nstart; mgi < (nstart + ndo); mgi++) - // for (int mgi = 0; mgi < grid::get_npts_model(); mgi++) - { - if (grid::get_numassociatedcells(mgi) > 0) { - const double cellmass = grid::get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); - - globals::timesteps[i].eps_positron_ana_power += - cellmass * decay::get_particle_injection_rate(mgi, t_mid, decay::DECAYTYPE_BETAPLUS); - globals::timesteps[i].eps_electron_ana_power += - cellmass * decay::get_particle_injection_rate(mgi, t_mid, decay::DECAYTYPE_BETAMINUS); - globals::timesteps[i].eps_alpha_ana_power += - cellmass * decay::get_particle_injection_rate(mgi, t_mid, decay::DECAYTYPE_ALPHA); - - if (i == nts) { - mtot += cellmass; - } + const double t_mid_nts = globals::timesteps[nts].mid; - for (const auto decaytype : decay::all_decaytypes) { - // Qdot here has been multiplied by mass, so it is in units of [erg/s] - const double qdot_cell = decay::get_qdot_modelcell(mgi, t_mid, decaytype) * cellmass; - globals::timesteps[i].qdot_total += qdot_cell; - if (decaytype == decay::DECAYTYPE_BETAMINUS) { - globals::timesteps[i].qdot_betaminus += qdot_cell; - } else if (decaytype == decay::DECAYTYPE_ALPHA) { - globals::timesteps[i].qdot_alpha += qdot_cell; - } - } + // power in [erg/s] + globals::timesteps[nts].eps_positron_ana_power = 0.; + globals::timesteps[nts].eps_electron_ana_power = 0.; + globals::timesteps[nts].eps_alpha_ana_power = 0.; + globals::timesteps[nts].qdot_betaminus = 0.; + globals::timesteps[nts].qdot_alpha = 0.; + globals::timesteps[nts].qdot_total = 0.; + + for (int nonemptymgi = nstart_nonempty; nonemptymgi < (nstart_nonempty + ndo_nonempty); nonemptymgi++) { + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); + const double cellmass = grid::get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); + + globals::timesteps[nts].eps_positron_ana_power += + cellmass * decay::get_particle_injection_rate(nonemptymgi, t_mid_nts, decay::DECAYTYPE_BETAPLUS); + globals::timesteps[nts].eps_electron_ana_power += + cellmass * decay::get_particle_injection_rate(nonemptymgi, t_mid_nts, decay::DECAYTYPE_BETAMINUS); + globals::timesteps[nts].eps_alpha_ana_power += + cellmass * decay::get_particle_injection_rate(nonemptymgi, t_mid_nts, decay::DECAYTYPE_ALPHA); + + mtot += cellmass; + + for (const auto decaytype : decay::all_decaytypes) { + // Qdot here has been multiplied by mass, so it is in units of [erg/s] + const double qdot_cell = decay::get_qdot_modelcell(nonemptymgi, t_mid_nts, decaytype) * cellmass; + globals::timesteps[nts].qdot_total += qdot_cell; + if (decaytype == decay::DECAYTYPE_BETAMINUS) { + globals::timesteps[nts].qdot_betaminus += qdot_cell; + } else if (decaytype == decay::DECAYTYPE_ALPHA) { + globals::timesteps[nts].qdot_alpha += qdot_cell; } } + } #ifdef MPI_ON - // in MPI mode, each process only did some fraction of the cells - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].eps_positron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].eps_electron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].eps_alpha_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].qdot_betaminus, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].qdot_alpha, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[i].qdot_total, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + // in MPI mode, each process only calculated the contribution of a subset of cells + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_positron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_electron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_alpha_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_betaminus, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_alpha, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_total, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #endif - } #ifdef MPI_ON MPI_Allreduce(MPI_IN_PLACE, &mtot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -220,36 +215,35 @@ void write_deposition_file(const int nts, const int my_rank, const int nstart, c } #ifdef MPI_ON -void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const int nstart, const int ndo) { - int position = 0; - for (int root = 0; root < nprocs; root++) { +void mpi_communicate_grid_properties() { + const auto nincludedions = get_includedions(); + const auto nelements = get_nelements(); + for (int root = 0; root < globals::nprocs; root++) { MPI_Barrier(MPI_COMM_WORLD); - int root_nstart = nstart; - MPI_Bcast(&root_nstart, 1, MPI_INT, root, MPI_COMM_WORLD); - int root_ndo = ndo; - MPI_Bcast(&root_ndo, 1, MPI_INT, root, MPI_COMM_WORLD); + int root_node_id = globals::node_id; MPI_Bcast(&root_node_id, 1, MPI_INT, root, MPI_COMM_WORLD); - for (int modelgridindex = root_nstart; modelgridindex < (root_nstart + root_ndo); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) < 1) { - continue; - } + const int root_nstart_nonempty = grid::get_nstart_nonempty(root); + const int root_ndo_nonempty = grid::get_ndo_nonempty(root); - radfield::do_MPI_Bcast(modelgridindex, root, root_node_id); + for (int nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); + nonemptymgi++) { + assert_always(root_ndo_nonempty > 0); - nonthermal::nt_MPI_Bcast(modelgridindex, root, root_node_id); + radfield::do_MPI_Bcast(nonemptymgi, root, root_node_id); + + nonthermal::nt_MPI_Bcast(nonemptymgi, root, root_node_id); if (globals::total_nlte_levels > 0 && globals::rank_in_node == 0) { - MPI_Bcast(grid::modelgrid[modelgridindex].nlte_pops.data(), globals::total_nlte_levels, MPI_DOUBLE, - root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::nltepops_allcells[nonemptymgi * globals::total_nlte_levels], globals::total_nlte_levels, + MPI_DOUBLE, root_node_id, globals::mpi_comm_internode); } if (USE_LUT_PHOTOION && globals::nbfcontinua_ground > 0) { - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); assert_always(globals::corrphotoionrenorm != nullptr); if (globals::rank_in_node == 0) { - MPI_Bcast(globals::corrphotoionrenorm + (nonemptymgi * globals::nbfcontinua_ground), + MPI_Bcast(&globals::corrphotoionrenorm[nonemptymgi * globals::nbfcontinua_ground], globals::nbfcontinua_ground, MPI_DOUBLE, root_node_id, globals::mpi_comm_internode); } @@ -258,54 +252,51 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_Bcast(&globals::gammaestimator[nonemptymgi * globals::nbfcontinua_ground], globals::nbfcontinua_ground, MPI_DOUBLE, root, MPI_COMM_WORLD); } - - assert_always(grid::modelgrid[modelgridindex].elem_meanweight != nullptr); if (globals::rank_in_node == 0) { - MPI_Bcast(grid::modelgrid[modelgridindex].elem_meanweight, get_nelements(), MPI_FLOAT, root_node_id, + MPI_Bcast(&grid::elem_meanweight_allcells[nonemptymgi * nelements], nelements, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); } - MPI_Bcast_binned_opacities(modelgridindex, root_node_id); + MPI_Bcast_binned_opacities(nonemptymgi, root_node_id); } - if (root == my_rank) { - position = 0; - MPI_Pack(&ndo, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - for (int mgi = nstart; mgi < (nstart + ndo); mgi++) { + if (root == globals::my_rank) { + int position = 0; + for (ptrdiff_t nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); + nonemptymgi++) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); MPI_Pack(&mgi, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - if (grid::get_numassociatedcells(mgi) > 0) { - MPI_Pack(&grid::modelgrid[mgi].Te, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].TR, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].W, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].rho, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].nne, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - - MPI_Pack(grid::modelgrid[mgi].elem_massfracs, get_nelements(), MPI_FLOAT, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - - MPI_Pack(grid::modelgrid[mgi].ion_groundlevelpops, get_includedions(), MPI_FLOAT, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].ion_partfuncts, get_includedions(), MPI_FLOAT, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].ion_cooling_contribs, get_includedions(), MPI_DOUBLE, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - } + MPI_Pack(&grid::modelgrid[mgi].Te, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].TR, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].W, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].rho, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].nne, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, + MPI_COMM_WORLD); + + MPI_Pack(&grid::elem_massfracs_allcells[(nonemptymgi * nelements)], nelements, MPI_FLOAT, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); + + MPI_Pack(grid::modelgrid[mgi].ion_groundlevelpops, nincludedions, MPI_FLOAT, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack(grid::modelgrid[mgi].ion_partfuncts, nincludedions, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, + &position, MPI_COMM_WORLD); + MPI_Pack(grid::modelgrid[mgi].ion_cooling_contribs, nincludedions, MPI_DOUBLE, mpi_grid_buffer, + mpi_grid_buffer_size, &position, MPI_COMM_WORLD); } printout("[info] mem_usage: MPI_BUFFER: used %d of %zu bytes allocated to mpi_grid_buffer\n", position, mpi_grid_buffer_size); @@ -315,51 +306,50 @@ void mpi_communicate_grid_properties(const int my_rank, const int nprocs, const MPI_Bcast(mpi_grid_buffer, mpi_grid_buffer_size, MPI_PACKED, root, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); - position = 0; - int nlp = 0; - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &nlp, 1, MPI_INT, MPI_COMM_WORLD); - for (int nn = 0; nn < nlp; nn++) { - int mgi = 0; - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &mgi, 1, MPI_INT, MPI_COMM_WORLD); - - if (grid::get_numassociatedcells(mgi) > 0) { - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].Te, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TR, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].W, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].rho, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nne, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_INT, - MPI_COMM_WORLD); - - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].elem_massfracs, - get_nelements(), MPI_FLOAT, MPI_COMM_WORLD); - - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_groundlevelpops, - get_includedions(), MPI_FLOAT, MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_partfuncts, - get_includedions(), MPI_FLOAT, MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_cooling_contribs, - get_includedions(), MPI_DOUBLE, MPI_COMM_WORLD); - } + int position = 0; + for (ptrdiff_t nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); + nonemptymgi++) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); + int mgi_check = -1; + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &mgi_check, 1, MPI_INT, MPI_COMM_WORLD); + assert_always(mgi == mgi_check); + + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].Te, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TR, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].W, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].rho, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nne, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_INT, + MPI_COMM_WORLD); + + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, + &grid::elem_massfracs_allcells[(nonemptymgi * nelements)], nelements, MPI_FLOAT, MPI_COMM_WORLD); + + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_groundlevelpops, + nincludedions, MPI_FLOAT, MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_partfuncts, nincludedions, + MPI_FLOAT, MPI_COMM_WORLD); + MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_cooling_contribs, + nincludedions, MPI_DOUBLE, MPI_COMM_WORLD); } } MPI_Barrier(MPI_COMM_WORLD); } -void mpi_reduce_estimators(int nts) { +void mpi_reduce_estimators(const int nts) { const int nonempty_npts_model = grid::get_nonempty_npts_model(); radfield::reduce_estimators(); MPI_Barrier(MPI_COMM_WORLD); @@ -410,7 +400,6 @@ void mpi_reduce_estimators(int nts) { MPI_Barrier(MPI_COMM_WORLD); - // Communicate gamma and positron deposition and write to file MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].cmf_lum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); globals::timesteps[nts].cmf_lum /= globals::nprocs; @@ -528,10 +517,11 @@ auto walltime_sufficient_to_continue(const int nts, const int nts_prev, const in return do_this_full_loop; } -void save_grid_and_packets(const int nts, const int my_rank, const Packet *packets) { +void save_grid_and_packets(const int nts, const Packet *packets) { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif + const auto my_rank = globals::my_rank; bool write_successful = false; while (!write_successful) { @@ -539,9 +529,9 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe printout("time before write temporary packets file %ld\n", time_write_packets_file_start); // save packet state at start of current timestep (before propagation) - write_temp_packetsfile(nts, my_rank, packets); + write_temp_packetsfile(nts, globals::my_rank, packets); - vpkt_write_timestep(nts, my_rank, false); + vpkt_write_timestep(nts, globals::my_rank, false); const auto time_write_packets_finished_thisrank = std::time(nullptr); @@ -583,7 +573,7 @@ void save_grid_and_packets(const int nts, const int my_rank, const Packet *packe } if (!KEEP_ALL_RESTART_FILES) { -// ensure new packets files have been written by all processes before we remove the old set + // ensure new packets files have been written by all processes before we remove the old set #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); #endif @@ -668,14 +658,13 @@ void normalise_deposition_estimators(int nts) { } } -auto do_timestep(const int nts, const int titer, const int my_rank, const int nstart, const int ndo, Packet *packets, - const int walltimelimitseconds) -> bool { +auto do_timestep(const int nts, const int titer, Packet *packets, const int walltimelimitseconds) -> bool { + const auto my_rank = globals::my_rank; bool do_this_full_loop = true; - const int nts_prev = (titer != 0 || nts == 0) ? nts : nts - 1; if ((titer > 0) || (globals::simulation_continued_from_saved && (nts == globals::timestep_initial))) { // Read the packets file to reset before each additional iteration on the timestep - read_temp_packetsfile(nts, my_rank, packets); + read_temp_packetsfile(nts, globals::my_rank, packets); } // Some counters on pkt-actions need to be reset to do statistics @@ -695,13 +684,13 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns // Update the matter quantities in the grid for the new timestep. - update_grid(estimators_file, nts, nts_prev, my_rank, nstart, ndo, titer, real_time_start); + update_grid(estimators_file, nts, nts_prev, titer, real_time_start); const auto sys_time_start_communicate_grid = std::time(nullptr); -// Each process has now updated its own set of cells. The results now need to be communicated between processes. + // Each process has now updated its own set of cells. The results now need to be communicated between processes. #ifdef MPI_ON - mpi_communicate_grid_properties(my_rank, globals::nprocs, nstart, ndo); + mpi_communicate_grid_properties(); #endif printout("timestep %d: time after grid properties have been communicated %ld (took %ld seconds)\n", nts, @@ -711,7 +700,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns // write out a snapshot of the grid properties for further restarts // and update input.txt accordingly if (((nts - globals::timestep_initial) != 0)) { - save_grid_and_packets(nts, my_rank, packets); + save_grid_and_packets(nts, packets); do_this_full_loop = walltime_sufficient_to_continue(nts, nts_prev, walltimelimitseconds); } time_timestep_start = std::time(nullptr); @@ -727,7 +716,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns if ((nts < globals::timestep_finish) && do_this_full_loop) { // Now process the packets. - update_packets(my_rank, nts, std::span{packets, static_cast(globals::npkts)}); + update_packets(nts, std::span{packets, static_cast(globals::npkts)}); #ifdef MPI_ON // All the processes have their own versions of the estimators for this time step now. @@ -748,7 +737,7 @@ auto do_timestep(const int nts, const int titer, const int my_rank, const int ns normalise_deposition_estimators(nts); - write_deposition_file(nts, my_rank, nstart, ndo); + write_deposition_file(); write_partial_lightcurve_spectra(my_rank, nts, packets); @@ -831,7 +820,7 @@ auto main(int argc, char *argv[]) -> int { check_already_running(); - const int my_rank = globals::rank_global; + const int my_rank = globals::my_rank; #if defined(_OPENMP) && !defined(GPU_ON) // Explicitly turn off dynamic threads because we use the threadprivate directive!!! @@ -902,7 +891,7 @@ auto main(int argc, char *argv[]) -> int { #ifdef MPI_ON printout("process id (pid): %d\n", getpid()); printout("MPI enabled:\n"); - printout(" rank %d of [0..%d] in MPI_COMM_WORLD\n", globals::rank_global, globals::nprocs - 1); + printout(" rank %d of [0..%d] in MPI_COMM_WORLD\n", globals::my_rank, globals::nprocs - 1); printout(" rank %d of [0..%d] in node %d of [0..%d]\n", globals::rank_in_node, globals::node_nprocs - 1, globals::node_id, globals::node_count - 1); #ifdef MAX_NODE_SIZE @@ -958,7 +947,6 @@ auto main(int argc, char *argv[]) -> int { write_timestep_file(); } - // Initialise the grid. Set up the initial positions and sizes of the grid cells. printout("time grid_init %ld\n", std::time(nullptr)); grid::grid_init(my_rank); @@ -969,9 +957,6 @@ auto main(int argc, char *argv[]) -> int { if (!globals::simulation_continued_from_saved) { std::remove("deposition.out"); - // Next we want to initialise the packets. - // Create a bunch of npkts packets - // and write them to a binary file for later readin. packet_init(packets); zero_estimators(); } @@ -1004,7 +989,7 @@ auto main(int argc, char *argv[]) -> int { MPI_Barrier(MPI_COMM_WORLD); #endif - int nts = globals::timestep_initial; + globals::timestep = globals::timestep_initial; macroatom_open_file(my_rank); if (ndo > 0) { @@ -1018,10 +1003,9 @@ auto main(int argc, char *argv[]) -> int { } // initialise or read in virtual packet spectra - vpkt_init(nts, my_rank, globals::simulation_continued_from_saved); + vpkt_init(globals::timestep, my_rank, globals::simulation_continued_from_saved); - while (nts < globals::timestep_finish && !terminate_early) { - globals::timestep = nts; + while (globals::timestep < globals::timestep_finish && !terminate_early) { #ifdef MPI_ON // const auto time_before_barrier = std::time(nullptr); MPI_Barrier(MPI_COMM_WORLD); @@ -1034,18 +1018,18 @@ auto main(int argc, char *argv[]) -> int { // globals::n_titer = (nts < 6) ? 3: 1; globals::n_titer = 1; - globals::lte_iteration = (nts < globals::num_lte_timesteps); + globals::lte_iteration = (globals::timestep < globals::num_lte_timesteps); assert_always(globals::num_lte_timesteps > 0); // The first time step must solve the ionisation balance in LTE for (int titer = 0; titer < globals::n_titer; titer++) { - terminate_early = do_timestep(nts, titer, my_rank, nstart, ndo, packets, walltimelimitseconds); + terminate_early = do_timestep(globals::timestep, titer, packets, walltimelimitseconds); #ifdef DO_TITER // No iterations over the zeroth timestep, set titer > n_titer - if (nts == 0) titer = globals::n_titer + 1; + if (globals::timestep == 0) titer = globals::n_titer + 1; #endif } - nts++; + globals::timestep++; } // The main calculation is now over. The packets now have all stored the time, place and direction diff --git a/sn3d.h b/sn3d.h index 701803ad5..9daf317f5 100644 --- a/sn3d.h +++ b/sn3d.h @@ -130,11 +130,11 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f const bool assertpass = static_cast(e); \ if (!assertpass) { \ if (output_file) { \ - output_file << "\n[rank " << globals::rank_global << "] " << __FILE__ << ":" << __LINE__ \ - << ": failed assertion `" << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ + output_file << "\n[rank " << globals::my_rank << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ + << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ output_file.flush(); \ } \ - std::cerr << "\n[rank " << globals::rank_global << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ + std::cerr << "\n[rank " << globals::my_rank << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ std::abort(); \ } \ @@ -289,7 +289,7 @@ inline auto rng_uniform_pos() -> float { } inline void check_already_running() { - if (globals::rank_global == 0) { + if (globals::my_rank == 0) { const pid_t artispid = getpid(); if (std::filesystem::exists("artis.pid")) { diff --git a/thermalbalance.cc b/thermalbalance.cc index ca5b907bb..c46bc5ec1 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -170,7 +170,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d // Free-free heating (from estimators) - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); ffheating = globals::ffheatingestimator[nonemptymgi]; if constexpr (DIRECT_COL_HEAT) { @@ -196,7 +196,7 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { grid::set_Te(modelgridindex, T_e); if constexpr (!USE_LUT_PHOTOION && !LTEPOP_EXCITATION_USE_TJ) { - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); for (int element = 0; element < get_nelements(); element++) { if (!elem_has_nlte_levels(element)) { // recalculate the Gammas using the current population estimates @@ -270,7 +270,7 @@ auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, c // depends only the radiation field - no dependence on T_e or populations void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs) { bfheatingcoeffs.resize(get_includedlevels()); - const int nonemptymgi = grid::get_modelcell_nonemptymgi(modelgridindex); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const double minelfrac = 0.01; for (int element = 0; element < get_nelements(); element++) { if (grid::get_elem_abundance(modelgridindex, element) <= minelfrac && !USE_LUT_BFHEATING) { @@ -313,11 +313,10 @@ void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatin } } -void call_T_e_finder(const int modelgridindex, const int timestep, const double t_current, const double T_min, - const double T_max, HeatingCoolingRates *heatingcoolingrates, - const std::vector &bfheatingcoeffs) { +void call_T_e_finder(const int modelgridindex, const double t_current, const double T_min, const double T_max, + HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { const double T_e_old = grid::get_Te(modelgridindex); - printout("Finding T_e in cell %d at timestep %d...", modelgridindex, timestep); + printout("Finding T_e in cell %d at timestep %d...", modelgridindex, globals::timestep); Te_solution_paras paras = {.t_current = t_current, .modelgridindex = modelgridindex, diff --git a/thermalbalance.h b/thermalbalance.h index 91a44c73d..e10b98962 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -24,7 +24,7 @@ struct HeatingCoolingRates { double eps_alpha_ana{0}; }; -void call_T_e_finder(int modelgridindex, int timestep, double t_current, double T_min, double T_max, +void call_T_e_finder(int modelgridindex, double t_current, double T_min, double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs); [[nodiscard]] auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, double W) -> double; diff --git a/update_grid.cc b/update_grid.cc index dea7db065..449f29285 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -42,7 +42,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti return; } - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const auto sys_time_start_write_estimators = std::time(nullptr); @@ -90,7 +90,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } fprintf(estimators_file, " SUM: %9.3e", elpop); - decay::fprint_nuc_abundances(estimators_file, mgi, globals::timesteps[timestep].mid, element); + decay::fprint_nuc_abundances(estimators_file, nonemptymgi, globals::timesteps[timestep].mid, element); if (nions == 0 || elpop <= 0.) { // dummy element for nuclear abundances only @@ -675,7 +675,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } } -void solve_Te_nltepops(const int mgi, const int nts, const int titer, HeatingCoolingRates *heatingcoolingrates) +void solve_Te_nltepops(const int mgi, const int nts, const int nts_prev, HeatingCoolingRates *heatingcoolingrates) // nts is the timestep number { // bfheating coefficients are needed for the T_e solver, but @@ -706,11 +706,9 @@ void solve_Te_nltepops(const int mgi, const int nts, const int titer, HeatingCoo const double prev_T_e = grid::get_Te(mgi); const auto sys_time_start_Te = std::time(nullptr); - const int nts_for_te = (titer == 0) ? nts - 1 : nts; // Find T_e as solution for thermal balance - call_T_e_finder(mgi, nts, globals::timesteps[nts_for_te].mid, MINTEMP, MAXTEMP, heatingcoolingrates, - bfheatingcoeffs); + call_T_e_finder(mgi, globals::timesteps[nts_prev].mid, MINTEMP, MAXTEMP, heatingcoolingrates, bfheatingcoeffs); const int duration_solve_T_e = std::time(nullptr) - sys_time_start_Te; @@ -769,7 +767,7 @@ void solve_Te_nltepops(const int mgi, const int nts, const int titer, HeatingCoo } void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const double estimator_normfactor) { - const int nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); if constexpr (USE_LUT_PHOTOION) { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); @@ -882,7 +880,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in return; } - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const double deltaV = grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); @@ -894,8 +892,8 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in grid::set_rho(mgi, grid::get_rho_tmin(mgi) / pow(tratmid, 3)); // Update elemental abundances with radioactive decays - decay::update_abundances(mgi, nts, globals::timesteps[nts].mid); - nonthermal::calculate_deposition_rate_density(mgi, nts, heatingcoolingrates); + decay::update_abundances(nonemptymgi, nts, globals::timesteps[nts].mid); + nonthermal::calculate_deposition_rate_density(nonemptymgi, nts, heatingcoolingrates); if (globals::opacity_case == 6) { grid::calculate_kappagrey(); @@ -1010,7 +1008,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // full-spectrum and binned J and nuJ estimators radfield::fit_parameters(mgi, nts); - solve_Te_nltepops(mgi, nts, titer, heatingcoolingrates); + solve_Te_nltepops(mgi, nts, nts_prev, heatingcoolingrates); } printout("Temperature/NLTE solution for cell %d timestep %d took %ld seconds\n", mgi, nts, std::time(nullptr) - sys_time_start_temperature_corrections); @@ -1083,12 +1081,13 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } // anonymous namespace -void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const int my_rank, const int nstart, - const int ndo, const int titer, const std::time_t real_time_start) +void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const int titer, + const std::time_t real_time_start) // Subroutine to update the matter quantities in the grid cells at the start // of the new timestep. // nts timestep { + const auto my_rank = globals::my_rank; const auto sys_time_start_update_grid = std::time(nullptr); printout("\n"); printout("timestep %d: time before update grid %ld (tstart + %ld) simtime ts_mid %g days\n", nts, @@ -1118,6 +1117,8 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const radfield::normalise_bf_estimators(nts, nts_prev, titer, deltat); } + const int nstart = grid::get_nstart(my_rank); + const int ndo = grid::get_ndo(my_rank); #ifdef _OPENMP #pragma omp parallel #endif diff --git a/update_grid.h b/update_grid.h index bfe60a2b5..76a0d5d50 100644 --- a/update_grid.h +++ b/update_grid.h @@ -4,8 +4,7 @@ #include #include -void update_grid(FILE *estimators_file, int nts, int nts_prev, int my_rank, int nstart, int ndo, int titer, - time_t real_time_start); +void update_grid(FILE *estimators_file, int nts, int nts_prev, int titer, time_t real_time_start); void cellcache_change_cell(int modelgridindex); #endif // UPDATE_GRID_H diff --git a/update_packets.cc b/update_packets.cc index 5f893e748..c6529c676 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -30,7 +30,7 @@ namespace { void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { double en_deposited = pkt.e_cmf; const auto mgi = grid::get_cell_modelgridindex(pkt.where); - const auto nonemptymgi = grid::get_modelcell_nonemptymgi(mgi); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const auto priortype = pkt.type; const double ts = pkt.prop_time; const auto deposit_type = @@ -356,7 +356,7 @@ void do_cell_packet_updates(std::span packets, const int nts, const doub } // anonymous namespace // Move and update packets during the current timestep (nts) -void update_packets(const int my_rank, const int nts, std::span packets) { +void update_packets(const int nts, std::span packets) { // At the start, the packets have all either just been initialised or have already been // processed for one or more timesteps. Those that are pellets will just be sitting in the // matter. Those that are photons (or one sort or another) will already have a position and @@ -431,6 +431,6 @@ void update_packets(const int my_rank, const int nts, std::span packets) #endif printout( "timestep %d: time after update packets for all processes %ld (rank %d took %lds, waited %lds, total %lds)\n", - nts, std::time(nullptr), my_rank, time_update_packets_end_thisrank - time_update_packets_start, + nts, std::time(nullptr), globals::my_rank, time_update_packets_end_thisrank - time_update_packets_start, std::time(nullptr) - time_update_packets_end_thisrank, std::time(nullptr) - time_update_packets_start); } diff --git a/update_packets.h b/update_packets.h index 88c40f665..90d0d6681 100644 --- a/update_packets.h +++ b/update_packets.h @@ -5,6 +5,6 @@ #include "packet.h" -void update_packets(int my_rank, int nts, std::span packets); +void update_packets(int nts, std::span packets); #endif // UPDATE_PACKETS_H From a4c619ef30f18cb1624ff61b6f7abf6a3b948859 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 31 Oct 2024 14:20:55 +0000 Subject: [PATCH 076/117] Share modelgrid array on node (#141) Reduce MPI communication by sharing modelgrid, ion_groundlevelpops, ion_partfuncts, ion_cooling_contribs on node. Eliminate MPI_Pack calls and complicated buffer size calculation. --- decay.cc | 16 +-- grid.cc | 263 +++++++++++++++------------------------------- grid.h | 19 ++-- input.cc | 54 +--------- kpkt.cc | 21 ++-- kpkt.h | 2 +- ltepop.cc | 51 ++++++--- nltepop.cc | 24 +++-- nonthermal.cc | 39 ++----- packet.cc | 2 +- radfield.cc | 41 +++----- ratecoeff.cc | 36 +------ rpkt.cc | 33 ++---- sn3d.cc | 127 ++++------------------ sn3d.h | 44 ++++++++ thermalbalance.cc | 10 +- thermalbalance.h | 4 +- update_grid.cc | 41 ++++---- 18 files changed, 298 insertions(+), 529 deletions(-) diff --git a/decay.cc b/decay.cc index c3f7a0d89..5c3d91f41 100644 --- a/decay.cc +++ b/decay.cc @@ -730,7 +730,7 @@ auto get_simtime_endecay_per_ejectamass(const int nonemptymgi, const int decaypa return chainendecay; } -auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int modelgridindex, const double time) -> double +auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int nonemptymgi, const double time) -> double // total decay power per mass [erg/s/g] for a given decaypath { // only decays at the end of the chain contributed from the initial abundance of the top of the chain are counted @@ -739,6 +739,7 @@ auto get_decaypath_power_per_ejectamass(const int decaypathindex, const int mode const int z_top = decaypaths[decaypathindex].z[0]; const int a_top = decaypaths[decaypathindex].a[0]; const int nucindex_top = decaypaths[decaypathindex].nucindex[0]; + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double top_initabund = grid::get_modelinitnucmassfrac(modelgridindex, nucindex_top); assert_always(top_initabund >= 0.); @@ -1053,15 +1054,8 @@ void setup_decaypath_energy_per_mass() { nonempty_npts_model * get_num_decaypaths() * sizeof(double) / 1024. / 1024.); double *decaypath_energy_per_mass_data{nullptr}; #ifdef MPI_ON - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - auto size = static_cast(noderank_nonemptycellcount * get_num_decaypaths() * sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &decaypath_energy_per_mass_data, - &win_decaypath_energy_per_mass) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_decaypath_energy_per_mass, 0, &size, &disp_unit, - &decaypath_energy_per_mass_data) == MPI_SUCCESS); + std::tie(decaypath_energy_per_mass_data, win_decaypath_energy_per_mass) = + MPI_shared_malloc_keepwin(nonempty_npts_model * get_num_decaypaths()); #else decaypath_energy_per_mass_data = static_cast(malloc(nonempty_npts_model * get_num_decaypaths() * sizeof(double))); @@ -1422,7 +1416,7 @@ void setup_radioactive_pellet(const double e0, const int mgi, Packet &pkt) { get_simtime_endecay_per_ejectamass(nonemptymgi, decaypathindex) / (globals::tmax - tdecaymin); assert_always(avgpower > 0.); assert_always(std::isfinite(avgpower)); - pkt.e_cmf = e0 * get_decaypath_power_per_ejectamass(decaypathindex, mgi, pkt.tdecay) / avgpower; + pkt.e_cmf = e0 * get_decaypath_power_per_ejectamass(decaypathindex, nonemptymgi, pkt.tdecay) / avgpower; assert_always(pkt.e_cmf >= 0); assert_always(std::isfinite(pkt.e_cmf)); } diff --git a/grid.cc b/grid.cc index 52d80c705..086c1f1b8 100644 --- a/grid.cc +++ b/grid.cc @@ -85,7 +85,6 @@ std::vector ranks_nstart; std::vector ranks_nstart_nonempty; std::vector ranks_ndo; std::vector ranks_ndo_nonempty; -int maxndo = -1; void set_rho_tmin(const int modelgridindex, const float x) { modelgrid[modelgridindex].rhoinit = x; } @@ -119,8 +118,13 @@ void set_npts_model(const int new_npts_model) { npts_model = new_npts_model; assert_always(modelgrid.data() == nullptr); - modelgrid = std::span(static_cast(calloc(npts_model + 1, sizeof(ModelGridCell))), npts_model + 1); - assert_always(modelgrid.data() != nullptr); + modelgrid = MPI_shared_malloc_span(npts_model + 1); + if (globals::rank_in_node == 0) { + std::ranges::fill(modelgrid, ModelGridCell{}); + } +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif mg_associated_cells.resize(npts_model + 1, 0); nonemptymgi_of_mgi.resize(npts_model + 1, -1); } @@ -130,23 +134,16 @@ void allocate_initradiobund() { const ptrdiff_t num_nuclides = decay::get_num_nuclides(); - const size_t totalradioabundsize = (npts_model + 1) * num_nuclides * sizeof(float); + const size_t totalradioabundcount = (npts_model + 1) * num_nuclides; #ifdef MPI_ON - const auto [_, noderank_cells] = get_range_chunk(npts_model + 1, globals::node_nprocs, globals::rank_in_node); - - auto size = static_cast(noderank_cells * num_nuclides * sizeof(float)); - - int disp_unit = sizeof(float); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initnucmassfrac_allcells, &win_initnucmassfrac_allcells) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_initnucmassfrac_allcells, 0, &size, &disp_unit, &initnucmassfrac_allcells) == - MPI_SUCCESS); + std::tie(initnucmassfrac_allcells, win_initnucmassfrac_allcells) = + MPI_shared_malloc_keepwin(totalradioabundcount); #else - initnucmassfrac_allcells = static_cast(malloc(totalradioabundsize)); + initnucmassfrac_allcells = static_cast(malloc(totalradioabundcount * sizeof(float))); #endif printout( "[info] mem_usage: radioabundance data for %td nuclides for %td cells occupies %.3f MB (node shared memory)\n", - num_nuclides, npts_model, static_cast(totalradioabundsize) / 1024. / 1024.); + num_nuclides, npts_model, static_cast(totalradioabundcount * sizeof(float)) / 1024. / 1024.); #ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); @@ -272,107 +269,34 @@ void allocate_nonemptycells_composition_cooling() const ptrdiff_t npts_nonempty = get_nonempty_npts_model(); const auto nelements = get_nelements(); -#ifdef MPI_ON - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - - { - auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win mpiwin = MPI_WIN_NULL; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &initmassfracuntrackedstable_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &initmassfracuntrackedstable_allcells) == - MPI_SUCCESS); - } - - { - auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win mpiwin = MPI_WIN_NULL; - - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &elem_meanweight_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_meanweight_allcells) == MPI_SUCCESS); - MPI_Barrier(globals::mpi_comm_node); - } - - { - auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(int)); - int disp_unit = sizeof(int); - MPI_Win mpiwin = MPI_WIN_NULL; - - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &elements_uppermost_ion_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elements_uppermost_ion_allcells) == MPI_SUCCESS); - MPI_Barrier(globals::mpi_comm_node); - } - - { - auto size = static_cast(noderank_nonemptycellcount * nelements * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win mpiwin = MPI_WIN_NULL; - - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &elem_massfracs_allcells, &mpiwin) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &elem_massfracs_allcells) == MPI_SUCCESS); - MPI_Barrier(globals::mpi_comm_node); - } -#else - initmassfracuntrackedstable_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); - elem_meanweight_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); - elements_uppermost_ion_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(int))); - elem_massfracs_allcells = static_cast(malloc(npts_nonempty * nelements * sizeof(float))); -#endif + initmassfracuntrackedstable_allcells = MPI_shared_malloc(npts_nonempty * nelements); + elem_meanweight_allcells = MPI_shared_malloc(npts_nonempty * nelements); + elements_uppermost_ion_allcells = MPI_shared_malloc(npts_nonempty * nelements); + elem_massfracs_allcells = MPI_shared_malloc(npts_nonempty * nelements); + ion_groundlevelpops_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); + ion_partfuncts_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); + ion_cooling_contribs_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); if (globals::total_nlte_levels > 0) { #ifdef MPI_ON - auto size = static_cast(noderank_nonemptycellcount * globals::total_nlte_levels * sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nltepops_allcells, - &win_nltepops_allcells) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_nltepops_allcells, 0, &size, &disp_unit, &nltepops_allcells) == MPI_SUCCESS); - - MPI_Barrier(globals::mpi_comm_node); + std::tie(nltepops_allcells, win_nltepops_allcells) = + MPI_shared_malloc_keepwin(npts_nonempty * globals::total_nlte_levels); #else nltepops_allcells = static_cast(malloc(npts_nonempty * globals::total_nlte_levels * sizeof(double))); #endif assert_always(nltepops_allcells != nullptr); + } else { + nltepops_allcells = nullptr; } - for (ptrdiff_t nonemptymgi = 0; nonemptymgi < npts_nonempty; nonemptymgi++) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - - if (globals::total_nlte_levels > 0) { - // -1 indicates that there is currently no information on the nlte populations - std::ranges::fill_n(&grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels)], - globals::total_nlte_levels, -1.); - } - - std::fill_n(&elem_massfracs_allcells[nonemptymgi * nelements], nelements, -1.); - - modelgrid[modelgridindex].ion_groundlevelpops = static_cast(calloc(get_includedions(), sizeof(float))); - if (modelgrid[modelgridindex].ion_groundlevelpops == nullptr) { - printout("[fatal] input: not enough memory to initialize ion_groundlevelpops in cell %d... abort\n", - modelgridindex); - std::abort(); - } - - modelgrid[modelgridindex].ion_partfuncts = static_cast(calloc(get_includedions(), sizeof(float))); - - if (modelgrid[modelgridindex].ion_partfuncts == nullptr) { - printout("[fatal] input: not enough memory to initialize partfunctlist in cell %d... abort\n", modelgridindex); - std::abort(); - } - - modelgrid[modelgridindex].ion_cooling_contribs = static_cast(malloc(get_includedions() * sizeof(double))); - - if (modelgrid[modelgridindex].ion_cooling_contribs == nullptr) { - printout("[fatal] input: not enough memory to initialize ion_cooling_contribs for cell %d... abort\n", - modelgridindex); - std::abort(); - } + if (globals::rank_in_node == 0) { + std::fill_n(initmassfracuntrackedstable_allcells, npts_nonempty * nelements, -1.); + std::fill_n(elem_meanweight_allcells, npts_nonempty * nelements, -1.); + std::fill_n(elements_uppermost_ion_allcells, npts_nonempty * nelements, -1); + std::fill_n(elem_massfracs_allcells, npts_nonempty * nelements, -1.); + // -1 indicates that there is currently no information on the nlte populations + std::ranges::fill_n(grid::nltepops_allcells, npts_nonempty * globals::total_nlte_levels, -1.); } } @@ -380,7 +304,9 @@ void allocate_nonemptymodelcells() { // Determine the number of simulation cells associated with the model cells for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { mg_associated_cells[mgi] = 0; - modelgrid[mgi].initial_radial_pos_sum = 0.; + if (globals::rank_in_node == 0) { + modelgrid[mgi].initial_radial_pos_sum = 0.; + } } for (int cellindex = 0; cellindex < ngrid; cellindex++) { @@ -396,7 +322,9 @@ void allocate_nonemptymodelcells() { assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); mg_associated_cells[mgi] += 1; - modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; + if (globals::rank_in_node == 0) { + modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; + } assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || (mgi == get_npts_model())); @@ -405,7 +333,7 @@ void allocate_nonemptymodelcells() { // find number of non-empty cells and allocate nonempty list nonempty_npts_model = 0; for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_numassociatedcells(mgi) > 0) { + if (get_numpropcells(mgi) > 0) { nonempty_npts_model++; } } @@ -416,7 +344,7 @@ void allocate_nonemptymodelcells() { int nonemptymgi = 0; // index within list of non-empty modelgrid cells for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_numassociatedcells(mgi) > 0) { + if (get_numpropcells(mgi) > 0) { if (get_rho_tmin(mgi) <= 0) { printout("Error: negative or zero density. Abort.\n"); std::abort(); @@ -450,16 +378,8 @@ void allocate_nonemptymodelcells() { if (ionestimsize > 0) { #ifdef MPI_ON - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - - auto size = static_cast(noderank_nonemptycellcount * globals::nbfcontinua_ground * sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &globals::corrphotoionrenorm, - &globals::win_corrphotoionrenorm) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(globals::win_corrphotoionrenorm, 0, &size, &disp_unit, - &globals::corrphotoionrenorm) == MPI_SUCCESS); + std::tie(globals::corrphotoionrenorm, globals::win_corrphotoionrenorm) = + MPI_shared_malloc_keepwin(ionestimcount); #else globals::corrphotoionrenorm = static_cast(malloc(ionestimsize)); #endif @@ -606,7 +526,7 @@ void abundances_read() { abundances_in[anumber - 1] = 0.; if (!(ssline >> abund_in)) { // at least one element (hydrogen) should have been specified for nonempty cells - assert_always(anumber > 1 || get_numassociatedcells(mgi) == 0); + assert_always(anumber > 1 || get_numpropcells(mgi) == 0); break; } @@ -618,7 +538,7 @@ void abundances_read() { normfactor += abundances_in[anumber - 1]; } - if (get_numassociatedcells(mgi) > 0) { + if (get_numpropcells(mgi) > 0) { if (threedimensional || normfactor <= 0.) { normfactor = 1.; } @@ -1085,6 +1005,26 @@ void read_3d_model() { printout("min_den %g [g/cm3]\n", min_den); } +auto get_inputcellvolume(const int mgi) -> double { + if (get_model_type() == GridType::SPHERICAL1D) { + const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; + // mass_in_shell = rho_model[mgi] * (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(t_model, 3) / 3.; + return (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(globals::tmin, 3) / 3.; + } + if (get_model_type() == GridType::CYLINDRICAL2D) { + const int n_r = mgi % ncoord_model[0]; + const double dcoord_rcyl = globals::vmax * t_model / ncoord_model[0]; // dr 2D for input model + const double dcoord_z = 2. * globals::vmax * t_model / ncoord_model[1]; // dz 2D for input model + return pow(globals::tmin / t_model, 3) * dcoord_z * PI * + (pow((n_r + 1) * dcoord_rcyl, 2.) - pow(n_r * dcoord_rcyl, 2.)); + } + if (get_model_type() == GridType::CARTESIAN3D) { + // Assumes cells are cubes here - all same volume. + return pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); + } + assert_always(false); +} + void calc_modelinit_totmassradionuclides() { mtot_input = 0.; mfegroup = 0.; @@ -1098,47 +1038,18 @@ void calc_modelinit_totmassradionuclides() { totmassradionuclide[nucindex] = 0.; } - const double dcoord_rcyl = globals::vmax * t_model / ncoord_model[0]; // dr for input model - const double dcoord_z = 2. * globals::vmax * t_model / ncoord_model[1]; // dz for input model - for (int mgi = 0; mgi < get_npts_model(); mgi++) { - if (get_rho_tmin(mgi) <= 0.) { - continue; - } - double cellvolume = 0.; - if (get_model_type() == GridType::SPHERICAL1D) { - const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; - // mass_in_shell = rho_model[mgi] * (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(t_model, 3) / 3.; - cellvolume = (pow(vout_model[mgi], 3) - pow(v_inner, 3)) * 4 * PI * pow(globals::tmin, 3) / 3.; - } else if (get_model_type() == GridType::CYLINDRICAL2D) { - const int n_r = mgi % ncoord_model[0]; - cellvolume = pow(globals::tmin / t_model, 3) * dcoord_z * PI * - (pow((n_r + 1) * dcoord_rcyl, 2.) - pow(n_r * dcoord_rcyl, 2.)); - } else if (get_model_type() == GridType::CARTESIAN3D) { - // Assumes cells are cubes here - all same volume. - cellvolume = pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); - } else { - assert_always(false); - } + const double mass_in_shell = get_rho_tmin(mgi) * get_inputcellvolume(mgi); + if (mass_in_shell > 0) { + mtot_input += mass_in_shell; - const double mass_in_shell = get_rho_tmin(mgi) * cellvolume; - - mtot_input += mass_in_shell; + for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { + totmassradionuclide[nucindex] += mass_in_shell * get_modelinitnucmassfrac(mgi, nucindex); + } - for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { - totmassradionuclide[nucindex] += mass_in_shell * get_modelinitnucmassfrac(mgi, nucindex); + mfegroup += mass_in_shell * get_ffegrp(mgi); } - - mfegroup += mass_in_shell * get_ffegrp(mgi); } - - printout("Total input model mass: %9.3e [Msun]\n", mtot_input / MSUN); - printout("Nuclide masses at t=t_model_init [Msun]:"); - printout(" 56Ni: %9.3e 56Co: %9.3e 52Fe: %9.3e 48Cr: %9.3e\n", get_totmassradionuclide(28, 56) / MSUN, - get_totmassradionuclide(27, 56) / MSUN, get_totmassradionuclide(26, 52) / MSUN, - get_totmassradionuclide(24, 48) / MSUN); - printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfegroup / MSUN, get_totmassradionuclide(28, 57) / MSUN, - get_totmassradionuclide(27, 57) / MSUN); } void read_grid_restart_data(const int timestep) { @@ -1286,7 +1197,7 @@ void assign_initial_temperatures() { // start at mgi_start and find the next non-empty cell, or return -1 if none found [[nodiscard]] auto get_next_nonemptymgi(const int mgi_start) -> int { for (int mgi = mgi_start; mgi < get_npts_model(); mgi++) { - if (get_numassociatedcells(mgi) > 0) { + if (get_numpropcells(mgi) > 0) { return nonemptymgi_of_mgi[mgi]; } } @@ -1298,7 +1209,6 @@ void setup_nstart_ndo() { const int npts_nonempty = get_nonempty_npts_model(); const int min_nonempty_perproc = npts_nonempty / nprocesses; // integer division, minimum non-empty cells per process const int n_remainder = npts_nonempty % nprocesses; - maxndo = 0; ranks_nstart.resize(nprocesses, -1); ranks_nstart_nonempty.resize(nprocesses, -1); @@ -1313,14 +1223,13 @@ void setup_nstart_ndo() { if (nprocesses >= get_npts_model()) { // for convenience, rank == mgi when there is at least one rank per cell - maxndo = 1; for (int rank = 0; rank < nprocesses; rank++) { if (rank < get_npts_model()) { const int mgi = rank; ranks_nstart[rank] = mgi; ranks_ndo[rank] = 1; - ranks_nstart_nonempty[rank] = (get_numassociatedcells(mgi) > 0) ? get_nonemptymgi_of_mgi(mgi) : 0; - ranks_ndo_nonempty[rank] = (get_numassociatedcells(mgi) > 0) ? 1 : 0; + ranks_nstart_nonempty[rank] = (get_numpropcells(mgi) > 0) ? get_nonemptymgi_of_mgi(mgi) : 0; + ranks_ndo_nonempty[rank] = (get_numpropcells(mgi) > 0) ? 1 : 0; } } } else { @@ -1338,8 +1247,7 @@ void setup_nstart_ndo() { } ranks_ndo[rank]++; - maxndo = std::max(maxndo, ranks_ndo[rank]); - if (get_numassociatedcells(mgi) > 0) { + if (get_numpropcells(mgi) > 0) { ranks_ndo_nonempty[rank]++; } } @@ -1692,7 +1600,7 @@ auto wid_init(const int cellindex, const int axis) -> double auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double { if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return (wid_init(modelgridindex, 0) * wid_init(modelgridindex, 1) * wid_init(modelgridindex, 2)) * - get_numassociatedcells(modelgridindex); + get_numpropcells(modelgridindex); } if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { @@ -1954,7 +1862,7 @@ __host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { } // number of propagation cells associated with each modelgrid cell -__host__ __device__ auto get_numassociatedcells(const int modelgridindex) -> int { +__host__ __device__ auto get_numpropcells(const int modelgridindex) -> int { assert_testmodeonly(modelgridindex <= get_npts_model()); return mg_associated_cells[modelgridindex]; } @@ -1965,7 +1873,7 @@ __host__ __device__ auto get_nonemptymgi_of_mgi(const int mgi) -> int { assert_testmodeonly(mgi < get_npts_model()); const int nonemptymgi = nonemptymgi_of_mgi[mgi]; - // assert_testmodeonly(nonemptymgi >= 0 || get_numassociatedcells(mgi) == 0); + // assert_testmodeonly(nonemptymgi >= 0 || get_numpropcells(mgi) == 0); assert_testmodeonly(nonemptymgi >= 0); assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); @@ -2015,8 +1923,8 @@ void set_element_meanweight(const int nonemptymgi, const int element, const floa elem_meanweight_allcells[(static_cast(nonemptymgi) * get_nelements()) + element] = meanweight; } -auto get_electronfrac(const int modelgridindex) -> double { - const auto nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); +auto get_electronfrac(const int nonemptymgi) -> double { + const auto modelgridindex = get_mgi_of_nonemptymgi(nonemptymgi); double nucleondens = 0.; for (int element = 0; element < get_nelements(); element++) { nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(nonemptymgi, element) / MH; @@ -2211,6 +2119,14 @@ void read_ejecta_model() { calc_modelinit_totmassradionuclides(); + printout("Total input model mass: %9.3e [Msun]\n", mtot_input / MSUN); + printout("Nuclide masses at t=t_model_init [Msun]:"); + printout(" 56Ni: %9.3e 56Co: %9.3e 52Fe: %9.3e 48Cr: %9.3e\n", get_totmassradionuclide(28, 56) / MSUN, + get_totmassradionuclide(27, 56) / MSUN, get_totmassradionuclide(26, 52) / MSUN, + get_totmassradionuclide(24, 48) / MSUN); + printout(" Fe-group: %9.3e 57Ni: %9.3e 57Co: %9.3e\n", mfegroup / MSUN, get_totmassradionuclide(28, 57) / MSUN, + get_totmassradionuclide(27, 57) / MSUN); + read_possible_yefile(); } @@ -2269,13 +2185,6 @@ void write_grid_restart_data(const int timestep) { printout("done in %ld seconds.\n", std::time(nullptr) - sys_time_start_write_restart); } -auto get_maxndo() -> int { - if (ranks_ndo.empty()) { - setup_nstart_ndo(); - } - return maxndo; -} - auto get_nstart(const int rank) -> int { if (ranks_ndo.empty()) { setup_nstart_ndo(); diff --git a/grid.h b/grid.h index c8bd2ed84..332e631be 100644 --- a/grid.h +++ b/grid.h @@ -30,13 +30,10 @@ struct ModelGridCell { float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] float ffegrp = 0.; float kappagrey = 0.; - float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell - // This is only stored to print it outside the OpenMP loop in update_grid to the - // estimatorsfile so there is no need to communicate it via MPI so far! - float *ion_groundlevelpops{}; // groundlevel populations of all included ions - float *ion_partfuncts{}; // partition functions for all included ions + float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell + // This is only stored to print it outside the OpenMP loop in update_grid to the + // estimatorsfile so there is no need to communicate it via MPI so far! double totalcooling = -1; - double *ion_cooling_contribs{}; int thick = 0; }; @@ -64,6 +61,9 @@ inline float *elem_meanweight_allcells{}; inline float *elem_massfracs_allcells; // mass fractions of elements in each cell for the current timestep inline double *nltepops_allcells{}; +inline float *ion_groundlevelpops_allcells{}; +inline float *ion_partfuncts_allcells{}; +inline double *ion_cooling_contribs_allcells{}; [[nodiscard]] auto get_elements_uppermost_ion(int modelgridindex, int element) -> int; void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); @@ -103,8 +103,8 @@ void grid_init(int my_rank); [[nodiscard]] auto get_element_meanweight(int nonemptymgi, int element) -> float; [[nodiscard]] auto get_elem_abundance(int modelgridindex, int element) -> float; void set_element_meanweight(int nonemptymgi, int element, float meanweight); -[[nodiscard]] auto get_electronfrac(int modelgridindex) -> double; -[[nodiscard]] auto get_numassociatedcells(int modelgridindex) -> int; +[[nodiscard]] auto get_electronfrac(int nonemptymgi) -> double; +[[nodiscard]] auto get_numpropcells(int modelgridindex) -> int; [[nodiscard]] auto get_nonemptymgi_of_mgi(int mgi) -> int; [[nodiscard]] auto get_mgi_of_nonemptymgi(int nonemptymgi) -> int; [[nodiscard]] auto get_model_type() -> GridType; @@ -116,7 +116,6 @@ void set_model_type(GridType model_type_value); [[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, double time) -> int; void read_ejecta_model(); void write_grid_restart_data(int timestep); -[[nodiscard]] auto get_maxndo() -> int; [[nodiscard]] auto get_nstart(int rank) -> int; [[nodiscard]] auto get_nstart_nonempty(int rank) -> int; [[nodiscard]] auto get_ndo(int rank) -> int; @@ -149,7 +148,7 @@ inline auto get_ejecta_kinetic_energy() { double E_kin = 0.; for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const int assoc_cells = grid::get_numassociatedcells(mgi); + const int assoc_cells = grid::get_numpropcells(mgi); double M_cell = grid::get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); const double radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum / assoc_cells; E_kin += 0.5 * M_cell * std::pow(radial_pos / globals::tmin, 2); diff --git a/input.cc b/input.cc index b0c34c793..a93d88fb7 100644 --- a/input.cc +++ b/input.cc @@ -899,18 +899,7 @@ void read_phixs_data() { // copy the photoionisation tables into one contiguous block of memory #ifdef MPI_ON - MPI_Win win_allphixsblock = MPI_WIN_NULL; - - const auto [_, noderank_points] = - get_range_chunk(std::ssize(tmpallphixs), globals::node_nprocs, globals::rank_in_node); - - auto size = static_cast(noderank_points * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &globals::allphixs, - &win_allphixsblock); - MPI_Win_shared_query(win_allphixsblock, MPI_PROC_NULL, &size, &disp_unit, &globals::allphixs); - - MPI_Barrier(MPI_COMM_WORLD); + globals::allphixs = MPI_shared_malloc(tmpallphixs.size()); #else globals::allphixs = static_cast(malloc(tmpallphixs.size() * sizeof(float))); #endif @@ -1189,16 +1178,8 @@ void read_atomicdata_files() { assert_always(totupdowntrans == static_cast(temp_alltranslist_size)); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); - MPI_Win win_alltransblock = MPI_WIN_NULL; - const auto [_, noderank_trans] = get_range_chunk(totupdowntrans, globals::node_nprocs, globals::rank_in_node); - - auto size = static_cast(noderank_trans * sizeof(LevelTransition)); - int disp_unit = sizeof(LevelTransition); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &globals::alltrans, - &win_alltransblock); - - MPI_Win_shared_query(win_alltransblock, 0, &size, &disp_unit, &globals::alltrans); + globals::alltrans = MPI_shared_malloc(totupdowntrans); #else globals::alltrans = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); #endif @@ -1211,22 +1192,11 @@ void read_atomicdata_files() { // create a linelist shared on node and then copy data across, freeing the local copy TransitionLine *nonconstlinelist{}; - { #ifdef MPI_ON - MPI_Win win_nonconstlinelist = MPI_WIN_NULL; - - const auto [_, noderank_lines] = get_range_chunk(globals::nlines, globals::node_nprocs, globals::rank_in_node); - - MPI_Aint size = noderank_lines * static_cast(sizeof(TransitionLine)); - int disp_unit = sizeof(TransitionLine); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &nonconstlinelist, - &win_nonconstlinelist); - - MPI_Win_shared_query(win_nonconstlinelist, 0, &size, &disp_unit, &nonconstlinelist); + nonconstlinelist = MPI_shared_malloc(globals::nlines); #else - nonconstlinelist = static_cast(malloc(globals::nlines * sizeof(TransitionLine))); + nonconstlinelist = static_cast(malloc(globals::nlines * sizeof(TransitionLine))); #endif - } if (globals::rank_in_node == 0) { memcpy(static_cast(nonconstlinelist), temp_linelist.data(), globals::nlines * sizeof(TransitionLine)); @@ -1242,22 +1212,6 @@ void read_atomicdata_files() { printout("[info] mem_usage: linelist occupies %.3f MB (node shared memory)\n", globals::nlines * sizeof(TransitionLine) / 1024. / 1024); - // Save sorted linelist into a file - // if (rank_global == 0) - // { - // FILE *linelist_file = fopen_required("linelist.dat", "w"); - // fprintf(linelist_file,"%d\n",nlines); - // for (int i = 0; i < nlines; i++) - // { - // fprintf(linelist_file,"%d %d %d %d %d %lg %lg %lg %lg %d\n", - // i, globals::linelist[i].elementindex, globals::linelist[i].ionindex, - // globals::linelist[i].upperlevelindex, globals::linelist[i].lowerlevelindex, - // globals::linelist[i].nu, globals::linelist[i].einstein_A, globals::linelist[i].osc_strength, - // globals::linelist[i].coll_str, globals::linelist[i].forbidden); - // } - // fclose(linelist_file); - // } - printout("establishing connection between transitions and sorted linelist...\n"); auto const time_start_establish_linelist_connections = std::time(nullptr); diff --git a/kpkt.cc b/kpkt.cc index 5efcc5d5a..214772190 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -256,22 +256,25 @@ auto sample_planck_montecarlo(const double T) -> double { // Calculate the cooling rates for a given cell and store them for each ion // optionally store components (ff, bf, collisional) in heatingcoolingrates struct -void calculate_cooling_rates(const int modelgridindex, HeatingCoolingRates *heatingcoolingrates) { +void calculate_cooling_rates(const int nonemptymgi, HeatingCoolingRates *heatingcoolingrates) { + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double C_ff_all = 0.; // free-free creation of rpkts double C_fb_all = 0.; // free-bound creation of rpkt double C_exc_all = 0.; // collisional excitation of macroatoms double C_ionization_all = 0.; // collisional ionisation of macroatoms for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { const auto [element, ion] = get_ionfromuniqueionindex(allionindex); - grid::modelgrid[modelgridindex].ion_cooling_contribs[allionindex] = calculate_cooling_rates_ion( - modelgridindex, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, &C_exc_all, &C_ionization_all); + grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + allionindex] = + calculate_cooling_rates_ion(modelgridindex, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, + &C_exc_all, &C_ionization_all); } // this loop is made separate for future parallelisation of upper loop. // the ion contributions must be added in this exact order double C_total = 0.; for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { - C_total += grid::modelgrid[modelgridindex].ion_cooling_contribs[allionindex]; + C_total += + grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + allionindex]; } grid::modelgrid[modelgridindex].totalcooling = C_total; @@ -400,6 +403,7 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { const double t1 = pkt.prop_time; const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // don't calculate cooling rates after each cell crossings any longer // but only if we really get a kpkt and they hadn't been calculated already @@ -432,7 +436,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { const int nions = get_nions(element); for (ion = 0; ion < nions; ion++) { const int uniqueionindex = get_uniqueionindex(element, ion); - coolingsum += grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]; + coolingsum += grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + + uniqueionindex]; // printout("Z=%d, ionstage %d, coolingsum %g\n", get_atomicnumber(element), get_ionstage(element, ion), // coolingsum); if (coolingsum > rndcool_ion) { @@ -456,7 +461,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { for (ion = 0; ion < nions; ion++) { const int uniqueionindex = get_uniqueionindex(element, ion); printout("do_kpkt: element %d, ion %d, coolingcontr %g\n", element, ion, - grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]); + grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + + uniqueionindex]); } } std::abort(); @@ -475,7 +481,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { nullptr, nullptr, nullptr); assert_testmodeonly( (std::fabs(C_ion_procsum - - grid::modelgrid[modelgridindex].ion_cooling_contribs[get_uniqueionindex(element, ion)]) / + grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + + get_uniqueionindex(element, ion)]) / C_ion_procsum) < 1e-3); } diff --git a/kpkt.h b/kpkt.h index 3c3a35125..abe0a1195 100644 --- a/kpkt.h +++ b/kpkt.h @@ -14,7 +14,7 @@ inline int ncoolingterms{0}; auto get_ncoolingterms() -> int; void setup_coolinglist(); void set_kpktdiffusion(float kpktdiffusion_timescale_in, int n_kpktdiffusion_timesteps_in); -void calculate_cooling_rates(int modelgridindex, HeatingCoolingRates *heatingcoolingrates); +void calculate_cooling_rates(int nonemptymgi, HeatingCoolingRates *heatingcoolingrates); void do_kpkt_blackbody(Packet &pkt); void do_kpkt(Packet &pkt, double t2, int nts); diff --git a/ltepop.cc b/ltepop.cc index 3206d5215..28c407a2e 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -46,9 +47,12 @@ auto interpolate_ions_spontrecombcoeff(const int uniqueionindex, const double T) // use Saha equation for LTE ionization balance auto phi_lte(const int element, const int ion, const int modelgridindex) -> double { + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int uniqueionindex = get_uniqueionindex(element, ion); - const auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; - const auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; + const auto partfunc_ion = + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; + const auto partfunc_upperion = + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex + 1]; const auto T_e = grid::get_Te(modelgridindex); const double ionpot = epsilon(element, ion + 1, 0) - epsilon(element, ion, 0); @@ -69,7 +73,8 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, assert_testmodeonly(!elem_has_nlte_levels(element)); // don't use this function if the NLTE solver is active const int uniqueionindex = get_uniqueionindex(element, ion); - const auto partfunc_ion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; + const auto partfunc_ion = + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; const auto T_e = grid::get_Te(modelgridindex); @@ -97,7 +102,8 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, // Y_nt should generally be higher than the Gamma term for nebular epoch if (!std::isfinite(phi) || phi == 0.) { - const auto partfunc_upperion = grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex + 1]; + const auto partfunc_upperion = + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex + 1]; printout( "[fatal] phi: phi %g exceeds numerically possible range for element %d, ion %d, T_e %g ... remove higher or " "lower ionisation stages\n", @@ -228,9 +234,11 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin // Calculates the partition function for ion=ion of element=element in // cell modelgridindex { + ; assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); double pop_store{NAN}; const int uniqueionindex = get_uniqueionindex(element, ion); @@ -242,7 +250,8 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin // of groundlevelpop for this calculation doesn't matter, so long as it's not zero! pop_store = get_groundlevelpop(modelgridindex, element, ion); initial = true; - grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = 1.; + grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = + 1.; } double U = 1.; @@ -266,7 +275,8 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin if (initial) { // put back the zero, just in case it matters for something - grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = pop_store; + grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = + pop_store; } return U; @@ -329,6 +339,7 @@ void set_calculated_nne(const int modelgridindex) { // Special case of only neutral ions, set nne to some finite value so that packets are not lost in kpkts void set_groundlevelpops_neutral(const int modelgridindex) { + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); printout("[warning] calculate_ion_balance_nne: only neutral ions in cell modelgridindex %d\n", modelgridindex); for (int element = 0; element < get_nelements(); element++) { const auto nnelement = grid::get_elem_numberdens(modelgridindex, element); @@ -345,9 +356,11 @@ void set_groundlevelpops_neutral(const int modelgridindex) { nnion = 0.; } const double groundpop = - (nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]); + (nnion * stat_weight(element, ion, 0) / + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]); - grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = groundpop; + grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = + groundpop; } } } @@ -457,8 +470,9 @@ auto get_groundlevelpop(const int modelgridindex, const int element, const int i assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); - - const double nn = grid::modelgrid[modelgridindex].ion_groundlevelpops[get_uniqueionindex(element, ion)]; + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double nn = grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + + get_uniqueionindex(element, ion)]; if (nn < MINPOP) { if (grid::get_elem_abundance(modelgridindex, element) > 0) { return MINPOP; @@ -524,10 +538,11 @@ __host__ __device__ auto get_levelpop(const int modelgridindex, const int elemen // taken out of calculate_ion_balance_nne to save runtime. // TODO: not true if LTEPOP_EXCITATION_USE_TJ is true unless LTE mode only (TJ=TR=Te) void calculate_cellpartfuncts(const int modelgridindex, const int element) { + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] = - calculate_partfunct(element, ion, modelgridindex); + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + + get_uniqueionindex(element, ion)] = calculate_partfunct(element, ion, modelgridindex); } } @@ -549,8 +564,11 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co // Use the ground level population and partition function to get an ion population [[nodiscard]] __host__ __device__ auto get_nnion(const int modelgridindex, const int element, const int ion) -> double { + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + return get_groundlevelpop(modelgridindex, element, ion) * - grid::modelgrid[modelgridindex].ion_partfuncts[get_uniqueionindex(element, ion)] / + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + + get_uniqueionindex(element, ion)] / stat_weight(element, ion, 0); } @@ -562,6 +580,7 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa if (nions <= 0) { return; } + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // calculate number density of the current element (abundances are given by mass) const double nnelement = grid::get_elem_numberdens(modelgridindex, element); @@ -588,13 +607,15 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa } const double groundpop = - nnion * stat_weight(element, ion, 0) / grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex]; + nnion * stat_weight(element, ion, 0) / + grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; if (!std::isfinite(groundpop)) { printout("[warning] calculate_ion_balance_nne: groundlevelpop infinite in connection with MINPOP\n"); } - grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex] = groundpop; + grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = + groundpop; } } diff --git a/nltepop.cc b/nltepop.cc index aa6d30022..13b8bb448 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -800,6 +800,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // (ionisation balance follows from this too) { const int atomic_number = get_atomicnumber(element); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if (grid::get_elem_abundance(modelgridindex, element) <= 0.) { // abundance of this element is zero, so do not store any NLTE populations @@ -1042,8 +1043,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } // store the ground level population - grid::modelgrid[modelgridindex].ion_groundlevelpops[get_uniqueionindex(element, ion)] = - gsl_vector_get(&popvec, index_gs); + grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + + get_uniqueionindex(element, ion)] = gsl_vector_get(&popvec, index_gs); // solution_ion_pop += gsl_vector_get(popvec, index_gs); calculate_cellpartfuncts(modelgridindex, element); @@ -1192,8 +1193,9 @@ void nltepop_write_restart_data(FILE *restart_file) { fprintf(restart_file, "%d\n", 75618527); // special number marking the beginning of nlte data fprintf(restart_file, "%d\n", globals::total_nlte_levels); + const auto nincludedions = get_includedions(); - for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); fprintf(restart_file, "%d %la\n", modelgridindex, grid::modelgrid[modelgridindex].totalcooling); for (int element = 0; element < get_nelements(); element++) { @@ -1201,9 +1203,9 @@ void nltepop_write_restart_data(FILE *restart_file) { for (int ion = 0; ion < nions; ion++) { const int uniqueionindex = get_uniqueionindex(element, ion); fprintf(restart_file, "%d %a %a %la\n", ion, - grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex], - grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex], - grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]); + grid::ion_groundlevelpops_allcells[(nonemptymgi * nincludedions) + uniqueionindex], + grid::ion_partfuncts_allcells[(nonemptymgi * nincludedions) + uniqueionindex], + grid::ion_cooling_contribs_allcells[(nonemptymgi * nincludedions) + uniqueionindex]); } } for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { @@ -1229,8 +1231,9 @@ void nltepop_read_restart_data(FILE *restart_file) { total_nlte_levels_in); std::abort(); } + const auto nincludedions = get_includedions(); - for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); int mgi_in = 0; assert_always(fscanf(restart_file, "%d %la\n", &mgi_in, &grid::modelgrid[modelgridindex].totalcooling) == 2); @@ -1245,9 +1248,10 @@ void nltepop_read_restart_data(FILE *restart_file) { int ion_in = 0; const int uniqueionindex = get_uniqueionindex(element, ion); assert_always(fscanf(restart_file, "%d %a %a %la\n", &ion_in, - &grid::modelgrid[modelgridindex].ion_groundlevelpops[uniqueionindex], - &grid::modelgrid[modelgridindex].ion_partfuncts[uniqueionindex], - &grid::modelgrid[modelgridindex].ion_cooling_contribs[uniqueionindex]) == 4); + &grid::ion_groundlevelpops_allcells[(nonemptymgi * nincludedions) + uniqueionindex], + &grid::ion_partfuncts_allcells[(nonemptymgi * nincludedions) + uniqueionindex], + &grid::ion_cooling_contribs_allcells[(nonemptymgi * nincludedions) + uniqueionindex]) == + 4); if (ion_in != ion) { printout("ERROR: expected data for ion %d but found ion %d\n", ion, ion_in); std::abort(); diff --git a/nonthermal.cc b/nonthermal.cc index a48b5a965..614119e66 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1387,7 +1387,7 @@ auto get_eff_ionpot(const int modelgridindex, const int element, const int ion) // Kozma & Fransson 1992 equation 13 // returns the rate coefficient in s^-1 auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, const int ion) -> double { - assert_testmodeonly(grid::get_numassociatedcells(modelgridindex) > 0); + assert_testmodeonly(grid::get_numpropcells(modelgridindex) > 0); const double deposition_rate_density = get_deposition_rate_density(modelgridindex); if (deposition_rate_density > 0.) { @@ -2111,32 +2111,9 @@ void init(const int my_rank, const int ndo_nonempty) { nt_excitations_stored, grid::get_nonempty_npts_model() * sizeof(NonThermalExcitation) * nt_excitations_stored / 1024. / 1024.); - const auto nonempty_npts_model = grid::get_nonempty_npts_model(); + const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); -#ifdef MPI_ON - - MPI_Win win_shared_excitations_list{}; - - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); - - auto size = - static_cast(noderank_nonemptycellcount * sizeof(NonThermalExcitation) * nt_excitations_stored); - - int disp_unit = sizeof(NonThermalExcitation); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &excitations_list_all_cells, - &win_shared_excitations_list); - - MPI_Win_shared_query(win_shared_excitations_list, 0, &size, &disp_unit, &excitations_list_all_cells); - - MPI_Barrier(MPI_COMM_WORLD); - -#else - - excitations_list_all_cells = static_cast( - malloc(nonempty_npts_model * sizeof(NonThermalExcitation) * nt_excitations_stored)); - -#endif + excitations_list_all_cells = MPI_shared_malloc(nonempty_npts_model * nt_excitations_stored); } nt_solution.resize(grid::get_npts_model()); @@ -2150,7 +2127,7 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[modelgridindex].nneperion_when_solved = -1.; nt_solution[modelgridindex].timestep_last_solved = -1; - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { nt_solution[modelgridindex].allions = static_cast(malloc(get_includedions() * sizeof(NonThermalSolutionIon))); @@ -2241,7 +2218,7 @@ void close_file() { nonthermalfile = nullptr; } for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { free(nt_solution[modelgridindex].allions); } } @@ -2352,7 +2329,7 @@ __host__ __device__ auto nt_random_upperion(const int modelgridindex, const int __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion) -> double { assert_always(NT_ON); - assert_always(grid::get_numassociatedcells(modelgridindex) > 0); + assert_always(grid::get_numpropcells(modelgridindex) > 0); if (NT_SOLVE_SPENCERFANO) { const double Y_nt = nt_ionization_ratecoeff_sf(modelgridindex, element, ion); @@ -2392,7 +2369,7 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const return 0.; } - assert_testmodeonly(grid::get_numassociatedcells(modelgridindex) > 0); + assert_testmodeonly(grid::get_numpropcells(modelgridindex) > 0); // binary search, assuming the excitation list is sorted by lineindex ascending const auto ntexclist = std::span(nt_solution[modelgridindex].frac_excitations_list, @@ -2509,7 +2486,7 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { // based on Equation (2) of Li et al. (2012) void solve_spencerfano(const int modelgridindex, const int timestep, const int iteration) { bool skip_solution = false; - if (grid::get_numassociatedcells(modelgridindex) < 1) { + if (grid::get_numpropcells(modelgridindex) < 1) { printout("Associated_cells < 1 in cell %d at timestep %d. Skipping Spencer-Fano solution.\n", modelgridindex, timestep); diff --git a/packet.cc b/packet.cc index 2b1e7cd06..7901f8f7d 100644 --- a/packet.cc +++ b/packet.cc @@ -112,7 +112,7 @@ void packet_init(Packet *pkt) double norm = 0.; for (int m = 0; m < grid::ngrid; m++) { const int mgi = grid::get_cell_modelgridindex(m); - if (mgi < grid::get_npts_model() && grid::get_numassociatedcells(mgi) > 0) // some grid cells are empty + if (mgi < grid::get_npts_model() && grid::get_numpropcells(mgi) > 0) // some grid cells are empty { const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); double q = decay::get_modelcell_simtime_endecay_per_mass(nonemptymgi); diff --git a/radfield.cc b/radfield.cc index 3361996dc..0faa020ab 100644 --- a/radfield.cc +++ b/radfield.cc @@ -152,7 +152,7 @@ void realloc_detailed_lines(const int new_size) { detailed_lineindicies = newptr; for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { prev_Jb_lu_normed[modelgridindex] = static_cast( realloc(prev_Jb_lu_normed[modelgridindex], new_size * sizeof(Jb_lu_estimator))); @@ -176,7 +176,7 @@ void add_detailed_line(const int lineindex) { } for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { prev_Jb_lu_normed[modelgridindex][detailed_linecount].value = 0; prev_Jb_lu_normed[modelgridindex][detailed_linecount].contribcount = 0; @@ -549,10 +549,6 @@ void init(const int my_rank, const int ndo_nonempty) { } else { printout("\n"); } -#ifdef MPI_ON - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(nonempty_npts_model, globals::node_nprocs, globals::rank_in_node); -#endif if (MULTIBIN_RADFIELD_MODEL_ON) { printout("The multibin radiation field is being used from timestep %d onwards.\n", FIRST_NLTE_RADFIELD_TIMESTEP); @@ -575,19 +571,11 @@ void init(const int my_rank, const int ndo_nonempty) { const size_t mem_usage_bin_solutions = nonempty_npts_model * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution); #ifdef MPI_ON - { - auto size = static_cast(noderank_nonemptycellcount * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution)); - int disp_unit = sizeof(RadFieldBinSolution); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &radfieldbin_solutions, - &win_radfieldbin_solutions); - - MPI_Win_shared_query(win_radfieldbin_solutions, 0, &size, &disp_unit, &radfieldbin_solutions); - } + std::tie(radfieldbin_solutions, win_radfieldbin_solutions) = + MPI_shared_malloc_keepwin(nonempty_npts_model * RADFIELDBINCOUNT); #else - { - radfieldbin_solutions = static_cast( - malloc(nonempty_npts_model * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution))); - } + radfieldbin_solutions = static_cast( + malloc(nonempty_npts_model * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution))); #endif printout("[info] mem_usage: radiation field bin accumulators for non-empty cells occupy %.3f MB\n", @@ -602,11 +590,8 @@ void init(const int my_rank, const int ndo_nonempty) { if constexpr (DETAILED_BF_ESTIMATORS_ON) { { #ifdef MPI_ON - auto size = static_cast(noderank_nonemptycellcount * globals::bfestimcount * sizeof(float)); - int disp_unit = sizeof(float); - MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &prev_bfrate_normed, - &win_prev_bfrate_normed); - MPI_Win_shared_query(win_prev_bfrate_normed, 0, &size, &disp_unit, &prev_bfrate_normed); + std::tie(prev_bfrate_normed, win_prev_bfrate_normed) = + MPI_shared_malloc_keepwin(nonempty_npts_model * globals::bfestimcount); #else prev_bfrate_normed = static_cast(malloc(nonempty_npts_model * globals::bfestimcount * sizeof(float))); #endif @@ -1161,7 +1146,7 @@ void reduce_estimators() printout("Reducing detailed line estimators"); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { MPI_Allreduce(MPI_IN_PLACE, &Jb_lu_raw[modelgridindex][jblueindex].value, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -1225,7 +1210,7 @@ void write_restart_data(FILE *gridsave_file) { fprintf(gridsave_file, "%d\n", bfestimcount); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); fprintf(gridsave_file, "%d\n", modelgridindex); for (int i = 0; i < bfestimcount; i++) { @@ -1244,7 +1229,7 @@ void write_restart_data(FILE *gridsave_file) { } for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); assert_testmodeonly(nonemptymgi >= 0); fprintf(gridsave_file, "%d %la\n", modelgridindex, J_normfactor[nonemptymgi]); @@ -1328,7 +1313,7 @@ void read_restart_data(FILE *gridsave_file) { assert_always(gridsave_nbfestim_in == globals::bfestimcount); for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); int mgi_in = 0; assert_always(fscanf(gridsave_file, "%d\n", &mgi_in) == 1); @@ -1361,7 +1346,7 @@ void read_restart_data(FILE *gridsave_file) { } for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numassociatedcells(modelgridindex) > 0) { + if (grid::get_numpropcells(modelgridindex) > 0) { const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); int mgi_in = 0; assert_always(fscanf(gridsave_file, "%d %la\n", &mgi_in, &J_normfactor[nonemptymgi]) == 2); diff --git a/ratecoeff.cc b/ratecoeff.cc index 10f5ab164..9ffa3dcc7 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -857,54 +857,26 @@ void setup_photoion_luts() { assert_always(globals::nbfcontinua > 0); size_t mem_usage_photoionluts = 2 * TABLESIZE * globals::nbfcontinua * sizeof(double); -#ifdef MPI_ON - MPI_Win win = MPI_WIN_NULL; - MPI_Aint size = - (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &spontrecombcoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &spontrecombcoeffs) == MPI_SUCCESS); -#else - spontrecombcoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif + spontrecombcoeffs = MPI_shared_malloc(TABLESIZE * globals::nbfcontinua); assert_always(spontrecombcoeffs != nullptr); if constexpr (USE_LUT_PHOTOION) { -#ifdef MPI_ON - size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &corrphotoioncoeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &corrphotoioncoeffs) == MPI_SUCCESS); -#else - corrphotoioncoeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif + corrphotoioncoeffs = MPI_shared_malloc(TABLESIZE * globals::nbfcontinua); assert_always(corrphotoioncoeffs != nullptr); mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); } if constexpr (USE_LUT_BFHEATING) { -#ifdef MPI_ON - size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &globals::bfheating_coeff, &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &globals::bfheating_coeff) == MPI_SUCCESS); -#else - globals::bfheating_coeff = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif + globals::bfheating_coeff = MPI_shared_malloc(TABLESIZE * globals::nbfcontinua); assert_always(globals::bfheating_coeff != nullptr); mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); } #ifdef MPI_ON - size = (globals::rank_in_node == 0) ? TABLESIZE * globals::nbfcontinua * static_cast(sizeof(double)) : 0; - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &bfcooling_coeffs, - &win) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win, 0, &size, &disp_unit, &bfcooling_coeffs) == MPI_SUCCESS); + bfcooling_coeffs = MPI_shared_malloc(TABLESIZE * globals::nbfcontinua); #else bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); #endif - assert_always(bfcooling_coeffs != nullptr); printout( "[info] mem_usage: lookup tables derived from photoionisation (spontrecombcoeff, bfcooling and " diff --git a/rpkt.cc b/rpkt.cc index 43ac93d0f..7590baa6e 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -987,35 +987,22 @@ void allocate_expansionopacities() { double *expansionopacity_planck_cumulative_data{}; #ifdef MPI_ON - const auto [_, noderank_nonemptycellcount] = - get_range_chunk(npts_nonempty, globals::node_nprocs, globals::rank_in_node); - - { - MPI_Aint size = noderank_nonemptycellcount * expopac_nbins * static_cast(sizeof(float)); - int disp_unit = sizeof(float); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &expansionopacities_data, &win_expansionopacities) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_expansionopacities, 0, &size, &disp_unit, &expansionopacities_data) == - MPI_SUCCESS); - } - - if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { - MPI_Aint size = noderank_nonemptycellcount * expopac_nbins * static_cast(sizeof(double)); - int disp_unit = sizeof(double); - assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, - &expansionopacity_planck_cumulative_data, - &win_expansionopacity_planck_cumulative) == MPI_SUCCESS); - assert_always(MPI_Win_shared_query(win_expansionopacity_planck_cumulative, 0, &size, &disp_unit, - &expansionopacity_planck_cumulative_data) == MPI_SUCCESS); - } - + std::tie(expansionopacities_data, win_expansionopacities) = + MPI_shared_malloc_keepwin(npts_nonempty * expopac_nbins); #else expansionopacities_data = static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(float))); +#endif + if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { +#ifdef MPI_ON + std::tie(expansionopacity_planck_cumulative_data, win_expansionopacity_planck_cumulative) = + MPI_shared_malloc_keepwin(npts_nonempty * expopac_nbins); +#else expansionopacity_planck_cumulative_data = static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(double))); - } #endif + } + expansionopacities = std::span(expansionopacities_data, npts_nonempty * expopac_nbins); expansionopacity_planck_cumulative = std::span(expansionopacity_planck_cumulative_data, diff --git a/sn3d.cc b/sn3d.cc index e4c091132..359aa902a 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -72,11 +72,6 @@ auto real_time_start = -1; auto time_timestep_start = -1; // this will be set after the first update of the grid and before packet prop FILE *estimators_file{}; -#ifdef MPI_ON -size_t mpi_grid_buffer_size = 0; -char *mpi_grid_buffer{}; -#endif - void initialise_linestat_file() { if (globals::simulation_continued_from_saved && !RECORD_LINESTAT) { // only write linestat.out on the first run, unless it contains statistics for each timestep @@ -216,18 +211,18 @@ void write_deposition_file() { #ifdef MPI_ON void mpi_communicate_grid_properties() { - const auto nincludedions = get_includedions(); - const auto nelements = get_nelements(); + const ptrdiff_t nincludedions = get_includedions(); + const ptrdiff_t nelements = get_nelements(); for (int root = 0; root < globals::nprocs; root++) { MPI_Barrier(MPI_COMM_WORLD); int root_node_id = globals::node_id; MPI_Bcast(&root_node_id, 1, MPI_INT, root, MPI_COMM_WORLD); - const int root_nstart_nonempty = grid::get_nstart_nonempty(root); - const int root_ndo_nonempty = grid::get_ndo_nonempty(root); + const ptrdiff_t root_nstart_nonempty = grid::get_nstart_nonempty(root); + const ptrdiff_t root_ndo_nonempty = grid::get_ndo_nonempty(root); - for (int nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); + for (ptrdiff_t nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); nonemptymgi++) { assert_always(root_ndo_nonempty > 0); @@ -252,100 +247,32 @@ void mpi_communicate_grid_properties() { MPI_Bcast(&globals::gammaestimator[nonemptymgi * globals::nbfcontinua_ground], globals::nbfcontinua_ground, MPI_DOUBLE, root, MPI_COMM_WORLD); } + if (globals::rank_in_node == 0) { - MPI_Bcast(&grid::elem_meanweight_allcells[nonemptymgi * nelements], nelements, MPI_FLOAT, root_node_id, - globals::mpi_comm_internode); + MPI_Bcast(&grid::modelgrid[grid::get_mgi_of_nonemptymgi(nonemptymgi)], sizeof(grid::ModelGridCell), MPI_BYTE, + root_node_id, globals::mpi_comm_internode); } MPI_Bcast_binned_opacities(nonemptymgi, root_node_id); } - if (root == globals::my_rank) { - int position = 0; - for (ptrdiff_t nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); - nonemptymgi++) { - const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - MPI_Pack(&mgi, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - - MPI_Pack(&grid::modelgrid[mgi].Te, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].TR, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].W, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].rho, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].nne, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - MPI_Pack(&grid::modelgrid[mgi].thick, 1, MPI_INT, mpi_grid_buffer, mpi_grid_buffer_size, &position, - MPI_COMM_WORLD); - - MPI_Pack(&grid::elem_massfracs_allcells[(nonemptymgi * nelements)], nelements, MPI_FLOAT, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - - MPI_Pack(grid::modelgrid[mgi].ion_groundlevelpops, nincludedions, MPI_FLOAT, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].ion_partfuncts, nincludedions, MPI_FLOAT, mpi_grid_buffer, mpi_grid_buffer_size, - &position, MPI_COMM_WORLD); - MPI_Pack(grid::modelgrid[mgi].ion_cooling_contribs, nincludedions, MPI_DOUBLE, mpi_grid_buffer, - mpi_grid_buffer_size, &position, MPI_COMM_WORLD); - } - printout("[info] mem_usage: MPI_BUFFER: used %d of %zu bytes allocated to mpi_grid_buffer\n", position, - mpi_grid_buffer_size); - assert_always(static_cast(position) <= mpi_grid_buffer_size); - } - MPI_Barrier(MPI_COMM_WORLD); - MPI_Bcast(mpi_grid_buffer, mpi_grid_buffer_size, MPI_PACKED, root, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); - - int position = 0; - for (ptrdiff_t nonemptymgi = root_nstart_nonempty; nonemptymgi < (root_nstart_nonempty + root_ndo_nonempty); - nonemptymgi++) { - const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - int mgi_check = -1; - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &mgi_check, 1, MPI_INT, MPI_COMM_WORLD); - assert_always(mgi == mgi_check); - - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].Te, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TR, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].TJ, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].W, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].rho, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nne, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].nnetot, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].kappagrey, 1, MPI_FLOAT, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].totalcooling, 1, MPI_DOUBLE, - MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, &grid::modelgrid[mgi].thick, 1, MPI_INT, - MPI_COMM_WORLD); - - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, - &grid::elem_massfracs_allcells[(nonemptymgi * nelements)], nelements, MPI_FLOAT, MPI_COMM_WORLD); - - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_groundlevelpops, - nincludedions, MPI_FLOAT, MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_partfuncts, nincludedions, - MPI_FLOAT, MPI_COMM_WORLD); - MPI_Unpack(mpi_grid_buffer, mpi_grid_buffer_size, &position, grid::modelgrid[mgi].ion_cooling_contribs, - nincludedions, MPI_DOUBLE, MPI_COMM_WORLD); + if (globals::rank_in_node == 0) { + MPI_Bcast(&grid::elem_meanweight_allcells[root_nstart_nonempty * nelements], root_ndo_nonempty * nelements, + MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::elem_massfracs_allcells[root_nstart_nonempty * nelements], root_ndo_nonempty * nelements, + MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::ion_groundlevelpops_allcells[root_nstart_nonempty * nincludedions], + root_ndo_nonempty * nincludedions, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::ion_partfuncts_allcells[root_nstart_nonempty * nincludedions], root_ndo_nonempty * nincludedions, + MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::ion_cooling_contribs_allcells[root_nstart_nonempty * nincludedions], + root_ndo_nonempty * nincludedions, MPI_DOUBLE, root_node_id, globals::mpi_comm_internode); } + + MPI_Barrier(MPI_COMM_WORLD); } + MPI_Barrier(MPI_COMM_WORLD); } @@ -978,15 +905,6 @@ auto main(int argc, char *argv[]) -> int { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); - const size_t maxndo = grid::get_maxndo(); - // Initialise the exchange buffer - // The factor 4 comes from the fact that our buffer should contain elements of 4 byte - // instead of 1 byte chars. But the MPI routines don't care about the buffers datatype - mpi_grid_buffer_size = 4 * ((12 + 4 * get_includedions() + get_nelements()) * (maxndo) + 1); - printout("reserve mpi_grid_buffer_size %zu space for MPI communication buffer\n", mpi_grid_buffer_size); - mpi_grid_buffer = static_cast(malloc(mpi_grid_buffer_size * sizeof(char))); - assert_always(mpi_grid_buffer != nullptr); - MPI_Barrier(MPI_COMM_WORLD); #endif globals::timestep = globals::timestep_initial; @@ -1039,7 +957,6 @@ auto main(int argc, char *argv[]) -> int { #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); - free(mpi_grid_buffer); #endif if (linestat_file != nullptr) { diff --git a/sn3d.h b/sn3d.h index 9daf317f5..d7431f563 100644 --- a/sn3d.h +++ b/sn3d.h @@ -1,6 +1,7 @@ #ifndef SN3D_H #define SN3D_H +#include #ifndef __host__ #define __host__ #endif @@ -333,4 +334,47 @@ constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, co return std::tuple{nstart, nsize}; } +#ifdef MPI_ON +template +[[nodiscard]] auto MPI_shared_malloc_keepwin(const ptrdiff_t num_allranks) -> std::tuple { + if (num_allranks == 0) { + return {nullptr, MPI_WIN_NULL}; + } + assert_always(num_allranks >= 0); + + const auto [_, num_thisnoderank] = get_range_chunk(num_allranks, globals::node_nprocs, globals::rank_in_node); + assert_always(num_thisnoderank >= 0); + + auto size = static_cast(num_thisnoderank * sizeof(T)); + int disp_unit = sizeof(T); + MPI_Win mpiwin{MPI_WIN_NULL}; + T *ptr{}; + + assert_always(MPI_Win_allocate_shared(size, disp_unit, MPI_INFO_NULL, globals::mpi_comm_node, &ptr, &mpiwin) == + MPI_SUCCESS); + assert_always(MPI_Win_shared_query(mpiwin, 0, &size, &disp_unit, &ptr) == MPI_SUCCESS); + MPI_Barrier(globals::mpi_comm_node); + return {ptr, mpiwin}; +} +#endif + +template +[[nodiscard]] auto MPI_shared_malloc(const ptrdiff_t num_allranks) -> T * { + if (num_allranks == 0) { + return nullptr; + } +#ifdef MPI_ON + T *ptr = std::get<0>(MPI_shared_malloc_keepwin(num_allranks)); +#else + T *ptr = static_cast(malloc(num_allranks * sizeof(T))); +#endif + assert_always(ptr != nullptr); + return ptr; +} + +template +[[nodiscard]] auto MPI_shared_malloc_span(const ptrdiff_t num_allranks) -> std::span { + return std::span(MPI_shared_malloc(num_allranks), num_allranks); +} + #endif // SN3D_H diff --git a/thermalbalance.cc b/thermalbalance.cc index c46bc5ec1..bbbae2675 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -213,7 +213,8 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const auto nne = grid::get_nne(modelgridindex); // Then calculate heating and cooling rates - kpkt::calculate_cooling_rates(modelgridindex, heatingcoolingrates); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + kpkt::calculate_cooling_rates(nonemptymgi, heatingcoolingrates); calculate_heating_rates(modelgridindex, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); const auto ntlepton_frac_heating = nonthermal::get_nt_frac_heating(modelgridindex); @@ -268,9 +269,9 @@ auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, c } // depends only the radiation field - no dependence on T_e or populations -void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs) { +void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingcoeffs) { bfheatingcoeffs.resize(get_includedlevels()); - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double minelfrac = 0.01; for (int element = 0; element < get_nelements(); element++) { if (grid::get_elem_abundance(modelgridindex, element) <= minelfrac && !USE_LUT_BFHEATING) { @@ -313,8 +314,9 @@ void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatin } } -void call_T_e_finder(const int modelgridindex, const double t_current, const double T_min, const double T_max, +void call_T_e_finder(const int nonemptymgi, const double t_current, const double T_min, const double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double T_e_old = grid::get_Te(modelgridindex); printout("Finding T_e in cell %d at timestep %d...", modelgridindex, globals::timestep); diff --git a/thermalbalance.h b/thermalbalance.h index e10b98962..a95a7ade9 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -24,10 +24,10 @@ struct HeatingCoolingRates { double eps_alpha_ana{0}; }; -void call_T_e_finder(int modelgridindex, double t_current, double T_min, double T_max, +void call_T_e_finder(int nonemptymgi, double t_current, double T_min, double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs); [[nodiscard]] auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, double W) -> double; -void calculate_bfheatingcoeffs(int modelgridindex, std::vector &bfheatingcoeffs); +void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingcoeffs); #endif // THERMALBALANCE_H diff --git a/update_grid.cc b/update_grid.cc index 449f29285..b302becc7 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti const HeatingCoolingRates *heatingcoolingrates) { // return; disable for better performance (if estimators files are not needed) - if (grid::get_numassociatedcells(mgi) < 1) { + if (grid::get_numpropcells(mgi) < 1) { // modelgrid cells that are not represented in the simulation grid fprintf(estimators_file, "timestep %d modelgridindex %d EMPTYCELL\n\n", timestep, mgi); fflush(estimators_file); @@ -50,7 +51,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti const auto T_e = grid::get_Te(mgi); const auto nne = grid::get_nne(mgi); - const auto Y_e = grid::get_electronfrac(mgi); + const auto Y_e = grid::get_electronfrac(nonemptymgi); // fprintf(estimators_file,"%d %g %g %g %g %d // ",n,get_TR(n),grid::get_Te(n),get_W(n),get_TJ(n),grid::modelgrid[n].thick); fprintf(estimators_file,"%d %g %g %g // %g %g ",n,get_TR(n),grid::get_Te(n),get_W(n),get_TJ(n),grey_optical_depth); @@ -675,16 +676,18 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } } -void solve_Te_nltepops(const int mgi, const int nts, const int nts_prev, HeatingCoolingRates *heatingcoolingrates) +void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, + HeatingCoolingRates *heatingcoolingrates) // nts is the timestep number { + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); // bfheating coefficients are needed for the T_e solver, but // they only depend on the radiation field, which is fixed during the iterations below printout("calculate_bfheatingcoeffs for timestep %d cell %d...", nts, mgi); const auto sys_time_start_calculate_bfheatingcoeffs = std::time(nullptr); thread_local static auto bfheatingcoeffs = std::vector(get_includedlevels()); - calculate_bfheatingcoeffs(mgi, bfheatingcoeffs); + calculate_bfheatingcoeffs(nonemptymgi, bfheatingcoeffs); printout("took %ld seconds\n", std::time(nullptr) - sys_time_start_calculate_bfheatingcoeffs); const double convergence_tolerance = 0.04; @@ -708,7 +711,8 @@ void solve_Te_nltepops(const int mgi, const int nts, const int nts_prev, Heating const auto sys_time_start_Te = std::time(nullptr); // Find T_e as solution for thermal balance - call_T_e_finder(mgi, globals::timesteps[nts_prev].mid, MINTEMP, MAXTEMP, heatingcoolingrates, bfheatingcoeffs); + call_T_e_finder(nonemptymgi, globals::timesteps[nts_prev].mid, MINTEMP, MAXTEMP, heatingcoolingrates, + bfheatingcoeffs); const int duration_solve_T_e = std::time(nullptr) - sys_time_start_Te; @@ -869,18 +873,7 @@ static void titer_average_estimators(const int nonemptymgi) { void update_grid_cell(const int mgi, const int nts, const int nts_prev, const int titer, const double tratmid, const double deltat, HeatingCoolingRates *heatingcoolingrates) { - const int assoc_cells = grid::get_numassociatedcells(mgi); - if (assoc_cells < 1) { - // For modelgrid cells that are not represented in the simulation grid, - // Set grid properties to zero - grid::set_TR(mgi, 0.); - grid::set_TJ(mgi, 0.); - grid::set_Te(mgi, 0.); - grid::set_W(mgi, 0.); - return; - } - - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const double deltaV = grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); @@ -1008,7 +1001,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // full-spectrum and binned J and nuJ estimators radfield::fit_parameters(mgi, nts); - solve_Te_nltepops(mgi, nts, nts_prev, heatingcoolingrates); + solve_Te_nltepops(nonemptymgi, nts, nts_prev, heatingcoolingrates); } printout("Temperature/NLTE solution for cell %d timestep %d took %ld seconds\n", mgi, nts, std::time(nullptr) - sys_time_start_temperature_corrections); @@ -1017,6 +1010,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in const float nne = grid::get_nne(mgi); const double compton_optical_depth = SIGMA_T * nne * grid::wid_init(mgi, 0) * tratmid; + const int assoc_cells = grid::get_numpropcells(mgi); const double radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum * tratmid / assoc_cells; const double grey_optical_deptha = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * grid::wid_init(mgi, 0) * tratmid; // cube corners will have radial pos > rmax, so clamp to 0. @@ -1046,13 +1040,13 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // cooling rates calculation can be skipped for thick cells // flag with negative numbers to indicate that the rates are invalid grid::modelgrid[mgi].totalcooling = -1.; - grid::modelgrid[mgi].ion_cooling_contribs[0] = -1.; + grid::ion_cooling_contribs_allcells[(nonemptymgi * get_includedions()) + 0] = -1.; } else if (globals::simulation_continued_from_saved && nts == globals::timestep_initial) { // cooling rates were read from the gridsave file for this timestep // make sure they are valid printout("cooling rates read from gridsave file for timestep %d cell %d...", nts, mgi); assert_always(grid::modelgrid[mgi].totalcooling >= 0.); - assert_always(grid::modelgrid[mgi].ion_cooling_contribs[0] >= 0.); + assert_always(grid::ion_cooling_contribs_allcells[(nonemptymgi * get_includedions()) + 0] >= 0.); } else { // Cooling rates depend only on cell properties, precalculate total cooling // and ion contributions inside update grid and communicate between MPI tasks @@ -1062,7 +1056,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // don't pass pointer to heatingcoolingrates because current populations and rates weren't // used to determine T_e - kpkt::calculate_cooling_rates(mgi, nullptr); + kpkt::calculate_cooling_rates(nonemptymgi, nullptr); printout("took %ld seconds\n", std::time(nullptr) - sys_time_start_calc_kpkt_rates); } @@ -1132,7 +1126,10 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const // Check if this task should work on the current model grid cell. // If yes, update the cell and write out the estimators HeatingCoolingRates heatingcoolingrates{}; - update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, &heatingcoolingrates); + const int assoc_cells = grid::get_numpropcells(mgi); + if (assoc_cells > 0) { + update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, &heatingcoolingrates); + } // maybe want to add omp ordered here if the modelgrid cells should be output in order #ifdef _OPENMP From 1b3229a427381cd7975ee5cf9d5c61165ef13993 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 1 Nov 2024 20:55:11 +0000 Subject: [PATCH 077/117] CI: Fix clang-tidy for brew llvm 19.1.3 --- .github/workflows/ci-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 1a3058714..21522f4c5 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -93,7 +93,7 @@ jobs: - name: run-clang-tidy run: | clang-tidy --version - run-clang-tidy + xcrun run-clang-tidy compile: env: From 6ed4fdb2ba72bea69e41ab09e1d185ddbde97bd6 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 4 Nov 2024 17:12:33 +0000 Subject: [PATCH 078/117] Share on node modelgrid array, non-thermal solver solution (#142) --- .clangd | 2 +- .github/workflows/ci-checks.yml | 41 +- Makefile | 38 +- atomic.h | 43 +- decay.cc | 43 +- decay.h | 2 +- gammapkt.cc | 54 +- globals.h | 2 +- grid.cc | 874 ++++++++++++++++---------------- grid.h | 61 ++- input.cc | 21 +- kpkt.cc | 57 +-- ltepop.cc | 190 ++++--- ltepop.h | 18 +- macroatom.cc | 134 +++-- macroatom.h | 10 +- nltepop.cc | 163 +++--- nltepop.h | 10 +- nonthermal.cc | 565 ++++++++++----------- nonthermal.h | 14 +- radfield.cc | 380 ++++++-------- radfield.h | 18 +- ratecoeff.cc | 133 +++-- ratecoeff.h | 14 +- rpkt.cc | 171 +++---- rpkt.h | 12 +- sn3d.cc | 9 +- sn3d.h | 17 +- stats.cc | 64 ++- stats.h | 12 +- thermalbalance.cc | 92 ++-- update_grid.cc | 237 ++++----- update_grid.h | 2 +- update_packets.cc | 19 +- vpkt.cc | 20 +- 35 files changed, 1683 insertions(+), 1859 deletions(-) diff --git a/.clangd b/.clangd index b168f5747..84021a87f 100644 --- a/.clangd +++ b/.clangd @@ -2,4 +2,4 @@ CompileFlags: # to make the compilation database, pip install compiledb, then run: # compiledb -n --full-path make TESTMODE=ON CompilationDatabase: compile_commands.json - Add: [-DMPI_ON=true, -std=c++20] + Add: [-DMPI_ON=true, -std=c++20, -DTESTMODE=true] diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 21522f4c5..08fba6c3c 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -12,7 +12,7 @@ on: jobs: cppcheck: - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 @@ -45,7 +45,7 @@ jobs: check-path: . clang-tidy: - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 @@ -53,12 +53,7 @@ jobs: with: xcode-version: 'latest-stable' - - name: install dependencies - run: | - brew update - brew install openmpi gsl || true - - - name: install llvm + - name: install llvm from brew run: | brew install llvm || true echo "/opt/homebrew/opt/llvm/bin" >> $GITHUB_PATH @@ -73,22 +68,20 @@ jobs: echo "CPATH=/opt/homebrew/opt/include" >> $GITHUB_ENV - echo "compiledb" > requirements.txt - - name: Set up Python uses: actions/setup-python@v5 - with: - cache: pip - - name: Generate compile_commands.json + - name: install dependencies run: | + brew update + brew install openmpi gsl || true python3 -m pip install compiledb - cp artisoptions_nltenebular.h artisoptions.h - make version.h - python3 -m compiledb -n --full-path make - - name: cat compile_commands.json - run: cat compile_commands.json + - name: Generate compile_commands.json + run: | + cp artisoptions_nltenebular.h artisoptions.h + make clean + python3 -m compiledb -n --full-path make TESTMODE=ON - name: run-clang-tidy run: | @@ -224,7 +217,7 @@ jobs: make MPI=${{matrix.mpi}} STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec mac-llvm: - runs-on: macos-14 + runs-on: macos-15 env: CXX: clang++ strategy: @@ -276,14 +269,6 @@ jobs: run: | brew install openmpi || true - - name: install onedpl and tbb - run: | - brew install onedpl tbb - - echo "LIBRARY_PATH=$HOMEBREW_PREFIX/lib:$LIBRARY_PATH" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$HOMEBREW_PREFIX/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV - echo "CPATH=$HOMEBREW_PREFIX/include:$CPATH" >> $GITHUB_ENV - - name: Compile classic mode run: | $CXX -v diff --git a/Makefile b/Makefile index ee8e21865..d85da383c 100644 --- a/Makefile +++ b/Makefile @@ -58,13 +58,16 @@ endif $(info detected compiler is $(COMPILER_NAME)) -CXXFLAGS += -std=c++20 -fstrict-aliasing -# CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true -ifneq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP -ftrivial-auto-var-init=pattern +ifeq ($(COMPILER_NAME),NVHPC) + CXXFLAGS += -std=c++20 +else + CXXFLAGS += -std=c++23 -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP -ftrivial-auto-var-init=pattern endif +CXXFLAGS += -fstrict-aliasing +# CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true + # profile-guided optimisation # generate profile: # CXXFLAGS += -fprofile-generate="profdataraw" @@ -153,8 +156,6 @@ ifeq ($(shell uname -s),Darwin) # CXXFLAGS += -Rpass-missed=loop-vectorize # CXXFLAGS += -Rpass-analysis=loop-vectorize - # CXXFLAGS += -fopenmp-simd - # add -lprofiler for gperftools # LDFLAGS += $(LIB) # LDFLAGS += -lprofiler @@ -213,7 +214,7 @@ ifeq ($(TESTMODE),ON) CXXFLAGS += -D_GLIBCXX_ASSERTIONS # CXXFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_BACKTRACE=1 - CXXFLAGS += -fno-omit-frame-pointer + CXXFLAGS += -fno-omit-frame-pointer -g # CXXFLAGS += -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE CXXFLAGS += -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG @@ -230,20 +231,17 @@ ifeq ($(OPTIMIZE),OFF) BUILD_DIR := $(BUILD_DIR)_optimizeoff CXXFLAGS += -O0 else - # ifeq ($(TESTMODE),ON) - # CXXFLAGS += -Og - # else - CXXFLAGS += -O3 - ifeq ($(FASTMATH),OFF) - BUILD_DIR := $(BUILD_DIR)_nofastmath + CXXFLAGS += -O3 + ifeq ($(FASTMATH),OFF) + BUILD_DIR := $(BUILD_DIR)_nofastmath + CXXFLAGS += -Wno-unknown-pragmas + else + ifeq ($(COMPILER_NAME),NVHPC) + CXXFLAGS += -fast else - ifeq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -fast - else - CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only -fopenmp-simd - endif + CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only -fopenmp-simd endif - # endif + endif endif CXXFLAGS += -Winline -Wall -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow @@ -304,7 +302,7 @@ sn3d: $(BUILD_DIR)/sn3d ln -sf $(BUILD_DIR)/sn3d sn3d $(BUILD_DIR)/sn3dwhole: $(sn3d_files) version.h artisoptions.h Makefile $(BUILD_DIR)/compiler.txt - $(CXX) $(CXXFLAGS) -g $(sn3d_files) $(gsl_objects) $(LDFLAGS) -o $(BUILD_DIR)/sn3dwhole + $(CXX) $(CXXFLAGS) $(sn3d_files) $(gsl_objects) $(LDFLAGS) -o $(BUILD_DIR)/sn3dwhole -include $(sn3d_dep) sn3dwhole: $(BUILD_DIR)/sn3dwhole diff --git a/atomic.h b/atomic.h index 4bc22848c..bb0e90706 100644 --- a/atomic.h +++ b/atomic.h @@ -29,10 +29,10 @@ constexpr std::array phixsdata_filenames = {"version0ignore", " [[nodiscard]] inline auto get_nelements() -> int { return static_cast(globals::elements.size()); } // total density of nuclei -inline auto get_nnion_tot(int modelgridindex) -> double { +inline auto get_nnion_tot(int nonemptymgi) -> double { double nntot = 0.; for (int element = 0; element < get_nelements(); element++) { - nntot += grid::get_elem_numberdens(modelgridindex, element); + nntot += grid::get_elem_numberdens(nonemptymgi, element); } return nntot; @@ -184,27 +184,42 @@ inline auto get_phixs_table(const int element, const int ion, const int level) - return sigma_bf; } -[[nodiscard]] inline auto get_tau_sobolev(const int modelgridindex, const int lineindex, const double t_current, - bool sub_updown) -> double { - const int element = globals::linelist[lineindex].elementindex; - const int ion = globals::linelist[lineindex].ionindex; - const int lower = globals::linelist[lineindex].lowerlevelindex; - const int upper = globals::linelist[lineindex].upperlevelindex; +[[nodiscard]] inline auto get_tau_sobolev(const int nonemptymgi, const int lineindex, const double t_current) + -> double { + const auto &line = globals::linelist[lineindex]; + const int element = line.elementindex; + const int ion = line.ionindex; + const int lower = line.lowerlevelindex; + const int upper = line.upperlevelindex; - const double n_l = get_levelpop(modelgridindex, element, ion, lower); + const double n_l = get_levelpop(nonemptymgi, element, ion, lower); const double nu_trans = (epsilon(element, ion, upper) - epsilon(element, ion, lower)) / H; - const double A_ul = globals::linelist[lineindex].einstein_A; + const double A_ul = line.einstein_A; const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; - if (sub_updown) { - const double n_u = get_levelpop(modelgridindex, element, ion, upper); - return std::max((B_lu * n_l - B_ul * n_u) * HCLIGHTOVERFOURPI * t_current, 0.); - } return std::max(B_lu * n_l * HCLIGHTOVERFOURPI * t_current, 0.); } +[[nodiscard]] inline auto get_tau_sobolev_subupdown(const int nonemptymgi, const TransitionLine &line, + const double t_current) -> double { + const int element = line.elementindex; + const int ion = line.ionindex; + const int lower = line.lowerlevelindex; + const int upper = line.upperlevelindex; + + const double n_l = get_levelpop(nonemptymgi, element, ion, lower); + + const double nu_trans = (epsilon(element, ion, upper) - epsilon(element, ion, lower)) / H; + const double A_ul = line.einstein_A; + const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; + const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; + + const double n_u = get_levelpop(nonemptymgi, element, ion, upper); + return std::max((B_lu * n_l - B_ul * n_u) * HCLIGHTOVERFOURPI * t_current, 0.); +} + // Returns the atomic number associated with a given elementindex. inline auto get_atomicnumber(const int element) -> int { assert_testmodeonly(element >= 0); diff --git a/decay.cc b/decay.cc index 5c3d91f41..a9cf5b505 100644 --- a/decay.cc +++ b/decay.cc @@ -548,12 +548,13 @@ constexpr auto calculate_decaychain(const double firstinitabund, const std::vect return lastabund; } -auto get_nuc_massfrac(const int modelgridindex, const int z, const int a, const double time) -> double +auto get_nuc_massfrac(const int nonemptymgi, const int z, const int a, const double time) -> double // Get the mass fraction of a nuclide accounting for all decays including those of its parent and grandparent. // e.g., Co56 abundance may first increase with time due to Ni56 decays, then decease due to Co56 decay // Can be called for stable nuclides that are one daughters of the radioactive nuclide list e.g., Fe56 // For stable nuclides, abundance returned only comes from other decays (some could be included in init model elem frac) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); assert_always(time >= 0.); const double t_afterinit = time - grid::get_t_model(); @@ -1103,7 +1104,6 @@ void free_decaypath_energy_per_mass() { // energy release rate in form of kinetic energy of positrons, electrons, and alpha particles in [erg/s/g] [[nodiscard]] auto get_particle_injection_rate(const int nonemptymgi, const double t, const int decaytype) -> double { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double dep_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1116,7 +1116,7 @@ void free_decaypath_energy_per_mass() { const double en_particles = nucdecayenergyparticle(nucindex, decaytype); if (en_particles > 0.) { const double nucdecayrate = - get_nuc_massfrac(modelgridindex, z, a, t) / meanlife * get_nuc_decaybranchprob(nucindex, decaytype); + get_nuc_massfrac(nonemptymgi, z, a, t) / meanlife * get_nuc_decaybranchprob(nucindex, decaytype); assert_testmodeonly(nucdecayrate >= 0); dep_sum += nucdecayrate * en_particles / nucmass(z, a); } @@ -1129,7 +1129,6 @@ void free_decaypath_energy_per_mass() { // energy release rate in form of gamma-rays in [erg/s/g] [[nodiscard]] auto get_gamma_emission_rate(const int nonemptymgi, const double t) -> double { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double eps_gamma_sum = 0.; const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { @@ -1141,7 +1140,7 @@ void free_decaypath_energy_per_mass() { } const double en_gamma = nucdecayenergygamma(nucindex); if (en_gamma > 0.) { - const double nucdecayrate = get_nuc_massfrac(modelgridindex, z, a, t) / meanlife; + const double nucdecayrate = get_nuc_massfrac(nonemptymgi, z, a, t) / meanlife; assert_testmodeonly(nucdecayrate >= 0); eps_gamma_sum += nucdecayrate * en_gamma / nucmass(z, a); } @@ -1155,7 +1154,6 @@ void free_decaypath_energy_per_mass() { // energy release rate [erg/s/g] including everything (even neutrinos that are ignored elsewhere) [[nodiscard]] auto get_qdot_modelcell(const int nonemptymgi, const double t, const int decaytype) -> double { double qdot = 0.; - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const auto num_nuclides = get_num_nuclides(); for (int nucindex = 0; nucindex < num_nuclides; nucindex++) { const auto [z, a] = get_nuc_z_a(nucindex); @@ -1167,7 +1165,7 @@ void free_decaypath_energy_per_mass() { if (q_decay <= 0.) { continue; } - const double nucdecayrate = get_nuc_massfrac(modelgridindex, z, a, t) / meanlife; + const double nucdecayrate = get_nuc_massfrac(nonemptymgi, z, a, t) / meanlife; assert_always(nucdecayrate >= 0); qdot += nucdecayrate * q_decay / nucmass(z, a); } @@ -1207,7 +1205,7 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t // this nucleus is an isotope of the element if (!a_isotopes.contains(a)) { a_isotopes.insert(a); - const double nuc_massfrac = get_nuc_massfrac(modelgridindex, atomic_number, a, t_current); + const double nuc_massfrac = get_nuc_massfrac(nonemptymgi, atomic_number, a, t_current); isomassfracsum += nuc_massfrac; isomassfrac_on_nucmass_sum += nuc_massfrac / nucmass(atomic_number, a); } @@ -1223,7 +1221,7 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t // nuclide decays into correct atomic number but outside of the radionuclide list // note: there could also be stable isotopes of this element included in stable_initabund(z), but // here we only count the contribution from decays - const double nuc_massfrac = get_nuc_massfrac(modelgridindex, atomic_number, daughter_a, t_current); + const double nuc_massfrac = get_nuc_massfrac(nonemptymgi, atomic_number, daughter_a, t_current); isomassfracsum += nuc_massfrac; isomassfrac_on_nucmass_sum += nuc_massfrac / nucmass(atomic_number, daughter_a); } @@ -1234,7 +1232,7 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t if (atomic_number == 2 && !nuc_exists(2, 4) && (!a_isotopes.contains(4))) { // 4He will not be identified as a daughter nucleus of above decays, so add it in - const double nuc_massfrac = get_nuc_massfrac(modelgridindex, 2, 4, t_current); + const double nuc_massfrac = get_nuc_massfrac(nonemptymgi, 2, 4, t_current); isomassfracsum += nuc_massfrac; isomassfrac_on_nucmass_sum += nuc_massfrac / nucmass(2, 4); } @@ -1256,10 +1254,10 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t double nnetot = 0.; const auto nelements = get_nelements(); for (int element = 0; element < nelements; element++) { - const double nnelement = grid::get_elem_numberdens(modelgridindex, element); + const double nnelement = grid::get_elem_numberdens(nonemptymgi, element); nnetot += nnelement * get_atomicnumber(element); } - grid::set_nnetot(modelgridindex, nnetot); + grid::set_nnetot(nonemptymgi, nnetot); // double initnucfracsum = 0.; // double nucfracsum = 0.; @@ -1267,11 +1265,11 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t // { // const auto [z, a] = get_nuc_z_a(nucindex); // initnucfracsum += grid::get_modelinitnucmassfrac(modelgridindex, z, a); - // nucfracsum += get_nuc_massfrac(modelgridindex, z, a, t_current); + // nucfracsum += get_nuc_massfrac(nonemptymgi, z, a, t_current); // // // printout_nuclidename(z, a); // // printout(" init: %g now: %g\n", grid::get_modelinitnucmassfrac(modelgridindex, z, a), - // get_nuc_massfrac(modelgridindex, z, a, t_current)); + // get_nuc_massfrac(nonemptymgi, z, a, t_current)); // // for (int dectypeindex = 0; dectypeindex < decaytypes::DECAYTYPE_COUNT; dectypeindex++) // { @@ -1279,10 +1277,10 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t // get_nuc_decaybranchprob(z, a, dectypeindex) > 0.) // { // // printout_nuclidename(decay_daughter_z(z, a), decay_daughter_a(z, a)); - // // printout("(stable) init: 0 now: %g\n", get_nuc_massfrac(modelgridindex, decay_daughter_z(z, a), + // // printout("(stable) init: 0 now: %g\n", get_nuc_massfrac(nonemptymgi, decay_daughter_z(z, a), // decay_daughter_a(z, a), t_current)); // // this decay steps off the nuclide list, so add its daughter abundance to the total - // nucfracsum += get_nuc_massfrac(modelgridindex, decay_daughter_z(z, a, dectypeindex), decay_daughter_a(z, a, + // nucfracsum += get_nuc_massfrac(nonemptymgi, decay_daughter_z(z, a, dectypeindex), decay_daughter_a(z, a, // dectypeindex), t_current); // } // } @@ -1294,9 +1292,8 @@ void update_abundances(const int nonemptymgi, const int timestep, const double t // assert_always(fabs(nucfracsum - initnucfracsum) < 0.001); // decays shouldn't change nuclear mass fraction sum } -void fprint_nuc_abundances(FILE *estimators_file, const int nonemptmgi, const double t_current, const int element) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptmgi); - const double rho = grid::get_rho(modelgridindex); +void fprint_nuc_abundances(FILE *estimators_file, const int nonemptymgi, const double t_current, const int element) { + const double rho = grid::get_rho(nonemptymgi); const int atomic_number = get_atomicnumber(element); std::set a_isotopes; // ensure we don't repeat isotopes @@ -1307,7 +1304,7 @@ void fprint_nuc_abundances(FILE *estimators_file, const int nonemptmgi, const do if (!a_isotopes.contains(nuc_a)) { a_isotopes.insert(nuc_a); // radioactive isotope of the element - const double massfrac = get_nuc_massfrac(modelgridindex, atomic_number, nuc_a, t_current); + const double massfrac = get_nuc_massfrac(nonemptymgi, atomic_number, nuc_a, t_current); if (massfrac > 0) { const double numberdens = massfrac / nucmass(atomic_number, nuc_a) * rho; @@ -1325,7 +1322,7 @@ void fprint_nuc_abundances(FILE *estimators_file, const int nonemptmgi, const do a_isotopes.insert(nuc_a); // nuclide decays into correct atomic number but outside of the radionuclide list. Daughter is assumed // stable - const double massfrac = get_nuc_massfrac(modelgridindex, atomic_number, nuc_a, t_current); + const double massfrac = get_nuc_massfrac(nonemptymgi, atomic_number, nuc_a, t_current); const double numberdens = massfrac / nucmass(nuc_z, nuc_a) * rho; fprintf(estimators_file, " %s%d: %9.3e", get_elname(atomic_number).c_str(), nuc_a, numberdens); } @@ -1335,10 +1332,10 @@ void fprint_nuc_abundances(FILE *estimators_file, const int nonemptmgi, const do } // factor to convert convert mass fraction to number density - const double otherstablemassfrac = grid::get_stable_initabund(nonemptmgi, element); + const double otherstablemassfrac = grid::get_stable_initabund(nonemptymgi, element); if (otherstablemassfrac > 0) { const double meannucmass = globals::elements[element].initstablemeannucmass; - const double otherstable_numberdens = otherstablemassfrac / meannucmass * grid::get_rho(modelgridindex); + const double otherstable_numberdens = otherstablemassfrac / meannucmass * grid::get_rho(nonemptymgi); fprintf(estimators_file, " %s_otherstable: %9.3e", get_elname(atomic_number).c_str(), otherstable_numberdens); } fprintf(estimators_file, "\n"); diff --git a/decay.h b/decay.h index 71ef0ee6a..b511d3183 100644 --- a/decay.h +++ b/decay.h @@ -44,7 +44,7 @@ void free_decaypath_energy_per_mass(); [[nodiscard]] auto get_particle_injection_rate(int nonemptymgi, double t, int decaytype) -> double; [[nodiscard]] auto get_gamma_emission_rate(int nonemptymgi, double t) -> double; [[nodiscard]] auto get_global_etot_t0_tinf() -> double; -void fprint_nuc_abundances(FILE *estimators_file, int nonemptmgi, double t_current, int element); +void fprint_nuc_abundances(FILE *estimators_file, int nonemptymgi, double t_current, int element); void setup_radioactive_pellet(double e0, int mgi, Packet &pkt); void cleanup(); diff --git a/gammapkt.cc b/gammapkt.cc index 458742b68..56893e361 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -267,6 +267,11 @@ auto get_chi_compton_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for Compton scattering in the observer reference frame // Start by working out the compton x-section in the co-moving frame. + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); + if (nonemptymgi < 0) { + return 0.; // empty cell + } + const double xx = H * pkt.nu_cmf / ME / CLIGHT / CLIGHT; // Use this to decide whether the Thompson limit is acceptable. @@ -274,8 +279,7 @@ auto get_chi_compton_rf(const Packet &pkt) -> double { const double sigma_cmf = (xx < THOMSON_LIMIT) ? SIGMA_T : sigma_compton_partial(xx, 1 + (2 * xx)); // Now need to multiply by the electron number density. - const auto mgi = grid::get_cell_modelgridindex(pkt.where); - const double chi_cmf = sigma_cmf * grid::get_nnetot(mgi); + const double chi_cmf = sigma_cmf * grid::get_nnetot(nonemptymgi); // convert between frames const double chi_rf = chi_cmf * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -459,15 +463,15 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { const int mgi = grid::get_cell_modelgridindex(pkt.where); if (mgi >= grid::get_npts_model()) { - // empty cell - return 0.; + return 0.; // empty cell } + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); - const double rho = grid::get_rho(mgi); + const double rho = grid::get_rho(nonemptymgi); if (globals::gamma_kappagrey < 0) { chi_cmf = 0.; - if (!USE_XCOM_GAMMAPHOTOION) { + if constexpr (!USE_XCOM_GAMMAPHOTOION) { // Cross sections from Equation 2 of Ambwani & Sutherland (1988), attributed to Veigele (1973) // 2.41326e19 Hz = 100 keV / H @@ -500,7 +504,7 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { if (numb_energies == 0) { continue; } - const double n_i = grid::get_elem_numberdens(mgi, i); // number density in the current cell + const double n_i = grid::get_elem_numberdens(nonemptymgi, i); // number density in the current cell if (n_i == 0) { continue; } @@ -551,7 +555,12 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame auto get_chi_pair_prod_rf(const Packet &pkt) -> double { const int mgi = grid::get_cell_modelgridindex(pkt.where); - const double rho = grid::get_rho(mgi); + if (mgi >= grid::get_npts_model()) { + return 0.; // empty cell + } + + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + const double rho = grid::get_rho(nonemptymgi); if (globals::gamma_kappagrey >= 0.) { return 0.; @@ -625,13 +634,8 @@ constexpr auto meanf_sigma(const double x) -> double { return tot; } -// Subroutine to record the heating rate in a cell due to gamma rays. -// By heating rate I mean, for now, really the rate at which the code is making -// k-packets in that cell which will then convert into r-packets. This is (going -// to be) used for the new light_curve syn-style calculation. -// The intention is that dep_estimator_gamma will contain the emissivity of r-packets -// in the co-moving frame (which is going to be isotropic). -void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const int nonemptymgi) { +// update the energy deposition estimator for gamma ray path increment +void update_gamma_dep(const Packet &pkt, const double dist, const int nonemptymgi) { if (!(dist > 0)) { return; } @@ -642,7 +646,7 @@ void update_gamma_dep(const Packet &pkt, const double dist, const int mgi, const const double doppler_sq = doppler_squared_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); const double xx = H * pkt.nu_cmf / ME / CLIGHT / CLIGHT; - double heating_cont = ((meanf_sigma(xx) * grid::get_nnetot(mgi)) + get_chi_photo_electric_rf(pkt) + + double heating_cont = ((meanf_sigma(xx) * grid::get_nnetot(nonemptymgi)) + get_chi_photo_electric_rf(pkt) + (get_chi_pair_prod_rf(pkt) * (1. - (2.46636e+20 / pkt.nu_cmf)))); heating_cont = heating_cont * pkt.e_rf * dist * doppler_sq; @@ -782,10 +786,9 @@ void transport_gamma(Packet &pkt, const double t2) { move_pkt_withtime(pkt, sdist / 2.); // Move it into the new cell. - const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + const int nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); if (chi_tot > 0 && nonemptymgi >= 0) { - update_gamma_dep(pkt, sdist, mgi, nonemptymgi); + update_gamma_dep(pkt, sdist, nonemptymgi); } move_pkt_withtime(pkt, sdist / 2.); @@ -796,20 +799,18 @@ void transport_gamma(Packet &pkt, const double t2) { } else if ((tdist < sdist) && (tdist < edist)) { // Doesn't reach boundary. move_pkt_withtime(pkt, tdist / 2.); - const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + const int nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); if (chi_tot > 0 && nonemptymgi >= 0) { - update_gamma_dep(pkt, tdist, mgi, nonemptymgi); + update_gamma_dep(pkt, tdist, nonemptymgi); } move_pkt_withtime(pkt, tdist / 2.); pkt.prop_time = t2; // prevent roundoff error } else if ((edist < sdist) && (edist < tdist)) { move_pkt_withtime(pkt, edist / 2.); - const int mgi = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + const int nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); if (chi_tot > 0 && nonemptymgi >= 0) { - update_gamma_dep(pkt, edist, mgi, nonemptymgi); + update_gamma_dep(pkt, edist, nonemptymgi); } move_pkt_withtime(pkt, edist / 2.); @@ -892,7 +893,8 @@ void wollaeger_thermalisation(Packet &pkt) { const double s_cont = sdist * t_current * t_current * t_current / std::pow(pkt_copy.prop_time, 3); const int mgi = grid::get_cell_modelgridindex(pkt_copy.where); if (mgi != grid::get_npts_model()) { - tau += grid::get_rho(mgi) * s_cont * mean_gamma_opac; // contribution to the integral + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + tau += grid::get_rho(nonemptymgi) * s_cont * mean_gamma_opac; // contribution to the integral } // move packet copy now move_pkt_withtime(pkt_copy, sdist); diff --git a/globals.h b/globals.h index b61b38159..de5f32104 100644 --- a/globals.h +++ b/globals.h @@ -196,7 +196,7 @@ struct CellCache { std::vector ch_allcont_nnlevel; std::vector ch_keep_this_cont; double chi_ff_nnionpart{-1}; - int cellnumber{-1}; // Identifies the cell the data is valid for. + int nonemptymgi{-1}; // Identifies the cell the data is valid for. }; namespace globals { diff --git a/grid.cc b/grid.cc index 086c1f1b8..277e162ef 100644 --- a/grid.cc +++ b/grid.cc @@ -41,6 +41,14 @@ namespace grid { namespace { +struct ModelGridCellInput { + float rhoinit = -1.; + float ffegrp = 0.; + float initial_radial_pos_sum = 0.; + float initelectronfrac = -1; // Ye: electrons (or protons) per nucleon + float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] +}; + std::array coordlabel{'?', '?', '?'}; std::array ncoordgrid{0}; // propagation grid dimensions @@ -66,6 +74,8 @@ struct PropGridCell { std::vector cell{}; +std::vector nonemptymgi_of_propcell; + std::vector mg_associated_cells; std::vector nonemptymgi_of_mgi; std::vector mgi_of_nonemptymgi; @@ -85,11 +95,12 @@ std::vector ranks_nstart; std::vector ranks_nstart_nonempty; std::vector ranks_ndo; std::vector ranks_ndo_nonempty; +inline std::span modelgrid_input{}; -void set_rho_tmin(const int modelgridindex, const float x) { modelgrid[modelgridindex].rhoinit = x; } +void set_rho_tmin(const int modelgridindex, const float x) { modelgrid_input[modelgridindex].rhoinit = x; } void set_initelectronfrac(const int modelgridindex, const double electronfrac) { - modelgrid[modelgridindex].initelectronfrac = electronfrac; + modelgrid_input[modelgridindex].initelectronfrac = electronfrac; } void read_possible_yefile() { @@ -114,21 +125,6 @@ void read_possible_yefile() { fclose(filein); } -void set_npts_model(const int new_npts_model) { - npts_model = new_npts_model; - - assert_always(modelgrid.data() == nullptr); - modelgrid = MPI_shared_malloc_span(npts_model + 1); - if (globals::rank_in_node == 0) { - std::ranges::fill(modelgrid, ModelGridCell{}); - } -#ifdef MPI_ON - MPI_Barrier(globals::mpi_comm_node); -#endif - mg_associated_cells.resize(npts_model + 1, 0); - nonemptymgi_of_mgi.resize(npts_model + 1, -1); -} - void allocate_initradiobund() { assert_always(npts_model > 0); @@ -192,7 +188,7 @@ void set_ffegrp(const int modelgridindex, float x) { assert_always(x >= 0); assert_always(x <= 1.001); - modelgrid[modelgridindex].ffegrp = x; + modelgrid_input[modelgridindex].ffegrp = x; } void set_cell_modelgridindex(const int cellindex, const int new_modelgridindex) { @@ -220,7 +216,7 @@ void set_modelinitnucmassfrac(const int modelgridindex, const int nucindex, floa } void set_initenergyq(const int modelgridindex, const double initenergyq) { - modelgrid[modelgridindex].initenergyq = initenergyq; + modelgrid_input[modelgridindex].initenergyq = initenergyq; } void set_elem_untrackedstable_abund_from_total(const int nonemptymgi, const int element, const float elemabundance) { @@ -266,23 +262,24 @@ void set_elem_untrackedstable_abund_from_total(const int nonemptymgi, const int void allocate_nonemptycells_composition_cooling() // Initialise composition dependent cell data for the given cell { - const ptrdiff_t npts_nonempty = get_nonempty_npts_model(); + const ptrdiff_t nonempty_npts_model_ptrdifft = get_nonempty_npts_model(); const auto nelements = get_nelements(); - initmassfracuntrackedstable_allcells = MPI_shared_malloc(npts_nonempty * nelements); - elem_meanweight_allcells = MPI_shared_malloc(npts_nonempty * nelements); - elements_uppermost_ion_allcells = MPI_shared_malloc(npts_nonempty * nelements); - elem_massfracs_allcells = MPI_shared_malloc(npts_nonempty * nelements); - ion_groundlevelpops_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); - ion_partfuncts_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); - ion_cooling_contribs_allcells = MPI_shared_malloc(npts_nonempty * get_includedions()); + initmassfracuntrackedstable_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * nelements); + elem_meanweight_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * nelements); + elements_uppermost_ion_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * nelements); + elem_massfracs_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * nelements); + ion_groundlevelpops_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * get_includedions()); + ion_partfuncts_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * get_includedions()); + ion_cooling_contribs_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * get_includedions()); if (globals::total_nlte_levels > 0) { #ifdef MPI_ON std::tie(nltepops_allcells, win_nltepops_allcells) = - MPI_shared_malloc_keepwin(npts_nonempty * globals::total_nlte_levels); + MPI_shared_malloc_keepwin(nonempty_npts_model_ptrdifft * globals::total_nlte_levels); #else - nltepops_allcells = static_cast(malloc(npts_nonempty * globals::total_nlte_levels * sizeof(double))); + nltepops_allcells = + static_cast(malloc(nonempty_npts_model * globals::total_nlte_levels * sizeof(double))); #endif assert_always(nltepops_allcells != nullptr); @@ -291,21 +288,21 @@ void allocate_nonemptycells_composition_cooling() } if (globals::rank_in_node == 0) { - std::fill_n(initmassfracuntrackedstable_allcells, npts_nonempty * nelements, -1.); - std::fill_n(elem_meanweight_allcells, npts_nonempty * nelements, -1.); - std::fill_n(elements_uppermost_ion_allcells, npts_nonempty * nelements, -1); - std::fill_n(elem_massfracs_allcells, npts_nonempty * nelements, -1.); + std::fill_n(initmassfracuntrackedstable_allcells, nonempty_npts_model_ptrdifft * nelements, -1.); + std::fill_n(elem_meanweight_allcells, nonempty_npts_model_ptrdifft * nelements, -1.); + std::fill_n(elements_uppermost_ion_allcells, nonempty_npts_model_ptrdifft * nelements, -1); + std::fill_n(elem_massfracs_allcells, nonempty_npts_model_ptrdifft * nelements, -1.); // -1 indicates that there is currently no information on the nlte populations - std::ranges::fill_n(grid::nltepops_allcells, npts_nonempty * globals::total_nlte_levels, -1.); + std::ranges::fill_n(grid::nltepops_allcells, nonempty_npts_model_ptrdifft * globals::total_nlte_levels, -1.); } } void allocate_nonemptymodelcells() { // Determine the number of simulation cells associated with the model cells - for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { - mg_associated_cells[mgi] = 0; - if (globals::rank_in_node == 0) { - modelgrid[mgi].initial_radial_pos_sum = 0.; + std::ranges::fill(mg_associated_cells, 0); + if (globals::rank_in_node == 0) { + for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { + modelgrid_input[mgi].initial_radial_pos_sum = 0.; } } @@ -323,13 +320,17 @@ void allocate_nonemptymodelcells() { mg_associated_cells[mgi] += 1; if (globals::rank_in_node == 0) { - modelgrid[mgi].initial_radial_pos_sum += radial_pos_mid; + modelgrid_input[mgi].initial_radial_pos_sum += radial_pos_mid; } assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || (mgi == get_npts_model())); } +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif + // find number of non-empty cells and allocate nonempty list nonempty_npts_model = 0; for (int mgi = 0; mgi < get_npts_model(); mgi++) { @@ -340,27 +341,43 @@ void allocate_nonemptymodelcells() { assert_always(nonempty_npts_model > 0); mgi_of_nonemptymgi.resize(nonempty_npts_model, -2); + nonemptymgi_of_propcell.resize(ngrid, -1); int nonemptymgi = 0; // index within list of non-empty modelgrid cells for (int mgi = 0; mgi < get_npts_model(); mgi++) { if (get_numpropcells(mgi) > 0) { - if (get_rho_tmin(mgi) <= 0) { - printout("Error: negative or zero density. Abort.\n"); - std::abort(); - } + assert_always(get_rho_tmin(mgi) >= 0); nonemptymgi_of_mgi[mgi] = nonemptymgi; mgi_of_nonemptymgi[nonemptymgi] = mgi; nonemptymgi++; } else { nonemptymgi_of_mgi[mgi] = -1; set_rho_tmin(mgi, 0.); - set_rho(mgi, 0.); for (int nucindex = 0; nucindex < decay::get_num_nuclides(); nucindex++) { set_modelinitnucmassfrac(mgi, nucindex, 0.); } } } +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif + + for (int cellindex = 0; cellindex < ngrid; cellindex++) { + const int mgi = get_cell_modelgridindex(cellindex); + if (mgi >= get_npts_model()) { + nonemptymgi_of_propcell[cellindex] = -1; + } else { + nonemptymgi_of_propcell[cellindex] = get_nonemptymgi_of_mgi(mgi); + } + } + + assert_always(modelgrid.data() == nullptr); + modelgrid = MPI_shared_malloc_span(nonempty_npts_model); + std::ranges::fill(modelgrid, ModelGridCell{}); +#ifdef MPI_ON + MPI_Barrier(MPI_COMM_WORLD); +#endif allocate_nonemptycells_composition_cooling(); @@ -438,7 +455,7 @@ void map_1dmodelto3dgrid() const double cellvmid = get_cellradialposmid(cellindex) / globals::tmin; const int mgi = static_cast(std::ranges::lower_bound(vout_model, cellvmid) - vout_model.begin()); - if (mgi < get_npts_model() && modelgrid[mgi].rhoinit > 0) { + if (mgi < get_npts_model() && modelgrid_input[mgi].rhoinit > 0) { set_cell_modelgridindex(cellindex, mgi); assert_always(vout_model[mgi] >= cellvmid); assert_always((mgi > 0 ? vout_model[mgi - 1] : 0.0) <= cellvmid); @@ -461,7 +478,7 @@ void map_2dmodelto3dgrid() const double rcylindrical = std::sqrt(std::pow(pos_mid[0], 2) + std::pow(pos_mid[1], 2)); - // 2D grid is uniform so rcyl and z indicies can be calculated with no lookup + // 2D grid is uniform so rcyl and z indices can be calculated with no lookup const int n_rcyl = static_cast(rcylindrical / globals::tmin / globals::vmax * ncoord_model[0]); const int n_z = static_cast((pos_mid[2] / globals::tmin + globals::vmax) / (2 * globals::vmax) * ncoord_model[1]); @@ -469,7 +486,7 @@ void map_2dmodelto3dgrid() if (n_rcyl >= 0 && n_rcyl < ncoord_model[0] && n_z >= 0 && n_z < ncoord_model[1]) { const int mgi = (n_z * ncoord_model[0]) + n_rcyl; - if (modelgrid[mgi].rhoinit > 0) { + if (modelgrid_input[mgi].rhoinit > 0) { set_cell_modelgridindex(cellindex, mgi); } else { set_cell_modelgridindex(cellindex, get_npts_model()); @@ -484,7 +501,7 @@ void map_2dmodelto3dgrid() // get_npts_model()) void map_modeltogrid_direct() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const int mgi = (modelgrid[cellindex].rhoinit > 0) ? cellindex : get_npts_model(); + const int mgi = (modelgrid_input[cellindex].rhoinit > 0) ? cellindex : get_npts_model(); set_cell_modelgridindex(cellindex, mgi); } } @@ -742,269 +759,6 @@ auto read_model_columns(std::fstream &fmodel) -> std::tuple> npts_model_in; - - set_npts_model(npts_model_in); - ncoord_model[0] = npts_model_in; - - vout_model.resize(get_npts_model(), NAN); - - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - - // Now read in the lines of the model. Each line has 5 entries: the - // cell number (integer) the velocity at outer boundary of cell (float), - // the mass density in the cell (float), the abundance of Ni56 by mass - // in the cell (float) and the total abundance of all Fe-grp elements - // in the cell (float). For now, the last number is recorded but never - // used. - - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - - int mgi = 0; - while (std::getline(fmodel, line)) { - double vout_kmps{NAN}; - double log_rho{NAN}; - int cellnumberin = 0; - std::istringstream ssline(line); - - if (ssline >> cellnumberin >> vout_kmps >> log_rho) { - if (mgi == 0) { - first_cellindex = cellnumberin; - printout("first_cellindex %d\n", first_cellindex); - } - assert_always(cellnumberin == mgi + first_cellindex); - - vout_model[mgi] = vout_kmps * 1.e5; - - const double rho_tmin = pow(10., log_rho) * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - } else { - printout("Unexpected number of values in model.txt\n"); - printout("line: %s\n", line.c_str()); - assert_always(false); - } - read_model_radioabundances(fmodel, ssline, mgi, true, colnames, nucindexlist, one_line_per_cell); - - mgi += 1; - if (mgi == get_npts_model()) { - break; - } - } - - if (mgi != get_npts_model()) { - printout("ERROR in model.txt. Found only %d cells instead of %d expected.\n", mgi - 1, get_npts_model()); - std::abort(); - } - - globals::vmax = vout_model[get_npts_model() - 1]; -} - -// Read in a 2D axisymmetric cylindrical model -void read_2d_model() { - auto fmodel = fstream_required("model.txt", std::ios::in); - - std::string line; - - // 1st read the number of data points in the table of input model. - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> ncoord_model[0] >> ncoord_model[1]; // r and z (cylindrical polar) - ncoord_model[2] = 0.; - - set_npts_model(ncoord_model[0] * ncoord_model[1]); - - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - - // Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; - - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - - // Now read in the model. Each point in the model has two lines of input. - // First is an index for the cell then its r-mid point then its z-mid point - // then its total mass density. - // Second is the total FeG mass, initial 56Ni mass, initial 56Co mass - - int mgi = 0; - while (std::getline(fmodel, line)) { - int cellnumberin = 0; - float cell_r_in{NAN}; - float cell_z_in{NAN}; - double rho_tmodel{NAN}; - std::istringstream ssline(line); - assert_always(ssline >> cellnumberin >> cell_r_in >> cell_z_in >> rho_tmodel); - - if (mgi == 0) { - first_cellindex = cellnumberin; - } - assert_always(cellnumberin == mgi + first_cellindex); - - const int n_rcyl = (mgi % ncoord_model[0]); - const double pos_r_cyl_mid = (n_rcyl + 0.5) * globals::vmax * t_model / ncoord_model[0]; - assert_always(fabs((cell_r_in / pos_r_cyl_mid) - 1) < 1e-3); - const int n_z = (mgi / ncoord_model[0]); - const double pos_z_mid = globals::vmax * t_model * (-1 + 2 * (n_z + 0.5) / ncoord_model[1]); - assert_always(fabs((cell_z_in / pos_z_mid) - 1) < 1e-3); - - if (rho_tmodel < 0) { - printout("negative input density %g %d\n", rho_tmodel, mgi); - std::abort(); - } - - const bool keepcell = (rho_tmodel > 0); - const double rho_tmin = rho_tmodel * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - - read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - - mgi++; - } - - if (mgi != get_npts_model()) { - printout("ERROR in model.txt. Found %d only cells instead of %d expected.\n", mgi - 1, get_npts_model()); - std::abort(); - } -} - -// read a 3D Cartesian model -void read_3d_model() { - auto fmodel = fstream_required("model.txt", std::ios::in); - - std::string line; - - // 1st read the number of data points in the table of input model. - // This MUST be the same number as the maximum number of points used in the grid - if not, abort. - int npts_model_in = 0; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> npts_model_in; - set_npts_model(npts_model_in); - - ncoord_model[0] = ncoord_model[1] = ncoord_model[2] = static_cast(round(pow(npts_model_in, 1 / 3.))); - assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_model_in); - - // for a 3D input model, the propagation cells will match the input cells exactly - ncoordgrid = ncoord_model; - ngrid = npts_model_in; - - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - - // Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; - - const double xmax_tmodel = globals::vmax * t_model; - - // Now read in the lines of the model. - min_den = -1.; - - // check if expected positions match in either xyz or zyx column order - // set false if a problem is detected - bool posmatch_xyz = true; - bool posmatch_zyx = true; - - const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); - - // mgi is the index to the model grid - empty cells are sent to special value get_npts_model(), - // otherwise each input cell is one modelgrid cell - int mgi = 0; // corresponds to model.txt index column, but zero indexed! (model.txt might be 1-indexed) - while (std::getline(fmodel, line)) { - int cellnumberin = 0; - std::array cellpos_in{}; - float rho_model{NAN}; - std::istringstream ssline(line); - - assert_always(ssline >> cellnumberin >> cellpos_in[0] >> cellpos_in[1] >> cellpos_in[2] >> rho_model); - - if (mgi == 0) { - first_cellindex = cellnumberin; - } - assert_always(cellnumberin == mgi + first_cellindex); - - if (mgi % (ncoord_model[1] * ncoord_model[2]) == 0) { - printout("read up to cell mgi %d\n", mgi); - } - - // cell coordinates in the 3D model.txt file are sometimes reordered by the scaling script - // however, the cellindex always should increment X first, then Y, then Z - - for (int axis = 0; axis < 3; axis++) { - const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; - const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); - // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid - // %d\n", - // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, - // get_cellcoordpointnum(mgi, axis), ncoordgrid[axis]); - if (fabs(cellpos_expected - cellpos_in[axis]) > 0.5 * cellwidth) { - posmatch_xyz = false; - } - if (fabs(cellpos_expected - cellpos_in[2 - axis]) > 0.5 * cellwidth) { - posmatch_zyx = false; - } - } - - if (rho_model < 0) { - printout("negative input density %g %d\n", rho_model, mgi); - std::abort(); - } - - // in 3D cartesian, cellindex and modelgridindex are interchangeable - const bool keepcell = (rho_model > 0); - const double rho_tmin = rho_model * pow(t_model / globals::tmin, 3); - set_rho_tmin(mgi, rho_tmin); - set_rho(mgi, rho_tmin); - - if (min_den < 0. || min_den > rho_model) { - min_den = rho_model; - } - - read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); - - mgi++; - } - if (mgi != npts_model_in) { - printout("ERROR in model.txt. Found %d cells instead of %d expected.\n", mgi, npts_model_in); - std::abort(); - } - - // assert_always(posmatch_zyx ^ posmatch_xyz); // xor because if both match then probably an infinity occurred - if (posmatch_xyz) { - printout("Cell positions in model.txt are consistent with calculated values when x-y-z column order is used.\n"); - } - if (posmatch_zyx) { - printout("Cell positions in model.txt are consistent with calculated values when z-y-x column order is used.\n"); - } - - if (!posmatch_xyz && !posmatch_zyx) { - printout( - "WARNING: Cell positions in model.txt are not consistent with calculated values in either x-y-z or z-y-x " - "order.\n"); - } - - printout("min_den %g [g/cm3]\n", min_den); -} - auto get_inputcellvolume(const int mgi) -> double { if (get_model_type() == GridType::SPHERICAL1D) { const double v_inner = (mgi == 0) ? 0. : vout_model[mgi - 1]; @@ -1100,8 +854,8 @@ void read_grid_restart_data(const int timestep) { assert_always(fscanf(gridsave_file, "%d %a %a %a %a %d %la %la %la %la %a %a", &mgi_in, &T_R, &T_e, &W, &T_J, &thick, &globals::dep_estimator_gamma[nonemptymgi], &globals::dep_estimator_positron[nonemptymgi], &globals::dep_estimator_electron[nonemptymgi], - &globals::dep_estimator_alpha[nonemptymgi], &modelgrid[mgi].nne, - &modelgrid[mgi].nnetot) == 12); + &globals::dep_estimator_alpha[nonemptymgi], &modelgrid[nonemptymgi].nne, + &modelgrid[nonemptymgi].nnetot) == 12); if (mgi_in != mgi) { printout("[fatal] read_grid_restart_data: cell mismatch in reading input gridsave.dat ... abort\n"); @@ -1118,11 +872,11 @@ void read_grid_restart_data(const int timestep) { assert_always(globals::dep_estimator_electron[nonemptymgi] >= 0.); assert_always(globals::dep_estimator_alpha[nonemptymgi] >= 0.); - set_TR(mgi, T_R); - set_Te(mgi, T_e); - set_W(mgi, W); - set_TJ(mgi, T_J); - modelgrid[mgi].thick = thick; + set_TR(nonemptymgi, T_R); + set_Te(nonemptymgi, T_e); + set_W(nonemptymgi, W); + set_TJ(nonemptymgi, T_J); + modelgrid[nonemptymgi].thick = thick; if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { @@ -1135,8 +889,14 @@ void read_grid_restart_data(const int timestep) { // the order of these calls is very important! radfield::read_restart_data(gridsave_file); - nonthermal::read_restart_data(gridsave_file); - nltepop_read_restart_data(gridsave_file); + if (globals::rank_in_node == 0) { + // all data is shared on the node + nonthermal::read_restart_data(gridsave_file); + nltepop_read_restart_data(gridsave_file); + } +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif fclose(gridsave_file); } @@ -1159,10 +919,10 @@ void assign_initial_temperatures() { int cells_below_mintemp = 0; int cells_above_maxtemp = 0; - for (int nonempymgi = 0; nonempymgi < get_nonempty_npts_model(); nonempymgi++) { - const int mgi = get_mgi_of_nonemptymgi(nonempymgi); + for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); - double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(nonempymgi, tstart); + double decayedenergy_per_mass = decay::get_endecay_per_ejectamass_t0_to_time_withexpansion(nonemptymgi, tstart); if constexpr (INITIAL_PACKETS_ON && USE_MODEL_INITIAL_ENERGY) { decayedenergy_per_mass += get_initenergyq(mgi); } @@ -1183,12 +943,11 @@ void assign_initial_temperatures() { } assert_always(std::isfinite(T_initial)); - set_Te(mgi, T_initial); - set_TJ(mgi, T_initial); - set_TR(mgi, T_initial); - - set_W(mgi, 1.); - modelgrid[mgi].thick = 0; + set_Te(nonemptymgi, T_initial); + set_TJ(nonemptymgi, T_initial); + set_TR(nonemptymgi, T_initial); + set_W(nonemptymgi, 1.); + modelgrid[nonemptymgi].thick = 0; } printout(" cells below MINTEMP %g: %d\n", MINTEMP, cells_below_mintemp); printout(" cells above MAXTEMP %g: %d\n", MAXTEMP, cells_above_maxtemp); @@ -1206,9 +965,10 @@ void assign_initial_temperatures() { void setup_nstart_ndo() { const int nprocesses = globals::nprocs; - const int npts_nonempty = get_nonempty_npts_model(); - const int min_nonempty_perproc = npts_nonempty / nprocesses; // integer division, minimum non-empty cells per process - const int n_remainder = npts_nonempty % nprocesses; + assert_always(nonempty_npts_model > 0); + const int min_nonempty_perproc = + nonempty_npts_model / nprocesses; // integer division, minimum non-empty cells per process + const int n_remainder = nonempty_npts_model % nprocesses; ranks_nstart.resize(nprocesses, -1); ranks_nstart_nonempty.resize(nprocesses, -1); @@ -1254,13 +1014,13 @@ void setup_nstart_ndo() { } int npts_assigned = 0; - int npts_nonempty_assigned = 0; + int nonempty_npts_model_assigned = 0; for (int r = 0; r < nprocesses; r++) { npts_assigned += ranks_ndo[r]; - npts_nonempty_assigned += ranks_ndo_nonempty[r]; + nonempty_npts_model_assigned += ranks_ndo_nonempty[r]; } assert_always(npts_assigned == get_npts_model()); - assert_always(npts_nonempty_assigned == get_nonempty_npts_model()); + assert_always(nonempty_npts_model_assigned == get_nonempty_npts_model()); if (globals::my_rank == 0) { auto fileout = std::ofstream("modelgridrankassignments.out"); @@ -1360,8 +1120,8 @@ void setup_grid_cylindrical_2d() { } } -auto get_grid_type_name() -> std::string { - switch (GRID_TYPE) { +auto get_grid_type_name(const GridType gridtype) -> std::string { + switch (gridtype) { case GridType::SPHERICAL1D: return "spherical"; case GridType::CYLINDRICAL2D: @@ -1659,8 +1419,6 @@ auto get_cellcoordmin(const int cellindex, const int axis) -> double { // how much do we change the cellindex to move along a coordinately axis (e.g., the x, y, z directions, or r // direction) auto get_coordcellindexincrement(const int axis) -> int { - // assert_testmodeonly(axis < get_ngriddimensions()); - switch (axis) { case 0: return 1; @@ -1713,34 +1471,40 @@ auto get_cellcoordpointnum(const int cellindex, const int axis) -> int { assert_always(false); } -auto get_rho_tmin(const int modelgridindex) -> float { return modelgrid[modelgridindex].rhoinit; } +auto get_rho_tmin(const int modelgridindex) -> float { return modelgrid_input[modelgridindex].rhoinit; } -__host__ __device__ auto get_rho(const int modelgridindex) -> float { return modelgrid[modelgridindex].rho; } - -__host__ __device__ auto get_nne(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); +__host__ __device__ auto get_rho(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return modelgrid[nonemptymgi].rho; +} - const double nne = modelgrid[modelgridindex].nne; +__host__ __device__ auto get_nne(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + const double nne = modelgrid[nonemptymgi].nne; assert_testmodeonly(std::isfinite(nne)); return nne; } -__host__ __device__ auto get_nnetot(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex < (get_npts_model() + 1)); - - const double nnetot = modelgrid[modelgridindex].nnetot; - assert_always(std::isfinite(nnetot)); +__host__ __device__ auto get_nnetot(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + const double nnetot = modelgrid[nonemptymgi].nnetot; return nnetot; } -__host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { return modelgrid[modelgridindex].ffegrp; } +__host__ __device__ auto get_ffegrp(const int modelgridindex) -> float { + return modelgrid_input[modelgridindex].ffegrp; +} + +__host__ __device__ auto get_initial_radial_pos_sum(const int modelgridindex) -> float { + return modelgrid_input[modelgridindex].initial_radial_pos_sum; +} -auto get_elem_abundance(int modelgridindex, int element) -> float +auto get_elem_abundance(int nonemptymgi, int element) -> float // mass fraction of an element (all isotopes combined) { - const int nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); const auto massfrac = elem_massfracs_allcells[(static_cast(nonemptymgi) * get_nelements()) + element]; assert_testmodeonly(massfrac >= 0.0); return massfrac; @@ -1752,67 +1516,63 @@ void set_elem_abundance(const int nonemptymgi, const int element, const float ne } // mass fraction of an element (all isotopes combined) -__host__ __device__ auto get_elem_numberdens(const int modelgridindex, const int element) -> double { - const auto nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); +__host__ __device__ auto get_elem_numberdens(const int nonemptymgi, const int element) -> double { const double elem_meanweight = grid::get_element_meanweight(nonemptymgi, element); - return get_elem_abundance(modelgridindex, element) / elem_meanweight * grid::get_rho(modelgridindex); + return get_elem_abundance(nonemptymgi, element) / elem_meanweight * grid::get_rho(nonemptymgi); } -__host__ __device__ auto get_kappagrey(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].kappagrey; -} +__host__ __device__ auto get_kappagrey(const int nonemptymgi) -> float { return modelgrid[nonemptymgi].kappagrey; } -__host__ __device__ auto get_Te(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].Te; +__host__ __device__ auto get_Te(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return modelgrid[nonemptymgi].Te; } -__host__ __device__ auto get_TR(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].TR; +__host__ __device__ auto get_TR(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return modelgrid[nonemptymgi].TR; } -__host__ __device__ auto get_TJ(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].TJ; +__host__ __device__ auto get_TJ(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return modelgrid[nonemptymgi].TJ; } -__host__ __device__ auto get_W(const int modelgridindex) -> float { - assert_testmodeonly(modelgridindex >= 0); - assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid[modelgridindex].W; +__host__ __device__ auto get_W(const int nonemptymgi) -> float { + assert_testmodeonly(nonemptymgi >= 0); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return modelgrid[nonemptymgi].W; } -void set_rho(const int modelgridindex, const float rho) { +void set_rho(const int nonemptymgi, const float rho) { assert_always(rho >= 0.); assert_always(std::isfinite(rho)); - modelgrid[modelgridindex].rho = rho; + modelgrid[nonemptymgi].rho = rho; } -void set_nne(const int modelgridindex, const float nne) { +void set_nne(const int nonemptymgi, const float nne) { assert_always(nne >= 0.); assert_always(std::isfinite(nne)); - modelgrid[modelgridindex].nne = nne; + modelgrid[nonemptymgi].nne = nne; } -void set_nnetot(const int modelgridindex, const float nnetot) { +void set_nnetot(const int nonemptymgi, const float nnetot) { assert_always(nnetot >= 0.); assert_always(std::isfinite(nnetot)); - modelgrid[modelgridindex].nnetot = nnetot; + modelgrid[nonemptymgi].nnetot = nnetot; } -void set_kappagrey(const int modelgridindex, const float kappagrey) { modelgrid[modelgridindex].kappagrey = kappagrey; } +void set_kappagrey(const int nonemptymgi, const float kappagrey) { modelgrid[nonemptymgi].kappagrey = kappagrey; } -void set_Te(const int modelgridindex, const float Te) { +void set_Te(const int nonemptymgi, const float Te) { if (Te > 0.) { // ignore the zero initialisation value for this check const double nu_peak = 5.879e10 * Te; if (nu_peak > NU_MAX_R || nu_peak < NU_MIN_R) { + const auto modelgridindex = get_mgi_of_nonemptymgi(nonemptymgi); printout( "[warning] modelgridindex %d B_planck(Te=%g K) peak at %g Hz is outside frequency range NU_MIN_R %g NU_MAX_R " "%g\n", @@ -1820,14 +1580,14 @@ void set_Te(const int modelgridindex, const float Te) { } } - modelgrid[modelgridindex].Te = Te; + modelgrid[nonemptymgi].Te = Te; } -void set_TR(const int modelgridindex, const float TR) { modelgrid[modelgridindex].TR = TR; } +void set_TR(const int nonemptymgi, const float TR) { modelgrid[nonemptymgi].TR = TR; } -void set_TJ(const int modelgridindex, const float TJ) { modelgrid[modelgridindex].TJ = TJ; } +void set_TJ(const int nonemptymgi, const float TJ) { modelgrid[nonemptymgi].TJ = TJ; } -void set_W(const int modelgridindex, const float W) { modelgrid[modelgridindex].W = W; } +void set_W(const int nonemptymgi, const float W) { modelgrid[nonemptymgi].W = W; } auto get_model_type() -> GridType { return model_type; } @@ -1852,15 +1612,22 @@ auto get_t_model() -> double { return t_model; } -__host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { +[[nodiscard]] __host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { assert_testmodeonly(cellindex >= 0); assert_testmodeonly(cellindex < ngrid); - const int mgi = cell[cellindex].modelgridindex; + const auto mgi = cell[cellindex].modelgridindex; assert_testmodeonly(mgi >= 0); assert_testmodeonly(mgi < (get_npts_model() + 1)); return mgi; } +[[nodiscard]] __host__ __device__ auto get_propcell_nonemptymgi(const int cellindex) -> int { + const auto nonemptymgi = nonemptymgi_of_propcell[cellindex]; + assert_testmodeonly(nonemptymgi >= -1); + assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); + return nonemptymgi; +} + // number of propagation cells associated with each modelgrid cell __host__ __device__ auto get_numpropcells(const int modelgridindex) -> int { assert_testmodeonly(modelgridindex <= get_npts_model()); @@ -1924,18 +1691,19 @@ void set_element_meanweight(const int nonemptymgi, const int element, const floa } auto get_electronfrac(const int nonemptymgi) -> double { - const auto modelgridindex = get_mgi_of_nonemptymgi(nonemptymgi); double nucleondens = 0.; for (int element = 0; element < get_nelements(); element++) { - nucleondens += get_elem_numberdens(modelgridindex, element) * get_element_meanweight(nonemptymgi, element) / MH; + nucleondens += get_elem_numberdens(nonemptymgi, element) * get_element_meanweight(nonemptymgi, element) / MH; } - return get_nnetot(modelgridindex) / nucleondens; + return get_nnetot(nonemptymgi) / nucleondens; } -auto get_initelectronfrac(const int modelgridindex) -> double { return modelgrid[modelgridindex].initelectronfrac; } +auto get_initelectronfrac(const int modelgridindex) -> double { + return modelgrid_input[modelgridindex].initelectronfrac; +} // q: energy in the model at tmin per gram to use with USE_MODEL_INITIAL_ENERGY option [erg/g] -auto get_initenergyq(const int modelgridindex) -> double { return modelgrid[modelgridindex].initenergyq; } +auto get_initenergyq(const int modelgridindex) -> double { return modelgrid_input[modelgridindex].initenergyq; } // get the radial distance from the origin to the centre of the cell at time tmin auto get_cellradialposmid(const int cellindex) -> double { @@ -1968,8 +1736,7 @@ auto get_cellradialposmid(const int cellindex) -> double { return elements_uppermost_ion_allcells[(nonemptymgi * get_nelements()) + element]; } -void set_elements_uppermost_ion(const int modelgridindex, const int element, const int newvalue) { - const ptrdiff_t nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); +void set_elements_uppermost_ion(const int nonemptymgi, const int element, const int newvalue) { elements_uppermost_ion_allcells[(nonemptymgi * get_nelements()) + element] = newvalue; } @@ -1979,8 +1746,8 @@ void calculate_kappagrey() { double opcase3_sum = 0.; const int empty_cells = 0; - for (int n = 0; n < ngrid; n++) { - const int mgi = get_cell_modelgridindex(n); + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); rho_sum += get_rho_tmin(mgi); fe_sum += get_ffegrp(mgi); @@ -1992,14 +1759,14 @@ void calculate_kappagrey() { kappagrey *= globals::rho_crit / get_rho_tmin(mgi); } - set_kappagrey(mgi, kappagrey); + set_kappagrey(nonemptymgi, kappagrey); } else if (get_rho_tmin(mgi) == 0.) { - set_kappagrey(mgi, 0.); + set_kappagrey(nonemptymgi, 0.); } else if (get_rho_tmin(mgi) < 0.) { printout("Error: negative density. Abort.\n"); std::abort(); } - opcase3_sum += get_kappagrey(mgi) * get_rho_tmin(mgi); + opcase3_sum += get_kappagrey(nonemptymgi) * get_rho_tmin(mgi); } } @@ -2020,7 +1787,7 @@ void calculate_kappagrey() { kappa = opcase2_normal / get_rho_tmin(mgi) * ((0.9 * get_ffegrp(mgi)) + 0.1); } else if (globals::opacity_case == 3) { globals::opcase3_normal = globals::GREY_OP * rho_sum / opcase3_sum; - kappa = get_kappagrey(mgi) * globals::opcase3_normal; + kappa = get_kappagrey(nonemptymgi) * globals::opcase3_normal; } else if (globals::opacity_case == 5) { // electron-fraction-dependent opacities // values from table 1 of Tanaka et al. (2020). @@ -2045,12 +1812,12 @@ void calculate_kappagrey() { // grey opacity used in Just+2022, https://ui.adsabs.harvard.edu/abs/2022MNRAS.510.2820J/abstract // kappa is a simple analytic function of temperature and lanthanide mass fraction // adapted to best fit lightcurves from Kasen+2017 in ALCAR simulations - const double T_rad = get_TR(mgi); + const double T_rad = get_TR(nonemptymgi); double X_lan = 0.; for (int element = 0; element < get_nelements(); element++) { const int z = get_atomicnumber(element); if (z >= 57 && z <= 71) { - X_lan += get_elem_abundance(mgi, element); + X_lan += get_elem_abundance(nonemptymgi, element); } } // first step: temperature-independent factor @@ -2072,15 +1839,15 @@ void calculate_kappagrey() { std::abort(); } - set_kappagrey(mgi, kappa); + set_kappagrey(nonemptymgi, kappa); } else if (get_rho_tmin(mgi) == 0.) { - set_kappagrey(mgi, 0.); + set_kappagrey(nonemptymgi, 0.); } else if (get_rho_tmin(mgi) < 0.) { printout("Error: negative density. Abort.\n"); std::abort(); } - check1 = check1 + (get_kappagrey(mgi) * get_rho_tmin(mgi)); + check1 = check1 + (get_kappagrey(nonemptymgi) * get_rho_tmin(mgi)); check2 = check2 + get_rho_tmin(mgi); } @@ -2088,26 +1855,263 @@ void calculate_kappagrey() { } void read_ejecta_model() { - switch (get_model_type()) { - case GridType::SPHERICAL1D: { - printout("Read 1D model\n"); - read_1d_model(); - break; + auto fmodel = fstream_required("model.txt", std::ios::in); + std::string line; + + // two integers on the first line of the model file + int npts_0 = 0; // total model points for 1D/3D, and number of points in r for 2D + int npts_1 = 0; // number of points in z for 2D + assert_always(get_noncommentline(fmodel, line)); + auto ssline = std::istringstream(line); + ssline >> npts_0; + if (get_model_type() == GridType::SPHERICAL1D) { + ncoord_model[0] = npts_0; + ncoord_model[1] = 0; + ncoord_model[2] = 0; + } else if (get_model_type() == GridType::CYLINDRICAL2D) { + ssline >> npts_1; // r and z (cylindrical polar) + ncoord_model[0] = npts_0; + ncoord_model[1] = npts_1; + ncoord_model[2] = 0; + } else if (get_model_type() == GridType::CARTESIAN3D) { + ncoord_model[0] = static_cast(round(pow(npts_0, 1 / 3.))); + ncoord_model[1] = ncoord_model[0]; + ncoord_model[2] = ncoord_model[0]; + assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_0); + } + npts_model = std::max(1, ncoord_model[0]) * std::max(1, ncoord_model[1]) * std::max(1, ncoord_model[2]); + + assert_always(modelgrid_input.data() == nullptr); + modelgrid_input = MPI_shared_malloc_span(npts_model + 1); + if (globals::rank_in_node == 0) { + std::ranges::fill(modelgrid_input, ModelGridCellInput{}); + } +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif + mg_associated_cells.resize(npts_model + 1, 0); + nonemptymgi_of_mgi.resize(npts_model + 1, -1); + + if (get_model_type() == GridType::SPHERICAL1D) { + printout("Read 1D model\n"); + + // Now read the time (in days) at which the model is specified. + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; + + vout_model.resize(get_npts_model(), NAN); + + // Now read in the lines of the model. Each line has 5 entries: the + // cell number (integer) the velocity at outer boundary of cell (float), + // the mass density in the cell (float), the abundance of Ni56 by mass + // in the cell (float) and the total abundance of all Fe-grp elements + // in the cell (float). For now, the last number is recorded but never + // used. + + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + + int mgi = 0; + while (std::getline(fmodel, line)) { + double vout_kmps{NAN}; + double log_rho{NAN}; + int cellnumberin = 0; + ssline = std::istringstream(line); + + if (ssline >> cellnumberin >> vout_kmps >> log_rho) { + if (mgi == 0) { + first_cellindex = cellnumberin; + printout("first_cellindex %d\n", first_cellindex); + } + assert_always(cellnumberin == mgi + first_cellindex); + + vout_model[mgi] = vout_kmps * 1.e5; + + const double rho_tmin = pow(10., log_rho) * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + } else { + printout("Unexpected number of values in model.txt\n"); + printout("line: %s\n", line.c_str()); + assert_always(false); + } + read_model_radioabundances(fmodel, ssline, mgi, true, colnames, nucindexlist, one_line_per_cell); + + mgi += 1; + if (mgi == get_npts_model()) { + break; + } + } + + if (mgi != get_npts_model()) { + printout("ERROR in model.txt. Found only %d cells instead of %d expected.\n", mgi - 1, get_npts_model()); + std::abort(); + } + + globals::vmax = vout_model[get_npts_model() - 1]; + } else if (get_model_type() == GridType::CYLINDRICAL2D) { + printout("Read 2D model\n"); + + // Now read the time (in days) at which the model is specified. + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; + + // Now read in vmax for the model (in cm s^-1). + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> globals::vmax; + + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + + // Now read in the model. Each point in the model has two lines of input. + // First is an index for the cell then its r-mid point then its z-mid point + // then its total mass density. + // Second is the total FeG mass, initial 56Ni mass, initial 56Co mass + + int mgi = 0; + while (std::getline(fmodel, line)) { + int cellnumberin = 0; + float cell_r_in{NAN}; + float cell_z_in{NAN}; + double rho_tmodel{NAN}; + ssline = std::istringstream(line); + assert_always(ssline >> cellnumberin >> cell_r_in >> cell_z_in >> rho_tmodel); + + if (mgi == 0) { + first_cellindex = cellnumberin; + } + assert_always(cellnumberin == mgi + first_cellindex); + + const int n_rcyl = (mgi % ncoord_model[0]); + const double pos_r_cyl_mid = (n_rcyl + 0.5) * globals::vmax * t_model / ncoord_model[0]; + assert_always(fabs((cell_r_in / pos_r_cyl_mid) - 1) < 1e-3); + const int n_z = (mgi / ncoord_model[0]); + const double pos_z_mid = globals::vmax * t_model * (-1 + 2 * (n_z + 0.5) / ncoord_model[1]); + assert_always(fabs((cell_z_in / pos_z_mid) - 1) < 1e-3); + + if (rho_tmodel < 0) { + printout("negative input density %g %d\n", rho_tmodel, mgi); + std::abort(); + } + + const bool keepcell = (rho_tmodel > 0); + const double rho_tmin = rho_tmodel * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + + read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); + + mgi++; + } + + if (mgi != get_npts_model()) { + printout("ERROR in model.txt. Found %d only cells instead of %d expected.\n", mgi - 1, get_npts_model()); + std::abort(); } + } else if (get_model_type() == GridType::CARTESIAN3D) { + printout("Read 3D model\n"); - case GridType::CYLINDRICAL2D: { - printout("Read 2D model\n"); + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; - read_2d_model(); - break; + // for a 3D input model, the propagation cells will match the input cells exactly + ncoordgrid = ncoord_model; + ngrid = npts_model; + + // Now read in vmax for the model (in cm s^-1). + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> globals::vmax; + + const double xmax_tmodel = globals::vmax * t_model; + + // Now read in the lines of the model. + min_den = -1.; + + // check if expected positions match in either xyz or zyx column order + // set false if a problem is detected + bool posmatch_xyz = true; + bool posmatch_zyx = true; + + const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); + + // mgi is the index to the model grid - empty cells are sent to special value get_npts_model(), + // otherwise each input cell is one modelgrid cell + int mgi = 0; // corresponds to model.txt index column, but zero indexed! (model.txt might be 1-indexed) + while (std::getline(fmodel, line)) { + int cellnumberin = 0; + std::array cellpos_in{}; + float rho_model{NAN}; + ssline = std::istringstream(line); + + assert_always(ssline >> cellnumberin >> cellpos_in[0] >> cellpos_in[1] >> cellpos_in[2] >> rho_model); + + if (mgi == 0) { + first_cellindex = cellnumberin; + } + assert_always(cellnumberin == mgi + first_cellindex); + + if (mgi % (ncoord_model[1] * ncoord_model[2]) == 0) { + printout("read up to cell mgi %d\n", mgi); + } + + // cell coordinates in the 3D model.txt file are sometimes reordered by the scaling script + // however, the cellindex always should increment X first, then Y, then Z + + for (int axis = 0; axis < 3; axis++) { + const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; + const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); + // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid + // %d\n", + // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, + // get_cellcoordpointnum(mgi, axis), ncoordgrid[axis]); + if (fabs(cellpos_expected - cellpos_in[axis]) > 0.5 * cellwidth) { + posmatch_xyz = false; + } + if (fabs(cellpos_expected - cellpos_in[2 - axis]) > 0.5 * cellwidth) { + posmatch_zyx = false; + } + } + + if (rho_model < 0) { + printout("negative input density %g %d\n", rho_model, mgi); + std::abort(); + } + + // in 3D cartesian, cellindex and modelgridindex are interchangeable + const bool keepcell = (rho_model > 0); + const double rho_tmin = rho_model * pow(t_model / globals::tmin, 3); + set_rho_tmin(mgi, rho_tmin); + + if (min_den < 0. || min_den > rho_model) { + min_den = rho_model; + } + + read_model_radioabundances(fmodel, ssline, mgi, keepcell, colnames, nucindexlist, one_line_per_cell); + + mgi++; + } + if (mgi != npts_model) { + printout("ERROR in model.txt. Found %d cells instead of %td expected.\n", mgi, npts_model); + std::abort(); } - case GridType::CARTESIAN3D: { - printout("Read 3D model\n"); + // assert_always(posmatch_zyx ^ posmatch_xyz); // xor because if both match then probably an infinity occurred + if (posmatch_xyz) { + printout("Cell positions in model.txt are consistent with calculated values when x-y-z column order is used.\n"); + } + if (posmatch_zyx) { + printout("Cell positions in model.txt are consistent with calculated values when z-y-x column order is used.\n"); + } - read_3d_model(); - break; + if (!posmatch_xyz && !posmatch_zyx) { + printout( + "WARNING: Cell positions in model.txt are not consistent with calculated values in either x-y-z or z-y-x " + "order.\n"); } + + printout("min_den %g [g/cm3]\n", min_den); } printout("npts_model: %d\n", get_npts_model()); @@ -2162,10 +2166,11 @@ void write_grid_restart_data(const int timestep) { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); assert_always(globals::dep_estimator_gamma[nonemptymgi] >= 0.); - fprintf(gridsave_file, "%d %a %a %a %a %d %la %la %la %la %a %a", mgi, get_TR(mgi), get_Te(mgi), get_W(mgi), - get_TJ(mgi), modelgrid[mgi].thick, globals::dep_estimator_gamma[nonemptymgi], - globals::dep_estimator_positron[nonemptymgi], globals::dep_estimator_electron[nonemptymgi], - globals::dep_estimator_alpha[nonemptymgi], modelgrid[mgi].nne, modelgrid[mgi].nnetot); + fprintf(gridsave_file, "%d %a %a %a %a %d %la %la %la %la %a %a", mgi, get_TR(nonemptymgi), get_Te(nonemptymgi), + get_W(nonemptymgi), get_TJ(nonemptymgi), modelgrid[nonemptymgi].thick, + globals::dep_estimator_gamma[nonemptymgi], globals::dep_estimator_positron[nonemptymgi], + globals::dep_estimator_electron[nonemptymgi], globals::dep_estimator_alpha[nonemptymgi], + modelgrid[nonemptymgi].nne, modelgrid[nonemptymgi].nnetot); if constexpr (USE_LUT_PHOTOION) { for (int i = 0; i < globals::nbfcontinua_ground; i++) { @@ -2229,9 +2234,10 @@ void grid_init(const int my_rank) { std::abort(); } - printout("propagation grid: %d-dimensional %s\n", get_ngriddimensions(), get_grid_type_name().c_str()); + printout("propagation grid: %d-dimensional %s\n", get_ngriddimensions(GRID_TYPE), + get_grid_type_name(GRID_TYPE).c_str()); - for (int d = 0; d < get_ngriddimensions(); d++) { + for (int d = 0; d < get_ngriddimensions(GRID_TYPE); d++) { printout(" coordinate %d '%c': cells have %d position values\n", d, coordlabel[d], ncoordgrid[d]); } printout(" total propagation cells: %d\n", ngrid); @@ -2342,13 +2348,13 @@ auto get_totmassradionuclide(const int z, const int a) -> double { [[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, const double time) -> int { auto posgridcoords = get_gridcoords_from_xyz(pos); int cellindex = 0; - for (int d = 0; d < get_ngriddimensions(); d++) { + for (int d = 0; d < get_ngriddimensions(GRID_TYPE); d++) { cellindex += get_coordcellindexincrement(d) * get_poscoordpointnum(posgridcoords[d], time, d); } // do a check that the position is within the cell const double trat = time / globals::tmin; - for (int n = 0; n < grid::get_ngriddimensions(); n++) { + for (int n = 0; n < grid::get_ngriddimensions(GRID_TYPE); n++) { assert_always(posgridcoords[n] >= grid::get_cellcoordmin(cellindex, n) * trat); assert_always(posgridcoords[n] <= grid::get_cellcoordmax(cellindex, n) * trat); } @@ -2370,7 +2376,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // d is used to loop over the coordinate indicies 0,1,2 for x,y,z // the following four vectors are in grid coordinates, so either x,y,z or r - const int ndim = grid::get_ngriddimensions(); + const int ndim = grid::get_ngriddimensions(GRID_TYPE); assert_testmodeonly(ndim <= 3); auto cellcoordmax = std::array{0}; auto pktvelgridcoord = std::array{0}; // dir * CLIGHT_PROP converted from xyz to grid coordinates @@ -2488,7 +2494,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // cartesian coordinates may be taken in turn. For x, the packet // trajectory is // x = x0 + (dir.x) * c * (t - tstart) - // the boundries follow + // the boundaries follow // x+/- = x+/-(tmin) * (t/tmin) // so the crossing occurs when // t = (x0 - (dir.x)*c*tstart)/(x+/-(tmin)/tmin - (dir.x)c) diff --git a/grid.h b/grid.h index 332e631be..d086e6b0b 100644 --- a/grid.h +++ b/grid.h @@ -21,14 +21,9 @@ struct ModelGridCell { float TJ = -1.; float W = -1.; float nne = -1.; - float initial_radial_pos_sum = 0.; - float rhoinit = -1.; float rho = -1.; // modelgrid nn_tot - float nnetot = -1.; // total electron density (free + bound). - float initelectronfrac = -1; // Ye: electrons (or protons) per nucleon - float initenergyq = 0.; // q: energy in the model at tmin to use with USE_MODEL_INITIAL_ENERGY [erg/g] - float ffegrp = 0.; + float nnetot = -1.; // total electron density (free + bound). float kappagrey = 0.; float grey_depth = 0.; // Grey optical depth to surface of the modelgridcell // This is only stored to print it outside the OpenMP loop in update_grid to the @@ -37,8 +32,8 @@ struct ModelGridCell { int thick = 0; }; -consteval auto get_ngriddimensions() -> int { - switch (GRID_TYPE) { +consteval auto get_ngriddimensions(const GridType gridtype) -> int { + switch (gridtype) { case GridType::SPHERICAL1D: return 1; case GridType::CYLINDRICAL2D: @@ -66,7 +61,7 @@ inline float *ion_partfuncts_allcells{}; inline double *ion_cooling_contribs_allcells{}; [[nodiscard]] auto get_elements_uppermost_ion(int modelgridindex, int element) -> int; -void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); +void set_elements_uppermost_ion(int nonemptymgi, int element, int newvalue); [[nodiscard]] auto wid_init(int cellindex, int axis) -> double; [[nodiscard]] auto get_modelcell_assocvolume_tmin(int modelgridindex) -> double; [[nodiscard]] auto get_gridcell_volume_tmin(int cellindex) -> double; @@ -76,32 +71,33 @@ void set_elements_uppermost_ion(int modelgridindex, int element, int newvalue); [[nodiscard]] auto get_cellradialposmid(int cellindex) -> double; [[nodiscard]] auto get_coordcellindexincrement(int axis) -> int; [[nodiscard]] auto get_rho_tmin(int modelgridindex) -> float; -[[nodiscard]] auto get_rho(int modelgridindex) -> float; -[[nodiscard]] auto get_nne(int modelgridindex) -> float; -[[nodiscard]] auto get_nnetot(int modelgridindex) -> float; +[[nodiscard]] auto get_rho(int nonemptymgi) -> float; +[[nodiscard]] auto get_nne(int nonemptymgi) -> float; +[[nodiscard]] auto get_nnetot(int nonemptymgi) -> float; [[nodiscard]] auto get_ffegrp(int modelgridindex) -> float; +[[nodiscard]] auto get_initial_radial_pos_sum(int modelgridindex) -> float; void set_elem_abundance(int nonemptymgi, int element, float newabundance); -[[nodiscard]] auto get_elem_numberdens(int modelgridindex, int element) -> double; +[[nodiscard]] auto get_elem_numberdens(int nonemptymgi, int element) -> double; [[nodiscard]] auto get_initelectronfrac(int modelgridindex) -> double; [[nodiscard]] auto get_initenergyq(int modelgridindex) -> double; -[[nodiscard]] auto get_kappagrey(int modelgridindex) -> float; -[[nodiscard]] auto get_Te(int modelgridindex) -> float; -[[nodiscard]] auto get_TR(int modelgridindex) -> float; -[[nodiscard]] auto get_TJ(int modelgridindex) -> float; -[[nodiscard]] auto get_W(int modelgridindex) -> float; -void set_nne(int modelgridindex, float nne); -void set_nnetot(int modelgridindex, float nnetot); -void set_kappagrey(int modelgridindex, float kappagrey); -void set_rho(int modelgridindex, float rho); -void set_Te(int modelgridindex, float Te); -void set_TR(int modelgridindex, float TR); -void set_TJ(int modelgridindex, float TJ); -void set_W(int modelgridindex, float W); +[[nodiscard]] auto get_kappagrey(int nonemptymgi) -> float; +[[nodiscard]] auto get_Te(int nonemptymgi) -> float; +[[nodiscard]] auto get_TR(int nonemptymgi) -> float; +[[nodiscard]] auto get_TJ(int nonemptymgi) -> float; +[[nodiscard]] auto get_W(int nonemptymgi) -> float; +void set_nne(int nonemptymgi, float nne); +void set_nnetot(int nonemptymgi, float nnetot); +void set_kappagrey(int nonemptymgi, float kappagrey); +void set_rho(int nonemptymgi, float rho); +void set_Te(int nonemptymgi, float Te); +void set_TR(int nonemptymgi, float TR); +void set_TJ(int nonemptymgi, float TJ); +void set_W(int nonemptymgi, float W); void grid_init(int my_rank); [[nodiscard]] auto get_modelinitnucmassfrac(int modelgridindex, int nucindex) -> float; [[nodiscard]] auto get_stable_initabund(int nonemptymgi, int element) -> float; [[nodiscard]] auto get_element_meanweight(int nonemptymgi, int element) -> float; -[[nodiscard]] auto get_elem_abundance(int modelgridindex, int element) -> float; +[[nodiscard]] auto get_elem_abundance(int nonemptymgi, int element) -> float; void set_element_meanweight(int nonemptymgi, int element, float meanweight); [[nodiscard]] auto get_electronfrac(int nonemptymgi) -> double; [[nodiscard]] auto get_numpropcells(int modelgridindex) -> int; @@ -113,6 +109,7 @@ void set_model_type(GridType model_type_value); [[nodiscard]] auto get_nonempty_npts_model() -> int; [[nodiscard]] auto get_t_model() -> double; [[nodiscard]] auto get_cell_modelgridindex(int cellindex) -> int; +[[nodiscard]] auto get_propcell_nonemptymgi(int cellindex) -> int; [[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, double time) -> int; void read_ejecta_model(); void write_grid_restart_data(int timestep); @@ -146,11 +143,11 @@ inline void change_cell(Packet &pkt, const int snext) inline auto get_ejecta_kinetic_energy() { double E_kin = 0.; - for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const int assoc_cells = grid::get_numpropcells(mgi); - double M_cell = grid::get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); - const double radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum / assoc_cells; + for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { + const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); + const int assoc_cells = get_numpropcells(mgi); + double M_cell = get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); + const double radial_pos = get_initial_radial_pos_sum(mgi) / assoc_cells; E_kin += 0.5 * M_cell * std::pow(radial_pos / globals::tmin, 2); } diff --git a/input.cc b/input.cc index a93d88fb7..43d432a12 100644 --- a/input.cc +++ b/input.cc @@ -474,8 +474,7 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons int alltransindex = temp_alltranslist_size; temp_alltranslist_size += totupdowntrans; if (globals::rank_in_node == 0) { - temp_alltranslist.reserve(temp_alltranslist_size); - temp_alltranslist.resize(temp_alltranslist_size); + resize_exactly(temp_alltranslist, temp_alltranslist_size); assert_always(temp_alltranslist_size >= temp_linelist.size()); temp_linelist.reserve(temp_alltranslist_size); } @@ -1286,7 +1285,7 @@ void setup_cellcache() { printout("[info] input: initializing cellcache for thread %d ...\n", cellcachenum); - globals::cellcache[cellcachenum].cellnumber = -99; + globals::cellcache[cellcachenum].nonemptymgi = -1; const auto ncoolingterms = kpkt::ncoolingterms; mem_usage_cellcache += ncoolingterms * sizeof(double); @@ -1321,8 +1320,8 @@ void setup_cellcache() { } } assert_always(chlevelcount > 0); - globals::cellcache[cellcachenum].ch_all_levels.reserve(chlevelcount); - globals::cellcache[cellcachenum].ch_all_levels.resize(chlevelcount); + resize_exactly(globals::cellcache[cellcachenum].ch_all_levels, chlevelcount); + chphixstargetsblock = chphixsblocksize > 0 ? static_cast(malloc(chphixsblocksize)) : nullptr; mem_usage_cellcache += chlevelcount * sizeof(CellCacheLevels) + chphixsblocksize; @@ -1379,12 +1378,9 @@ void setup_cellcache() { assert_always(chtransindex == chtransblocksize); assert_always(globals::nbfcontinua >= 0); - globals::cellcache[cellcachenum].ch_allcont_departureratios.reserve(globals::nbfcontinua); - globals::cellcache[cellcachenum].ch_allcont_departureratios.resize(globals::nbfcontinua); - globals::cellcache[cellcachenum].ch_allcont_nnlevel.reserve(globals::nbfcontinua); - globals::cellcache[cellcachenum].ch_allcont_nnlevel.resize(globals::nbfcontinua); - globals::cellcache[cellcachenum].ch_keep_this_cont.reserve(globals::nbfcontinua); - globals::cellcache[cellcachenum].ch_keep_this_cont.resize(globals::nbfcontinua); + resize_exactly(globals::cellcache[cellcachenum].ch_allcont_departureratios, globals::nbfcontinua); + resize_exactly(globals::cellcache[cellcachenum].ch_allcont_nnlevel, globals::nbfcontinua); + resize_exactly(globals::cellcache[cellcachenum].ch_keep_this_cont, globals::nbfcontinua); mem_usage_cellcache += 2 * globals::nbfcontinua * sizeof(double); printout("[info] mem_usage: cellcache for thread %d occupies %.3f MB\n", cellcachenum, @@ -1393,8 +1389,7 @@ void setup_cellcache() { } void write_bflist_file() { - globals::bflist.reserve(globals::nbfcontinua); - globals::bflist.resize(globals::nbfcontinua); + resize_exactly(globals::bflist, globals::nbfcontinua); FILE *bflist_file{}; if (globals::my_rank == 0) { diff --git a/kpkt.cc b/kpkt.cc index 214772190..b7a4ee4ec 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -44,11 +44,11 @@ float kpktdiffusion_timescale{0.}; // calculate the cooling contribution list of individual levels/processes for an ion // oldcoolingsum is the sum of lower ion (of same element or all ions of lower elements) cooling contributions template -auto calculate_cooling_rates_ion(const int modelgridindex, const int element, const int ion, const int indexionstart, +auto calculate_cooling_rates_ion(const int nonemptymgi, const int element, const int ion, const int indexionstart, const int cellcacheslotid, double *const C_ff, double *const C_fb, double *const C_exc, double *const C_ionization) -> double { - const auto nne = grid::get_nne(modelgridindex); - const auto T_e = grid::get_Te(modelgridindex); + const auto nne = grid::get_nne(nonemptymgi); + const auto T_e = grid::get_Te(nonemptymgi); if constexpr (update_cooling_contrib_list) { assert_always(indexionstart >= 0); @@ -58,7 +58,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co int i = indexionstart; // NOLINT(misc-const-correctness) const int nionisinglevels = get_nlevels_ionising(element, ion); - const double nncurrention = get_nnion(modelgridindex, element, ion); + const double nncurrention = get_nnion(nonemptymgi, element, ion); // ff creation of rpkt const int ioncharge = get_ionstage(element, ion) - 1; @@ -82,7 +82,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { // printout("[debug] do_kpkt: element %d, ion %d, level %d\n", element, ion, level); - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); const double epsilon_current = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); @@ -111,12 +111,12 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co } if (ion < (get_nions(element) - 1)) { - const double nnupperion = get_nnion(modelgridindex, element, ion + 1); + const double nnupperion = get_nnion(nonemptymgi, element, ion + 1); // ionization to higher ionization stage for (int level = 0; level < nionisinglevels; level++) { const double epsilon_current = epsilon(element, ion, level); - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upper = get_phixsupperlevel(element, ion, level, phixstargetindex); @@ -147,7 +147,7 @@ auto calculate_cooling_rates_ion(const int modelgridindex, const int element, co const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const double pop = - (BFCOOLING_USELEVELPOPNOTIONPOP ? get_levelpop(modelgridindex, element, ion + 1, + (BFCOOLING_USELEVELPOPNOTIONPOP ? get_levelpop(nonemptymgi, element, ion + 1, get_phixsupperlevel(element, ion, level, phixstargetindex)) : nnupperion); const double C = get_bfcoolingcoeff(element, ion, level, phixstargetindex, T_e) * pop * nne; @@ -257,7 +257,6 @@ auto sample_planck_montecarlo(const double T) -> double { // Calculate the cooling rates for a given cell and store them for each ion // optionally store components (ff, bf, collisional) in heatingcoolingrates struct void calculate_cooling_rates(const int nonemptymgi, HeatingCoolingRates *heatingcoolingrates) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double C_ff_all = 0.; // free-free creation of rpkts double C_fb_all = 0.; // free-bound creation of rpkt double C_exc_all = 0.; // collisional excitation of macroatoms @@ -265,7 +264,7 @@ void calculate_cooling_rates(const int nonemptymgi, HeatingCoolingRates *heating for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { const auto [element, ion] = get_ionfromuniqueionindex(allionindex); grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + allionindex] = - calculate_cooling_rates_ion(modelgridindex, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, + calculate_cooling_rates_ion(nonemptymgi, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, &C_exc_all, &C_ionization_all); } @@ -276,7 +275,7 @@ void calculate_cooling_rates(const int nonemptymgi, HeatingCoolingRates *heating C_total += grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + allionindex]; } - grid::modelgrid[modelgridindex].totalcooling = C_total; + grid::modelgrid[nonemptymgi].totalcooling = C_total; // only used in the T_e solver and write_to_estimators file if (heatingcoolingrates != nullptr) { @@ -373,15 +372,14 @@ void setup_coolinglist() { __host__ __device__ void do_kpkt_blackbody(Packet &pkt) // handle a k-packet (e.g., in a thick cell) by emitting according to the planck function { - const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); - if (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0. && grid::modelgrid[modelgridindex].thick != 1) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + if (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0. && grid::modelgrid[nonemptymgi].thick != 1) { pkt.nu_cmf = sample_planck_times_expansion_opacity(nonemptymgi); } else { - pkt.nu_cmf = sample_planck_montecarlo(grid::get_Te(modelgridindex)); + pkt.nu_cmf = sample_planck_montecarlo(grid::get_Te(nonemptymgi)); // TODO: is this alternative method faster or more accurate or neither? - // pkt.nu_cmf = sample_planck_analytic(grid::get_Te(modelgridindex)); + // pkt.nu_cmf = sample_planck_analytic(grid::get_Te(nonemptymgi)); } assert_always(std::isfinite(pkt.nu_cmf)); @@ -402,8 +400,7 @@ __host__ __device__ void do_kpkt_blackbody(Packet &pkt) // handle a k-packet (kinetic energy of the free electrons) __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { const double t1 = pkt.prop_time; - const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); // don't calculate cooling rates after each cell crossings any longer // but only if we really get a kpkt and they hadn't been calculated already @@ -425,8 +422,8 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { pkt.pos = vec_scale(pkt.pos, t_current / t1); pkt.prop_time = t_current; - assert_always(grid::modelgrid[modelgridindex].totalcooling > 0.); - const double rndcool_ion = rng_uniform() * grid::modelgrid[modelgridindex].totalcooling; + assert_always(grid::modelgrid[nonemptymgi].totalcooling > 0.); + const double rndcool_ion = rng_uniform() * grid::modelgrid[nonemptymgi].totalcooling; // Randomly select the occurring cooling process double coolingsum = 0.; @@ -450,12 +447,12 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { } if (element >= get_nelements() || element < 0 || ion >= get_nions(element) || ion < 0) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout("do_kpkt: problem selecting a cooling process ... abort\n"); printout("do_kpkt: modelgridindex %d element %d ion %d\n", modelgridindex, element, ion); - printout("do_kpkt: totalcooling %g, coolingsum %g, rndcool_ion %g\n", grid::modelgrid[modelgridindex].totalcooling, + printout("do_kpkt: totalcooling %g, coolingsum %g, rndcool_ion %g\n", grid::modelgrid[nonemptymgi].totalcooling, coolingsum, rndcool_ion); - printout("do_kpkt: modelgridindex %d, cellno %d, nne %g\n", modelgridindex, pkt.where, - grid::get_nne(modelgridindex)); + printout("do_kpkt: modelgridindex %d, cellno %d, nne %g\n", modelgridindex, pkt.where, grid::get_nne(nonemptymgi)); for (element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (ion = 0; ion < nions; ion++) { @@ -477,7 +474,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { // printout("calculate kpkt rates on demand modelgridindex %d element %d ion %d ilow %d ihigh %d // oldcoolingsum %g\n", // modelgridindex, element, ion, ilow, high, oldcoolingsum); - C_ion_procsum = calculate_cooling_rates_ion(modelgridindex, element, ion, ilow, cellcacheslotid, nullptr, + C_ion_procsum = calculate_cooling_rates_ion(nonemptymgi, element, ion, ilow, cellcacheslotid, nullptr, nullptr, nullptr, nullptr); assert_testmodeonly( (std::fabs(C_ion_procsum - @@ -506,7 +503,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { // printout("do_kpkt: selected process %d, coolingsum %g\n", i, coolingsum); const auto rndcoolingtype = coolinglist[i].type; - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); if (rndcoolingtype == CoolingType::FREEFREE) { // The k-packet converts directly into a r-packet by free-free-emission. @@ -559,7 +556,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { emit_rpkt(pkt); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, lowerion + 1, stats::ION_RADRECOMB_KPKT, + stats::increment_ion_stats(nonemptymgi, element, lowerion + 1, stats::ION_RADRECOMB_KPKT, pkt.e_cmf / H / pkt.nu_cmf); } @@ -578,7 +575,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { } else if (rndcoolingtype == CoolingType::COLLEXC) { // the k-packet activates a macro-atom due to collisional excitation // printout("[debug] do_kpkt: k-pkt -> collisional excitation of MA\n"); - const float nne = grid::get_nne(modelgridindex); + const float nne = grid::get_nne(nonemptymgi); // if the previous entry belongs to the same ion, then pick up the cumulative sum from // the previous entry, otherwise start from zero @@ -587,7 +584,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { double contrib = contrib_low; const int level = coolinglist[i].level; const double epsilon_current = epsilon(element, ion, level); - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); const double statweight = stat_weight(element, ion, level); int upper = -1; // excitation to same ionization stage @@ -610,7 +607,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { assert_always(upper >= 0); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLEXC, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLEXC, pkt.e_cmf); } pkt.type = TYPE_MA; @@ -630,7 +627,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { const int upper = coolinglist[i].upperlevel; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, upperion, stats::ION_MACROATOM_ENERGYIN_COLLION, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, upperion, stats::ION_MACROATOM_ENERGYIN_COLLION, pkt.e_cmf); } pkt.type = TYPE_MA; diff --git a/ltepop.cc b/ltepop.cc index 28c407a2e..1e87463df 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -25,7 +25,7 @@ namespace { struct nneSolutionParas { - int modelgridindex; + int nonemptymgi; bool force_lte; }; @@ -54,7 +54,7 @@ auto phi_lte(const int element, const int ion, const int modelgridindex) -> doub const auto partfunc_upperion = grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex + 1]; - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); const double ionpot = epsilon(element, ion + 1, 0) - epsilon(element, ion, 0); const double partfunct_ratio = partfunc_ion / partfunc_upperion; return partfunct_ratio * SAHACONST * pow(T_e, -1.5) * exp(ionpot / KB / T_e); @@ -68,7 +68,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(!globals::lte_iteration); - assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); // should use use phi_lte instead + assert_testmodeonly(grid::modelgrid[nonemptymgi].thick != 1); // should use use phi_lte instead assert_testmodeonly(!elem_has_nlte_levels(element)); // don't use this function if the NLTE solver is active @@ -76,7 +76,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const auto partfunc_ion = grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); // photoionisation plus collisional ionisation rate coefficient per ground level pop const double Gamma = globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]; @@ -90,7 +90,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, // false); const double Col_rec = 0.; - const double gamma_nt = NT_ON ? nonthermal::nt_ionization_ratecoeff(modelgridindex, element, ion) : 0.; + const double gamma_nt = NT_ON ? nonthermal::nt_ionization_ratecoeff(nonemptymgi, element, ion) : 0.; if ((Gamma + gamma_nt) == 0) { printout("Fatal: Gamma = 0 for element %d, ion %d in phi ... abort\n", element, ion); @@ -112,8 +112,8 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, stat_weight(element, ion, 0)); printout("[fatal] phi: upperionpartfunct %g, upperionstatweight %g\n", partfunc_upperion, stat_weight(element, ion + 1, 0)); - printout("[fatal] phi: gamma_nt %g Col_rec %g grid::get_nne(modelgridindex) %g\n", gamma_nt, Col_rec, - grid::get_nne(modelgridindex)); + printout("[fatal] phi: gamma_nt %g Col_rec %g grid::get_nne(nonemptymgi) %g\n", gamma_nt, Col_rec, + grid::get_nne(nonemptymgi)); std::abort(); } @@ -121,15 +121,15 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, } // calculate the free electron contribution from an element -auto get_element_nne_contrib(const int modelgridindex, const int element) -> double { - if (grid::get_elem_numberdens(modelgridindex, element) <= 0.) { +auto get_element_nne_contrib(const int nonemptymgi, const int element) -> double { + if (grid::get_elem_numberdens(nonemptymgi, element) <= 0.) { return 0.; } double nne = 0.; const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - const auto nnion = get_nnion(modelgridindex, element, ion); + const auto nnion = get_nnion(nonemptymgi, element, ion); const int ioncharge = get_ionstage(element, ion) - 1; nne += ioncharge * nnion; } @@ -140,19 +140,19 @@ auto get_element_nne_contrib(const int modelgridindex, const int element) -> dou // the difference between the assumed and calculated nne is returned auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double { const auto *paras = static_cast(voidparas); - const int modelgridindex = paras->modelgridindex; + const int nonemptymgi = paras->nonemptymgi; const bool force_lte = paras->force_lte; double nne_after = 0.; // the resulting nne after setting the ion balance with nne_assumed for (int element = 0; element < get_nelements(); element++) { - const double nnelement = grid::get_elem_numberdens(modelgridindex, element); + const double nnelement = grid::get_elem_numberdens(nonemptymgi, element); if (nnelement > 0 && get_nions(element) > 0) { if (!force_lte && elem_has_nlte_levels(element)) { // populations from the NLTE solver are fixed during the nne solver - nne_after += get_element_nne_contrib(modelgridindex, element); + nne_after += get_element_nne_contrib(nonemptymgi, element); } else { const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); - const auto ionfractions = calculate_ionfractions(element, modelgridindex, nne_assumed, use_phi_lte); + const auto ionfractions = calculate_ionfractions(element, nonemptymgi, nne_assumed, use_phi_lte); const int uppermost_ion = static_cast(ionfractions.size() - 1); for (int ion = 0; ion <= uppermost_ion; ion++) { const double nnion = nnelement * ionfractions[ion]; @@ -169,31 +169,31 @@ auto nne_solution_f(const double nne_assumed, void *const voidparas) -> double { return nne_after - nne_assumed; } -auto calculate_levelpop_nominpop(const int modelgridindex, const int element, const int ion, const int level, +auto calculate_levelpop_nominpop(const int nonemptymgi, const int element, const int ion, const int level, bool *const skipminpop) -> double { - assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); double nn{NAN}; + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if (level == 0) { - nn = get_groundlevelpop(modelgridindex, element, ion); + nn = get_groundlevelpop(nonemptymgi, element, ion); } else if (elem_has_nlte_levels(element)) { if (is_nlte(element, ion, level)) { // first_nlte refers to the first excited state (level=1) - const double nltepop_over_rho = get_nlte_levelpop_over_rho(modelgridindex, element, ion, level); + const double nltepop_over_rho = get_nlte_levelpop_over_rho(nonemptymgi, element, ion, level); if (nltepop_over_rho < -0.9) { // Case for when no NLTE level information is available yet - nn = calculate_levelpop_lte(modelgridindex, element, ion, level); + nn = calculate_levelpop_lte(nonemptymgi, element, ion, level); } else { - nn = nltepop_over_rho * grid::get_rho(modelgridindex); + nn = nltepop_over_rho * grid::get_rho(nonemptymgi); if (!std::isfinite(nn)) { printout("[fatal] NLTE population failure.\n"); printout("element %d ion %d level %d\n", element, ion, level); - printout("nn %g nltepop_over_rho %g rho %g\n", nn, nltepop_over_rho, grid::get_rho(modelgridindex)); - printout("ground level %g\n", get_groundlevelpop(modelgridindex, element, ion)); + printout("nn %g nltepop_over_rho %g rho %g\n", nn, nltepop_over_rho, grid::get_rho(nonemptymgi)); + printout("ground level %g\n", get_groundlevelpop(nonemptymgi, element, ion)); std::abort(); } *skipminpop = true; @@ -203,20 +203,19 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co // level is in the superlevel assert_testmodeonly(level_isinsuperlevel(element, ion, level)); - const double superlevelpop_over_rho = get_nlte_superlevelpop_over_rho(modelgridindex, element, ion); + const double superlevelpop_over_rho = get_nlte_superlevelpop_over_rho(nonemptymgi, element, ion); if (superlevelpop_over_rho < -0.9) // TODO: should change this to less than zero? { // Case for when no NLTE level information is available yet - nn = calculate_levelpop_lte(modelgridindex, element, ion, level); + nn = calculate_levelpop_lte(nonemptymgi, element, ion, level); } else { - nn = superlevelpop_over_rho * grid::get_rho(modelgridindex) * + nn = superlevelpop_over_rho * grid::get_rho(nonemptymgi) * superlevel_boltzmann(modelgridindex, element, ion, level); if (!std::isfinite(nn)) { printout("[fatal] NLTE population failure.\n"); printout("element %d ion %d level %d\n", element, ion, level); - printout("nn %g superlevelpop_over_rho %g rho %g\n", nn, superlevelpop_over_rho, - grid::get_rho(modelgridindex)); - printout("ground level %g\n", get_groundlevelpop(modelgridindex, element, ion)); + printout("nn %g superlevelpop_over_rho %g rho %g\n", nn, superlevelpop_over_rho, grid::get_rho(nonemptymgi)); + printout("ground level %g\n", get_groundlevelpop(nonemptymgi, element, ion)); std::abort(); } *skipminpop = true; @@ -224,31 +223,29 @@ auto calculate_levelpop_nominpop(const int modelgridindex, const int element, co } } } else { - nn = calculate_levelpop_lte(modelgridindex, element, ion, level); + nn = calculate_levelpop_lte(nonemptymgi, element, ion, level); } *skipminpop = false; return nn; } -auto calculate_partfunct(const int element, const int ion, const int modelgridindex) -> double +auto calculate_partfunct(const int element, const int ion, const int nonemptymgi) -> double // Calculates the partition function for ion=ion of element=element in // cell modelgridindex { - ; - assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double pop_store{NAN}; const int uniqueionindex = get_uniqueionindex(element, ion); bool initial = false; - if (get_groundlevelpop(modelgridindex, element, ion) < MINPOP) { + if (get_groundlevelpop(nonemptymgi, element, ion) < MINPOP) { // either there really is none of this ion or this is a first pass through // in either case, we won't have any real nlte_populations so the actual value of // of groundlevelpop for this calculation doesn't matter, so long as it's not zero! - pop_store = get_groundlevelpop(modelgridindex, element, ion); + pop_store = get_groundlevelpop(nonemptymgi, element, ion); initial = true; grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = 1.; @@ -257,10 +254,10 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin double U = 1.; const int nlevels = get_nlevels(element, ion); - const double groundpop = get_groundlevelpop(modelgridindex, element, ion); + const double groundpop = get_groundlevelpop(nonemptymgi, element, ion); for (int level = 1; level < nlevels; level++) { bool skipminpop = false; - const double nn = calculate_levelpop_nominpop(modelgridindex, element, ion, level, &skipminpop) / groundpop; + const double nn = calculate_levelpop_nominpop(nonemptymgi, element, ion, level, &skipminpop) / groundpop; U += nn; } U *= stat_weight(element, ion, 0); @@ -282,7 +279,7 @@ auto calculate_partfunct(const int element, const int ion, const int modelgridin return U; } -auto find_uppermost_ion(const int modelgridindex, const int element, const double nne_hi, const bool force_lte) -> int { +auto find_uppermost_ion(const int nonemptymgi, const int element, const double nne_hi, const bool force_lte) -> int { const int nions = get_nions(element); if (nions == 0) { return -1; @@ -290,8 +287,7 @@ auto find_uppermost_ion(const int modelgridindex, const int element, const doubl if (!force_lte && elem_has_nlte_levels(element)) { return nions - 1; } - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const bool use_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); int uppermost_ion = 0; @@ -327,22 +323,21 @@ auto find_uppermost_ion(const int modelgridindex, const int element, const doubl return uppermost_ion; } -void set_calculated_nne(const int modelgridindex) { +void set_calculated_nne(const int nonemptymgi) { double nne = 0.; // free electron density - for (int element = 0; element < get_nelements(); element++) { - nne += get_element_nne_contrib(modelgridindex, element); + nne += get_element_nne_contrib(nonemptymgi, element); } - grid::set_nne(modelgridindex, std::max(MINPOP, nne)); + grid::set_nne(nonemptymgi, std::max(MINPOP, nne)); } // Special case of only neutral ions, set nne to some finite value so that packets are not lost in kpkts -void set_groundlevelpops_neutral(const int modelgridindex) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - printout("[warning] calculate_ion_balance_nne: only neutral ions in cell modelgridindex %d\n", modelgridindex); +void set_groundlevelpops_neutral(const int nonemptymgi) { + printout("[warning] calculate_ion_balance_nne: only neutral ions in cell modelgridindex %d\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi)); for (int element = 0; element < get_nelements(); element++) { - const auto nnelement = grid::get_elem_numberdens(modelgridindex, element); + const auto nnelement = grid::get_elem_numberdens(nonemptymgi, element); const int nions = get_nions(element); // Assign the species population to the neutral ion and set higher ions to MINPOP for (int ion = 0; ion < nions; ion++) { @@ -365,19 +360,20 @@ void set_groundlevelpops_neutral(const int modelgridindex) { } } -auto find_converged_nne(const int modelgridindex, double nne_hi, const bool force_lte) -> float { +auto find_converged_nne(const int nonemptymgi, double nne_hi, const bool force_lte) -> float { // Search solution for nne in [nne_lo,nne_hi] - nneSolutionParas paras = {.modelgridindex = modelgridindex, .force_lte = force_lte}; + nneSolutionParas paras = {.nonemptymgi = nonemptymgi, .force_lte = force_lte}; gsl_function f = {.function = &nne_solution_f, .params = ¶s}; double nne_lo = 0.; // MINPOP; if (nne_solution_f(nne_lo, f.params) * nne_solution_f(nne_hi, f.params) > 0) { - const auto T_R = grid::get_TR(modelgridindex); - const auto T_e = grid::get_Te(modelgridindex); - const auto W = grid::get_W(modelgridindex); + const auto T_R = grid::get_TR(nonemptymgi); + const auto T_e = grid::get_Te(nonemptymgi); + const auto W = grid::get_W(nonemptymgi); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout("n, nne_lo, nne_hi, T_R, T_e, W, rho %d, %g, %g, %g, %g, %g, %g\n", modelgridindex, nne_lo, nne_hi, T_R, - T_e, W, grid::get_rho(modelgridindex)); + T_e, W, grid::get_rho(nonemptymgi)); printout("nne@x_lo %g\n", nne_solution_f(nne_lo, f.params)); printout("nne@x_hi %g\n", nne_solution_f(nne_hi, f.params)); @@ -427,13 +423,12 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc // Calculate the fractions of an element's population in each ionization stage based on Saha LTE or ionisation // equilibrium -[[nodiscard]] auto calculate_ionfractions(const int element, const int modelgridindex, const double nne, +[[nodiscard]] auto calculate_ionfractions(const int element, const int nonemptymgi, const double nne, const bool use_phi_lte) -> std::vector { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const int uppermost_ion = grid::get_elements_uppermost_ion(modelgridindex, element); - assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(uppermost_ion <= std::max(0, get_nions(element) - 1)); - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); if (uppermost_ion < 0) { return {}; @@ -456,8 +451,8 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc if (normfactor == 0. || !std::isfinite(ionfractions[ion])) { printout("[warning] ionfract set to zero for ionstage %d of Z=%d in cell %d with T_e %g, T_R %g\n", - get_ionstage(element, ion), get_atomicnumber(element), modelgridindex, grid::get_Te(modelgridindex), - grid::get_TR(modelgridindex)); + get_ionstage(element, ion), get_atomicnumber(element), modelgridindex, grid::get_Te(nonemptymgi), + grid::get_TR(nonemptymgi)); ionfractions[ion] = 0; } } @@ -466,15 +461,13 @@ auto find_converged_nne(const int modelgridindex, double nne_hi, const bool forc // Return the given ions groundlevel population for modelgridindex which was precalculated // during update_grid and stored to the grid. -auto get_groundlevelpop(const int modelgridindex, const int element, const int ion) -> double { - assert_testmodeonly(modelgridindex < grid::get_npts_model()); +auto get_groundlevelpop(const int nonemptymgi, const int element, const int ion) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const double nn = grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + get_uniqueionindex(element, ion)]; if (nn < MINPOP) { - if (grid::get_elem_abundance(modelgridindex, element) > 0) { + if (grid::get_elem_abundance(nonemptymgi, element) > 0) { return MINPOP; } return 0.; @@ -483,18 +476,16 @@ auto get_groundlevelpop(const int modelgridindex, const int element, const int i } // Calculate occupation population of a level assuming LTE excitation -auto calculate_levelpop_lte(const int modelgridindex, const int element, const int ion, const int level) -> double { - assert_testmodeonly(modelgridindex < grid::get_npts_model()); +auto calculate_levelpop_lte(const int nonemptymgi, const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); assert_testmodeonly(level < get_nlevels(element, ion)); - - const auto nnground = get_groundlevelpop(modelgridindex, element, ion); + const auto nnground = get_groundlevelpop(nonemptymgi, element, ion); if (level == 0) { return nnground; } - const auto T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(modelgridindex) : grid::get_Te(modelgridindex); + const auto T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(nonemptymgi) : grid::get_Te(nonemptymgi); const double E_aboveground = epsilon(element, ion, level) - epsilon(element, ion, 0); @@ -502,11 +493,11 @@ auto calculate_levelpop_lte(const int modelgridindex, const int element, const i exp(-E_aboveground / KB / T_exc)); } -auto calculate_levelpop(const int modelgridindex, const int element, const int ion, const int level) -> double { +auto calculate_levelpop(const int nonemptymgi, const int element, const int ion, const int level) -> double { bool skipminpop = false; - double nn = calculate_levelpop_nominpop(modelgridindex, element, ion, level, &skipminpop); + double nn = calculate_levelpop_nominpop(nonemptymgi, element, ion, level, &skipminpop); if (!skipminpop && nn < MINPOP) { - if (grid::get_elem_abundance(modelgridindex, element) > 0) { + if (grid::get_elem_abundance(nonemptymgi, element) > 0) { nn = MINPOP; } else { nn = 0.; @@ -517,14 +508,14 @@ auto calculate_levelpop(const int modelgridindex, const int element, const int i } // Calculate the population of a level from either LTE or NLTE information -__host__ __device__ auto get_levelpop(const int modelgridindex, const int element, const int ion, const int level) +__host__ __device__ auto get_levelpop(const int nonemptymgi, const int element, const int ion, const int level) -> double { double nn = 0.; if (use_cellcache) { - assert_testmodeonly(modelgridindex == globals::cellcache[cellcacheslotid].cellnumber); + assert_testmodeonly(globals::cellcache[cellcacheslotid].nonemptymgi == nonemptymgi); nn = globals::cellcache[cellcacheslotid].chelements[element].chions[ion].chlevels[level].population; } else { - nn = calculate_levelpop(modelgridindex, element, ion, level); + nn = calculate_levelpop(nonemptymgi, element, ion, level); } assert_testmodeonly(nn >= 0.); @@ -537,12 +528,11 @@ __host__ __device__ auto get_levelpop(const int modelgridindex, const int elemen // change during any iteration on T_e. Therefore their precalculation was // taken out of calculate_ion_balance_nne to save runtime. // TODO: not true if LTEPOP_EXCITATION_USE_TJ is true unless LTE mode only (TJ=TR=Te) -void calculate_cellpartfuncts(const int modelgridindex, const int element) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +void calculate_cellpartfuncts(const int nonemptymgi, const int element) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + - get_uniqueionindex(element, ion)] = calculate_partfunct(element, ion, modelgridindex); + get_uniqueionindex(element, ion)] = calculate_partfunct(element, ion, nonemptymgi); } } @@ -563,10 +553,8 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co } // Use the ground level population and partition function to get an ion population -[[nodiscard]] __host__ __device__ auto get_nnion(const int modelgridindex, const int element, const int ion) -> double { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - - return get_groundlevelpop(modelgridindex, element, ion) * +[[nodiscard]] __host__ __device__ auto get_nnion(const int nonemptymgi, const int element, const int ion) -> double { + return get_groundlevelpop(nonemptymgi, element, ion) * grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + get_uniqueionindex(element, ion)] / stat_weight(element, ion, 0); @@ -574,23 +562,23 @@ __host__ __device__ auto calculate_sahafact(const int element, const int ion, co // If not already set by the NLTE solver, set the ground level populations from either Saha LTE or // ionization/recombination balance (Photoionization Equilibrium) -void set_groundlevelpops(const int modelgridindex, const int element, const float nne, const bool force_lte) { +void set_groundlevelpops(const int nonemptymgi, const int element, const float nne, const bool force_lte) { const int nions = get_nions(element); if (nions <= 0) { return; } - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // calculate number density of the current element (abundances are given by mass) - const double nnelement = grid::get_elem_numberdens(modelgridindex, element); + const double nnelement = grid::get_elem_numberdens(nonemptymgi, element); const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); const auto ionfractions = - (nnelement > 0) ? calculate_ionfractions(element, modelgridindex, nne, use_phi_lte) : std::vector(); + (nnelement > 0) ? calculate_ionfractions(element, nonemptymgi, nne, use_phi_lte) : std::vector(); const int uppermost_ion = static_cast(ionfractions.size() - 1); + const ptrdiff_t nincludedions = get_includedions(); // Use ion fractions to calculate the groundlevel populations for (int ion = 0; ion < nions; ion++) { @@ -606,52 +594,50 @@ void set_groundlevelpops(const int modelgridindex, const int element, const floa nnion = MINPOP; } - const double groundpop = - nnion * stat_weight(element, ion, 0) / - grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; + const double groundpop = nnion * stat_weight(element, ion, 0) / + grid::ion_partfuncts_allcells[(nonemptymgi * nincludedions) + uniqueionindex]; if (!std::isfinite(groundpop)) { printout("[warning] calculate_ion_balance_nne: groundlevelpop infinite in connection with MINPOP\n"); } - grid::ion_groundlevelpops_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex] = - groundpop; + grid::ion_groundlevelpops_allcells[(nonemptymgi * nincludedions) + uniqueionindex] = groundpop; } } // Determine the electron number density for a given cell using one of // libgsl's root_solvers and calculates the depending level populations. -auto calculate_ion_balance_nne(const int modelgridindex) -> void { - const bool force_lte = globals::lte_iteration || grid::modelgrid[modelgridindex].thick == 1; +auto calculate_ion_balance_nne(const int nonemptymgi) -> void { + const bool force_lte = globals::lte_iteration || grid::modelgrid[nonemptymgi].thick == 1; - const double nne_hi = grid::get_rho(modelgridindex) / MH; + const double nne_hi = grid::get_rho(nonemptymgi) / MH; bool only_lowest_ionstage = true; // could be completely neutral, or just at each element's lowest ion stage for (int element = 0; element < get_nelements(); element++) { - if (grid::get_elem_abundance(modelgridindex, element) > 0) { - const int uppermost_ion = find_uppermost_ion(modelgridindex, element, nne_hi, force_lte); - grid::set_elements_uppermost_ion(modelgridindex, element, uppermost_ion); + if (grid::get_elem_abundance(nonemptymgi, element) > 0) { + const int uppermost_ion = find_uppermost_ion(nonemptymgi, element, nne_hi, force_lte); + grid::set_elements_uppermost_ion(nonemptymgi, element, uppermost_ion); only_lowest_ionstage = only_lowest_ionstage && (uppermost_ion <= 0); } else { - grid::set_elements_uppermost_ion(modelgridindex, element, get_nions(element) - 1); + grid::set_elements_uppermost_ion(nonemptymgi, element, get_nions(element) - 1); } } if (only_lowest_ionstage) { - set_groundlevelpops_neutral(modelgridindex); + set_groundlevelpops_neutral(nonemptymgi); } else { - const auto nne_solution = find_converged_nne(modelgridindex, nne_hi, force_lte); - grid::set_nne(modelgridindex, nne_solution); + const auto nne_solution = find_converged_nne(nonemptymgi, nne_hi, force_lte); + grid::set_nne(nonemptymgi, nne_solution); for (int element = 0; element < get_nelements(); element++) { // avoid overwriting the ground level populations set by the NLTE pop solver const bool already_set_by_nlte_solver = !force_lte && elem_has_nlte_levels(element); if (!already_set_by_nlte_solver) { - set_groundlevelpops(modelgridindex, element, nne_solution, force_lte); + set_groundlevelpops(nonemptymgi, element, nne_solution, force_lte); } } } - set_calculated_nne(modelgridindex); + set_calculated_nne(nonemptymgi); } diff --git a/ltepop.h b/ltepop.h index 965245d4b..9d7d1c8e6 100644 --- a/ltepop.h +++ b/ltepop.h @@ -3,20 +3,20 @@ #include -[[nodiscard]] auto get_groundlevelpop(int modelgridindex, int element, int ion) -> double; +[[nodiscard]] auto get_groundlevelpop(int nonemptymgi, int element, int ion) -> double; #pragma omp declare simd -[[nodiscard]] auto calculate_levelpop(int modelgridindex, int element, int ion, int level) -> double; +[[nodiscard]] auto calculate_levelpop(int nonemptymgi, int element, int ion, int level) -> double; #pragma omp declare simd -[[nodiscard]] auto calculate_levelpop_lte(int modelgridindex, int element, int ion, int level) -> double; +[[nodiscard]] auto calculate_levelpop_lte(int nonemptymgi, int element, int ion, int level) -> double; #pragma omp declare simd -[[nodiscard]] auto get_levelpop(int modelgridindex, int element, int ion, int level) -> double; +[[nodiscard]] auto get_levelpop(int nonemptymgi, int element, int ion, int level) -> double; [[nodiscard]] auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, double E_threshold) -> double; -[[nodiscard]] auto get_nnion(int modelgridindex, int element, int ion) -> double; -void calculate_ion_balance_nne(int modelgridindex); -void calculate_cellpartfuncts(int modelgridindex, int element); -[[nodiscard]] auto calculate_ionfractions(int element, int modelgridindex, double nne, bool use_phi_lte) +[[nodiscard]] auto get_nnion(int nonemptymgi, int element, int ion) -> double; +void calculate_ion_balance_nne(int nonemptymgi); +void calculate_cellpartfuncts(int nonemptymgi, int element); +[[nodiscard]] auto calculate_ionfractions(int element, int nonemptymgi, double nne, bool use_phi_lte) -> std::vector; -void set_groundlevelpops(int modelgridindex, int element, float nne, bool force_lte); +void set_groundlevelpops(int nonemptymgi, int element, float nne, bool force_lte); #endif // LTEPOP_H diff --git a/macroatom.cc b/macroatom.cc index 1f50ccf57..0521e419b 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #if defined(STDPAR_ON) || defined(_OPENMP_ON) @@ -34,16 +33,16 @@ constexpr bool LOG_MACROATOM = false; FILE *macroatom_file{}; -auto calculate_macroatom_transitionrates(const int modelgridindex, const int element, const int ion, const int level, +auto calculate_macroatom_transitionrates(const int nonemptymgi, const int element, const int ion, const int level, const double t_mid, CellCacheLevels &chlevel) { // printout("Calculating transition rates for element %d ion %d level %d\n", element, ion, level); auto processrates = std::array{}; - const auto T_e = grid::get_Te(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); const double epsilon_current = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); - const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); + const auto nnlevel = get_levelpop(nonemptymgi, element, ion, level); // Downward transitions within the current ionisation stage: // radiative/collisional deexcitation and internal downward jumps @@ -61,8 +60,8 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const double epsilon_target = epsilon(element, ion, lower); const double epsilon_trans = epsilon_current - epsilon_target; - const double R = rad_deexcitation_ratecoeff(modelgridindex, element, ion, lower, epsilon_trans, A_ul, statweight, - nnlevel, t_mid); + const double R = + rad_deexcitation_ratecoeff(nonemptymgi, element, ion, lower, epsilon_trans, A_ul, statweight, nnlevel, t_mid); const double C = col_deexcitation_ratecoeff(T_e, nne, epsilon_trans, element, ion, level, downtrans); sum_raddeexc += R * epsilon_trans; @@ -87,10 +86,10 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const auto &uptrans = uptranslist[i]; const double epsilon_trans = epsilon(element, ion, uptrans.targetlevelindex) - epsilon_current; - const double R = rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, nnlevel, - uptrans.lineindex, t_mid); + const double R = + rad_excitation_ratecoeff(nonemptymgi, element, ion, level, i, epsilon_trans, nnlevel, uptrans.lineindex, t_mid); const double C = col_excitation_ratecoeff(T_e, nne, element, ion, level, i, epsilon_trans, statweight); - const double NT = nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, uptrans.lineindex); + const double NT = nonthermal::nt_excitation_ratecoeff(nonemptymgi, element, ion, level, i, uptrans.lineindex); sum_internal_up_same += (R + C + NT) * epsilon_current; chlevel.sum_internal_up_same[i] = sum_internal_up_same; @@ -111,8 +110,8 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const double epsilon_target = epsilon(element, ion - 1, lower); const double epsilon_trans = epsilon_current - epsilon_target; - const double R = rad_recombination_ratecoeff(T_e, nne, element, ion, level, lower, modelgridindex); - const double C = col_recombination_ratecoeff(modelgridindex, element, ion, level, lower, epsilon_trans); + const double R = rad_recombination_ratecoeff(T_e, nne, element, ion, level, lower, nonemptymgi); + const double C = col_recombination_ratecoeff(T_e, nne, element, ion, level, lower, epsilon_trans); sum_internal_down_lower += (R + C) * epsilon_target; @@ -130,14 +129,14 @@ auto calculate_macroatom_transitionrates(const int modelgridindex, const int ele const int ionisinglevels = get_nlevels_ionising(element, ion); if (ion < get_nions(element) - 1 && level < ionisinglevels) { if (NT_ON) { - sum_up_highernt = nonthermal::nt_ionization_ratecoeff(modelgridindex, element, ion) * epsilon_current; + sum_up_highernt = nonthermal::nt_ionization_ratecoeff(nonemptymgi, element, ion) * epsilon_current; } const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const double epsilon_trans = get_phixs_threshold(element, ion, level, phixstargetindex); - const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); + const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, nonemptymgi); const double C = col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); sum_up_higher += (R + C) * epsilon_current; @@ -221,10 +220,10 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, // get the level index of the lower ionisation stage after a randomly selected radiative recombination and update // counters -[[nodiscard]] auto do_macroatom_radrecomb(Packet &pkt, const int modelgridindex, const int element, const int upperion, +[[nodiscard]] auto do_macroatom_radrecomb(Packet &pkt, const int nonemptymgi, const int element, const int upperion, const int upperionlevel, const double rad_recomb) -> int { - const auto T_e = grid::get_Te(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); const double epsilon_current = epsilon(element, upperion, upperionlevel); // Randomly select a continuum const double targetval = rng_uniform() * rad_recomb; @@ -234,7 +233,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, for (lowerionlevel = 0; lowerionlevel < nlevels; lowerionlevel++) { const double epsilon_trans = epsilon_current - epsilon(element, upperion - 1, lowerionlevel); const double R = - rad_recombination_ratecoeff(T_e, nne, element, upperion, upperionlevel, lowerionlevel, modelgridindex); + rad_recombination_ratecoeff(T_e, nne, element, upperion, upperionlevel, lowerionlevel, nonemptymgi); rate += R * epsilon_trans; @@ -265,7 +264,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, emit_rpkt(pkt); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, upperion, stats::ION_RADRECOMB_MACROATOM, + stats::increment_ion_stats(nonemptymgi, element, upperion, stats::ION_RADRECOMB_MACROATOM, pkt.e_cmf / H / pkt.nu_cmf); } @@ -279,10 +278,10 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, // get the level index of the upper ionisation stage after randomly-selected photoionisation or thermal collisional // ionisation and update counters -[[nodiscard]] auto do_macroatom_ionisation(const int modelgridindex, const int element, const int ion, const int level, +[[nodiscard]] auto do_macroatom_ionisation(const int nonemptymgi, const int element, const int ion, const int level, const double epsilon_current, const double internal_up_higher) -> int { - const auto T_e = grid::get_Te(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); // Randomly select the occurring transition const double targetrate = rng_uniform() * internal_up_higher; @@ -290,7 +289,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const double epsilon_trans = get_phixs_threshold(element, ion, level, phixstargetindex); - const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); + const double R = get_corrphotoioncoeff(element, ion, level, phixstargetindex, nonemptymgi); const double C = col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); rate += (R + C) * epsilon_current; if (rate > targetrate) { @@ -306,18 +305,17 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, // handle activated macro atoms __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate) { - const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); assert_testmodeonly(nonemptymgi >= 0); - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); const double t_mid = globals::timesteps[globals::timestep].mid; // printout("[debug] do MA\n"); - const auto nne = grid::get_nne(modelgridindex); + const auto nne = grid::get_nne(nonemptymgi); - assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); // macroatom should not be used in thick cells + assert_testmodeonly(grid::modelgrid[nonemptymgi].thick != 1); // macroatom should not be used in thick cells // calculate occupation number for active MA level //////////////////////////////////// // general QUESTION: is it better to calculate the n_1 (later the n_ionstage and @@ -338,7 +336,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast const double nu_rf_in = pkt.nu_rf; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_TOTAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_TOTAL, pkt.e_cmf); } bool end_packet = false; @@ -362,11 +360,11 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast std::lock_guard(globals::mutex_cellcachemacroatom[get_uniquelevelindex(element, ion, level)]); #endif - assert_testmodeonly(globals::cellcache[cellcacheslotid].cellnumber == modelgridindex); + assert_testmodeonly(globals::cellcache[cellcacheslotid].nonemptymgi == nonemptymgi); // If there are no precalculated rates available then calculate them if (chlevel.processrates[MA_ACTION_INTERNALUPHIGHER] < 0) { - chlevel.processrates = calculate_macroatom_transitionrates(modelgridindex, element, ion, level, t_mid, chlevel); + chlevel.processrates = calculate_macroatom_transitionrates(nonemptymgi, element, ion, level, t_mid, chlevel); } } @@ -402,15 +400,16 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast do_macroatom_raddeexcitation(pkt, element, ion, level, activatingline, chlevel); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADDEEXC, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADDEEXC, pkt.e_cmf); - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_BOUNDBOUND_MACROATOM, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_BOUNDBOUND_MACROATOM, pkt.e_cmf / H / pkt.nu_cmf); - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); } if constexpr (LOG_MACROATOM) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); fprintf(macroatom_file, "%8d %14d %2d %12d %12d %9d %9d %9d %11.5e %11.5e %11.5e %11.5e\n", globals::timestep, modelgridindex, get_atomicnumber(element), get_ionstage(element, ion_in), get_ionstage(element, ion), level_in, level, activatingline, nu_cmf_in, pkt.nu_cmf, nu_rf_in, pkt.nu_rf); @@ -429,8 +428,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast pkt.last_event = 10; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLDEEXC, pkt.e_cmf); - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLDEEXC, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); } pkt.type = TYPE_KPKT; @@ -452,12 +451,12 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // printout("[debug] do_ma: element %d, ion %d, level %d\n", element, ion, level); if constexpr (TRACK_ION_STATS) { - // stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADRECOMB, - // pkt.e_cmf); stats::increment_ion_stats(modelgridindex, element, ion, + // stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADRECOMB, + // pkt.e_cmf); stats::increment_ion_stats(nonemptymgi, element, ion, // stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); } - level = do_macroatom_radrecomb(pkt, modelgridindex, element, ion, level, processrates[MA_ACTION_RADRECOMB]); + level = do_macroatom_radrecomb(pkt, nonemptymgi, element, ion, level, processrates[MA_ACTION_RADRECOMB]); ion -= 1; end_packet = true; break; @@ -471,9 +470,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast pkt.last_event = 11; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLRECOMB, - pkt.e_cmf); - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLRECOMB, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL, pkt.e_cmf); } pkt.type = TYPE_KPKT; @@ -500,8 +498,8 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast for (lower = 0; lower < nlevels; lower++) { const double epsilon_target = epsilon(element, ion - 1, lower); const double epsilon_trans = epsilon_current - epsilon_target; - const double R = rad_recombination_ratecoeff(T_e, nne, element, ion, level, lower, modelgridindex); - const double C = col_recombination_ratecoeff(modelgridindex, element, ion, level, lower, epsilon_trans); + const double R = rad_recombination_ratecoeff(T_e, nne, element, ion, level, lower, nonemptymgi); + const double C = col_recombination_ratecoeff(T_e, nne, element, ion, level, lower, epsilon_trans); rate += (R + C) * epsilon_target; if (targetrate < rate) { break; @@ -510,14 +508,14 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast // and set the macroatom's new state if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); } ion -= 1; level = lower; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); } if (lower >= nlevels) { @@ -563,15 +561,15 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment(stats::COUNTER_MA_STAT_INTERNALUPHIGHER); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); } - level = do_macroatom_ionisation(modelgridindex, element, ion, level, epsilon_current, + level = do_macroatom_ionisation(nonemptymgi, element, ion, level, epsilon_current, processrates[MA_ACTION_INTERNALUPHIGHER]); ion += 1; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); } break; @@ -581,15 +579,15 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast stats::increment(stats::COUNTER_INTERACTIONS); // ion += 1; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL, pkt.e_cmf); } - ion = nonthermal::nt_random_upperion(modelgridindex, element, ion, false); + ion = nonthermal::nt_random_upperion(nonemptymgi, element, ion, false); level = 0; stats::increment(stats::COUNTER_MA_STAT_INTERNALUPHIGHERNT); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL, pkt.e_cmf); } break; } @@ -647,11 +645,11 @@ void macroatom_close_file() { // radiative deexcitation rate: paperII 3.5.2 // multiply by upper level population to get a rate per second #pragma omp declare simd -auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, +auto rad_deexcitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lower, const double epsilon_trans, const float A_ul, const double upperstatweight, const double nnlevelupper, const double t_current) -> double { const auto &n_u = nnlevelupper; - const double n_l = get_levelpop(modelgridindex, element, ion, lower); + const double n_l = get_levelpop(nonemptymgi, element, ion, lower); double R = 0.; @@ -673,7 +671,7 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con // printout("[warning] rad_deexcitation: element %d, ion %d, upper %d, lower %d\n",element,ion,upper,lower); // printout("[warning] rad_deexcitation: n_l %g, n_u %g, B_lu %g, B_ul %g\n",n_l,n_u,B_lu,B_ul); // printout("[warning] rad_deexcitation: T_e %g, T_R %g, W %g in model cell - // %d\n",grid::get_Te(modelgridindex),get_TR(modelgridindex),get_W(modelgridindex),modelgridindex); + // %d\n",grid::get_Te(nonemptymgi),get_TR(nonemptymgi),get_W(nonemptymgi),modelgridindex); R = 0.; // printout("[fatal] rad_excitation: tau_sobolev <= 0 ... %g abort",tau_sobolev); // abort(); @@ -691,13 +689,13 @@ auto rad_deexcitation_ratecoeff(const int modelgridindex, const int element, con // radiative excitation rate: paperII 3.5.2 // multiply by lower level population to get a rate per second #pragma omp declare simd -auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, const int lower, +auto rad_excitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double nnlevel_lower, const int lineindex, const double t_current) -> double { const auto &uptr = get_uptranslist(element, ion, lower)[uptransindex]; const int upper = uptr.targetlevelindex; - const double n_u = get_levelpop(modelgridindex, element, ion, upper); + const double n_u = get_levelpop(nonemptymgi, element, ion, upper); const auto &n_l = nnlevel_lower; const double nu_trans = epsilon_trans / H; const double A_ul = uptr.einstein_A; @@ -715,12 +713,12 @@ auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const if (!globals::lte_iteration) { // check for a detailed line flux estimator to replace the binned/blackbody radiation field estimate if (const int jblueindex = radfield::get_Jblueindex(lineindex); jblueindex >= 0) { - return R_over_J_nu * radfield::get_Jb_lu(modelgridindex, jblueindex); + return R_over_J_nu * radfield::get_Jb_lu(nonemptymgi, jblueindex); } } } - const double R = R_over_J_nu * radfield::radfield(nu_trans, modelgridindex); + const double R = R_over_J_nu * radfield::radfield(nu_trans, nonemptymgi); assert_testmodeonly(R >= 0.); assert_testmodeonly(std::isfinite(R)); @@ -734,7 +732,7 @@ auto rad_excitation_ratecoeff(const int modelgridindex, const int element, const // multiply by upper level population to get a rate per second #pragma omp declare simd auto rad_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, - const int upperionlevel, const int lowerionlevel, const int modelgridindex) -> double { + const int upperionlevel, const int lowerionlevel, const int nonemptymgi) -> double { // it's probably faster to only check this condition outside this function // in a case where this wasn't checked, the function will return zero anyway // if (upperionlevel > get_maxrecombininglevel(element, upperion)) @@ -748,9 +746,7 @@ auto rad_recombination_ratecoeff(const float T_e, const float nne, const int ele R = nne * get_spontrecombcoeff(element, lowerion, lowerionlevel, phixstargetindex, T_e); if constexpr (SEPARATE_STIMRECOMB) { - if (modelgridindex >= 0) { - R += nne * get_stimrecombcoeff(element, lowerion, lowerionlevel, phixstargetindex, modelgridindex); - } + R += nne * get_stimrecombcoeff(element, lowerion, lowerionlevel, phixstargetindex, nonemptymgi); } break; } @@ -762,19 +758,17 @@ auto rad_recombination_ratecoeff(const float T_e, const float nne, const int ele } auto stim_recombination_ratecoeff(const float nne, const int element, const int upperion, const int upper, - const int lower, const int modelgridindex) -> double { + const int lower, const int nonemptymgi) -> double { double R = 0.; if constexpr (SEPARATE_STIMRECOMB) { const int nphixstargets = get_nphixstargets(element, upperion - 1, lower); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { if (get_phixsupperlevel(element, upperion - 1, lower, phixstargetindex) == upper) { - R = nne * get_stimrecombcoeff(element, upperion - 1, lower, phixstargetindex, modelgridindex); + R = nne * get_stimrecombcoeff(element, upperion - 1, lower, phixstargetindex, nonemptymgi); break; } } - - assert_always(std::isfinite(R)); } return R; @@ -782,8 +776,8 @@ auto stim_recombination_ratecoeff(const float nne, const int element, const int // multiply by upper level population to get a rate per second #pragma omp declare simd -auto col_recombination_ratecoeff(const int modelgridindex, const int element, const int upperion, const int upper, - const int lower, const double epsilon_trans) -> double { +auto col_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, + const int upper, const int lower, const double epsilon_trans) -> double { // it's probably faster to only check this condition outside this function // in a case where this wasn't checked, the function will return zero anyway // if (upper > get_maxrecombininglevel(element, upperion)) @@ -792,8 +786,6 @@ auto col_recombination_ratecoeff(const int modelgridindex, const int element, co const int nphixstargets = get_nphixstargets(element, upperion - 1, lower); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { if (get_phixsupperlevel(element, upperion - 1, lower, phixstargetindex) == upper) { - const float nne = grid::get_nne(modelgridindex); - const auto T_e = grid::get_Te(modelgridindex); const double fac1 = epsilon_trans / KB / T_e; const int ionstage = get_ionstage(element, upperion); diff --git a/macroatom.h b/macroatom.h index 9593987a9..bee0939cc 100644 --- a/macroatom.h +++ b/macroatom.h @@ -10,24 +10,24 @@ void macroatom_close_file(); void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate); #pragma omp declare simd -[[nodiscard]] auto rad_deexcitation_ratecoeff(int modelgridindex, int element, int ion, int lower, double epsilon_trans, +[[nodiscard]] auto rad_deexcitation_ratecoeff(int nonemptymgi, int element, int ion, int lower, double epsilon_trans, float A_ul, double upperstatweight, double nnlevelupper, double t_current) -> double; #pragma omp declare simd -[[nodiscard]] auto rad_excitation_ratecoeff(int modelgridindex, int element, int ion, int lower, int uptransindex, +[[nodiscard]] auto rad_excitation_ratecoeff(int nonemptymgi, int element, int ion, int lower, int uptransindex, double epsilon_trans, double nnlevel_lower, int lineindex, double t_current) -> double; #pragma omp declare simd [[nodiscard]] auto rad_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upperionlevel, - int lowerionlevel, int modelgridindex) -> double; + int lowerionlevel, int nonemptymgi) -> double; #pragma omp declare simd [[nodiscard]] auto stim_recombination_ratecoeff(float nne, int element, int upperion, int upper, int lower, - int modelgridindex) -> double; + int nonemptymgi) -> double; #pragma omp declare simd -[[nodiscard]] auto col_recombination_ratecoeff(int modelgridindex, int element, int upperion, int upper, int lower, +[[nodiscard]] auto col_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upper, int lower, double epsilon_trans) -> double; #pragma omp declare simd [[nodiscard]] auto col_ionization_ratecoeff(float T_e, float nne, int element, int ion, int lower, int phixstargetindex, diff --git a/nltepop.cc b/nltepop.cc index 13b8bb448..43820f6dc 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -35,11 +35,11 @@ FILE *nlte_file{}; constexpr bool individual_process_matrices = true; // this is the index for the NLTE solver that is handling all ions of a single element -// This is NOT an index into grid::modelgrid[modelgridindex].nlte_pops that contains all elements +// This is NOT an index into grid::modelgrid[nonemptymgi].nlte_pops that contains all elements auto get_nlte_vector_index(const int element, const int ion, const int level) -> int { // have to convert from nlte_pops index to nlte_vector index // the difference is that nlte vectors apply to a single element and include ground states - // The (+ ion) term accounts for the ground state population indicies that are not counted in the NLTE array + // The (+ ion) term accounts for the ground state population indices that are not counted in the NLTE array const int gs_index = globals::elements[element].ions[ion].first_nlte - globals::elements[element].ions[0].first_nlte + ion; @@ -242,6 +242,7 @@ void print_element_rates_summary(const int element, const int modelgridindex, co const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, const gsl_matrix *rate_matrix_ntcoll_bf) { + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); @@ -255,7 +256,7 @@ void print_element_rates_summary(const int element, const int modelgridindex, co for (int level = 0; (level < max_printed_levels) && (level < nlevels) && (level <= nlevels_nlte + 1); level++) { if (level == 0) { printout(" modelgridindex %d timestep %d NLTE iteration %d Te %g nne %g: NLTE summary for Z=%d ionstage %d:\n", - modelgridindex, timestep, nlte_iter, grid::get_Te(modelgridindex), grid::get_nne(modelgridindex), + modelgridindex, timestep, nlte_iter, grid::get_Te(nonemptymgi), grid::get_nne(nonemptymgi), atomic_number, ionstage); printout( " pop rates bb_rad bb_col bb_ntcol bf_rad bf_col " @@ -280,6 +281,7 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e const gsl_matrix *rate_matrix_coll_bb, const gsl_matrix *rate_matrix_ntcoll_bb, const gsl_matrix *rate_matrix_rad_bf, const gsl_matrix *rate_matrix_coll_bf, const gsl_matrix *rate_matrix_ntcoll_bf) { + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // very detailed output of the NLTE processes for a particular levels if (element > get_nelements() - 1 || selected_ion > get_nions(element) - 1 || @@ -304,8 +306,8 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e printout( "timestep %d cell %d Te %g nne %g NLTE level diagnostics for Z=%d ionstage %d level %d rates into and out of " "this level\n", - timestep, modelgridindex, grid::get_Te(modelgridindex), grid::get_nne(modelgridindex), atomic_number, - selected_ionstage, selected_level); + timestep, modelgridindex, grid::get_Te(nonemptymgi), grid::get_nne(nonemptymgi), atomic_number, selected_ionstage, + selected_level); const double rad_bb_in_total = get_total_rate_in(selected_index, rate_matrix_rad_bb, popvec); const double coll_bb_in_total = get_total_rate_in(selected_index, rate_matrix_coll_bb, popvec); @@ -383,8 +385,7 @@ void print_level_rates(const int modelgridindex, const int timestep, const int e printout("\n"); } -void nltepop_reset_element(const int modelgridindex, const int element) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +void nltepop_reset_element(const int nonemptymgi, const int element) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { std::fill_n(&grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels)], @@ -434,17 +435,17 @@ auto get_element_superlevelpartfuncs(const int modelgridindex, const int element return max_nlte_dimension; } -void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const int ion, const double t_mid, +void nltepop_matrix_add_boundbound(const int nonemptymgi, const int element, const int ion, const double t_mid, const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bb, gsl_matrix *rate_matrix_coll_bb, gsl_matrix *rate_matrix_ntcoll_bb) { - const auto T_e = grid::get_Te(modelgridindex); - const float nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const float nne = grid::get_nne(nonemptymgi); const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { const int level_index = get_nlte_vector_index(element, ion, level); const double epsilon_level = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); - const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); + const auto nnlevel = get_levelpop(nonemptymgi, element, ion, level); // de-excitation const int ndowntrans = get_ndowntrans(element, ion, level); @@ -456,7 +457,7 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const double epsilon_trans = epsilon_level - epsilon(element, ion, lower); - const double R = rad_deexcitation_ratecoeff(modelgridindex, element, ion, lower, epsilon_trans, A_ul, statweight, + const double R = rad_deexcitation_ratecoeff(nonemptymgi, element, ion, lower, epsilon_trans, A_ul, statweight, nnlevel, t_mid) * s_renorm[level]; const double C = @@ -484,7 +485,7 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, const double epsilon_trans = epsilon(element, ion, upper) - epsilon_level; const double R = - rad_excitation_ratecoeff(modelgridindex, element, ion, level, i, epsilon_trans, nnlevel, lineindex, t_mid) * + rad_excitation_ratecoeff(nonemptymgi, element, ion, level, i, epsilon_trans, nnlevel, lineindex, t_mid) * s_renorm[level]; assert_always(R >= 0); assert_always(std::isfinite(R)); @@ -495,7 +496,7 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, assert_always(std::isfinite(C)); const double NTC = - nonthermal::nt_excitation_ratecoeff(modelgridindex, element, ion, level, i, lineindex) * s_renorm[level]; + nonthermal::nt_excitation_ratecoeff(nonemptymgi, element, ion, level, i, lineindex) * s_renorm[level]; const int lower_index = level_index; const int upper_index = get_nlte_vector_index(element, ion, upper); @@ -517,9 +518,10 @@ void nltepop_matrix_add_boundbound(const int modelgridindex, const int element, void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const int ion, const std::vector &s_renorm, gsl_matrix *rate_matrix_rad_bf, gsl_matrix *rate_matrix_coll_bf) { - assert_always(ion + 1 < get_nions(element)); // can't ionise the top ion - const auto T_e = grid::get_Te(modelgridindex); - const float nne = grid::get_nne(modelgridindex); + assert_always((ion + 1) < get_nions(element)); // can't ionise the top ion + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const float nne = grid::get_nne(nonemptymgi); const int nionisinglevels = get_nlevels_ionising(element, ion); const int maxrecombininglevel = get_maxrecombininglevel(element, ion + 1); @@ -538,7 +540,7 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, // ionization // the R part is slow! - const double R_ionisation = get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); + const double R_ionisation = get_corrphotoioncoeff(element, ion, level, phixstargetindex, nonemptymgi); const double C_ionisation = col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); @@ -555,9 +557,8 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, // recombination if (upper <= maxrecombininglevel) // we can skip this part if the functions below will return zero anyway { - const double R_recomb = rad_recombination_ratecoeff(T_e, nne, element, ion + 1, upper, level, modelgridindex); - const double C_recomb = - col_recombination_ratecoeff(modelgridindex, element, ion + 1, upper, level, epsilon_trans); + const double R_recomb = rad_recombination_ratecoeff(T_e, nne, element, ion + 1, upper, level, nonemptymgi); + const double C_recomb = col_recombination_ratecoeff(T_e, nne, element, ion + 1, upper, level, epsilon_trans); *gsl_matrix_ptr(rate_matrix_rad_bf, upper_index, upper_index) -= R_recomb * s_renorm[upper]; *gsl_matrix_ptr(rate_matrix_rad_bf, lower_index, upper_index) += R_recomb * s_renorm[upper]; @@ -573,12 +574,12 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, } } -void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int element, const int ion, +void nltepop_matrix_add_nt_ionisation(const int nonemptymgi, const int element, const int ion, const std::vector &s_renorm, gsl_matrix *rate_matrix_ntcoll_bf) { // collisional ionization by non-thermal electrons assert_always(ion + 1 < get_nions(element)); // can't ionise the top ion - const double Y_nt = nonthermal::nt_ionization_ratecoeff(modelgridindex, element, ion); + const double Y_nt = nonthermal::nt_ionization_ratecoeff(nonemptymgi, element, ion); if (Y_nt < 0.) { printout(" WARNING: Negative NT_ionization rate from ionstage %d\n", get_ionstage(element, ion)); } @@ -587,7 +588,7 @@ void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int elemen for (int upperion = ion + 1; upperion <= nonthermal::nt_ionisation_maxupperion(element, ion); upperion++) { const double Y_nt_thisupperion = - Y_nt * nonthermal::nt_ionization_upperion_probability(modelgridindex, element, ion, upperion, false); + Y_nt * nonthermal::nt_ionization_upperion_probability(nonemptymgi, element, ion, upperion, false); if (Y_nt_thisupperion > 0.) { const int upper_groundstate_index = get_nlte_vector_index(element, upperion, 0); @@ -602,7 +603,7 @@ void nltepop_matrix_add_nt_ionisation(const int modelgridindex, const int elemen } } -void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_matrix *rate_matrix, +void nltepop_matrix_normalise(const int nonemptymgi, const int element, gsl_matrix *rate_matrix, gsl_vector *pop_norm_factor_vec) { const size_t nlte_dimension = pop_norm_factor_vec->size; assert_always(pop_norm_factor_vec->size == nlte_dimension); @@ -614,21 +615,20 @@ void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_m for (size_t column = 0; column < nlte_dimension; column++) { const auto [ion, level] = get_ion_level_of_nlte_vector_index(column, element); - gsl_vector_set(pop_norm_factor_vec, column, calculate_levelpop_lte(modelgridindex, element, ion, level)); + gsl_vector_set(pop_norm_factor_vec, column, calculate_levelpop_lte(nonemptymgi, element, ion, level)); if ((level != 0) && (!is_nlte(element, ion, level))) { // level is a superlevel, so add populations of higher levels to the norm factor for (int dummylevel = level + 1; dummylevel < get_nlevels(element, ion); dummylevel++) { if (!is_nlte(element, ion, dummylevel)) { - *gsl_vector_ptr(pop_norm_factor_vec, column) += - calculate_levelpop_lte(modelgridindex, element, ion, dummylevel); + *gsl_vector_ptr(pop_norm_factor_vec, column) += calculate_levelpop_lte(nonemptymgi, element, ion, dummylevel); } } // NOTE: above calculation is not always equal to the sum of LTE populations // since calculate_levelpop_lte imposes MINPOP minimum // printout("superlevel norm factor index %d is %g, partfunc is %g, partfunc*levelpop(SL)/g(SL) %g\n", // column, gsl_vector_get(pop_norm_factor_vec, column), superlevel_partfunc[ion], - // superlevel_partfunc[ion] * calculate_levelpop_lte(modelgridindex,element,ion,level) / + // superlevel_partfunc[ion] * calculate_levelpop_lte(nonemptymgi,element,ion,level) / // stat_weight(element,ion,level)); } @@ -638,11 +638,10 @@ void nltepop_matrix_normalise(const int modelgridindex, const int element, gsl_m } } -void set_element_pops_lte(const int modelgridindex, const int element) { - nltepop_reset_element(modelgridindex, element); // set NLTE pops as invalid so that LTE pops will be used instead - - calculate_cellpartfuncts(modelgridindex, element); - set_groundlevelpops(modelgridindex, element, grid::get_nne(modelgridindex), true); +void set_element_pops_lte(const int nonemptymgi, const int element) { + nltepop_reset_element(nonemptymgi, element); // set NLTE pops as invalid so that LTE pops will be used instead + calculate_cellpartfuncts(nonemptymgi, element); + set_groundlevelpops(nonemptymgi, element, grid::get_nne(nonemptymgi), true); } [[nodiscard]] auto lumatrix_is_singular(const gsl_matrix *LU, const int element) -> bool { @@ -802,22 +801,22 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const int atomic_number = get_atomicnumber(element); const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - if (grid::get_elem_abundance(modelgridindex, element) <= 0.) { + if (grid::get_elem_abundance(nonemptymgi, element) <= 0.) { // abundance of this element is zero, so do not store any NLTE populations printout("Not solving for NLTE populations in cell %d at timestep %d for element Z=%d due to zero abundance\n", modelgridindex, timestep, atomic_number); - nltepop_reset_element(modelgridindex, element); + nltepop_reset_element(nonemptymgi, element); return; } - const double cell_Te = grid::get_Te(modelgridindex); + const double cell_Te = grid::get_Te(nonemptymgi); if (cell_Te == MINTEMP) { printout( "Not solving for NLTE populations in cell %d at timestep %d for element Z=%d due to low temperature Te=%g\n", modelgridindex, timestep, atomic_number, cell_Te); - set_element_pops_lte(modelgridindex, element); + set_element_pops_lte(nonemptymgi, element); return; } @@ -825,12 +824,12 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const const double t_mid = globals::timesteps[timestep].mid; const int nions = get_nions(element); - const double nnelement = grid::get_elem_numberdens(modelgridindex, element); + const double nnelement = grid::get_elem_numberdens(nonemptymgi, element); printout( "Solving for NLTE populations in cell %d at timestep %d NLTE iteration %d for element Z=%d (mass fraction %.2e, " "nnelement %.2e cm^-3)\n", - modelgridindex, timestep, nlte_iter, atomic_number, grid::get_elem_abundance(modelgridindex, element), nnelement); + modelgridindex, timestep, nlte_iter, atomic_number, grid::get_elem_abundance(nonemptymgi, element), nnelement); const auto superlevel_partfunc = get_element_superlevelpartfuncs(modelgridindex, element); const int nlte_dimension = get_element_nlte_dimension(element); @@ -909,14 +908,14 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const s_renorm[level] = superlevel_boltzmann(modelgridindex, element, ion, level) / superlevel_partfunc[ion]; } - nltepop_matrix_add_boundbound(modelgridindex, element, ion, t_mid, s_renorm, &rate_matrix_rad_bb, - &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb); + nltepop_matrix_add_boundbound(nonemptymgi, element, ion, t_mid, s_renorm, &rate_matrix_rad_bb, &rate_matrix_coll_bb, + &rate_matrix_ntcoll_bb); if (ion < nions - 1) { // this is the slowest component nltepop_matrix_add_ionisation(modelgridindex, element, ion, s_renorm, &rate_matrix_rad_bf, &rate_matrix_coll_bf); if (NT_ON) { - nltepop_matrix_add_nt_ionisation(modelgridindex, element, ion, s_renorm, &rate_matrix_ntcoll_bf); + nltepop_matrix_add_nt_ionisation(nonemptymgi, element, ion, s_renorm, &rate_matrix_ntcoll_bf); } } } @@ -945,7 +944,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const gsl_vector_set(&balance_vector, 0, nnelement); if (FORCE_SAHA_ION_BALANCE(atomic_number)) { - const auto ionfractions = calculate_ionfractions(element, modelgridindex, grid::get_nne(modelgridindex), true); + const auto ionfractions = calculate_ionfractions(element, nonemptymgi, grid::get_nne(nonemptymgi), true); const int uppermost_ion = static_cast(ionfractions.size() - 1); for (int ion = 1; ion <= uppermost_ion; ion++) { // replace matrix row for ion's ground state with sum of this ion's level populations is equal to the ion @@ -970,7 +969,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const auto pop_norm_factor_vec = gsl_vector_view_array(vec_pop_norm_factor_vec.data(), nlte_dimension).vector; gsl_vector_set_all(&pop_norm_factor_vec, 1.0); - nltepop_matrix_normalise(modelgridindex, element, &rate_matrix, &pop_norm_factor_vec); + nltepop_matrix_normalise(nonemptymgi, element, &rate_matrix, &pop_norm_factor_vec); // printout("Rate matrix | balance vector:\n"); // for (int row = 0; row < nlte_dimension; row++) @@ -1005,7 +1004,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const "WARNING: Can't solve for NLTE populations in cell %d at timestep %d for element Z=%d due to singular matrix. " "Attempting to use LTE solution instead\n", modelgridindex, timestep, atomic_number); - set_element_pops_lte(modelgridindex, element); + set_element_pops_lte(nonemptymgi, element); } else { // check calculated NLTE populations are valid for (int index = 0; index < nlte_dimension; index++) { @@ -1021,15 +1020,15 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const // // printout(" For ionstage %d, the ground state populations are %g (function) and %g (matrix result with // normed pop %g, ltepopnormfactor %g)\n",get_ionstage(element,ion), - // get_groundlevelpop(modelgridindex, element, ion), gsl_vector_get(popvec, index_gs), + // get_groundlevelpop(nonemptymgi, element, ion), gsl_vector_get(popvec, index_gs), // gsl_vector_get(x, index_gs), gsl_vector_get(pop_norm_factor_vec, index_gs)); // store the NLTE level populations // double solution_ion_pop = 0.; for (int level = 1; level <= nlevels_nlte; level++) { const int index = get_nlte_vector_index(element, ion, level); - set_nlte_levelpop_over_rho(modelgridindex, element, ion, level, - gsl_vector_get(&popvec, index) / grid::get_rho(modelgridindex)); + set_nlte_levelpop_over_rho(nonemptymgi, element, ion, level, + gsl_vector_get(&popvec, index) / grid::get_rho(nonemptymgi)); // solution_ion_pop += gsl_vector_get(popvec, index); } @@ -1038,8 +1037,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const { const int index_sl = get_nlte_vector_index(element, ion, nlevels_nlte + 1); set_nlte_superlevelpop_over_rho( - modelgridindex, element, ion, - gsl_vector_get(&popvec, index_sl) / grid::get_rho(modelgridindex) / superlevel_partfunc[ion]); + nonemptymgi, element, ion, + gsl_vector_get(&popvec, index_sl) / grid::get_rho(nonemptymgi) / superlevel_partfunc[ion]); } // store the ground level population @@ -1047,7 +1046,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const get_uniqueionindex(element, ion)] = gsl_vector_get(&popvec, index_gs); // solution_ion_pop += gsl_vector_get(popvec, index_gs); - calculate_cellpartfuncts(modelgridindex, element); + calculate_cellpartfuncts(nonemptymgi, element); } const double elem_pop_matrix = gsl_blas_dasum(&popvec); @@ -1057,7 +1056,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const " WARNING: The Z=%d element population is: %g (from abundance) and %g (from matrix solution sum of level " "pops), error: %.1f%%. Forcing element pops to LTE.\n", atomic_number, nnelement, elem_pop_matrix, elem_pop_error_percent); - set_element_pops_lte(modelgridindex, element); + set_element_pops_lte(nonemptymgi, element); } if (individual_process_matrices && (timestep % 5 == 0) && @@ -1103,7 +1102,8 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const __host__ __device__ auto superlevel_boltzmann(const int modelgridindex, const int element, const int ion, const int level) -> double { const int superlevel_index = get_nlevels_nlte(element, ion) + 1; - const double T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(modelgridindex) : grid::get_Te(modelgridindex); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(nonemptymgi) : grid::get_Te(nonemptymgi); const double E_level = epsilon(element, ion, level); const double E_superlevel = epsilon(element, ion, superlevel_index); @@ -1126,8 +1126,9 @@ void nltepop_close_file() { } } -void nltepop_write_to_file(const int modelgridindex, const int timestep) { - if (globals::lte_iteration || grid::modelgrid[modelgridindex].thick == 1) { // NLTE solver hasn't been run yet +void nltepop_write_to_file(const int nonemptymgi, const int timestep) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); + if (globals::lte_iteration || grid::modelgrid[nonemptymgi].thick == 1) { // NLTE solver hasn't been run yet return; } @@ -1149,7 +1150,7 @@ void nltepop_write_to_file(const int modelgridindex, const int timestep) { const int nsuperlevels = ion_has_superlevel(element, ion) ? 1 : 0; for (int level = 0; level <= nlevels_nlte + nsuperlevels; level++) { - double nnlevellte = calculate_levelpop_lte(modelgridindex, element, ion, level); + double nnlevellte = calculate_levelpop_lte(nonemptymgi, element, ion, level); double nnlevelnlte{NAN}; fprintf(nlte_file, "%d %d %d %d ", timestep, modelgridindex, atomic_number, ionstage); @@ -1157,28 +1158,28 @@ void nltepop_write_to_file(const int modelgridindex, const int timestep) { fprintf(nlte_file, "%d ", level); if (level == 0) { - nnlevelnlte = get_groundlevelpop(modelgridindex, element, ion); + nnlevelnlte = get_groundlevelpop(nonemptymgi, element, ion); } else { nnlevelnlte = - get_nlte_levelpop_over_rho(modelgridindex, element, ion, level) * grid::modelgrid[modelgridindex].rho; + get_nlte_levelpop_over_rho(nonemptymgi, element, ion, level) * grid::modelgrid[nonemptymgi].rho; } } else { // superlevel, so add the populations of all other levels in the superlevel const double slpopfactor = - get_nlte_superlevelpop_over_rho(modelgridindex, element, ion) * grid::modelgrid[modelgridindex].rho; + get_nlte_superlevelpop_over_rho(nonemptymgi, element, ion) * grid::modelgrid[nonemptymgi].rho; nnlevellte = 0; double superlevel_partfunc = 0; fprintf(nlte_file, "%d ", -1); for (int level_sl = nlevels_nlte + 1; level_sl < get_nlevels(element, ion); level_sl++) { - nnlevellte += calculate_levelpop_lte(modelgridindex, element, ion, level_sl); + nnlevellte += calculate_levelpop_lte(nonemptymgi, element, ion, level_sl); superlevel_partfunc += superlevel_boltzmann(modelgridindex, element, ion, level_sl); } nnlevelnlte = slpopfactor * superlevel_partfunc; } - const double ion_popfrac = nnlevelnlte / get_nnion(modelgridindex, element, ion); + const double ion_popfrac = nnlevelnlte / get_nnion(nonemptymgi, element, ion); fprintf(nlte_file, "%.5e %.5e %.5e\n", nnlevellte, nnlevelnlte, ion_popfrac); } } @@ -1197,7 +1198,7 @@ void nltepop_write_restart_data(FILE *restart_file) { for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - fprintf(restart_file, "%d %la\n", modelgridindex, grid::modelgrid[modelgridindex].totalcooling); + fprintf(restart_file, "%d %la\n", modelgridindex, grid::modelgrid[nonemptymgi].totalcooling); for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -1234,13 +1235,9 @@ void nltepop_read_restart_data(FILE *restart_file) { const auto nincludedions = get_includedions(); for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); int mgi_in = 0; - assert_always(fscanf(restart_file, "%d %la\n", &mgi_in, &grid::modelgrid[modelgridindex].totalcooling) == 2); - if (mgi_in != modelgridindex) { - printout("ERROR: expected data for cell %d but found cell %d\n", modelgridindex, mgi_in); - std::abort(); - } + assert_always(fscanf(restart_file, "%d %la\n", &mgi_in, &grid::modelgrid[nonemptymgi].totalcooling) == 2); + assert_always(mgi_in == grid::get_mgi_of_nonemptymgi(nonemptymgi)); for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); @@ -1252,49 +1249,37 @@ void nltepop_read_restart_data(FILE *restart_file) { &grid::ion_partfuncts_allcells[(nonemptymgi * nincludedions) + uniqueionindex], &grid::ion_cooling_contribs_allcells[(nonemptymgi * nincludedions) + uniqueionindex]) == 4); - if (ion_in != ion) { - printout("ERROR: expected data for ion %d but found ion %d\n", ion, ion_in); - std::abort(); - } + assert_always(ion_in == ion); } } for (int nlteindex = 0; nlteindex < globals::total_nlte_levels; nlteindex++) { -#ifdef MPI_ON - if (globals::rank_in_node != 0) { - assert_always(fscanf(restart_file, "%*a ") == 0); // discard value (master rank of this node will set it) - } else -#endif - assert_always(fscanf(restart_file, "%la ", - &grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + nlteindex]) == 1); + assert_always(fscanf(restart_file, "%la ", + &grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + nlteindex]) == 1); } } } -auto get_nlte_levelpop_over_rho(const int modelgridindex, const int element, const int ion, const int level) -> double { +auto get_nlte_levelpop_over_rho(const int nonemptymgi, const int element, const int ion, const int level) -> double { assert_testmodeonly(level <= get_nlevels_nlte(element, ion)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - return grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + + return grid::nltepops_allcells[(static_cast(nonemptymgi) * globals::total_nlte_levels) + globals::elements[element].ions[ion].first_nlte + level - 1]; } -auto get_nlte_superlevelpop_over_rho(const int modelgridindex, const int element, const int ion) -> double { +auto get_nlte_superlevelpop_over_rho(const int nonemptymgi, const int element, const int ion) -> double { assert_testmodeonly(ion_has_superlevel(element, ion)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int sl_nlte_index = globals::elements[element].ions[ion].first_nlte + get_nlevels_nlte(element, ion); return grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + sl_nlte_index]; } -void set_nlte_levelpop_over_rho(const int modelgridindex, const int element, const int ion, const int level, +void set_nlte_levelpop_over_rho(const int nonemptymgi, const int element, const int ion, const int level, const double value) { assert_testmodeonly(level <= get_nlevels_nlte(element, ion)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + globals::elements[element].ions[ion].first_nlte + level - 1] = value; } -void set_nlte_superlevelpop_over_rho(const int modelgridindex, const int element, const int ion, const double value) { +void set_nlte_superlevelpop_over_rho(const int nonemptymgi, const int element, const int ion, const double value) { assert_testmodeonly(ion_has_superlevel(element, ion)); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int sl_nlte_index = globals::elements[element].ions[ion].first_nlte + get_nlevels_nlte(element, ion); grid::nltepops_allcells[(nonemptymgi * globals::total_nlte_levels) + sl_nlte_index] = value; } diff --git a/nltepop.h b/nltepop.h index 4d2cd18c8..edd565722 100644 --- a/nltepop.h +++ b/nltepop.h @@ -5,11 +5,11 @@ void solve_nlte_pops_element(int element, int modelgridindex, int timestep, int nlte_iter); [[nodiscard]] auto superlevel_boltzmann(int modelgridindex, int element, int ion, int level) -> double; -[[nodiscard]] auto get_nlte_levelpop_over_rho(int modelgridindex, int element, int ion, int level) -> double; -[[nodiscard]] auto get_nlte_superlevelpop_over_rho(int modelgridindex, int element, int ion) -> double; -void set_nlte_levelpop_over_rho(int modelgridindex, int element, int ion, int level, double value); -void set_nlte_superlevelpop_over_rho(int modelgridindex, int element, int ion, double value); -void nltepop_write_to_file(int modelgridindex, int timestep); +[[nodiscard]] auto get_nlte_levelpop_over_rho(int nonemptymgi, int element, int ion, int level) -> double; +[[nodiscard]] auto get_nlte_superlevelpop_over_rho(int nonemptymgi, int element, int ion) -> double; +void set_nlte_levelpop_over_rho(int nonemptymgi, int element, int ion, int level, double value); +void set_nlte_superlevelpop_over_rho(int nonemptymgi, int element, int ion, double value); +void nltepop_write_to_file(int nonemptymgi, int timestep); void nltepop_open_file(int my_rank); void nltepop_close_file(); void nltepop_write_restart_data(FILE *restart_file); diff --git a/nonthermal.cc b/nonthermal.cc index 614119e66..ebc92b75b 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -93,7 +93,6 @@ struct collionrow { std::vector colliondata; FILE *nonthermalfile{}; -bool nonthermal_initialized = false; static_assert(SF_EMIN > 0.); constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); @@ -156,13 +155,12 @@ struct NonThermalExcitation { }; // pointer to either local or node-shared memory excitation list of all cells -NonThermalExcitation *excitations_list_all_cells{}; +std::span excitations_list_all_cells{}; // the minimum of MAX_NT_EXCITATIONS_STORED and the number of included excitation transitions in the atomic dataset int nt_excitations_stored = 0; struct NonThermalSolutionIon { - // these points arrays of length includedions. TODO: move to NonThermalSolutionIon float eff_ionpot{0.}; // these are used to calculate the non-thermal ionization rate double fracdep_ionization_ion{0.}; // the fraction of the non-thermal deposition energy going to ionizing each ion @@ -173,23 +171,22 @@ struct NonThermalSolutionIon { std::array ionenfrac_num_auger{}; }; +std::span ion_data_all_cells{}; + struct NonThermalCellSolution { float frac_heating = 1.; // energy fractions should add up to 1.0 if the solution is good float frac_ionization = 0.; // fraction of deposition energy going to ionization float frac_excitation = 0.; // fraction of deposition energy going to excitation - NonThermalSolutionIon *allions{}; - int frac_excitations_list_size = 0; - NonThermalExcitation *frac_excitations_list{}; int timestep_last_solved = -1; // the quantities above were calculated for this timestep float nneperion_when_solved{NAN}; // the nne when the solver was last run }; -std::vector nt_solution; +std::span nt_solution; -std::vector deposition_rate_density_all_cells; +std::span deposition_rate_density_all_cells; constexpr auto uppertriangular(const int i, const int j) -> int { assert_testmodeonly(i >= 0); @@ -307,19 +304,28 @@ void read_binding_energies() { } } -auto get_auger_probability(const int modelgridindex, const int element, const int ion, const int naugerelec) { +[[nodiscard]] auto get_cell_ntexcitations(const int nonemptymgi) { + return excitations_list_all_cells.subspan(nonemptymgi * nt_excitations_stored, + nt_solution[nonemptymgi].frac_excitations_list_size); +} + +[[nodiscard]] auto get_cell_ion_data(const int nonemptymgi) { + return ion_data_all_cells.subspan(nonemptymgi * get_includedions(), get_includedions()); +} + +auto get_auger_probability(const int nonemptymgi, const int element, const int ion, const int naugerelec) { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[naugerelec]; + return get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[naugerelec]; } -auto get_ion_auger_enfrac(const int modelgridindex, const int element, const int ion, const int naugerelec) { +auto get_ion_auger_enfrac(const int nonemptymgi, const int element, const int ion, const int naugerelec) { assert_always(naugerelec <= NT_MAX_AUGER_ELECTRONS); const int uniqueionindex = get_uniqueionindex(element, ion); - return nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[naugerelec]; + return get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[naugerelec]; } -void check_auger_probabilities(int modelgridindex) { +void check_auger_probabilities(int nonemptymgi) { bool problem_found = false; for (int element = 0; element < get_nelements(); element++) { @@ -327,33 +333,33 @@ void check_auger_probabilities(int modelgridindex) { double prob_sum = 0.; double ionenfrac_sum = 0.; for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - prob_sum += get_auger_probability(modelgridindex, element, ion, a); - ionenfrac_sum += get_ion_auger_enfrac(modelgridindex, element, ion, a); + prob_sum += get_auger_probability(nonemptymgi, element, ion, a); + ionenfrac_sum += get_ion_auger_enfrac(nonemptymgi, element, ion, a); } if (fabs(prob_sum - 1.0) > 0.001) { - printout("Problem with Auger probabilities for cell %d Z=%d ionstage %d prob_sum %g\n", modelgridindex, - get_atomicnumber(element), get_ionstage(element, ion), prob_sum); + printout("Problem with Auger probabilities for cell %d Z=%d ionstage %d prob_sum %g\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi), get_atomicnumber(element), get_ionstage(element, ion), + prob_sum); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - printout("%d: %g\n", a, get_auger_probability(modelgridindex, element, ion, a)); + printout("%d: %g\n", a, get_auger_probability(nonemptymgi, element, ion, a)); } problem_found = true; } if (fabs(ionenfrac_sum - 1.0) > 0.001) { - printout("Problem with Auger energy frac sum for cell %d Z=%d ionstage %d ionenfrac_sum %g\n", modelgridindex, - get_atomicnumber(element), get_ionstage(element, ion), ionenfrac_sum); + printout("Problem with Auger energy frac sum for cell %d Z=%d ionstage %d ionenfrac_sum %g\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi), get_atomicnumber(element), get_ionstage(element, ion), + ionenfrac_sum); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - printout("%d: %g\n", a, get_ion_auger_enfrac(modelgridindex, element, ion, a)); + printout("%d: %g\n", a, get_ion_auger_enfrac(nonemptymgi, element, ion, a)); } problem_found = true; } } } - if (problem_found) { - std::abort(); - } + assert_always(!problem_found); } void read_auger_data() { @@ -733,20 +739,21 @@ auto get_possible_nt_excitation_count() -> int { return ntexcitationcount; } -void zero_all_effionpot(const int modelgridindex) { +void zero_all_effionpot(const int nonemptymgi) { for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = 0.; + auto &ion_data = get_cell_ion_data(nonemptymgi)[uniqueionindex]; + ion_data.eff_ionpot = 0.; - std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger, 0.); - std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger, 0.); - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[0] = 1.; - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[0] = 1.; + std::ranges::fill(get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger, 0.); + std::ranges::fill(get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger, 0.); + ion_data.prob_num_auger[0] = 1.; + ion_data.ionenfrac_num_auger[0] = 1.; const auto [element, ion] = get_ionfromuniqueionindex(uniqueionindex); - assert_always(fabs(get_auger_probability(modelgridindex, element, ion, 0) - 1.0) < 1e-3); - assert_always(fabs(get_ion_auger_enfrac(modelgridindex, element, ion, 0) - 1.0) < 1e-3); + assert_always(fabs(get_auger_probability(nonemptymgi, element, ion, 0) - 1.0) < 1e-3); + assert_always(fabs(get_ion_auger_enfrac(nonemptymgi, element, ion, 0) - 1.0) < 1e-3); } - check_auger_probabilities(modelgridindex); + check_auger_probabilities(nonemptymgi); } [[nodiscard]] constexpr auto get_energyindex_ev_lteq(const double energy_ev) -> int @@ -800,10 +807,7 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it #pragma omp critical(nonthermal_out_file) { #endif - if (!nonthermal_initialized || nonthermalfile == nullptr) { - printout("Call to nonthermal_write_to_file before nonthermal_init"); - std::abort(); - } + assert_always(nonthermalfile != nullptr); static int64_t nonthermalfile_offset_iteration_zero = 0; #ifdef _OPENMP @@ -818,7 +822,8 @@ void nt_write_to_file(const int modelgridindex, const int timestep, const int it } } - const double yscalefactor = get_deposition_rate_density(modelgridindex) / (E_init_ev * EV); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double yscalefactor = get_deposition_rate_density(nonemptymgi) / (E_init_ev * EV); for (int s = 0; s < SFPTS; s++) { fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, engrid(s), sourcevec(s), @@ -1020,9 +1025,9 @@ constexpr auto xs_impactionization(const double energy_ev, const collionrow &col // Kozma & Fransson equation 6. // Something related to a number of electrons, needed to calculate the heating fraction in equation 3 // not valid for energy > SF_EMIN -auto N_e(const int modelgridindex, const double energy, const std::array &yfunc) -> double { +auto N_e(const int nonemptymgi, const double energy, const std::array &yfunc) -> double { const double energy_ev = energy / EV; - const double tot_nion = get_nnion_tot(modelgridindex); + const double tot_nion = get_nnion_tot(nonemptymgi); double N_e = 0.; for (int element = 0; element < get_nelements(); element++) { @@ -1032,7 +1037,7 @@ auto N_e(const int modelgridindex, const double energy, const std::array &yfunc) -> float { +auto calculate_frac_heating(const int nonemptymgi, const std::array &yfunc) -> float { // frac_heating multiplied by E_init, which will be divided out at the end double frac_heating_Einit = 0.; - - const float nne = grid::get_nne(modelgridindex); - // const float nnetot = grid::get_nnetot(modelgridindex); + const float nne = grid::get_nne(nonemptymgi); for (int i = 0; i < SFPTS; i++) { const double endash = engrid(i); @@ -1126,7 +1129,7 @@ auto calculate_frac_heating(const int modelgridindex, const std::array float { if (!NT_SOLVE_SPENCERFANO) { return 0.03; } + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - const float frac_ionization = nt_solution[modelgridindex].frac_ionization; + const float frac_ionization = nt_solution[nonemptymgi].frac_ionization; if (frac_ionization < 0 || !std::isfinite(frac_ionization)) { printout("ERROR: get_nt_frac_ionization called with no valid solution stored for cell %d. frac_ionization = %g\n", @@ -1167,7 +1171,8 @@ auto get_nt_frac_excitation(const int modelgridindex) -> float { return 0.; } - const float frac_excitation = nt_solution[modelgridindex].frac_excitation; + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const float frac_excitation = nt_solution[nonemptymgi].frac_excitation; if (frac_excitation < 0 || !std::isfinite(frac_excitation)) { printout("ERROR: get_nt_frac_excitation called with no valid solution stored for cell %d. frac_excitation = %g\n", @@ -1186,9 +1191,10 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> // We are going to start by taking all the high energy limits and ignoring Lelec, so that the // denominator is extremely simplified. Need to get the mean Z value. + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); double Zbar = 0.; // mass-weighted average atomic number for (int ielement = 0; ielement < get_nelements(); ielement++) { - Zbar += grid::get_elem_abundance(modelgridindex, ielement) * get_atomicnumber(ielement); + Zbar += grid::get_elem_abundance(nonemptymgi, ielement) * get_atomicnumber(ielement); } const double binding = get_sum_q_over_binding_energy(element, ion); @@ -1199,10 +1205,10 @@ auto get_oneoverw(const int element, const int ion, const int modelgridindex) -> } // the fraction of deposited energy that goes into ionising electrons in a particular shell -auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int element, const int ion, +auto calculate_nt_frac_ionization_shell(const int nonemptymgi, const int element, const int ion, const collionrow &collionrow, const std::array &yfunc) -> double { - const double nnion = get_nnion(modelgridindex, element, ion); + const double nnion = get_nnion(nonemptymgi, element, ion); const double ionpot_ev = collionrow.ionpot_ev; std::array cross_section_vec{}; @@ -1216,21 +1222,22 @@ auto calculate_nt_frac_ionization_shell(const int modelgridindex, const int elem auto nt_ionization_ratecoeff_wfapprox(const int modelgridindex, const int element, const int ion) -> double // non-thermal ionization rate coefficient (multiply by population to get rate) { - const double deposition_rate_density = get_deposition_rate_density(modelgridindex); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double deposition_rate_density = get_deposition_rate_density(nonemptymgi); // to get the non-thermal ionization rate we need to divide the energy deposited // per unit volume per unit time in the grid cell (sum of terms above) // by the total ion number density and the "work per ion pair" - return deposition_rate_density / get_nnion_tot(modelgridindex) * get_oneoverw(element, ion, modelgridindex); + return deposition_rate_density / get_nnion_tot(nonemptymgi) * get_oneoverw(element, ion, modelgridindex); } -auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion, - const bool assumeshellpotentialisvalence, const std::array &yfunc) - -> double // Integrate the ionization cross section over the electron degradation function to get the ionization rate // coefficient i.e. multiply this by ion population to get a rate of ionizations per second Do not call during packet // propagation, as the y vector may not be in memory! IMPORTANT: we are dividing by the shell potential, not the // valence potential here! To change this set assumeshellpotentialisvalence to true -{ +auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion, + const bool assumeshellpotentialisvalence, const std::array &yfunc) + -> double { + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); std::array cross_section_vec{}; auto gsl_cross_section_vec = gsl_vector_view_array(cross_section_vec.data(), SFPTS).vector; std::array cross_section_vec_allshells{}; @@ -1263,13 +1270,13 @@ auto calculate_nt_ionization_ratecoeff(const int modelgridindex, const int eleme const double y_xs_de = cblas_ddot(SFPTS, yfunc.data(), 1, cross_section_vec_allshells.data(), 1) * DELTA_E; - const double deposition_rate_density_ev = get_deposition_rate_density(modelgridindex) / EV; + const double deposition_rate_density_ev = get_deposition_rate_density(nonemptymgi) / EV; const double yscalefactor = deposition_rate_density_ev / E_init_ev; return yscalefactor * y_xs_de; } -void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int element, const int ion, +void calculate_eff_ionpot_auger_rates(const int nonemptymgi, const int element, const int ion, const std::array &yfunc) // Kozma & Fransson 1992 equation 12, except modified to be a sum over all shells of an ion // the result is in ergs @@ -1277,8 +1284,8 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen const int Z = get_atomicnumber(element); const int ionstage = get_ionstage(element, ion); const int uniqueionindex = get_uniqueionindex(element, ion); - const double nnion = get_nnion(modelgridindex, element, ion); // ions/cm^3 - const double tot_nion = get_nnion_tot(modelgridindex); + const double nnion = get_nnion(nonemptymgi, element, ion); // ions/cm^3 + const double tot_nion = get_nnion_tot(nonemptymgi); const double X_ion = nnion / tot_nion; // molar fraction of this ion // The ionization rates of all shells of an ion add to make the ion's total ionization rate, @@ -1290,9 +1297,9 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen std::array eta_nauger_ionize_over_ionpot_sum{}; std::array eta_nauger_ionize_sum{}; - - std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger, 0.); - std::ranges::fill(nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger, 0.); + const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); + std::ranges::fill(get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger, 0.); + std::ranges::fill(get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger, 0.); double eta_over_ionpot_sum = 0.; double eta_sum = 0.; @@ -1302,7 +1309,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen if (collionrow.Z == Z && collionrow.ionstage == ionstage) { matching_nlsubshell_count++; const double frac_ionization_shell = - calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); + calculate_nt_frac_ionization_shell(nonemptymgi, element, ion, collionrow, yfunc); eta_sum += frac_ionization_shell; const double ionpot_shell = collionrow.ionpot_ev * EV; @@ -1334,29 +1341,28 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen const int upperion = ion + 1 + a; if (upperion <= topion) // not too many Auger electrons to exceed the top ion of this element { - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = + get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[a] = eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = - eta_nauger_ionize_sum[a] / eta_sum; + get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[a] = eta_nauger_ionize_sum[a] / eta_sum; } else { // the following ensures that multiple ionisations can't send you to an ion stage that is not in // the model. Send it to the highest ion stage instead const int a_replace = topion - ion - 1; - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger.at(a_replace) += + get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger.at(a_replace) += eta_nauger_ionize_over_ionpot_sum[a] / eta_over_ionpot_sum; - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger.at(a_replace) += + get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger.at(a_replace) += eta_nauger_ionize_sum[a] / eta_sum; - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = 0; - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = 0.; + get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[a] = 0; + get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[a] = 0.; } } } } else { const int a = 0; - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a] = 1.; - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a] = 1.; + get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[a] = 1.; + get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[a] = 1.; } if (matching_nlsubshell_count > 0) { @@ -1364,7 +1370,7 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen if (!std::isfinite(eff_ionpot)) { eff_ionpot = 0.; } - nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = eff_ionpot; + get_cell_ion_data(nonemptymgi)[uniqueionindex].eff_ionpot = eff_ionpot; } else { printout("WARNING! No matching subshells in NT impact ionisation cross section data for Z=%d ionstage %d.\n", get_atomicnumber(element), get_ionstage(element, ion)); @@ -1372,28 +1378,26 @@ void calculate_eff_ionpot_auger_rates(const int modelgridindex, const int elemen "-> Defaulting to work function approximation and ionisation energy is not accounted for in Spencer-Fano " "solution.\n"); - nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot = 1. / get_oneoverw(element, ion, modelgridindex); + get_cell_ion_data(nonemptymgi)[uniqueionindex].eff_ionpot = 1. / get_oneoverw(element, ion, modelgridindex); } } // get the effective ion potential from the stored value // a value of 0. should be treated as invalid -auto get_eff_ionpot(const int modelgridindex, const int element, const int ion) { - return nt_solution[modelgridindex].allions[get_uniqueionindex(element, ion)].eff_ionpot; +auto get_eff_ionpot(const int nonemptymgi, const int element, const int ion) { + return get_cell_ion_data(nonemptymgi)[get_uniqueionindex(element, ion)].eff_ionpot; // OR // return calculate_eff_ionpot(modelgridindex, element, ion); } // Kozma & Fransson 1992 equation 13 // returns the rate coefficient in s^-1 -auto nt_ionization_ratecoeff_sf(const int modelgridindex, const int element, const int ion) -> double { - assert_testmodeonly(grid::get_numpropcells(modelgridindex) > 0); - - const double deposition_rate_density = get_deposition_rate_density(modelgridindex); +auto nt_ionization_ratecoeff_sf(const int nonemptymgi, const int element, const int ion) -> double { + const double deposition_rate_density = get_deposition_rate_density(nonemptymgi); if (deposition_rate_density > 0.) { - return deposition_rate_density / get_nnion_tot(modelgridindex) / get_eff_ionpot(modelgridindex, element, ion); + return deposition_rate_density / get_nnion_tot(nonemptymgi) / get_eff_ionpot(nonemptymgi, element, ion); // alternatively, if the y vector is still in memory: - // return calculate_nt_ionization_ratecoeff(modelgridindex, element, ion); + // return calculate_nt_ionization_ratecoeff(nonemptymgi, element, ion); } return 0.; @@ -1480,23 +1484,23 @@ auto calculate_nt_excitation_ratecoeff_perdeposition(const std::array double { - const double nnlowerion = get_nnion(modelgridindex, element, lowerion); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double nnlowerion = get_nnion(nonemptymgi, element, lowerion); double enrate = 0.; const auto maxupperion = nt_ionisation_maxupperion(element, lowerion); for (int upperion = lowerion + 1; upperion <= maxupperion; upperion++) { - const double upperionprobfrac = - nt_ionization_upperion_probability(modelgridindex, element, lowerion, upperion, false); + const double upperionprobfrac = nt_ionization_upperion_probability(nonemptymgi, element, lowerion, upperion, false); // for (int lower = 0; lower < get_nlevels(element, lowerion); lower++) // { // const double epsilon_trans = epsilon(element, upperion, 0) - epsilon(element, lowerion, lower); - // const double nnlower = get_levelpop(modelgridindex, element, lowerion, lower); + // const double nnlower = get_levelpop(nonemptymgi, element, lowerion, lower); // enrate += nnlower * upperionprobfrac * epsilon_trans; // } const double epsilon_trans = epsilon(element, upperion, 0) - epsilon(element, lowerion, 0); enrate += nnlowerion * upperionprobfrac * epsilon_trans; } - const double gamma_nt = nt_ionization_ratecoeff(modelgridindex, element, lowerion); + const double gamma_nt = nt_ionization_ratecoeff(nonemptymgi, element, lowerion); return gamma_nt * enrate; } @@ -1522,7 +1526,7 @@ auto select_nt_ionization(const int modelgridindex) -> std::tuple { // // e.g. if zrand was less than frac_dep_trans1, then use the first transition // // e.g. if zrand was between frac_dep_trans1 and frac_dep_trans2 then use the second transition, etc // for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { - // frac_deposition_ion_sum += nt_solution[modelgridindex].fracdep_ionization_ion[allionindex]; + // frac_deposition_ion_sum += nt_solution[nonemptymgi].fracdep_ionization_ion[allionindex]; // if (frac_deposition_ion_sum >= zrand) { // get_ionfromuniqueionindex(allionindex, element, lowerion); @@ -1559,11 +1563,12 @@ auto get_uptransindex(const int element, const int ion, const int lower, const i return -1; } -void analyse_sf_solution(const int modelgridindex, const int timestep, const bool enable_sfexcitation, +void analyse_sf_solution(const int nonemptymgi, const int timestep, const bool enable_sfexcitation, const std::array &yfunc) { - const float nne = grid::get_nne(modelgridindex); - const double nntot = get_nnion_tot(modelgridindex); - const double nnetot = grid::get_nnetot(modelgridindex); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); + const auto nntot = get_nnion_tot(nonemptymgi); + const auto nnetot = grid::get_nnetot(nonemptymgi); double frac_excitation_total = 0.; double frac_ionization_total = 0.; @@ -1580,9 +1585,9 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const int uniqueionindex = get_uniqueionindex(element, ion); const int ionstage = get_ionstage(element, ion); - const double nnion = get_nnion(modelgridindex, element, ion); + const double nnion = get_nnion(nonemptymgi, element, ion); - // if (nnion < minionfraction * get_nnion_tot(modelgridindex)) // skip negligible ions + // if (nnion < minionfraction * get_nnion_tot(nonemptymgi)) // skip negligible ions if (nnion <= 0.) { // skip zero-abundance ions continue; } @@ -1593,13 +1598,13 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // printout(" nnion: %g\n", nnion); printout(" nnion/nntot: %g\n", nnion / nntot); - calculate_eff_ionpot_auger_rates(modelgridindex, element, ion, yfunc); + calculate_eff_ionpot_auger_rates(nonemptymgi, element, ion, yfunc); int matching_subshell_count = 0; for (const auto &collionrow : colliondata) { if (collionrow.Z == Z && collionrow.ionstage == ionstage) { const double frac_ionization_ion_shell = - calculate_nt_frac_ionization_shell(modelgridindex, element, ion, collionrow, yfunc); + calculate_nt_frac_ionization_shell(nonemptymgi, element, ion, collionrow, yfunc); frac_ionization_ion += frac_ionization_ion_shell; matching_subshell_count++; printout(" shell "); @@ -1622,11 +1627,11 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo // do not ionize the top ion if (ion < nions - 1) { - nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion = frac_ionization_ion; + get_cell_ion_data(nonemptymgi)[uniqueionindex].fracdep_ionization_ion = frac_ionization_ion; frac_ionization_total += frac_ionization_ion; } else { - nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion = 0.; + get_cell_ion_data(nonemptymgi)[uniqueionindex].fracdep_ionization_ion = 0.; } printout(" frac_ionization: %g (%d subshells)\n", frac_ionization_ion, matching_subshell_count); @@ -1637,13 +1642,13 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo if (!enable_sfexcitation) { nlevels = -1; // disable all excitations } - const bool above_minionfraction = (nnion >= minionfraction * get_nnion_tot(modelgridindex)); + const bool above_minionfraction = (nnion >= minionfraction * get_nnion_tot(nonemptymgi)); for (int lower = 0; lower < nlevels; lower++) { const double statweight_lower = stat_weight(element, ion, lower); const int nuptrans = get_nuptrans(element, ion, lower); const auto *const uptranslist = get_uptranslist(element, ion, lower); - const double nnlevel = get_levelpop(modelgridindex, element, ion, lower); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, lower); const double epsilon_lower = epsilon(element, ion, lower); for (int t = 0; t < nuptrans; t++) { @@ -1685,24 +1690,24 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo frac_excitation_total += frac_excitation_ion; printout(" workfn: %9.2f eV\n", (1. / get_oneoverw(element, ion, modelgridindex)) / EV); printout(" eff_ionpot: %9.2f eV (always use valence potential is %s)\n", - get_eff_ionpot(modelgridindex, element, ion) / EV, (NT_USE_VALENCE_IONPOTENTIAL ? "true" : "false")); + get_eff_ionpot(nonemptymgi, element, ion) / EV, (NT_USE_VALENCE_IONPOTENTIAL ? "true" : "false")); printout(" workfn approx Gamma: %9.3e\n", nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion)); printout(" SF integral Gamma: %9.3e\n", - calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, false, yfunc)); + calculate_nt_ionization_ratecoeff(nonemptymgi, element, ion, false, yfunc)); printout(" SF integral(I=Iv) Gamma: %9.3e (if always use valence potential)\n", - calculate_nt_ionization_ratecoeff(modelgridindex, element, ion, true, yfunc)); + calculate_nt_ionization_ratecoeff(nonemptymgi, element, ion, true, yfunc)); - printout(" ARTIS using Gamma: %9.3e\n", nt_ionization_ratecoeff(modelgridindex, element, ion)); + printout(" ARTIS using Gamma: %9.3e\n", nt_ionization_ratecoeff(nonemptymgi, element, ion)); // the ion values (unlike shell ones) have been collapsed down to ensure that upperion < nions if (ion < nions - 1) { printout(" probability to ionstage:"); double prob_sum = 0.; for (int upperion = ion + 1; upperion <= nt_ionisation_maxupperion(element, ion); upperion++) { - const double probability = nt_ionization_upperion_probability(modelgridindex, element, ion, upperion, false); + const double probability = nt_ionization_upperion_probability(nonemptymgi, element, ion, upperion, false); prob_sum += probability; if (probability > 0.) { printout(" %d: %.3f", get_ionstage(element, upperion), probability); @@ -1710,12 +1715,12 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } printout("\n"); assert_always((fabs(prob_sum - 1.0) <= 1e-2) || - (nt_ionization_ratecoeff_sf(modelgridindex, element, ion) < 1e-20)); + (nt_ionization_ratecoeff_sf(nonemptymgi, element, ion) < 1e-20)); printout(" enfrac to ionstage:"); double enfrac_sum = 0.; for (int upperion = ion + 1; upperion <= nt_ionisation_maxupperion(element, ion); upperion++) { - const double probability = nt_ionization_upperion_probability(modelgridindex, element, ion, upperion, true); + const double probability = nt_ionization_upperion_probability(nonemptymgi, element, ion, upperion, true); enfrac_sum += probability; if (probability > 0.) { printout(" %d: %.3f", get_ionstage(element, upperion), probability); @@ -1723,7 +1728,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } printout("\n"); assert_always(fabs(enfrac_sum - 1.0) <= 1e-2 || - (nt_ionization_ratecoeff_sf(modelgridindex, element, ion) < 1e-20)); + (nt_ionization_ratecoeff_sf(nonemptymgi, element, ion) < 1e-20)); } } } @@ -1734,7 +1739,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo &NonThermalExcitation::frac_deposition); // the excitation list is now sorted by frac_deposition descending - const double deposition_rate_density = get_deposition_rate_density(modelgridindex); + const double deposition_rate_density = get_deposition_rate_density(nonemptymgi); if (std::ssize(tmp_excitation_list) > nt_excitations_stored) { // truncate the sorted list to save memory @@ -1743,18 +1748,16 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo tmp_excitation_list.resize(nt_excitations_stored); } - nt_solution[modelgridindex].frac_excitations_list_size = tmp_excitation_list.size(); - std::copy(tmp_excitation_list.begin(), tmp_excitation_list.end(), - nt_solution[modelgridindex].frac_excitations_list); + nt_solution[nonemptymgi].frac_excitations_list_size = tmp_excitation_list.size(); + std::copy(tmp_excitation_list.begin(), tmp_excitation_list.end(), get_cell_ntexcitations(nonemptymgi).begin()); printout("[info] mem_usage: non-thermal excitations for cell %d at this timestep occupy %.3f MB\n", modelgridindex, - nt_solution[modelgridindex].frac_excitations_list_size * - sizeof(nt_solution[modelgridindex].frac_excitations_list[0]) / 1024. / 1024.); + nt_solution[nonemptymgi].frac_excitations_list_size * sizeof(NonThermalExcitation) / 1024. / 1024.); - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); printout(" Top non-thermal excitation fractions (total excitations = %d):\n", - nt_solution[modelgridindex].frac_excitations_list_size); - const int ntransdisplayed = std::min(50, nt_solution[modelgridindex].frac_excitations_list_size); + nt_solution[nonemptymgi].frac_excitations_list_size); + const int ntransdisplayed = std::min(50, nt_solution[nonemptymgi].frac_excitations_list_size); for (int excitationindex = 0; excitationindex < ntransdisplayed; excitationindex++) { const auto &ntexc = tmp_excitation_list[excitationindex]; @@ -1765,7 +1768,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const int ion = line.ionindex; const int lower = line.lowerlevelindex; const int upper = line.upperlevelindex; - const auto nnlevel_lower = get_levelpop(modelgridindex, element, ion, lower); + const auto nnlevel_lower = get_levelpop(nonemptymgi, element, ion, lower); const auto uptransindex = get_uptransindex(element, ion, lower, upper); const double epsilon_trans = epsilon(element, ion, upper) - epsilon(element, ion, lower); @@ -1773,7 +1776,7 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo const double ntcollexc_ratecoeff = ntexc.ratecoeffperdeposition * deposition_rate_density; const double t_mid = globals::timesteps[timestep].mid; - const double radexc_ratecoeff = rad_excitation_ratecoeff(modelgridindex, element, ion, lower, uptransindex, + const double radexc_ratecoeff = rad_excitation_ratecoeff(nonemptymgi, element, ion, lower, uptransindex, epsilon_trans, nnlevel_lower, lineindex, t_mid); const double collexc_ratecoeff = col_excitation_ratecoeff(T_e, nne, element, ion, lower, uptransindex, @@ -1792,14 +1795,13 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo } // sort the excitation list by ascending lineindex for fast lookup with a binary search - std::ranges::SORT_OR_STABLE_SORT(std::span(nt_solution[modelgridindex].frac_excitations_list, - nt_solution[modelgridindex].frac_excitations_list_size), - std::ranges::less{}, &NonThermalExcitation::lineindex); + std::ranges::SORT_OR_STABLE_SORT(get_cell_ntexcitations(nonemptymgi), std::ranges::less{}, + &NonThermalExcitation::lineindex); } // NT_EXCITATION_ON // calculate number density of non-thermal electrons - const double deposition_rate_density_ev = get_deposition_rate_density(modelgridindex) / EV; + const double deposition_rate_density_ev = get_deposition_rate_density(nonemptymgi) / EV; const double yscalefactor = deposition_rate_density_ev / E_init_ev; double nne_nt_max = 0.; @@ -1810,8 +1812,8 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo nne_nt_max += yscalefactor * yfunc[i] * oneovervelocity * delta_endash; } - nt_solution[modelgridindex].frac_excitation = frac_excitation_total; - nt_solution[modelgridindex].frac_ionization = frac_ionization_total; + nt_solution[nonemptymgi].frac_excitation = frac_excitation_total; + nt_solution[nonemptymgi].frac_ionization = frac_ionization_total; printout(" E_init: %9.2f eV/s/cm^3\n", E_init_ev); printout(" deposition: %9.2f eV/s/cm^3\n", deposition_rate_density_ev); @@ -1821,29 +1823,30 @@ void analyse_sf_solution(const int modelgridindex, const int timestep, const boo printout(" nne_nt/nne < %9.3e\n", nne_nt_max / nne); // store the solution properties now while the NT spectrum is in memory (in case we free before packet prop) - nt_solution[modelgridindex].frac_heating = calculate_frac_heating(modelgridindex, yfunc); + nt_solution[nonemptymgi].frac_heating = calculate_frac_heating(nonemptymgi, yfunc); - printout(" frac_heating_tot: %g\n", nt_solution[modelgridindex].frac_heating); + printout(" frac_heating_tot: %g\n", nt_solution[nonemptymgi].frac_heating); printout(" frac_excitation_tot: %g\n", frac_excitation_total); printout(" frac_ionization_tot: %g\n", frac_ionization_total); - const double frac_sum = nt_solution[modelgridindex].frac_heating + frac_excitation_total + frac_ionization_total; + const double frac_sum = nt_solution[nonemptymgi].frac_heating + frac_excitation_total + frac_ionization_total; printout(" frac_sum: %g (should be close to 1.0)\n", frac_sum); - nt_solution[modelgridindex].frac_heating = 1. - frac_excitation_total - frac_ionization_total; + nt_solution[nonemptymgi].frac_heating = 1. - frac_excitation_total - frac_ionization_total; printout(" (replacing calculated frac_heating_tot with %g to make frac_sum = 1.0)\n", - nt_solution[modelgridindex].frac_heating); + nt_solution[nonemptymgi].frac_heating); } void sfmatrix_add_excitation(std::vector &sfmatrixuppertri, const int modelgridindex, const int element, const int ion) { // excitation terms + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const int nlevels_all = get_nlevels(element, ion); const int nlevels = (nlevels_all > NTEXCITATION_MAXNLEVELS_LOWER) ? NTEXCITATION_MAXNLEVELS_LOWER : nlevels_all; for (int lower = 0; lower < nlevels; lower++) { const double statweight_lower = stat_weight(element, ion, lower); - const double nnlevel = get_levelpop(modelgridindex, element, ion, lower); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, lower); const double epsilon_lower = epsilon(element, ion, lower); const int nuptrans = get_nuptrans(element, ion, lower); const auto *const uptranslist = get_uptranslist(element, ion, lower); @@ -2067,12 +2070,13 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array(nonempty_npts_model); - std::ranges::fill(deposition_rate_density_all_cells, -1.); + if (globals::rank_in_node == 0) { + std::ranges::fill(deposition_rate_density_all_cells, -1.); + } if (!NT_ON) { return; @@ -2109,42 +2113,34 @@ void init(const int my_rank, const int ndo_nonempty) { nt_excitations_stored = std::min(MAX_NT_EXCITATIONS_STORED, get_possible_nt_excitation_count()); printout("[info] mem_usage: storing %d non-thermal excitations for non-empty cells occupies %.3f MB\n", nt_excitations_stored, - grid::get_nonempty_npts_model() * sizeof(NonThermalExcitation) * nt_excitations_stored / 1024. / 1024.); + nonempty_npts_model * sizeof(NonThermalExcitation) * nt_excitations_stored / 1024. / 1024.); - const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); - - excitations_list_all_cells = MPI_shared_malloc(nonempty_npts_model * nt_excitations_stored); + excitations_list_all_cells = + MPI_shared_malloc_span(nonempty_npts_model * nt_excitations_stored); } - nt_solution.resize(grid::get_npts_model()); - - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - // should make these negative? - nt_solution[modelgridindex].frac_heating = 0.97; - nt_solution[modelgridindex].frac_ionization = 0.03; - nt_solution[modelgridindex].frac_excitation = 0.; - - nt_solution[modelgridindex].nneperion_when_solved = -1.; - nt_solution[modelgridindex].timestep_last_solved = -1; + ion_data_all_cells = MPI_shared_malloc_span(nonempty_npts_model * get_includedions()); - if (grid::get_numpropcells(modelgridindex) > 0) { - nt_solution[modelgridindex].allions = - static_cast(malloc(get_includedions() * sizeof(NonThermalSolutionIon))); + nt_solution = MPI_shared_malloc_span(nonempty_npts_model); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + if (globals::rank_in_node == 0) { + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < nonempty_npts_model; nonemptymgi++) { + // should make these negative? + nt_solution[nonemptymgi].frac_heating = 0.97; + nt_solution[nonemptymgi].frac_ionization = 0.03; + nt_solution[nonemptymgi].frac_excitation = 0.; - nt_solution[modelgridindex].frac_excitations_list = - NT_EXCITATION_ON ? &excitations_list_all_cells[nonemptymgi * nt_excitations_stored] : nullptr; + nt_solution[nonemptymgi].nneperion_when_solved = -1.; + nt_solution[nonemptymgi].timestep_last_solved = -1; - zero_all_effionpot(modelgridindex); - } else { - nt_solution[modelgridindex].allions = nullptr; + zero_all_effionpot(nonemptymgi); - nt_solution[modelgridindex].frac_excitations_list = nullptr; + nt_solution[nonemptymgi].frac_excitations_list_size = 0; } - - nt_solution[modelgridindex].frac_excitations_list_size = 0; } +#ifdef MPI_ON + MPI_Barrier(globals::mpi_comm_node); +#endif double sourceintegral = 0.; // integral of S(e) dE for (int s = 0; s < SFPTS; s++) { @@ -2156,7 +2152,6 @@ void init(const int my_rank, const int ndo_nonempty) { read_collion_data(); - nonthermal_initialized = true; printout("Finished initializing non-thermal solver\n"); } @@ -2164,11 +2159,10 @@ void init(const int my_rank, const int ndo_nonempty) { // after packet propagation is finished for this timestep and normalise_deposition_estimators() has been done void calculate_deposition_rate_density(const int nonemptymgi, const int timestep, HeatingCoolingRates *heatingcoolingrates) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); heatingcoolingrates->dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; const double tmid = globals::timesteps[timestep].mid; - const double rho = grid::get_rho(modelgridindex); + const double rho = grid::get_rho(nonemptymgi); // if INSTANT_PARTICLE_DEPOSITION, use the analytic rate at t_mid since it will have no Monte Carlo noise (although // strictly, it should be an integral from the timestep start to the end) @@ -2196,19 +2190,17 @@ void calculate_deposition_rate_density(const int nonemptymgi, const int timestep heatingcoolingrates->dep_alpha = globals::dep_estimator_alpha[nonemptymgi]; } - deposition_rate_density_all_cells[modelgridindex] = + deposition_rate_density_all_cells[nonemptymgi] = (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron); } // get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() -__host__ __device__ auto get_deposition_rate_density(const int modelgridindex) -> double { - assert_always(deposition_rate_density_all_cells[modelgridindex] >= 0); - return deposition_rate_density_all_cells[modelgridindex]; +__host__ __device__ auto get_deposition_rate_density(const int nonemptymgi) -> double { + assert_always(deposition_rate_density_all_cells[nonemptymgi] >= 0); + return deposition_rate_density_all_cells[nonemptymgi]; } void close_file() { - nonthermal_initialized = false; - if (!NT_ON || !NT_SOLVE_SPENCERFANO) { return; } @@ -2217,11 +2209,6 @@ void close_file() { fclose(nonthermalfile); nonthermalfile = nullptr; } - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - free(nt_solution[modelgridindex].allions); - } - } colliondata.clear(); } @@ -2232,12 +2219,12 @@ auto get_nt_frac_heating(const int modelgridindex) -> float { if (!NT_SOLVE_SPENCERFANO) { return 0.97; } - const float frac_heating = nt_solution[modelgridindex].frac_heating; - // add any debugging checks here? + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const float frac_heating = nt_solution[nonemptymgi].frac_heating; return frac_heating; } -__host__ __device__ auto nt_ionization_upperion_probability(const int modelgridindex, const int element, +__host__ __device__ auto nt_ionization_upperion_probability(const int nonemptymgi, const int element, const int lowerion, const int upperion, const bool energyweighted) -> double { assert_always(upperion > lowerion); @@ -2246,33 +2233,31 @@ __host__ __device__ auto nt_ionization_upperion_probability(const int modelgridi if (NT_SOLVE_SPENCERFANO && NT_MAX_AUGER_ELECTRONS > 0) { const int numaugerelec = upperion - lowerion - 1; // number of Auger electrons to go from lowerin to upper ion const int uniqueionindex = get_uniqueionindex(element, lowerion); - + const auto &cell_ion_data = get_cell_ion_data(nonemptymgi)[uniqueionindex]; if (numaugerelec < NT_MAX_AUGER_ELECTRONS) { if (energyweighted) { - return nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[numaugerelec]; + return cell_ion_data.ionenfrac_num_auger[numaugerelec]; } - return nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[numaugerelec]; + return cell_ion_data.prob_num_auger[numaugerelec]; } if (numaugerelec == NT_MAX_AUGER_ELECTRONS) { double prob_remaining = 1.; for (int a = 0; a < NT_MAX_AUGER_ELECTRONS; a++) { if (energyweighted) { - prob_remaining -= nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]; + prob_remaining -= cell_ion_data.ionenfrac_num_auger[a]; } else { - prob_remaining -= nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a]; + prob_remaining -= cell_ion_data.prob_num_auger[a]; } } if (energyweighted) { - assert_always(fabs(prob_remaining - - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[numaugerelec]) < - 0.001); + assert_always(fabs(prob_remaining - cell_ion_data.ionenfrac_num_auger[numaugerelec]) < 0.001); } else { - if (fabs(prob_remaining - nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[numaugerelec]) >= - 0.001) { - printout("Auger probabilities issue for cell %d Z=%02d ionstage %d to %d\n", modelgridindex, - get_atomicnumber(element), get_ionstage(element, lowerion), get_ionstage(element, upperion)); + if (fabs(prob_remaining - cell_ion_data.prob_num_auger[numaugerelec]) >= 0.001) { + printout("Auger probabilities issue for cell %d Z=%02d ionstage %d to %d\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi), get_atomicnumber(element), + get_ionstage(element, lowerion), get_ionstage(element, upperion)); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - printout(" a %d prob %g\n", a, nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a]); + printout(" a %d prob %g\n", a, cell_ion_data.prob_num_auger[a]); } std::abort(); } @@ -2300,7 +2285,7 @@ __host__ __device__ auto nt_ionisation_maxupperion(const int element, const int return maxupper; } -__host__ __device__ auto nt_random_upperion(const int modelgridindex, const int element, const int lowerion, +__host__ __device__ auto nt_random_upperion(const int nonemptymgi, const int element, const int lowerion, const bool energyweighted) -> int { assert_testmodeonly(lowerion < get_nions(element) - 1); if (NT_SOLVE_SPENCERFANO && NT_MAX_AUGER_ELECTRONS > 0) { @@ -2309,7 +2294,7 @@ __host__ __device__ auto nt_random_upperion(const int modelgridindex, const int double prob_sum = 0.; for (int upperion = lowerion + 1; upperion <= nt_ionisation_maxupperion(element, lowerion); upperion++) { - prob_sum += nt_ionization_upperion_probability(modelgridindex, element, lowerion, upperion, energyweighted); + prob_sum += nt_ionization_upperion_probability(nonemptymgi, element, lowerion, upperion, energyweighted); if (zrand <= prob_sum) { return upperion; @@ -2327,12 +2312,12 @@ __host__ __device__ auto nt_random_upperion(const int modelgridindex, const int } } -__host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const int element, const int ion) -> double { +__host__ __device__ auto nt_ionization_ratecoeff(const int nonemptymgi, const int element, const int ion) -> double { assert_always(NT_ON); - assert_always(grid::get_numpropcells(modelgridindex) > 0); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if (NT_SOLVE_SPENCERFANO) { - const double Y_nt = nt_ionization_ratecoeff_sf(modelgridindex, element, ion); + const double Y_nt = nt_ionization_ratecoeff_sf(nonemptymgi, element, ion); if (!std::isfinite(Y_nt)) { // probably because eff_ionpot = 0 because the solver hasn't been run yet, or no impact ionization cross sections // exist @@ -2355,7 +2340,7 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int modelgridindex, const } #pragma omp declare simd -__host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const int element, const int ion, +__host__ __device__ auto nt_excitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lowerlevel, const int uptransindex, const int lineindex) -> double { if constexpr (!NT_EXCITATION_ON) { @@ -2369,17 +2354,14 @@ __host__ __device__ auto nt_excitation_ratecoeff(const int modelgridindex, const return 0.; } - assert_testmodeonly(grid::get_numpropcells(modelgridindex) > 0); - // binary search, assuming the excitation list is sorted by lineindex ascending - const auto ntexclist = std::span(nt_solution[modelgridindex].frac_excitations_list, - nt_solution[modelgridindex].frac_excitations_list_size); + const auto ntexclist = get_cell_ntexcitations(nonemptymgi); const auto ntexcitation = std::ranges::lower_bound(ntexclist, lineindex, {}, &NonThermalExcitation::lineindex); if (ntexcitation == ntexclist.end() || ntexcitation->lineindex != lineindex) { return 0.; } - const double deposition_rate_density = get_deposition_rate_density(modelgridindex); + const double deposition_rate_density = get_deposition_rate_density(nonemptymgi); const double ratecoeffperdeposition = ntexcitation->ratecoeffperdeposition; return ratecoeffperdeposition * deposition_rate_density; @@ -2399,9 +2381,10 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { atomicadd(nt_energy_deposited, pkt.e_cmf); const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // macroatom should not be activated in thick cells - if (NT_ON && NT_SOLVE_SPENCERFANO && grid::modelgrid[modelgridindex].thick != 1) { + if (NT_ON && NT_SOLVE_SPENCERFANO && grid::modelgrid[nonemptymgi].thick != 1) { // here there is some probability to cause ionisation or excitation to a macroatom packet // instead of converting directly to k-packet (unless the heating channel is selected) @@ -2411,13 +2394,13 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { // until we end and select transition_ij when zrand < dep_frac_transition_ij // const double frac_ionization = get_nt_frac_ionization(modelgridindex); - const double frac_ionization = get_ntion_energyrate(modelgridindex) / get_deposition_rate_density(modelgridindex); + const double frac_ionization = get_ntion_energyrate(modelgridindex) / get_deposition_rate_density(nonemptymgi); // printout("frac_ionization compare %g and %g\n", frac_ionization, get_nt_frac_ionization(modelgridindex)); // const double frac_ionization = 0.; if (zrand < frac_ionization) { const auto [element, lowerion] = select_nt_ionization(modelgridindex); - const int upperion = nt_random_upperion(modelgridindex, element, lowerion, true); + const int upperion = nt_random_upperion(nonemptymgi, element, lowerion, true); // const int upperion = lowerion + 1; pkt.type = TYPE_MA; @@ -2433,9 +2416,8 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { assert_always(upperion < get_nions(element)); assert_always(lowerion >= 0); const double epsilon_trans = epsilon(element, upperion, 0) - epsilon(element, lowerion, 0); - stats::increment_ion_stats(modelgridindex, element, lowerion, stats::ION_NTION, pkt.e_cmf / epsilon_trans); - stats::increment_ion_stats(modelgridindex, element, upperion, stats::ION_MACROATOM_ENERGYIN_NTCOLLION, - pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, lowerion, stats::ION_NTION, pkt.e_cmf / epsilon_trans); + stats::increment_ion_stats(nonemptymgi, element, upperion, stats::ION_MACROATOM_ENERGYIN_NTCOLLION, pkt.e_cmf); } do_macroatom(pkt, {.element = element, .ion = upperion, .level = 0, .activatingline = -99}); @@ -2448,8 +2430,7 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { zrand -= frac_ionization; // now zrand is between zero and frac_excitation // the selection algorithm is the same as for the ionization transitions - for (const auto &ntexcitation : std::span(nt_solution[modelgridindex].frac_excitations_list, - nt_solution[modelgridindex].frac_excitations_list_size)) { + for (const auto &ntexcitation : get_cell_ntexcitations(nonemptymgi)) { const double frac_deposition_exc = ntexcitation.frac_deposition; if (zrand < frac_deposition_exc) { const int lineindex = ntexcitation.lineindex; @@ -2484,46 +2465,41 @@ __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { // solve the Spencer-Fano equation to get the non-thermal electron flux energy distribution // based on Equation (2) of Li et al. (2012) -void solve_spencerfano(const int modelgridindex, const int timestep, const int iteration) { +void solve_spencerfano(const int nonemptymgi, const int timestep, const int iteration) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); bool skip_solution = false; - if (grid::get_numpropcells(modelgridindex) < 1) { - printout("Associated_cells < 1 in cell %d at timestep %d. Skipping Spencer-Fano solution.\n", modelgridindex, - timestep); - - return; - } if (timestep < globals::num_lte_timesteps + 1) { printout("Skipping Spencer-Fano solution for first NLTE timestep\n"); skip_solution = true; - } else if (get_deposition_rate_density(modelgridindex) / EV < MINDEPRATE) { + } else if (get_deposition_rate_density(nonemptymgi) / EV < MINDEPRATE) { printout( "Non-thermal deposition rate of %g eV/cm/s/cm^3 below MINDEPRATE %g in cell %d at timestep %d. Skipping " "Spencer-Fano solution.\n", - get_deposition_rate_density(modelgridindex) / EV, MINDEPRATE, modelgridindex, timestep); + get_deposition_rate_density(nonemptymgi) / EV, MINDEPRATE, modelgridindex, timestep); skip_solution = true; } if (skip_solution) { // Axelrod values - nt_solution[modelgridindex].frac_heating = 0.97; - nt_solution[modelgridindex].frac_ionization = 0.03; - nt_solution[modelgridindex].frac_excitation = 0.; + nt_solution[nonemptymgi].frac_heating = 0.97; + nt_solution[nonemptymgi].frac_ionization = 0.03; + nt_solution[nonemptymgi].frac_excitation = 0.; - nt_solution[modelgridindex].nneperion_when_solved = -1.; - nt_solution[modelgridindex].timestep_last_solved = -1; + nt_solution[nonemptymgi].nneperion_when_solved = -1.; + nt_solution[nonemptymgi].timestep_last_solved = -1; - nt_solution[modelgridindex].frac_excitations_list_size = 0; + nt_solution[nonemptymgi].frac_excitations_list_size = 0; - zero_all_effionpot(modelgridindex); + zero_all_effionpot(nonemptymgi); return; } - const auto nne = grid::get_nne(modelgridindex); // electrons per cm^3 - const double nne_per_ion = nne / get_nnion_tot(modelgridindex); - const double nne_per_ion_last = nt_solution[modelgridindex].nneperion_when_solved; + const auto nne = grid::get_nne(nonemptymgi); // electrons per cm^3 + const double nne_per_ion = nne / get_nnion_tot(nonemptymgi); + const double nne_per_ion_last = nt_solution[nonemptymgi].nneperion_when_solved; const double nne_per_ion_fracdiff = fabs((nne_per_ion_last / nne_per_ion) - 1.); - const int timestep_last_solved = nt_solution[modelgridindex].timestep_last_solved; + const int timestep_last_solved = nt_solution[nonemptymgi].timestep_last_solved; printout( "Spencer-Fano solver at timestep %d (last solution was at timestep %d) nne/niontot = %g, at last solution was %g " @@ -2546,8 +2522,8 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i "%d (nne=%g e-/cm^3)\n", SFPTS, SF_EMIN, SF_EMAX, modelgridindex, timestep, iteration, nne); - nt_solution[modelgridindex].nneperion_when_solved = nne_per_ion; - nt_solution[modelgridindex].timestep_last_solved = timestep; + nt_solution[nonemptymgi].nneperion_when_solved = nne_per_ion; + nt_solution[nonemptymgi].timestep_last_solved = timestep; const bool enable_sfexcitation = true; const bool enable_sfionization = true; @@ -2555,7 +2531,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // { // // for the first run of the solver at the first NLTE timestep (which usually requires many iterations), // // do a fast initial solution but mark it has an invalid nne per ion so it gets replaced at the next timestep - // nt_solution[modelgridindex].nneperion_when_solved = -1.; + // nt_solution[nonemptymgi].nneperion_when_solved = -1.; // enable_sfexcitation = false; // enable_sfionization = false; // @@ -2565,7 +2541,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i // if (timestep <= globals::num_lte_timesteps + 2) // { // // run the solver in a faster mode for the first couple of NLTE timesteps - // // nt_solution[modelgridindex].nneperion_when_solved = -1.; + // // nt_solution[nonemptymgi].nneperion_when_solved = -1.; // enable_sfexcitation = false; // // enable_sfionization = false; // @@ -2589,10 +2565,10 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i const int nions = get_nions(element); bool first_included_ion_of_element = true; for (int ion = 0; ion < nions; ion++) { - const double nnion = get_nnion(modelgridindex, element, ion); + const double nnion = get_nnion(nonemptymgi, element, ion); // skip negligible ions - if (nnion < minionfraction * get_nnion_tot(modelgridindex)) { + if (nnion < minionfraction * get_nnion_tot(nonemptymgi)) { continue; } @@ -2642,7 +2618,7 @@ void solve_spencerfano(const int modelgridindex, const int timestep, const int i nt_write_to_file(modelgridindex, timestep, iteration, yfunc); } - analyse_sf_solution(modelgridindex, timestep, enable_sfexcitation, yfunc); + analyse_sf_solution(nonemptymgi, timestep, enable_sfexcitation, yfunc); } void write_restart_data(FILE *gridsave_file) { @@ -2652,31 +2628,29 @@ void write_restart_data(FILE *gridsave_file) { fprintf(gridsave_file, "%d %la %la\n", SFPTS, SF_EMIN, SF_EMAX); for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - fprintf(gridsave_file, "%d %la ", modelgridindex, deposition_rate_density_all_cells[modelgridindex]); + fprintf(gridsave_file, "%d %la ", nonemptymgi, deposition_rate_density_all_cells[nonemptymgi]); if (NT_ON && NT_SOLVE_SPENCERFANO) { - check_auger_probabilities(modelgridindex); + check_auger_probabilities(nonemptymgi); - fprintf(gridsave_file, "%a %a %a %a\n", nt_solution[modelgridindex].nneperion_when_solved, - nt_solution[modelgridindex].frac_heating, nt_solution[modelgridindex].frac_ionization, - nt_solution[modelgridindex].frac_excitation); + fprintf(gridsave_file, "%a %a %a %a\n", nt_solution[nonemptymgi].nneperion_when_solved, + nt_solution[nonemptymgi].frac_heating, nt_solution[nonemptymgi].frac_ionization, + nt_solution[nonemptymgi].frac_excitation); for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - fprintf(gridsave_file, "%la ", nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion); - fprintf(gridsave_file, "%a ", nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot); + fprintf(gridsave_file, "%la ", get_cell_ion_data(nonemptymgi)[uniqueionindex].fracdep_ionization_ion); + fprintf(gridsave_file, "%a ", get_cell_ion_data(nonemptymgi)[uniqueionindex].eff_ionpot); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { - fprintf(gridsave_file, "%a %a ", nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a], - nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]); + fprintf(gridsave_file, "%a %a ", get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[a], + get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[a]); } } // write NT excitations - fprintf(gridsave_file, "%d\n", nt_solution[modelgridindex].frac_excitations_list_size); + fprintf(gridsave_file, "%d\n", nt_solution[nonemptymgi].frac_excitations_list_size); - for (const auto &excitation : std::span(nt_solution[modelgridindex].frac_excitations_list, - nt_solution[modelgridindex].frac_excitations_list_size)) { + for (const auto &excitation : get_cell_ntexcitations(nonemptymgi)) { fprintf(gridsave_file, "%la %la %d\n", excitation.frac_deposition, excitation.ratecoeffperdeposition, excitation.lineindex); } @@ -2707,83 +2681,74 @@ void read_restart_data(FILE *gridsave_file) { } for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - - int mgi_in = 0; - assert_always(fscanf(gridsave_file, "%d %la ", &mgi_in, &deposition_rate_density_all_cells[modelgridindex]) == 2); + int nonemptymgi_in = 0; + assert_always(fscanf(gridsave_file, "%d %la ", &nonemptymgi_in, &deposition_rate_density_all_cells[nonemptymgi]) == + 2); + assert_always(nonemptymgi_in == nonemptymgi); if (NT_ON && NT_SOLVE_SPENCERFANO) { - assert_always(fscanf(gridsave_file, "%a %a %a %a\n", &nt_solution[modelgridindex].nneperion_when_solved, - &nt_solution[modelgridindex].frac_heating, &nt_solution[modelgridindex].frac_ionization, - &nt_solution[modelgridindex].frac_excitation) == 4); - - if (mgi_in != modelgridindex) { - printout("ERROR: expected data for cell %d but found cell %d\n", modelgridindex, mgi_in); - std::abort(); - } + assert_always(fscanf(gridsave_file, "%a %a %a %a\n", &nt_solution[nonemptymgi].nneperion_when_solved, + &nt_solution[nonemptymgi].frac_heating, &nt_solution[nonemptymgi].frac_ionization, + &nt_solution[nonemptymgi].frac_excitation) == 4); for (int uniqueionindex = 0; uniqueionindex < get_includedions(); uniqueionindex++) { - assert_always(fscanf(gridsave_file, "%la ", - &nt_solution[modelgridindex].allions[uniqueionindex].fracdep_ionization_ion) == 1); - assert_always(fscanf(gridsave_file, "%a ", &nt_solution[modelgridindex].allions[uniqueionindex].eff_ionpot) == - 1); + assert_always( + fscanf(gridsave_file, "%la ", &get_cell_ion_data(nonemptymgi)[uniqueionindex].fracdep_ionization_ion) == 1); + assert_always(fscanf(gridsave_file, "%a ", &get_cell_ion_data(nonemptymgi)[uniqueionindex].eff_ionpot) == 1); for (int a = 0; a <= NT_MAX_AUGER_ELECTRONS; a++) { assert_always(fscanf(gridsave_file, "%a %a ", - &nt_solution[modelgridindex].allions[uniqueionindex].prob_num_auger[a], - &nt_solution[modelgridindex].allions[uniqueionindex].ionenfrac_num_auger[a]) == 2); + &get_cell_ion_data(nonemptymgi)[uniqueionindex].prob_num_auger[a], + &get_cell_ion_data(nonemptymgi)[uniqueionindex].ionenfrac_num_auger[a]) == 2); } } - check_auger_probabilities(modelgridindex); + check_auger_probabilities(nonemptymgi); // read NT excitations int frac_excitations_list_size_in = 0; assert_always(fscanf(gridsave_file, "%d\n", &frac_excitations_list_size_in) == 1); - nt_solution[modelgridindex].frac_excitations_list_size = frac_excitations_list_size_in; + nt_solution[nonemptymgi].frac_excitations_list_size = frac_excitations_list_size_in; + const auto ntexclist = get_cell_ntexcitations(nonemptymgi); for (int excitationindex = 0; excitationindex < frac_excitations_list_size_in; excitationindex++) { - assert_always(fscanf(gridsave_file, "%la %la %d\n", - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].frac_deposition, - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].ratecoeffperdeposition, - &nt_solution[modelgridindex].frac_excitations_list[excitationindex].lineindex) == 3); + assert_always(fscanf(gridsave_file, "%la %la %d\n", &ntexclist[excitationindex].frac_deposition, + &ntexclist[excitationindex].ratecoeffperdeposition, + &ntexclist[excitationindex].lineindex) == 3); } } } } #ifdef MPI_ON -void nt_MPI_Bcast(const int nonemptymgi, const int root, const int root_node_id) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - - MPI_Bcast(&deposition_rate_density_all_cells[modelgridindex], 1, MPI_DOUBLE, root, MPI_COMM_WORLD); +void nt_MPI_Bcast(const int nonemptymgi, const int root_node_id) { + MPI_Bcast(&deposition_rate_density_all_cells[nonemptymgi], 1, MPI_DOUBLE, root_node_id, globals::mpi_comm_internode); if (NT_ON && NT_SOLVE_SPENCERFANO) { - assert_always(nonthermal_initialized); - MPI_Bcast(&nt_solution[modelgridindex].nneperion_when_solved, 1, MPI_FLOAT, root, MPI_COMM_WORLD); - MPI_Bcast(&nt_solution[modelgridindex].timestep_last_solved, 1, MPI_INT, root, MPI_COMM_WORLD); - MPI_Bcast(&nt_solution[modelgridindex].frac_heating, 1, MPI_FLOAT, root, MPI_COMM_WORLD); - MPI_Bcast(&nt_solution[modelgridindex].frac_ionization, 1, MPI_FLOAT, root, MPI_COMM_WORLD); - MPI_Bcast(&nt_solution[modelgridindex].frac_excitation, 1, MPI_FLOAT, root, MPI_COMM_WORLD); - - MPI_Bcast(nt_solution[modelgridindex].allions, - static_cast(get_includedions()) * sizeof(NonThermalSolutionIon), MPI_BYTE, root, MPI_COMM_WORLD); - - // communicate NT excitations - MPI_Bcast(&nt_solution[modelgridindex].frac_excitations_list_size, 1, MPI_INT, root, MPI_COMM_WORLD); - if (globals::rank_in_node == 0) { - // communicate NT excitation list via inter-node communication - MPI_Bcast( - nt_solution[modelgridindex].frac_excitations_list, - static_cast(nt_solution[modelgridindex].frac_excitations_list_size) * sizeof(NonThermalExcitation), - MPI_BYTE, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&nt_solution[nonemptymgi].nneperion_when_solved, 1, MPI_FLOAT, root_node_id, + globals::mpi_comm_internode); + MPI_Bcast(&nt_solution[nonemptymgi].timestep_last_solved, 1, MPI_INT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&nt_solution[nonemptymgi].frac_heating, 1, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&nt_solution[nonemptymgi].frac_ionization, 1, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&nt_solution[nonemptymgi].frac_excitation, 1, MPI_FLOAT, root_node_id, globals::mpi_comm_internode); + + MPI_Bcast(&nt_solution[nonemptymgi].frac_excitations_list_size, 1, MPI_INT, root_node_id, + globals::mpi_comm_internode); + + MPI_Bcast(get_cell_ntexcitations(nonemptymgi).data(), + static_cast(nt_solution[nonemptymgi].frac_excitations_list_size) * sizeof(NonThermalExcitation), + MPI_BYTE, root_node_id, globals::mpi_comm_internode); + + const auto ion_data = get_cell_ion_data(nonemptymgi); + MPI_Bcast(ion_data.data(), ion_data.size() * sizeof(NonThermalSolutionIon), MPI_BYTE, root_node_id, + globals::mpi_comm_internode); } MPI_Barrier(MPI_COMM_WORLD); - check_auger_probabilities(modelgridindex); + check_auger_probabilities(nonemptymgi); } } #endif diff --git a/nonthermal.h b/nonthermal.h index f137c9274..fd54a1dcf 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -9,23 +9,23 @@ namespace nonthermal { void init(int my_rank, int ndo_nonempty); void close_file(); -void solve_spencerfano(int modelgridindex, int timestep, int iteration); -[[nodiscard]] auto nt_ionization_ratecoeff(int modelgridindex, int element, int ion) -> double; -[[nodiscard]] auto nt_ionization_upperion_probability(int modelgridindex, int element, int lowerion, int upperion, +void solve_spencerfano(int nonemptymgi, int timestep, int iteration); +[[nodiscard]] auto nt_ionization_ratecoeff(int nonemptymgi, int element, int ion) -> double; +[[nodiscard]] auto nt_ionization_upperion_probability(int nonemptymgi, int element, int lowerion, int upperion, bool energyweighted) -> double; [[nodiscard]] auto nt_ionisation_maxupperion(int element, int lowerion) -> int; -[[nodiscard]] auto nt_random_upperion(int modelgridindex, int element, int lowerion, bool energyweighted) -> int; +[[nodiscard]] auto nt_random_upperion(int nonemptymgi, int element, int lowerion, bool energyweighted) -> int; void calculate_deposition_rate_density(int nonemptymgi, int timestep, HeatingCoolingRates *heatingcoolingrates); -[[nodiscard]] auto get_deposition_rate_density(int modelgridindex) -> double; +[[nodiscard]] auto get_deposition_rate_density(int nonemptymgi) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; #pragma omp declare simd -[[nodiscard]] auto nt_excitation_ratecoeff(int modelgridindex, int element, int ion, int lowerlevel, int uptransindex, +[[nodiscard]] auto nt_excitation_ratecoeff(int nonemptymgi, int element, int ion, int lowerlevel, int uptransindex, int lineindex) -> double; void do_ntalpha_deposit(Packet &pkt); void do_ntlepton_deposit(Packet &pkt); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); -void nt_MPI_Bcast(int nonemptymgi, int root, int root_node_id); +void nt_MPI_Bcast(int nonemptymgi, int root_node_id); void nt_reset_stats(); void nt_print_stats(double modelvolume, double deltat); } // namespace nonthermal diff --git a/radfield.cc b/radfield.cc index 0faa020ab..6cf4b1643 100644 --- a/radfield.cc +++ b/radfield.cc @@ -63,15 +63,13 @@ struct Jb_lu_estimator { int contribcount = 0; }; -// reallocate the detailed line arrays in units of BLOCKSIZEJBLUE -constexpr int BLOCKSIZEJBLUE = 128; int detailed_linecount = 0; -// array of indicies into the linelist[] array for selected lines -int *detailed_lineindicies; +// array of indices into the linelist[] array for selected lines +std::vector detailed_lineindicies; -Jb_lu_estimator **prev_Jb_lu_normed{}; // value from the previous timestep -Jb_lu_estimator **Jb_lu_raw{}; // unnormalised estimator for the current timestep +std::vector> prev_Jb_lu_normed{}; // value from the previous timestep +std::vector> Jb_lu_raw{}; // unnormalised estimator for the current timestep float *prev_bfrate_normed{}; // values from the previous timestep std::vector bfrate_raw; // unnormalised estimators for the current timestep @@ -95,8 +93,8 @@ struct gsl_planck_integral_paras { bool times_nu; }; -struct gsl_T_R_solver_paras { - int modelgridindex; +struct GSLT_RSolverParams { + int nonemptymgi; int binindex; }; @@ -142,91 +140,55 @@ constexpr auto select_bin(const double nu) -> int { return binindex; } -void realloc_detailed_lines(const int new_size) { - auto *newptr = static_cast(realloc(detailed_lineindicies, new_size * sizeof(int))); - if (newptr == nullptr) { - printout("ERROR: Not enough memory to reallocate detailed Jblue estimator line list\n"); - std::abort(); - } - assert_always(newptr != nullptr); - detailed_lineindicies = newptr; - - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - prev_Jb_lu_normed[modelgridindex] = static_cast( - realloc(prev_Jb_lu_normed[modelgridindex], new_size * sizeof(Jb_lu_estimator))); - - Jb_lu_raw[modelgridindex] = - static_cast(realloc(Jb_lu_raw[modelgridindex], new_size * sizeof(Jb_lu_estimator))); - - if (prev_Jb_lu_normed[modelgridindex] == nullptr || Jb_lu_raw[modelgridindex] == nullptr) { - printout("ERROR: Not enough memory to reallocate detailed Jblue estimator list for cell %d.\n", modelgridindex); - std::abort(); - } - } - } -} - // associate a Jb_lu estimator with a particular lineindex to be used // instead of the general radiation field model void add_detailed_line(const int lineindex) { - if (detailed_linecount % BLOCKSIZEJBLUE == 0) { - const int new_size = detailed_linecount + BLOCKSIZEJBLUE; - realloc_detailed_lines(new_size); - } - - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - prev_Jb_lu_normed[modelgridindex][detailed_linecount].value = 0; - prev_Jb_lu_normed[modelgridindex][detailed_linecount].contribcount = 0; + detailed_linecount++; + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + prev_Jb_lu_normed[nonemptymgi].push_back({.value = 0, .contribcount = 0}); + assert_always(detailed_linecount == std::ssize(prev_Jb_lu_normed[nonemptymgi])); - // zero_estimators should do the next part anyway, but just to be sure: - Jb_lu_raw[modelgridindex][detailed_linecount].value = 0; - Jb_lu_raw[modelgridindex][detailed_linecount].contribcount = 0; - } + // zero_estimators should do the next part anyway, but just to be sure: + Jb_lu_raw[nonemptymgi].push_back({.value = 0, .contribcount = 0}); + assert_always(detailed_linecount == std::ssize(Jb_lu_raw[nonemptymgi])); } - detailed_lineindicies[detailed_linecount] = lineindex; - detailed_linecount++; + detailed_lineindicies.push_back(lineindex); + assert_always(detailed_linecount == std::ssize(detailed_lineindicies)); } // get the normalised J_nu -auto get_bin_J(const int modelgridindex, const int binindex) -> double { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_bin_J(const int nonemptymgi, const int binindex) -> double { assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); - assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); assert_testmodeonly(binindex < RADFIELDBINCOUNT); - return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].J_raw * J_normfactor[nonemptymgi]; + return radfieldbins[(static_cast(nonemptymgi) * RADFIELDBINCOUNT) + binindex].J_raw * + J_normfactor[nonemptymgi]; } -auto get_bin_nuJ(const int modelgridindex, const int binindex) -> double { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_bin_nuJ(const int nonemptymgi, const int binindex) -> double { assert_testmodeonly(J_normfactor[nonemptymgi] > 0.0); - assert_testmodeonly(modelgridindex < grid::get_npts_model()); assert_testmodeonly(binindex >= 0); assert_testmodeonly(binindex < RADFIELDBINCOUNT); - return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].nuJ_raw * J_normfactor[nonemptymgi]; + return radfieldbins[(static_cast(nonemptymgi) * RADFIELDBINCOUNT) + binindex].nuJ_raw * + J_normfactor[nonemptymgi]; } // get / for a bin -auto get_bin_nu_bar(const int modelgridindex, const int binindex) -> double { - const double nuJ_sum = get_bin_nuJ(modelgridindex, binindex); - const double J_sum = get_bin_J(modelgridindex, binindex); +auto get_bin_nu_bar(const int nonemptymgi, const int binindex) -> double { + const double nuJ_sum = get_bin_nuJ(nonemptymgi, binindex); + const double J_sum = get_bin_J(nonemptymgi, binindex); return nuJ_sum / J_sum; } -auto get_bin_contribcount(const int modelgridindex, const int binindex) -> int { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_bin_contribcount(const int nonemptymgi, const int binindex) -> int { return radfieldbins[(nonemptymgi * RADFIELDBINCOUNT) + binindex].contribcount; } -auto get_bin_W(const int modelgridindex, const int binindex) -> float { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_bin_W(const int nonemptymgi, const int binindex) -> float { return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].W; } -auto get_bin_T_R(const int modelgridindex, const int binindex) -> float { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_bin_T_R(const int nonemptymgi, const int binindex) -> float { return radfieldbin_solutions[(nonemptymgi * RADFIELDBINCOUNT) + binindex].T_R; } @@ -300,14 +262,13 @@ auto delta_nu_bar(const double T_R, void *const paras) -> double // difference between the average nu and the average nu of a Planck function // at temperature T_R, in the frequency range corresponding to a bin { - const auto *params = static_cast(paras); - const int modelgridindex = params->modelgridindex; + const auto *params = static_cast(paras); + const auto nonemptymgi = params->nonemptymgi; const int binindex = params->binindex; const double nu_lower = get_bin_nu_lower(binindex); const double nu_upper = get_bin_nu_upper(binindex); - - const double nu_bar_estimator = get_bin_nu_bar(modelgridindex, binindex); + const double nu_bar_estimator = get_bin_nu_bar(nonemptymgi, binindex); const double nu_times_planck_numerical = planck_integral(T_R, nu_lower, nu_upper, true); const double planck_integral_numerical = planck_integral(T_R, nu_lower, nu_upper, false); @@ -341,11 +302,11 @@ auto delta_nu_bar(const double T_R, void *const paras) -> double return delta_nu_bar; } -auto find_T_R(const int modelgridindex, const int binindex) -> float { +auto find_T_R(const int nonemptymgi, const int binindex) -> float { double T_R = 0.; - gsl_T_R_solver_paras paras{}; - paras.modelgridindex = modelgridindex; + GSLT_RSolverParams paras{}; + paras.nonemptymgi = nonemptymgi; paras.binindex = binindex; // Check whether the equation has a root in [T_min,T_max] @@ -396,20 +357,20 @@ auto find_T_R(const int modelgridindex, const int binindex) -> float { } else if (delta_nu_bar_max < 0) { // Thermal balance equation always negative ===> T_R = T_min // Calculate the rates again at this T_e to print them to file + printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_max=%g\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi), binindex, T_R_max); T_R = T_R_max; - printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_max=%g\n", modelgridindex, binindex, - T_R_max); } else { + printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_min=%g\n", + grid::get_mgi_of_nonemptymgi(nonemptymgi), binindex, T_R_min); T_R = T_R_min; - printout("find_T_R: cell %d bin %4d no solution in interval, clamping to T_R_min=%g\n", modelgridindex, binindex, - T_R_min); } return T_R; } // namespace radfield -void set_params_fullspec(const int modelgridindex, const int timestep) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +void set_params_fullspec(const int nonemptymgi, const int timestep) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double nubar = nuJ[nonemptymgi] / J[nonemptymgi]; if (!std::isfinite(nubar) || nubar == 0.) { printout("[warning] T_R estimator infinite in cell %d, keep T_R, T_J, W of last timestep. J = %g. nuJ = %g\n", @@ -425,7 +386,7 @@ void set_params_fullspec(const int modelgridindex, const int timestep) { MINTEMP, modelgridindex); T_J = MINTEMP; } - grid::set_TJ(modelgridindex, T_J); + grid::set_TJ(nonemptymgi, T_J); float T_R = H * nubar / KB / 3.832229494; if (T_R > MAXTEMP) { @@ -437,10 +398,10 @@ void set_params_fullspec(const int modelgridindex, const int timestep) { MINTEMP, modelgridindex); T_R = MINTEMP; } - grid::set_TR(modelgridindex, T_R); + grid::set_TR(nonemptymgi, T_R); const float W = J[nonemptymgi] * PI / STEBO / pow(T_R, 4); - grid::set_W(modelgridindex, W); + grid::set_W(nonemptymgi, W); printout( "Full-spectrum fit radfield for cell %d at timestep %d: J %g, nubar %5.1f Angstrom, T_J %g, T_R %g, W %g\n", @@ -487,17 +448,11 @@ void init(const int my_rank, const int ndo_nonempty) { nuJ.resize(nonempty_npts_model + 1); #endif - prev_Jb_lu_normed = static_cast(malloc((grid::get_npts_model() + 1) * sizeof(Jb_lu_estimator *))); - Jb_lu_raw = static_cast(malloc((grid::get_npts_model() + 1) * sizeof(Jb_lu_estimator *))); + resize_exactly(prev_Jb_lu_normed, nonempty_npts_model); + resize_exactly(Jb_lu_raw, nonempty_npts_model); detailed_linecount = 0; - detailed_lineindicies = nullptr; - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - prev_Jb_lu_normed[modelgridindex] = nullptr; - Jb_lu_raw[modelgridindex] = nullptr; - } - if constexpr (DETAILED_LINE_ESTIMATORS_ON) { for (int i = 0; i < globals::nlines; i++) { const int element = globals::linelist[i].elementindex; @@ -530,15 +485,6 @@ void init(const int my_rank, const int ndo_nonempty) { } } } - - // shrink the detailed line list in case detailed_linecount isn't a multiple of BLOCKSIZEJBLUE - // (important for saving memory if there are a lot of grid cells) - realloc_detailed_lines(detailed_linecount); - - // these are probably sorted anyway because the previous loop goes in ascending - // lineindex. But this sorting step is quick and makes sure that the - // binary searching later will work correctly - std::SORT_OR_STABLE_SORT(detailed_lineindicies, detailed_lineindicies + detailed_linecount); } printout("There are %d lines with detailed Jblue_lu estimators.\n", detailed_linecount); @@ -660,7 +606,7 @@ auto get_Jblueindex(const int lineindex) -> int { // use a binary search, assuming the list is sorted int low = 0; - int high = detailed_linecount; + int high = detailed_linecount - 1; while (low <= high) { const int mid = low + ((high - low) / 2); if (detailed_lineindicies[mid] < lineindex) { @@ -668,6 +614,7 @@ auto get_Jblueindex(const int lineindex) -> int { } else if (detailed_lineindicies[mid] > lineindex) { high = mid - 1; } else { + assert_always(mid < detailed_linecount); return mid; } } @@ -675,16 +622,16 @@ auto get_Jblueindex(const int lineindex) -> int { return -1; } -auto get_Jb_lu(const int modelgridindex, const int jblueindex) -> double { +auto get_Jb_lu(const int nonemptymgi, const int jblueindex) -> double { assert_always(jblueindex >= 0); assert_always(jblueindex < detailed_linecount); - return prev_Jb_lu_normed[modelgridindex][jblueindex].value; + return prev_Jb_lu_normed[nonemptymgi][jblueindex].value; } -auto get_Jb_lu_contribcount(const int modelgridindex, const int jblueindex) -> int { +auto get_Jb_lu_contribcount(const int nonemptymgi, const int jblueindex) -> int { assert_always(jblueindex >= 0); assert_always(jblueindex < detailed_linecount); - return prev_Jb_lu_normed[modelgridindex][jblueindex].contribcount; + return prev_Jb_lu_normed[nonemptymgi][jblueindex].contribcount; } void write_to_file(const int modelgridindex, const int timestep) { @@ -697,7 +644,7 @@ void write_to_file(const int modelgridindex, const int timestep) { int totalcontribs = 0; for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - totalcontribs += get_bin_contribcount(modelgridindex, binindex); + totalcontribs += get_bin_contribcount(nonemptymgi, binindex); } for (int binindex = -1 - detailed_linecount; binindex < RADFIELDBINCOUNT; binindex++) { @@ -715,17 +662,17 @@ void write_to_file(const int modelgridindex, const int timestep) { if (binindex >= 0) { nu_lower = get_bin_nu_lower(binindex); nu_upper = get_bin_nu_upper(binindex); - nuJ_out = get_bin_nuJ(modelgridindex, binindex); - J_out = get_bin_J(modelgridindex, binindex); - T_R = get_bin_T_R(modelgridindex, binindex); - W = get_bin_W(modelgridindex, binindex); + nuJ_out = get_bin_nuJ(nonemptymgi, binindex); + J_out = get_bin_J(nonemptymgi, binindex); + T_R = get_bin_T_R(nonemptymgi, binindex); + W = get_bin_W(nonemptymgi, binindex); J_nu_bar = J_out / (nu_upper - nu_lower); - contribcount = get_bin_contribcount(modelgridindex, binindex); + contribcount = get_bin_contribcount(nonemptymgi, binindex); } else if (binindex == -1) { // bin -1 is the full spectrum fit nuJ_out = nuJ[nonemptymgi]; J_out = J[nonemptymgi]; - T_R = grid::get_TR(modelgridindex); - W = grid::get_W(modelgridindex); + T_R = grid::get_TR(nonemptymgi); + W = grid::get_W(nonemptymgi); contribcount = totalcontribs; } else // use binindex < -1 for detailed line Jb_lu estimators { @@ -738,8 +685,8 @@ void write_to_file(const int modelgridindex, const int timestep) { J_out = -1.; T_R = -1.; W = -1.; - J_nu_bar = prev_Jb_lu_normed[modelgridindex][jblueindex].value, - contribcount = prev_Jb_lu_normed[modelgridindex][jblueindex].contribcount; + J_nu_bar = prev_Jb_lu_normed[nonemptymgi][jblueindex].value, + contribcount = prev_Jb_lu_normed[nonemptymgi][jblueindex].contribcount; } if (!skipoutput) { @@ -795,24 +742,14 @@ void zero_estimators() { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { assert_always(radfieldbins != nullptr); for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; - radfieldbins[mgibinindex].J_raw = 0.; - radfieldbins[mgibinindex].nuJ_raw = 0.; - radfieldbins[mgibinindex].contribcount = 0; - } + std::fill_n(&radfieldbins[nonemptymgi * RADFIELDBINCOUNT], RADFIELDBINCOUNT, + RadFieldBin{.J_raw = 0., .nuJ_raw = 0., .contribcount = 0}); } } if constexpr (DETAILED_LINE_ESTIMATORS_ON) { for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - assert_always(Jb_lu_raw != nullptr); - assert_always(Jb_lu_raw[modelgridindex] != nullptr); - for (int i = 0; i < detailed_linecount; i++) { - Jb_lu_raw[modelgridindex][i].value = 0.; - Jb_lu_raw[modelgridindex][i].contribcount = 0.; - } + std::fill_n(Jb_lu_raw[nonemptymgi].data(), detailed_linecount, Jb_lu_estimator{.value = 0., .contribcount = 0}); } } } @@ -847,26 +784,25 @@ __host__ __device__ void update_estimators(const int nonemptymgi, const double d } } -__host__ __device__ void update_lineestimator(const int modelgridindex, const int lineindex, const double increment) { +__host__ __device__ void update_lineestimator(const int nonemptymgi, const int lineindex, const double increment) { if constexpr (!DETAILED_LINE_ESTIMATORS_ON) { return; } const int jblueindex = get_Jblueindex(lineindex); if (jblueindex >= 0) { - Jb_lu_raw[modelgridindex][jblueindex].value += increment; - Jb_lu_raw[modelgridindex][jblueindex].contribcount += 1; + Jb_lu_raw[nonemptymgi][jblueindex].value += increment; + Jb_lu_raw[nonemptymgi][jblueindex].contribcount += 1; } } // mean intensity J_nu [ergs/s/sr/cm2/Hz] -__host__ __device__ auto radfield(const double nu, const int modelgridindex) -> double { +__host__ __device__ auto radfield(const double nu, const int nonemptymgi) -> double { if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { if (globals::timestep >= FIRST_NLTE_RADFIELD_TIMESTEP) { const int binindex = select_bin(nu); if (binindex >= 0) { - const auto &bin = - radfieldbin_solutions[(grid::get_nonemptymgi_of_mgi(modelgridindex) * RADFIELDBINCOUNT) + binindex]; + const auto &bin = radfieldbin_solutions[(static_cast(nonemptymgi) * RADFIELDBINCOUNT) + binindex]; if (bin.W >= 0.) { const double J_nu = dbb(nu, bin.T_R, bin.W); return J_nu; @@ -876,8 +812,8 @@ __host__ __device__ auto radfield(const double nu, const int modelgridindex) -> } } - const float T_R_fullspec = grid::get_TR(modelgridindex); - const float W_fullspec = grid::get_W(modelgridindex); + const float T_R_fullspec = grid::get_TR(nonemptymgi); + const float W_fullspec = grid::get_W(nonemptymgi); const double J_nu_fullspec = dbb(nu, T_R_fullspec, W_fullspec); return J_nu_fullspec; } @@ -921,11 +857,9 @@ auto planck_integral_analytic(const double T_R, const double nu_lower, const dou } // finds the best fitting W and temperature parameters in each spectral bin using J and nuJ -void fit_parameters(const int modelgridindex, const int timestep) { - set_params_fullspec(modelgridindex, timestep); - - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - +void fit_parameters(const int nonemptymgi, const int timestep) { + set_params_fullspec(nonemptymgi, timestep); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { if (J_normfactor[nonemptymgi] <= 0) { printout("radfield: FATAL J_normfactor = %g in cell %d at call to fit_parameters", J_normfactor[nonemptymgi], @@ -935,7 +869,7 @@ void fit_parameters(const int modelgridindex, const int timestep) { double J_bin_sum = 0.; for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - J_bin_sum += get_bin_J(modelgridindex, binindex); + J_bin_sum += get_bin_J(nonemptymgi, binindex); } printout("radfield bins sum to J of %g (%.1f%% of total J).\n", J_bin_sum, 100. * J_bin_sum / J[nonemptymgi]); @@ -943,26 +877,26 @@ void fit_parameters(const int modelgridindex, const int timestep) { double J_bin_max = 0.; for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const double J_bin = get_bin_J(modelgridindex, binindex); + const double J_bin = get_bin_J(nonemptymgi, binindex); J_bin_max = std::max(J_bin_max, J_bin); } for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { const double nu_lower = get_bin_nu_lower(binindex); const double nu_upper = get_bin_nu_upper(binindex); - const double J_bin = get_bin_J(modelgridindex, binindex); + const double J_bin = get_bin_J(nonemptymgi, binindex); float T_R_bin = -1.; double W_bin = -1.; - const int contribcount = get_bin_contribcount(modelgridindex, binindex); + const int contribcount = get_bin_contribcount(nonemptymgi, binindex); if (contribcount > 0) { { - T_R_bin = find_T_R(modelgridindex, binindex); + T_R_bin = find_T_R(nonemptymgi, binindex); if (binindex == RADFIELDBINCOUNT - 1) { - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); printout(" replacing bin %d T_R %7.1f with cell T_e = %7.1f\n", binindex, - get_bin_T_R(modelgridindex, binindex), T_e); + get_bin_T_R(nonemptymgi, binindex), T_e); T_R_bin = T_e; } @@ -1004,13 +938,12 @@ void fit_parameters(const int modelgridindex, const int timestep) { void set_J_normfactor(const int nonemptymgi, const double normfactor) { J_normfactor[nonemptymgi] = normfactor; } -void normalise_J(const int modelgridindex, const double estimator_normfactor_over4pi) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +void normalise_J(const int nonemptymgi, const double estimator_normfactor_over4pi) { assert_always(std::isfinite(J[nonemptymgi])); J[nonemptymgi] *= estimator_normfactor_over4pi; for (int i = 0; i < detailed_linecount; i++) { - prev_Jb_lu_normed[modelgridindex][i].value = Jb_lu_raw[modelgridindex][i].value * estimator_normfactor_over4pi; - prev_Jb_lu_normed[modelgridindex][i].contribcount = Jb_lu_raw[modelgridindex][i].contribcount; + prev_Jb_lu_normed[nonemptymgi][i].value = Jb_lu_raw[nonemptymgi][i].value * estimator_normfactor_over4pi; + prev_Jb_lu_normed[nonemptymgi][i].contribcount = Jb_lu_raw[nonemptymgi][i].contribcount; } } @@ -1027,10 +960,10 @@ void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, const auto bfestimcount = globals::bfestimcount; const ptrdiff_t nonempty_npts_model = grid::get_nonempty_npts_model(); for (ptrdiff_t nonemptymgi = 0; nonemptymgi < nonempty_npts_model; nonemptymgi++) { - const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); - if (grid::modelgrid[mgi].thick == 1) { + if (grid::modelgrid[nonemptymgi].thick == 1) { continue; } + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double deltaV = grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); const double estimator_normfactor = 1 / deltaV / deltat / globals::nprocs; @@ -1042,13 +975,12 @@ void normalise_bf_estimators(const int nts, const int nts_prev, const int titer, } auto get_bfrate_estimator(const int element, const int lowerion, const int lower, const int phixstargetindex, - const int modelgridindex) -> double { + const int nonemptymgi) -> double { if constexpr (DETAILED_BF_ESTIMATORS_ON) { const int allcontindex = get_bfcontindex(element, lowerion, lower, phixstargetindex); if (allcontindex >= 0) { const auto bfestimindex = globals::allcont[allcontindex].bfestimindex; if (bfestimindex >= 0) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); return prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + bfestimindex]; } } @@ -1057,20 +989,19 @@ auto get_bfrate_estimator(const int element, const int lowerion, const int lower return -1.; } -void normalise_nuJ(const int modelgridindex, const double estimator_normfactor_over4pi) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +void normalise_nuJ(const int nonemptymgi, const double estimator_normfactor_over4pi) { assert_always(std::isfinite(nuJ[nonemptymgi])); nuJ[nonemptymgi] *= estimator_normfactor_over4pi; } -auto get_T_J_from_J(const int modelgridindex) -> double { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto get_T_J_from_J(const int nonemptymgi) -> double { const double T_J = pow(J[nonemptymgi] * PI / STEBO, 1. / 4.); if (!std::isfinite(T_J)) { // keep old value of T_J + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout("[warning] get_T_J_from_J: T_J estimator infinite in cell %d, use value of last timestep\n", modelgridindex); - return grid::get_TR(modelgridindex); + return grid::get_TR(nonemptymgi); } // Make sure that T is in the allowed temperature range. if (T_J > MAXTEMP) { @@ -1145,14 +1076,11 @@ void reduce_estimators() const auto sys_time_start_reduction = std::time(nullptr); printout("Reducing detailed line estimators"); - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { - MPI_Allreduce(MPI_IN_PLACE, &Jb_lu_raw[modelgridindex][jblueindex].value, 1, MPI_DOUBLE, MPI_SUM, - MPI_COMM_WORLD); - MPI_Allreduce(MPI_IN_PLACE, &Jb_lu_raw[modelgridindex][jblueindex].contribcount, 1, MPI_INT, MPI_SUM, - MPI_COMM_WORLD); - } + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { + MPI_Allreduce(MPI_IN_PLACE, &Jb_lu_raw[nonemptymgi][jblueindex].value, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(MPI_IN_PLACE, &Jb_lu_raw[nonemptymgi][jblueindex].contribcount, 1, MPI_INT, MPI_SUM, + MPI_COMM_WORLD); } } const int duration_reduction = std::time(nullptr) - sys_time_start_reduction; @@ -1177,10 +1105,9 @@ void do_MPI_Bcast(const ptrdiff_t nonemptymgi, const int root, const int root_no } if constexpr (DETAILED_LINE_ESTIMATORS_ON) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { - MPI_Bcast(&prev_Jb_lu_normed[modelgridindex][jblueindex].value, 1, MPI_DOUBLE, root, MPI_COMM_WORLD); - MPI_Bcast(&prev_Jb_lu_normed[modelgridindex][jblueindex].contribcount, 1, MPI_INT, root, MPI_COMM_WORLD); + MPI_Bcast(&prev_Jb_lu_normed[nonemptymgi][jblueindex].value, 1, MPI_DOUBLE, root, MPI_COMM_WORLD); + MPI_Bcast(&prev_Jb_lu_normed[nonemptymgi][jblueindex].contribcount, 1, MPI_INT, root, MPI_COMM_WORLD); } } @@ -1209,13 +1136,10 @@ void write_restart_data(FILE *gridsave_file) { const int bfestimcount = globals::bfestimcount; fprintf(gridsave_file, "%d\n", bfestimcount); - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - fprintf(gridsave_file, "%d\n", modelgridindex); - for (int i = 0; i < bfestimcount; i++) { - fprintf(gridsave_file, "%a ", prev_bfrate_normed[(nonemptymgi * bfestimcount) + i]); - } + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + fprintf(gridsave_file, "%d\n", nonemptymgi); + for (int i = 0; i < bfestimcount; i++) { + fprintf(gridsave_file, "%a ", prev_bfrate_normed[(nonemptymgi * bfestimcount) + i]); } } } @@ -1228,26 +1152,23 @@ void write_restart_data(FILE *gridsave_file) { } } - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - assert_testmodeonly(nonemptymgi >= 0); - fprintf(gridsave_file, "%d %la\n", modelgridindex, J_normfactor[nonemptymgi]); + for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + assert_testmodeonly(nonemptymgi >= 0); + fprintf(gridsave_file, "%d %la\n", nonemptymgi, J_normfactor[nonemptymgi]); - if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { - for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; - fprintf(gridsave_file, "%la %la %a %a %d\n", radfieldbins[mgibinindex].J_raw, - radfieldbins[mgibinindex].nuJ_raw, radfieldbin_solutions[mgibinindex].W, - radfieldbin_solutions[mgibinindex].T_R, radfieldbins[mgibinindex].contribcount); - } + if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { + for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; + fprintf(gridsave_file, "%la %la %a %a %d\n", radfieldbins[mgibinindex].J_raw, radfieldbins[mgibinindex].nuJ_raw, + radfieldbin_solutions[mgibinindex].W, radfieldbin_solutions[mgibinindex].T_R, + radfieldbins[mgibinindex].contribcount); } + } - if constexpr (DETAILED_LINE_ESTIMATORS_ON) { - for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { - fprintf(gridsave_file, "%la %d\n", Jb_lu_raw[modelgridindex][jblueindex].value, - Jb_lu_raw[modelgridindex][jblueindex].contribcount); - } + if constexpr (DETAILED_LINE_ESTIMATORS_ON) { + for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { + fprintf(gridsave_file, "%la %d\n", Jb_lu_raw[nonemptymgi][jblueindex].value, + Jb_lu_raw[nonemptymgi][jblueindex].contribcount); } } } @@ -1312,19 +1233,16 @@ void read_restart_data(FILE *gridsave_file) { assert_always(fscanf(gridsave_file, "%d\n", &gridsave_nbfestim_in) == 1); assert_always(gridsave_nbfestim_in == globals::bfestimcount); - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - int mgi_in = 0; - assert_always(fscanf(gridsave_file, "%d\n", &mgi_in) == 1); - assert_always(mgi_in == modelgridindex); - for (int i = 0; i < globals::bfestimcount; i++) { - float bfrate_normed = 0; - assert_always(fscanf(gridsave_file, "%a ", &bfrate_normed) == 1); - - if (globals::rank_in_node == 0) { - prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + i] = bfrate_normed; - } + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + int nonemptymgi_in = 0; + assert_always(fscanf(gridsave_file, "%d\n", &nonemptymgi_in) == 1); + assert_always(nonemptymgi_in == nonemptymgi); + for (int i = 0; i < globals::bfestimcount; i++) { + float bfrate_normed = 0; + assert_always(fscanf(gridsave_file, "%a ", &bfrate_normed) == 1); + + if (globals::rank_in_node == 0) { + prev_bfrate_normed[(nonemptymgi * globals::bfestimcount) + i] = bfrate_normed; } } } @@ -1345,39 +1263,33 @@ void read_restart_data(FILE *gridsave_file) { } } - for (int modelgridindex = 0; modelgridindex < grid::get_npts_model(); modelgridindex++) { - if (grid::get_numpropcells(modelgridindex) > 0) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - int mgi_in = 0; - assert_always(fscanf(gridsave_file, "%d %la\n", &mgi_in, &J_normfactor[nonemptymgi]) == 2); - if (mgi_in != modelgridindex) { - printout("ERROR: expected data for cell %d but found cell %d\n", modelgridindex, mgi_in); - std::abort(); - } + for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { + int nonemptymgi_in = 0; + assert_always(fscanf(gridsave_file, "%d %la\n", &nonemptymgi_in, &J_normfactor[nonemptymgi]) == 2); + assert_always(nonemptymgi_in == nonemptymgi); - if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { - for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { - const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; - float W = 0; - float T_R = 0; - assert_always(fscanf(gridsave_file, "%la %la %a %a %d\n", &radfieldbins[mgibinindex].J_raw, - &radfieldbins[mgibinindex].nuJ_raw, &W, &T_R, - &radfieldbins[mgibinindex].contribcount) == 5); + if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { + for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { + const auto mgibinindex = (nonemptymgi * RADFIELDBINCOUNT) + binindex; + float W = 0; + float T_R = 0; + assert_always(fscanf(gridsave_file, "%la %la %a %a %d\n", &radfieldbins[mgibinindex].J_raw, + &radfieldbins[mgibinindex].nuJ_raw, &W, &T_R, + &radfieldbins[mgibinindex].contribcount) == 5); #ifdef MPI_ON - if (globals::rank_in_node == 0) + if (globals::rank_in_node == 0) #endif - { - radfieldbin_solutions[mgibinindex].W = W; - radfieldbin_solutions[mgibinindex].T_R = T_R; - } + { + radfieldbin_solutions[mgibinindex].W = W; + radfieldbin_solutions[mgibinindex].T_R = T_R; } } + } - if constexpr (DETAILED_LINE_ESTIMATORS_ON) { - for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { - assert_always(fscanf(gridsave_file, "%la %d\n", &Jb_lu_raw[modelgridindex][jblueindex].value, - &Jb_lu_raw[modelgridindex][jblueindex].contribcount) == 2); - } + if constexpr (DETAILED_LINE_ESTIMATORS_ON) { + for (int jblueindex = 0; jblueindex < detailed_linecount; jblueindex++) { + assert_always(fscanf(gridsave_file, "%la %d\n", &Jb_lu_raw[nonemptymgi][jblueindex].value, + &Jb_lu_raw[nonemptymgi][jblueindex].contribcount) == 2); } } } diff --git a/radfield.h b/radfield.h index e0ad0c20f..b29f0d66c 100644 --- a/radfield.h +++ b/radfield.h @@ -17,16 +17,16 @@ void write_to_file(int modelgridindex, int timestep); void close_file(); void update_estimators(int nonemptymgi, double distance_e_cmf, double nu_cmf, double doppler_nucmf_on_nurf, const Phixslist &phixslist, bool thickcell); -void update_lineestimator(int modelgridindex, int lineindex, double increment); -[[nodiscard]] auto radfield(double nu, int modelgridindex) -> double; -void fit_parameters(int modelgridindex, int timestep); +void update_lineestimator(int nonemptymgi, int lineindex, double increment); +[[nodiscard]] auto radfield(double nu, int nonemptymgi) -> double; +void fit_parameters(int nonemptymgi, int timestep); void set_J_normfactor(int nonemptymgi, double normfactor); -void normalise_J(int modelgridindex, double estimator_normfactor_over4pi); -void normalise_nuJ(int modelgridindex, double estimator_normfactor_over4pi); -[[nodiscard]] auto get_T_J_from_J(int modelgridindex) -> double; +void normalise_J(int nonemptymgi, double estimator_normfactor_over4pi); +void normalise_nuJ(int nonemptymgi, double estimator_normfactor_over4pi); +[[nodiscard]] auto get_T_J_from_J(int nonemptymgi) -> double; [[nodiscard]] auto get_Jblueindex(int lineindex) -> int; -[[nodiscard]] auto get_Jb_lu(int modelgridindex, int jblueindex) -> double; -[[nodiscard]] auto get_Jb_lu_contribcount(int modelgridindex, int jblueindex) -> int; +[[nodiscard]] auto get_Jb_lu(int nonemptymgi, int jblueindex) -> double; +[[nodiscard]] auto get_Jb_lu_contribcount(int nonemptymgi, int jblueindex) -> int; void titer_J(int modelgridindex); void titer_nuJ(int modelgridindex); void reduce_estimators(); @@ -34,7 +34,7 @@ void do_MPI_Bcast(ptrdiff_t nonemptymgi, int root, int root_node_id); void write_restart_data(FILE *gridsave_file); void read_restart_data(FILE *gridsave_file); void normalise_bf_estimators(int nts, int nts_prev, int titer, double deltat); -[[nodiscard]] auto get_bfrate_estimator(int element, int lowerion, int lower, int phixstargetindex, int modelgridindex) +[[nodiscard]] auto get_bfrate_estimator(int element, int lowerion, int lower, int phixstargetindex, int nonemptymgi) -> double; void print_bfrate_contributions(int element, int lowerion, int lower, int phixstargetindex, int modelgridindex, double nnlowerlevel, double nnlowerion); diff --git a/ratecoeff.cc b/ratecoeff.cc index 9ffa3dcc7..24e507d2e 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -40,12 +40,12 @@ double *corrphotoioncoeffs{}; double *bfcooling_coeffs{}; -struct gsl_integral_paras_gammacorr { +struct GSLIntegralParasGammaCorr { double nu_edge; double departure_ratio; const float *photoion_xs; float T_e; - int modelgridindex; + int nonemptymgi; }; char adatafile_hash[33]; @@ -668,20 +668,20 @@ void precalculate_ion_alpha_sp() { } auto integrand_stimrecombination_custom_radfield(const double nu, void *const voidparas) -> double { - const auto *const params = static_cast(voidparas); - const int modelgridindex = params->modelgridindex; + const auto *const params = static_cast(voidparas); + const int nonemptymgi = params->nonemptymgi; const float T_e = params->T_e; const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, params->nu_edge, nu); - const double Jnu = radfield::radfield(nu, modelgridindex); + const double Jnu = radfield::radfield(nu, nonemptymgi); // TODO: MK thesis page 41, use population ratios and Te? return ONEOVERH * sigma_bf / nu * Jnu * exp(-HOVERKB * nu / T_e); } auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, const int level, - const int phixstargetindex, const int modelgridindex) -> double { + const int phixstargetindex, const int nonemptymgi) -> double { const double epsrel = 1e-3; const double epsabs = 0.; @@ -689,12 +689,12 @@ auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, c const double nu_threshold = ONEOVERH * E_threshold; const double nu_max_phixs = nu_threshold * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table - const auto T_e = grid::get_Te(modelgridindex); - const auto intparas = gsl_integral_paras_gammacorr{ + const auto T_e = grid::get_Te(nonemptymgi); + const auto intparas = GSLIntegralParasGammaCorr{ .nu_edge = nu_threshold, .photoion_xs = get_phixs_table(element, lowerion, level), .T_e = T_e, - .modelgridindex = modelgridindex, + .nonemptymgi = nonemptymgi, }; const int upperionlevel = get_phixsupperlevel(element, lowerion, level, phixstargetindex); @@ -729,8 +729,8 @@ auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *const vo // Integrand to calculate the rate coefficient for photoionization // using gsl integrators. Corrected for stimulated recombination. { - const gsl_integral_paras_gammacorr *const params = static_cast(voidparas); - const int modelgridindex = params->modelgridindex; + const GSLIntegralParasGammaCorr *const params = static_cast(voidparas); + const int nonemptymgi = params->nonemptymgi; #if (SEPARATE_STIMRECOMB) const double corrfactor = 1.; @@ -744,14 +744,14 @@ auto integrand_corrphotoioncoeff_custom_radfield(const double nu, void *const vo const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, params->nu_edge, nu); - const double Jnu = radfield::radfield(nu, modelgridindex); + const double Jnu = radfield::radfield(nu, nonemptymgi); // TODO: MK thesis page 41, use population ratios and Te? return ONEOVERH * sigma_bf / nu * Jnu * corrfactor; } auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int level, const int phixstargetindex, - int modelgridindex) -> double { + int nonemptymgi) -> double { constexpr double epsrel = 1e-3; constexpr double epsrelwarning = 1e-1; constexpr double epsabs = 0.; @@ -760,28 +760,28 @@ auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int const double nu_threshold = ONEOVERH * E_threshold; const double nu_max_phixs = nu_threshold * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); #if SEPARATE_STIMRECOMB const double departure_ratio = 0.; // zero the stimulated recomb contribution #else // stimulated recombination is negative photoionisation - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); - const double nne = grid::get_nne(modelgridindex); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); + const double nne = grid::get_nne(nonemptymgi); const int upperionlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); const double sf = calculate_sahafact(element, ion, level, upperionlevel, T_e, H * nu_threshold); - const double nnupperionlevel = get_levelpop(modelgridindex, element, ion + 1, upperionlevel); + const double nnupperionlevel = get_levelpop(nonemptymgi, element, ion + 1, upperionlevel); double departure_ratio = nnlevel > 0. ? nnupperionlevel / nnlevel * nne * sf : 1.; // put that to phixslist if (!std::isfinite(departure_ratio)) { departure_ratio = 0.; } #endif - const auto intparas = gsl_integral_paras_gammacorr{ + const auto intparas = GSLIntegralParasGammaCorr{ .nu_edge = nu_threshold, .departure_ratio = departure_ratio, .photoion_xs = get_phixs_table(element, ion, level), .T_e = T_e, - .modelgridindex = modelgridindex, + .nonemptymgi = nonemptymgi, }; double error = 0.; @@ -798,8 +798,8 @@ auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int printout( "corrphotoioncoeff gsl integrator warning %d. modelgridindex %d Z=%d ionstage %d lower %d phixstargetindex %d " "integral %g error %g\n", - status, modelgridindex, get_atomicnumber(element), get_ionstage(element, ion), level, phixstargetindex, - gammacorr, error); + status, grid::get_mgi_of_nonemptymgi(nonemptymgi), get_atomicnumber(element), get_ionstage(element, ion), level, + phixstargetindex, gammacorr, error); if (!std::isfinite(gammacorr)) { gammacorr = 0.; } @@ -812,10 +812,10 @@ auto calculate_corrphotoioncoeff_integral(int element, const int ion, const int // get the number of levels that make up a fraction of the ion population // of at least IONGAMMA_POPFRAC_LEVELS_INCLUDED -auto get_nlevels_important(const int modelgridindex, const int element, const int ion, const bool assume_lte, +auto get_nlevels_important(const int nonemptymgi, const int element, const int ion, const bool assume_lte, const float T_e) -> std::tuple { // get the stored ion population for comparison with the cumulative sum of level pops - const double nnion_real = get_nnion(modelgridindex, element, ion); + const double nnion_real = get_nnion(nonemptymgi, element, ion); if (IONGAMMA_POPFRAC_LEVELS_INCLUDED >= 1.) { return {get_nlevels(element, ion), nnion_real}; @@ -834,12 +834,12 @@ auto get_nlevels_important(const int modelgridindex, const int element, const in const double T_exc = T_e; // remember, other parts of the code in LTE mode use TJ, not T_e const double E_level = epsilon(element, ion, lower); const double E_ground = epsilon(element, ion, 0); - const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, ion) : 1.; + const double nnground = get_groundlevelpop(nonemptymgi, element, ion); nnlowerlevel = (nnground * stat_weight(element, ion, lower) / stat_weight(element, ion, 0) * exp(-(E_level - E_ground) / KB / T_exc)); } else { - nnlowerlevel = get_levelpop(modelgridindex, element, ion, lower); + nnlowerlevel = get_levelpop(nonemptymgi, element, ion, lower); } nnlevelsum += nnlowerlevel; nlevels_important = lower + 1; @@ -972,8 +972,10 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i double alpha = 0.; if (lowerion < get_nions(element) - 1) { + const auto nonemptymgi = (modelgridindex >= 0) ? grid::get_nonemptymgi_of_mgi(modelgridindex) : -1; + // this gets divided and cancelled out in the radiative case anyway - const double nne = (modelgridindex >= 0) ? grid::get_nne(modelgridindex) : 1.; + const double nne = (modelgridindex >= 0) ? grid::get_nne(nonemptymgi) : 1.; double nnupperion = 0; // nnupperion = get_groundmultiplet_pop(modelgridindex, T_e, element, upperion, assume_lte); @@ -994,12 +996,12 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i const double T_exc = T_e; const double E_level = epsilon(element, lowerion + 1, upper); const double E_ground = epsilon(element, lowerion + 1, 0); - const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; + const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(nonemptymgi, element, lowerion + 1) : 1.; nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * exp(-(E_level - E_ground) / KB / T_exc)); } else { - nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); + nnupperlevel = get_levelpop(nonemptymgi, element, lowerion + 1, upper); } nnupperion += nnupperlevel; } @@ -1016,12 +1018,12 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i const double T_exc = T_e; const double E_level = epsilon(element, lowerion + 1, upper); const double E_ground = epsilon(element, lowerion + 1, 0); - const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(modelgridindex, element, lowerion + 1) : 1.; + const double nnground = (modelgridindex >= 0) ? get_groundlevelpop(nonemptymgi, element, lowerion + 1) : 1.; nnupperlevel = (nnground * stat_weight(element, lowerion + 1, upper) / stat_weight(element, lowerion + 1, 0) * exp(-(E_level - E_ground) / KB / T_exc)); } else { - nnupperlevel = get_levelpop(modelgridindex, element, lowerion + 1, upper); + nnupperlevel = get_levelpop(nonemptymgi, element, lowerion + 1, upper); } nnupperlevel_so_far += nnupperlevel; for (int lower = 0; lower < get_nlevels(element, lowerion); lower++) { @@ -1032,11 +1034,11 @@ auto calculate_ionrecombcoeff(const int modelgridindex, const float T_e, const i double recomb_coeff = 0.; if (collisional_not_radiative) { const double epsilon_trans = epsilon(element, lowerion + 1, upper) - epsilon(element, lowerion, lower); - recomb_coeff += col_recombination_ratecoeff(modelgridindex, element, upperion, upper, lower, epsilon_trans); + recomb_coeff += col_recombination_ratecoeff(T_e, nne, element, upperion, upper, lower, epsilon_trans); } else if (!stimonly) { - recomb_coeff += rad_recombination_ratecoeff(T_e, nne, element, lowerion + 1, upper, lower, modelgridindex); + recomb_coeff += rad_recombination_ratecoeff(T_e, nne, element, lowerion + 1, upper, lower, nonemptymgi); } else { - recomb_coeff += stim_recombination_ratecoeff(nne, element, upperion, upper, lower, modelgridindex); + recomb_coeff += stim_recombination_ratecoeff(nne, element, upperion, upper, lower, nonemptymgi); } const double alpha_level = recomb_coeff / nne; @@ -1137,22 +1139,22 @@ auto interpolate_corrphotoioncoeff(const int element, const int ion, const int l } auto get_corrphotoioncoeff_ana(int element, const int ion, const int level, const int phixstargetindex, - const int modelgridindex) -> double + const int nonemptymgi) -> double // Returns the for stimulated emission corrected photoionisation rate coefficient. { assert_always(USE_LUT_PHOTOION); // The correction factor for stimulated emission in gammacorr is set to its // LTE value. Because the T_e dependence of gammacorr is weak, this correction // correction may be evaluated at T_R! - const double W = grid::get_W(modelgridindex); - const double T_R = grid::get_TR(modelgridindex); + const double W = grid::get_W(nonemptymgi); + const double T_R = grid::get_TR(nonemptymgi); return W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); } // Returns the stimulated recombination rate coefficient. multiply by upper level population and nne to get rate auto get_stimrecombcoeff(int element, const int lowerion, const int level, const int phixstargetindex, - const int modelgridindex) -> double { + const int nonemptymgi) -> double { double stimrecombcoeff = -1.; #if (SEPARATE_STIMRECOMB) if (use_cellcache) { @@ -1166,7 +1168,7 @@ auto get_stimrecombcoeff(int element, const int lowerion, const int level, const #endif if (!use_cellcache || stimrecombcoeff < 0) { - stimrecombcoeff = calculate_stimrecombcoeff_integral(element, lowerion, level, phixstargetindex, modelgridindex); + stimrecombcoeff = calculate_stimrecombcoeff_integral(element, lowerion, level, phixstargetindex, nonemptymgi); #if (SEPARATE_STIMRECOMB) if (use_cellcache) { @@ -1179,6 +1181,7 @@ auto get_stimrecombcoeff(int element, const int lowerion, const int level, const } #endif } + assert_always(std::isfinite(stimrecombcoeff)); return stimrecombcoeff; } @@ -1201,7 +1204,7 @@ __host__ __device__ auto get_bfcoolingcoeff(const int element, const int ion, co // Return the photoionisation rate coefficient (corrected for stimulated emission) __host__ __device__ auto get_corrphotoioncoeff(const int element, const int ion, const int level, - const int phixstargetindex, const int modelgridindex) -> double { + const int phixstargetindex, const int nonemptymgi) -> double { // The correction factor for stimulated emission in gammacorr is set to its // LTE value. Because the T_e dependence of gammacorr is weak, this correction // correction may be evaluated at T_R! @@ -1215,17 +1218,16 @@ __host__ __device__ auto get_corrphotoioncoeff(const int element, const int ion, if (!use_cellcache || gammacorr < 0) { if (DETAILED_BF_ESTIMATORS_ON && globals::timestep >= DETAILED_BF_ESTIMATORS_USEFROMTIMESTEP) { - gammacorr = radfield::get_bfrate_estimator(element, ion, level, phixstargetindex, modelgridindex); + gammacorr = radfield::get_bfrate_estimator(element, ion, level, phixstargetindex, nonemptymgi); // gammacorr will be -1 if no estimators available } if (!DETAILED_BF_ESTIMATORS_ON || gammacorr < 0) { if constexpr (!USE_LUT_PHOTOION) { - gammacorr = calculate_corrphotoioncoeff_integral(element, ion, level, phixstargetindex, modelgridindex); + gammacorr = calculate_corrphotoioncoeff_integral(element, ion, level, phixstargetindex, nonemptymgi); } else { - const double W = grid::get_W(modelgridindex); - const double T_R = grid::get_TR(modelgridindex); - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const double W = grid::get_W(nonemptymgi); + const double T_R = grid::get_TR(nonemptymgi); gammacorr = W * interpolate_corrphotoioncoeff(element, ion, level, phixstargetindex, T_R); const int index_in_groundlevelcontestimator = @@ -1254,17 +1256,16 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - if (ion >= nions - 1) { return true; } - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if (USE_LUT_PHOTOION || !elem_has_nlte_levels(element)) { return (globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] == 0); } - const auto T_e = grid::get_Te(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); for (int level = 0; level < get_nlevels(element, ion); level++) { - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); if (nnlevel == 0.) { continue; } @@ -1272,7 +1273,7 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upperlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); - if (nnlevel * get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex) > 0.) { + if (nnlevel * get_corrphotoioncoeff(element, ion, level, phixstargetindex, nonemptymgi) > 0.) { return false; } @@ -1287,27 +1288,27 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - } // ionisation rate coefficient. multiply by get_groundlevelpop to get a rate [s^-1] -auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, const int ion) -> double { +auto calculate_iongamma_per_gspop(const int nonemptymgi, const int element, const int ion) -> double { const int nions = get_nions(element); double Gamma = 0.; if (ion >= nions - 1) { return 0.; } - const auto T_e = grid::get_Te(modelgridindex); - const float nne = grid::get_nne(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const float nne = grid::get_nne(nonemptymgi); - // const auto [nlevels_important, _] = get_nlevels_important(modelgridindex, element, ion, false, T_e); + // const auto [nlevels_important, _] = get_nlevels_important(nonemptymgi, element, ion, false, T_e); const int nlevels_important = get_nlevels(element, ion); double Col_ion = 0.; for (int level = 0; level < nlevels_important; level++) { - const double nnlevel = calculate_levelpop(modelgridindex, element, ion, level); + const double nnlevel = calculate_levelpop(nonemptymgi, element, ion, level); const int nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { const int upperlevel = get_phixsupperlevel(element, ion, level, phixstargetindex); - Gamma += nnlevel * get_corrphotoioncoeff(element, ion, level, phixstargetindex, modelgridindex); + Gamma += nnlevel * get_corrphotoioncoeff(element, ion, level, phixstargetindex, nonemptymgi); const double epsilon_trans = epsilon(element, ion + 1, upperlevel) - epsilon(element, ion, level); @@ -1315,22 +1316,21 @@ auto calculate_iongamma_per_gspop(const int modelgridindex, const int element, c } } Gamma += Col_ion; - Gamma /= get_groundlevelpop(modelgridindex, element, ion); + Gamma /= get_groundlevelpop(nonemptymgi, element, ion); return Gamma; } // ionisation rate coefficient. multiply by the lower ion pop to get a rate. // Currently only used for the estimator output file, not the simulation -auto calculate_iongamma_per_ionpop(const int modelgridindex, const float T_e, const int element, const int lowerion, +auto calculate_iongamma_per_ionpop(const int nonemptymgi, const float T_e, const int element, const int lowerion, const bool assume_lte, const bool collisional_not_radiative, const bool printdebug, const bool force_bfest, const bool force_bfintegral) -> double { assert_always(lowerion < get_nions(element) - 1); assert_always(!force_bfest || !force_bfintegral); - const float nne = (modelgridindex >= 0) ? grid::get_nne(modelgridindex) : 1.; + const auto nne = grid::get_nne(nonemptymgi); - const auto [nlevels_important, nnlowerion] = - get_nlevels_important(modelgridindex, element, lowerion, assume_lte, T_e); + const auto [nlevels_important, nnlowerion] = get_nlevels_important(nonemptymgi, element, lowerion, assume_lte, T_e); if (nnlowerion <= 0.) { return 0.; @@ -1344,12 +1344,12 @@ auto calculate_iongamma_per_ionpop(const int modelgridindex, const float T_e, co const double T_exc = T_e; const double E_level = epsilon(element, lowerion, lower); const double E_ground = epsilon(element, lowerion, 0); - const double nnground = get_groundlevelpop(modelgridindex, element, lowerion); + const double nnground = get_groundlevelpop(nonemptymgi, element, lowerion); nnlowerlevel = (nnground * stat_weight(element, lowerion, lower) / stat_weight(element, lowerion, 0) * exp(-(E_level - E_ground) / KB / T_exc)); } else { - nnlowerlevel = get_levelpop(modelgridindex, element, lowerion, lower); + nnlowerlevel = get_levelpop(nonemptymgi, element, lowerion, lower); } for (int phixstargetindex = 0; phixstargetindex < get_nphixstargets(element, lowerion, lower); phixstargetindex++) { @@ -1363,18 +1363,17 @@ auto calculate_iongamma_per_ionpop(const int modelgridindex, const float T_e, co gamma_coeff_used += col_ionization_ratecoeff(T_e, nne, element, lowerion, lower, phixstargetindex, epsilon_trans); } else { - gamma_coeff_used = get_corrphotoioncoeff(element, lowerion, lower, phixstargetindex, - modelgridindex); // whatever ARTIS uses internally + // whatever ARTIS uses internally + gamma_coeff_used = get_corrphotoioncoeff(element, lowerion, lower, phixstargetindex, nonemptymgi); if (force_bfest || printdebug) { - gamma_coeff_bfest = - radfield::get_bfrate_estimator(element, lowerion, lower, phixstargetindex, modelgridindex); + gamma_coeff_bfest = radfield::get_bfrate_estimator(element, lowerion, lower, phixstargetindex, nonemptymgi); } if (force_bfintegral || printdebug) { // use the cellcache but not the detailed bf estimators gamma_coeff_integral += - calculate_corrphotoioncoeff_integral(element, lowerion, lower, phixstargetindex, modelgridindex); + calculate_corrphotoioncoeff_integral(element, lowerion, lower, phixstargetindex, nonemptymgi); // double gamma_coeff_integral_level_ch = globals::cellcache[cellcacheslotid] // .chelements[element] // .chions[lowerion] diff --git a/ratecoeff.h b/ratecoeff.h index c351b6979..3bf607815 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -21,22 +21,22 @@ void setup_photoion_luts(); -> double; [[nodiscard]] auto get_spontrecombcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double; -[[nodiscard]] auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetindex, int modelgridindex) +[[nodiscard]] auto get_stimrecombcoeff(int element, int lowerion, int level, int phixstargetindex, int nonemptymgi) -> double; [[nodiscard]] auto get_bfcoolingcoeff(int element, int ion, int level, int phixstargetindex, float T_e) -> double; -[[nodiscard]] auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, int modelgridindex) +[[nodiscard]] auto get_corrphotoioncoeff(int element, int ion, int level, int phixstargetindex, int nonemptymgi) -> double; -[[nodiscard]] auto get_corrphotoioncoeff_ana(int element, int ion, int level, int phixstargetindex, int modelgridindex) +[[nodiscard]] auto get_corrphotoioncoeff_ana(int element, int ion, int level, int phixstargetindex, int nonemptymgi) -> double; [[nodiscard]] auto iongamma_is_zero(int nonemptymgi, int element, int ion) -> bool; -[[nodiscard]] auto calculate_iongamma_per_gspop(int modelgridindex, int element, int ion) -> double; -[[nodiscard]] auto calculate_iongamma_per_ionpop(int modelgridindex, float T_e, int element, int lowerion, - bool assume_lte, bool collisional_not_radiative, bool printdebug, - bool force_bfest, bool force_bfintegral) -> double; +[[nodiscard]] auto calculate_iongamma_per_gspop(int nonemptymgi, int element, int ion) -> double; +[[nodiscard]] auto calculate_iongamma_per_ionpop(int nonemptymgi, float T_e, int element, int lowerion, bool assume_lte, + bool collisional_not_radiative, bool printdebug, bool force_bfest, + bool force_bfintegral) -> double; [[nodiscard]] auto calculate_ionrecombcoeff(int modelgridindex, float T_e, int element, int upperion, bool assume_lte, bool collisional_not_radiative, bool printdebug, bool lower_superlevel_only, diff --git a/rpkt.cc b/rpkt.cc index 7590baa6e..d869b77fb 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -78,14 +78,12 @@ constexpr auto get_expopac_bin_nu_lower(const ptrdiff_t binindex) -> double { // return edist, the distance to the next physical event (continuum or bound-bound) and is_boundbound_event, a // boolean BE AWARE THAT THIS PROCEDURE SHOULD BE ONLY CALLED FOR NON EMPTY CELLS!! -auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, +auto get_event(const int nonemptymgi, const Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, MacroAtomState &mastate, const double tau_rnd, // random optical depth until which the packet travels const double abort_dist, // maximal travel distance before packet leaves cell or time step ends const double nu_cmf_abort, const double d_nu_on_d_l, const double doppler, const auto *const linelist, const int nlines) -> std::tuple { - assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); - auto pos = pkt.pos; auto nu_cmf = pkt.nu_cmf; auto e_cmf = pkt.e_cmf; @@ -104,8 +102,9 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum // returns negative value if nu_cmf > nu_trans if (const int lineindex = closest_transition(nu_cmf, next_trans, nlines, linelist); lineindex >= 0) [[likely]] { // line interaction is possible (nu_cmf > nu_trans) + const auto &line = globals::linelist[lineindex]; - const double nu_trans = linelist[lineindex].nu; + const double nu_trans = line.nu; // helper variable to overcome numerical problems after line scattering // further scattering events should be located at lower frequencies to prevent @@ -125,18 +124,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum return {std::numeric_limits::max(), next_trans - 1, false}; } - const int element = linelist[lineindex].elementindex; - const int ion = linelist[lineindex].ionindex; - const int upper = linelist[lineindex].upperlevelindex; - const int lower = linelist[lineindex].lowerlevelindex; - const double A_ul = linelist[lineindex].einstein_A; - const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nu_trans, 3) * A_ul; - const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; - - const double n_u = get_levelpop(modelgridindex, element, ion, upper); - const double n_l = get_levelpop(modelgridindex, element, ion, lower); - - const double tau_line = std::max(0., (B_lu * n_l - B_ul * n_u) * HCLIGHTOVERFOURPI * prop_time); + const double tau_line = get_tau_sobolev_subupdown(nonemptymgi, line, prop_time); // printout("[debug] get_event: tau_line %g\n", tau_line); // printout("[debug] get_event: tau_rnd - tau > tau_cont\n"); @@ -164,17 +152,22 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum assert_testmodeonly(nu_cmf <= pkt.nu_cmf); } - radfield::update_lineestimator(modelgridindex, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); + if constexpr (DETAILED_LINE_ESTIMATORS_ON) { + radfield::update_lineestimator(nonemptymgi, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); + } } else { // bound-bound process occurs // printout("[debug] get_event: tau_rnd - tau <= tau_cont + tau_line: bb-process occurs\n"); - mastate = {.element = element, .ion = ion, .level = upper, .activatingline = lineindex}; + mastate = {.element = line.elementindex, + .ion = line.ionindex, + .level = line.upperlevelindex, + .activatingline = lineindex}; if constexpr (DETAILED_LINE_ESTIMATORS_ON) { move_pkt_withtime(pos, pkt.dir, prop_time, pkt.nu_rf, nu_cmf, pkt.e_rf, e_cmf, ldist); - radfield::update_lineestimator(modelgridindex, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); + radfield::update_lineestimator(nonemptymgi, lineindex, prop_time * CLIGHT * e_cmf / nu_cmf); } // the line and its parameters were already selected by closest_transition! @@ -208,7 +201,7 @@ auto get_event(const int modelgridindex, const Packet &pkt, const Rpkt_continuum } auto get_event_expansion_opacity( - const int modelgridindex, const int nonemptymgi, const Packet &pkt, + const int nonemptymgi, const Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, // NOLINT(misc-unused-parameters) MacroAtomState &mastate, const double tau_rnd, const double nu_cmf_abort, const double d_nu_on_d_l, const double doppler) -> std::tuple { @@ -222,7 +215,7 @@ auto get_event_expansion_opacity( // with thermalisation, we don't keep track of line interactions auto next_trans = RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0. ? -1 : pkt.next_trans; - assert_always(globals::cellcache[cellcacheslotid].cellnumber == modelgridindex); + assert_always(globals::cellcache[cellcacheslotid].nonemptymgi == nonemptymgi); double dist = 0.; double tau = 0.; auto binindex_start = static_cast(((1e8 * CLIGHT / nu_cmf) - expopac_lambdamin) / expopac_deltalambda); @@ -239,7 +232,7 @@ auto get_event_expansion_opacity( double chi_bb_expansionopac = 0.; if (binindex >= 0) { const auto kappa = expansionopacities[(nonemptymgi * expopac_nbins) + binindex]; - chi_bb_expansionopac = kappa * grid::get_rho(modelgridindex) * doppler; + chi_bb_expansionopac = kappa * grid::get_rho(nonemptymgi) * doppler; } const double chi_tot = chi_cont + chi_bb_expansionopac; @@ -264,7 +257,7 @@ auto get_event_expansion_opacity( double edist_after_bin = 0.; bool event_is_boundbound = false; std::tie(edist_after_bin, next_trans, event_is_boundbound) = - get_event(modelgridindex, pkt_bin_start, chi_rpkt_cont, mastate, tau_rnd - tau, + get_event(nonemptymgi, pkt_bin_start, chi_rpkt_cont, mastate, tau_rnd - tau, std::numeric_limits::max(), 0., d_nu_on_d_l, doppler, globals::linelist, globals::nlines); // assert_always(edist_after_bin <= 1.1 * binedgedist); dist = dist + edist_after_bin; @@ -420,7 +413,7 @@ void electron_scatter_rpkt(Packet &pkt) { pkt.e_rf = pkt.e_cmf / dopplerfactor; } -void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const int modelgridindex) { +void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, const int nonemptymgi) { const double nu = pkt.nu_cmf; const double dopplerfactor = calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); @@ -498,7 +491,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch // 1, 0, ion, level); printout("[debug] rpkt_event: bound-free: nu_edge %g, nu %g\n", nu_edge, nu); if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats_contabsorption(pkt, modelgridindex, element, ion); + stats::increment_ion_stats_contabsorption(pkt, nonemptymgi, element, ion); } // and decide whether we go to ionisation energy @@ -508,7 +501,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch pkt.last_event = 3; if constexpr (TRACK_ION_STATS) { - stats::increment_ion_stats(modelgridindex, element, ion + 1, stats::ION_MACROATOM_ENERGYIN_PHOTOION, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion + 1, stats::ION_MACROATOM_ENERGYIN_PHOTOION, pkt.e_cmf); } pkt.type = TYPE_MA; @@ -531,7 +524,7 @@ void rpkt_event_continuum(Packet &pkt, const Rpkt_continuum_absorptioncoeffs &ch } // handle bound-bound transition and activate macro-atom in corresponding upper-level -void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const int mgi) { +void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const int nonemptymgi) { stats::increment(stats::COUNTER_MA_STAT_ACTIVATION_BB); stats::increment(stats::COUNTER_INTERACTIONS); pkt.last_event = 1; @@ -544,13 +537,13 @@ void rpkt_event_boundbound(Packet &pkt, const MacroAtomState &pktmastate, const if constexpr (TRACK_ION_STATS) { const int element = pktmastate.element; const int ion = pktmastate.ion; - stats::increment_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_RADEXC, pkt.e_cmf); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_RADEXC, pkt.e_cmf); const int et = pkt.emissiontype; if (et >= 0) { const int emissionelement = globals::linelist[et].elementindex; const int emissionion = globals::linelist[et].ionindex; - stats::increment_ion_stats(mgi, emissionelement, emissionion, stats::ION_BOUNDBOUND_ABSORBED, + stats::increment_ion_stats(nonemptymgi, emissionelement, emissionion, stats::ION_BOUNDBOUND_ABSORBED, pkt.e_cmf / H / pkt.nu_cmf); } } @@ -623,9 +616,7 @@ void update_estimators(const double e_cmf, const double nu_cmf, const double dis // Update an r-packet and return true if no mgi change (or it goes into an empty cell) and no pkttype change and not // reached end of timestep, otherwise false auto do_rpkt_step(Packet &pkt, const double t2) -> bool { - const int cellindex = pkt.where; - const int mgi = grid::get_cell_modelgridindex(cellindex); - const int nonemptymgi = (mgi != grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); MacroAtomState pktmastate{}; @@ -649,7 +640,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { .ffescat = NAN, .ffheat = NAN, .bf = NAN, - .modelgridindex = -1, + .nonemptymgi = -1, .timestep = -1, .phixslist = &phixslist, }; @@ -665,10 +656,9 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { if (sdist == 0) { grid::change_cell(pkt, snext); - const int cellindexnew = pkt.where; - const int newmgi = grid::get_cell_modelgridindex(cellindexnew); + const int new_nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); - return (pkt.type == TYPE_RPKT && (newmgi == grid::get_npts_model() || newmgi == mgi)); + return (pkt.type == TYPE_RPKT && (new_nonemptymgi < 0 || new_nonemptymgi == nonemptymgi)); } const double maxsdist = (GRID_TYPE == GridType::CARTESIAN3D) ? globals::rmax * pkt.prop_time / globals::tmin @@ -717,7 +707,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { // Get distance to the next physical event (continuum or bound-bound) double edist = -1; bool event_is_boundbound = true; - const bool thickcell = grid::modelgrid[mgi].thick == 1; + const bool thickcell = (nonemptymgi >= 0) && (grid::modelgrid[nonemptymgi].thick == 1); if (nonemptymgi < 0) { // for empty cells no physical event occurs. The packets just propagate. edist = std::numeric_limits::max(); @@ -725,13 +715,13 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { } else if (thickcell) [[unlikely]] { // In the case of optically thick cells, we treat the packets in grey approximation to speed up the calculation - const double chi_grey = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * + const double chi_grey = grid::get_kappagrey(nonemptymgi) * grid::get_rho(nonemptymgi) * calculate_doppler_nucmf_on_nurf(pkt.pos, pkt.dir, pkt.prop_time); edist = tau_next / chi_grey; pkt.next_trans = -1; } else { - calculate_chi_rpkt_cont(pkt.nu_cmf, chi_rpkt_cont, mgi); + calculate_chi_rpkt_cont(pkt.nu_cmf, chi_rpkt_cont, nonemptymgi); // for USE_RELATIVISTIC_DOPPLER_SHIFT, we will use a linear approximation for // the frequency change from start to abort (cell boundary/timestep end) @@ -742,11 +732,11 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { if constexpr (EXPANSIONOPACITIES_ON) { std::tie(edist, pkt.next_trans, event_is_boundbound) = get_event_expansion_opacity( - mgi, nonemptymgi, pkt, chi_rpkt_cont, pktmastate, tau_next, nu_cmf_abort, d_nu_on_d_l, doppler); + nonemptymgi, pkt, chi_rpkt_cont, pktmastate, tau_next, nu_cmf_abort, d_nu_on_d_l, doppler); } else { std::tie(edist, pkt.next_trans, event_is_boundbound) = - get_event(mgi, pkt, chi_rpkt_cont, pktmastate, tau_next, abort_dist, nu_cmf_abort, d_nu_on_d_l, doppler, - globals::linelist, globals::nlines); + get_event(nonemptymgi, pkt, chi_rpkt_cont, pktmastate, tau_next, abort_dist, nu_cmf_abort, d_nu_on_d_l, + doppler, globals::linelist, globals::nlines); } } assert_always(edist >= 0); @@ -759,16 +749,15 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { } move_pkt_withtime(pkt, sdist / 2.); - int newmgi = mgi; + int new_nonemptymgi = nonemptymgi; if (snext != pkt.where) { grid::change_cell(pkt, snext); - const int cellindexnew = pkt.where; - newmgi = grid::get_cell_modelgridindex(cellindexnew); + new_nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); } pkt.last_event = pkt.last_event + 100; - return (pkt.type == TYPE_RPKT && (newmgi == grid::get_npts_model() || newmgi == mgi)); + return (pkt.type == TYPE_RPKT && (new_nonemptymgi < 0 || new_nonemptymgi == nonemptymgi)); } if ((edist <= sdist) && (edist <= tdist)) [[likely]] { @@ -782,7 +771,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { rpkt_event_thickcell(pkt); } else if (event_is_boundbound) { if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY < 0.) { - rpkt_event_boundbound(pkt, pktmastate, mgi); + rpkt_event_boundbound(pkt, pktmastate, nonemptymgi); } else { // Probability based thermalisation (i.e. redistibution of the packet frequency) or scattering if (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 1. || @@ -793,7 +782,7 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { rpkt_event_thickcell(pkt); } } else { - rpkt_event_continuum(pkt, chi_rpkt_cont, mgi); + rpkt_event_continuum(pkt, chi_rpkt_cont, nonemptymgi); } return (pkt.type == TYPE_RPKT); @@ -818,30 +807,30 @@ auto do_rpkt_step(Packet &pkt, const double t2) -> bool { std::abort(); } -auto calculate_chi_ffheat_nnionpart(const int modelgridindex) -> double { +auto calculate_chi_ffheat_nnionpart(const int nonemptymgi) -> double { const double g_ff = 1; double chi_ff_nnionpart = 0.; const int nelements = get_nelements(); for (int element = 0; element < nelements; element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { - const double nnion = get_nnion(modelgridindex, element, ion); + const double nnion = get_nnion(nonemptymgi, element, ion); const int ioncharge = get_ionstage(element, ion) - 1; chi_ff_nnionpart += ioncharge * ioncharge * g_ff * nnion; } } - const auto T_e = grid::get_Te(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); return chi_ff_nnionpart * 3.69255e8 / sqrt(T_e); } -auto get_chi_ff_nnionpart(const int modelgridindex) -> double { - if (!use_cellcache || globals::cellcache[cellcacheslotid].cellnumber != modelgridindex) { - return calculate_chi_ffheat_nnionpart(modelgridindex); +auto get_chi_ff_nnionpart(const int nonemptymgi) -> double { + if (!use_cellcache || globals::cellcache[cellcacheslotid].nonemptymgi != nonemptymgi) { + return calculate_chi_ffheat_nnionpart(nonemptymgi); } if (globals::cellcache[cellcacheslotid].chi_ff_nnionpart < 0.) { - globals::cellcache[cellcacheslotid].chi_ff_nnionpart = calculate_chi_ffheat_nnionpart(modelgridindex); + globals::cellcache[cellcacheslotid].chi_ff_nnionpart = calculate_chi_ffheat_nnionpart(nonemptymgi); } return globals::cellcache[cellcacheslotid].chi_ff_nnionpart; @@ -849,12 +838,12 @@ auto get_chi_ff_nnionpart(const int modelgridindex) -> double { // calculate the free-free absorption (to kpkt heating) coefficient [cm^-1] // = kappa(free-free) * nne -auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> double { +auto calculate_chi_ffheating(const int nonemptymgi, const double nu) -> double { assert_always(nu > 0.); - const auto nne = grid::get_nne(modelgridindex); - const auto T_e = grid::get_Te(modelgridindex); - const double chi_ff = get_chi_ff_nnionpart(modelgridindex) * pow(nu, -3) * nne * (1 - exp(-HOVERKB * nu / T_e)); + const auto nne = grid::get_nne(nonemptymgi); + const auto T_e = grid::get_Te(nonemptymgi); + const double chi_ff = get_chi_ff_nnionpart(nonemptymgi) * pow(nu, -3) * nne * (1 - exp(-HOVERKB * nu / T_e)); assert_testmodeonly(std::isfinite(chi_ff)); @@ -863,7 +852,7 @@ auto calculate_chi_ffheating(const int modelgridindex, const double nu) -> doubl // get bound-free opacity template -auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phixslist *phixslist) -> double { +auto calculate_chi_bf_gammacontr(const int nonemptymgi, const double nu, Phixslist *phixslist) -> double { assert_always(!USECELLHISTANDUPDATEPHIXSLIST || phixslist != nullptr); double chi_bf_sum = 0.; @@ -873,9 +862,9 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix } } - const auto T_e = grid::get_Te(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); - const auto nnetot = grid::get_nnetot(modelgridindex); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); + const auto nnetot = grid::get_nnetot(nonemptymgi); const auto &allcont_nu_edge = globals::allcont_nu_edge; // The phixslist is sorted by nu_edge in ascending order (longest to shortest wavelength) @@ -924,11 +913,11 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix // the involved atomic species const bool should_keep_this_cont = USECELLHISTANDUPDATEPHIXSLIST ? globals::cellcache[cellcacheslotid].ch_keep_this_cont[i] - : keep_this_cont(element, ion, level, modelgridindex, nnetot); + : keep_this_cont(element, ion, level, nonemptymgi, nnetot); if (should_keep_this_cont) [[likely]] { const double nnlevel = USECELLHISTANDUPDATEPHIXSLIST ? globals::cellcache[cellcacheslotid].ch_allcont_nnlevel[i] - : calculate_levelpop(modelgridindex, element, ion, level); + : calculate_levelpop(nonemptymgi, element, ion, level); if (USECELLHISTANDUPDATEPHIXSLIST || nnlevel > 0) { const double nu_edge = allcont[i].nu_edge; @@ -940,8 +929,8 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix if (!USECELLHISTANDUPDATEPHIXSLIST || departure_ratio < 0) { const int upper = allcont[i].upperlevel; const double nnupperionlevel = USECELLHISTANDUPDATEPHIXSLIST - ? get_levelpop(modelgridindex, element, ion + 1, upper) - : calculate_levelpop(modelgridindex, element, ion + 1, upper); + ? get_levelpop(nonemptymgi, element, ion + 1, upper) + : calculate_levelpop(nonemptymgi, element, ion + 1, upper); const double sf = calculate_sahafact(element, ion, level, upper, T_e, H * nu_edge); departure_ratio = nnupperionlevel / nnlevel * nne * sf; // put that to phixslist if (USECELLHISTANDUPDATEPHIXSLIST) { @@ -982,31 +971,31 @@ auto calculate_chi_bf_gammacontr(const int modelgridindex, const double nu, Phix } // anonymous namespace void allocate_expansionopacities() { - const auto npts_nonempty = grid::get_nonempty_npts_model(); + const auto nonempty_npts_model = grid::get_nonempty_npts_model(); float *expansionopacities_data{}; double *expansionopacity_planck_cumulative_data{}; #ifdef MPI_ON std::tie(expansionopacities_data, win_expansionopacities) = - MPI_shared_malloc_keepwin(npts_nonempty * expopac_nbins); + MPI_shared_malloc_keepwin(nonempty_npts_model * expopac_nbins); #else - expansionopacities_data = static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(float))); + expansionopacities_data = static_cast(malloc(nonempty_npts_model * expopac_nbins * sizeof(float))); #endif if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { #ifdef MPI_ON std::tie(expansionopacity_planck_cumulative_data, win_expansionopacity_planck_cumulative) = - MPI_shared_malloc_keepwin(npts_nonempty * expopac_nbins); + MPI_shared_malloc_keepwin(nonempty_npts_model * expopac_nbins); #else expansionopacity_planck_cumulative_data = - static_cast(malloc(npts_nonempty * expopac_nbins * sizeof(double))); + static_cast(malloc(nonempty_npts_model * expopac_nbins * sizeof(double))); #endif } - expansionopacities = std::span(expansionopacities_data, npts_nonempty * expopac_nbins); + expansionopacities = std::span(expansionopacities_data, nonempty_npts_model * expopac_nbins); expansionopacity_planck_cumulative = std::span(expansionopacity_planck_cumulative_data, - expansionopacity_planck_cumulative_data == nullptr ? 0 : npts_nonempty * expopac_nbins); + expansionopacity_planck_cumulative_data == nullptr ? 0 : nonempty_npts_model * expopac_nbins); } // return a randomly chosen frequency with a distribution of Planck function times the expansion opacity @@ -1075,20 +1064,19 @@ __host__ __device__ void emit_rpkt(Packet &pkt) { } void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, - const int modelgridindex) { - assert_testmodeonly(modelgridindex != grid::get_npts_model()); - assert_testmodeonly(grid::modelgrid[modelgridindex].thick != 1); - if ((modelgridindex == chi_rpkt_cont.modelgridindex) && (globals::timestep == chi_rpkt_cont.timestep) && + const int nonemptymgi) { + assert_testmodeonly(grid::modelgrid[nonemptymgi].thick != 1); + if ((nonemptymgi == chi_rpkt_cont.nonemptymgi) && (globals::timestep == chi_rpkt_cont.timestep) && (fabs((chi_rpkt_cont.nu / nu_cmf) - 1.0) < 1e-4)) { // calculated values are a match already return; } - const auto nne = grid::get_nne(modelgridindex); + const auto nne = grid::get_nne(nonemptymgi); double chi_escat = 0.; // free-free absorption - const double chi_ff = calculate_chi_ffheating(modelgridindex, nu_cmf); + const double chi_ff = calculate_chi_ffheating(nonemptymgi, nu_cmf); double chi_bf = 0.; if (globals::opacity_case >= 4) { @@ -1097,8 +1085,8 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff // Third contribution: bound-free absorption chi_bf = chi_rpkt_cont.phixslist != nullptr - ? calculate_chi_bf_gammacontr(modelgridindex, nu_cmf, chi_rpkt_cont.phixslist) - : calculate_chi_bf_gammacontr(modelgridindex, nu_cmf, nullptr); + ? calculate_chi_bf_gammacontr(nonemptymgi, nu_cmf, chi_rpkt_cont.phixslist) + : calculate_chi_bf_gammacontr(nonemptymgi, nu_cmf, nullptr); } else { // in the other cases chi_grey is an mass absorption coefficient @@ -1112,7 +1100,7 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff chi_bf = 0.; } - chi_rpkt_cont.modelgridindex = modelgridindex; + chi_rpkt_cont.nonemptymgi = nonemptymgi; chi_rpkt_cont.timestep = globals::timestep; chi_rpkt_cont.nu = nu_cmf; chi_rpkt_cont.ffescat = chi_escat; @@ -1124,7 +1112,8 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff printout("[fatal] calculate_chi_rpkt_cont: resulted in non-finite chi_rpkt_cont.total ... abort\n"); printout("[fatal] es %g, ff %g, bf %g\n", chi_rpkt_cont.ffescat, chi_rpkt_cont.ffheat, chi_rpkt_cont.bf); printout("[fatal] nbfcontinua %d\n", globals::nbfcontinua); - printout("[fatal] in cell %d with density %g\n", modelgridindex, grid::get_rho(modelgridindex)); + printout("[fatal] in cell %d with density %g\n", grid::get_mgi_of_nonemptymgi(nonemptymgi), + grid::get_rho(nonemptymgi)); printout("[fatal] pkt.nu_cmf %g\n", nu_cmf); if (std::isfinite(chi_rpkt_cont.ffescat)) { chi_rpkt_cont.ffheat = 0.; @@ -1153,12 +1142,12 @@ void MPI_Bcast_binned_opacities(const ptrdiff_t nonemptymgi, const int root_node } #endif -void calculate_expansion_opacities(const int modelgridindex) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - const auto rho = grid::get_rho(modelgridindex); +void calculate_expansion_opacities(const int nonemptymgi) { + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); + const auto rho = grid::get_rho(nonemptymgi); const auto sys_time_start_calc = std::time(nullptr); - const auto temperature = grid::get_TR(modelgridindex); + const auto temperature = grid::get_TR(nonemptymgi); printout("calculating expansion opacities for cell %d...", modelgridindex); @@ -1183,7 +1172,7 @@ void calculate_expansion_opacities(const int modelgridindex) { const auto delta_nu = nu_upper - nu_lower; while (lineindex < globals::nlines && globals::linelist[lineindex].nu >= nu_lower) { - const float tau_line = get_tau_sobolev(modelgridindex, lineindex, t_mid, false); + const float tau_line = get_tau_sobolev(nonemptymgi, lineindex, t_mid); const auto linelambda = 1e8 * CLIGHT / globals::linelist[lineindex].nu; bin_linesum += (linelambda / expopac_deltalambda) * -std::expm1(-tau_line); lineindex++; @@ -1195,9 +1184,9 @@ void calculate_expansion_opacities(const int modelgridindex) { if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { // thread_local Rpkt_continuum_absorptioncoeffs chi_rpkt_cont {}; - // calculate_chi_rpkt_cont(nu_mid, chi_rpkt_cont, nullptr, modelgridindex); + // calculate_chi_rpkt_cont(nu_mid, chi_rpkt_cont, nullptr, nonemptymgi); // const auto bin_kappa_cont = chi_rpkt_cont.total / rho; - const auto bin_kappa_cont = calculate_chi_ffheating(modelgridindex, nu_mid) / rho; + const auto bin_kappa_cont = calculate_chi_ffheating(nonemptymgi, nu_mid) / rho; const auto planck_val = radfield::dbb(nu_mid, temperature, 1); const auto kappa_planck = (bin_kappa_bb + bin_kappa_cont) * planck_val; diff --git a/rpkt.h b/rpkt.h index 634a0e14a..bf0465702 100644 --- a/rpkt.h +++ b/rpkt.h @@ -22,7 +22,7 @@ struct Rpkt_continuum_absorptioncoeffs { double ffescat{0.}; double ffheat{0.}; double bf{0.}; - int modelgridindex{-1}; + int nonemptymgi{-1}; int timestep{-1}; Phixslist *phixslist{nullptr}; }; @@ -33,10 +33,10 @@ struct Rpkt_continuum_absorptioncoeffs { void do_rpkt(Packet &pkt, double t2); void emit_rpkt(Packet &pkt); -void calculate_chi_rpkt_cont(double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, int modelgridindex); +void calculate_chi_rpkt_cont(double nu_cmf, Rpkt_continuum_absorptioncoeffs &chi_rpkt_cont, int nonemptymgi); [[nodiscard]] auto sample_planck_times_expansion_opacity(int nonemptymgi) -> double; void allocate_expansionopacities(); -void calculate_expansion_opacities(int modelgridindex); +void calculate_expansion_opacities(int nonemptymgi); void MPI_Bcast_binned_opacities(ptrdiff_t nonemptymgi, int root_node_id); [[nodiscard]] constexpr auto get_linedistance(const double prop_time, const double nu_cmf, const double nu_trans, @@ -112,12 +112,12 @@ constexpr auto closest_transition(const double nu_cmf, const int next_trans, con return (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; } -inline auto keep_this_cont(int element, const int ion, const int level, const int modelgridindex, const float nnetot) +inline auto keep_this_cont(int element, const int ion, const int level, const int nonemptymgi, const float nnetot) -> bool { if constexpr (DETAILED_BF_ESTIMATORS_ON) { - return grid::get_elem_abundance(modelgridindex, element) > 0; + return grid::get_elem_abundance(nonemptymgi, element) > 0; } - return ((get_nnion(modelgridindex, element, ion) / nnetot > 1.e-6) || (level == 0)); + return ((get_nnion(nonemptymgi, element, ion) / nnetot > 1.e-6) || (level == 0)); } #endif // RPKT_H diff --git a/sn3d.cc b/sn3d.cc index 359aa902a..3c08e6625 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -228,7 +228,7 @@ void mpi_communicate_grid_properties() { radfield::do_MPI_Bcast(nonemptymgi, root, root_node_id); - nonthermal::nt_MPI_Bcast(nonemptymgi, root, root_node_id); + nonthermal::nt_MPI_Bcast(nonemptymgi, root_node_id); if (globals::total_nlte_levels > 0 && globals::rank_in_node == 0) { MPI_Bcast(&grid::nltepops_allcells[nonemptymgi * globals::total_nlte_levels], globals::total_nlte_levels, @@ -249,8 +249,8 @@ void mpi_communicate_grid_properties() { } if (globals::rank_in_node == 0) { - MPI_Bcast(&grid::modelgrid[grid::get_mgi_of_nonemptymgi(nonemptymgi)], sizeof(grid::ModelGridCell), MPI_BYTE, - root_node_id, globals::mpi_comm_internode); + MPI_Bcast(&grid::modelgrid[nonemptymgi], sizeof(grid::ModelGridCell), MPI_BYTE, root_node_id, + globals::mpi_comm_internode); } MPI_Bcast_binned_opacities(nonemptymgi, root_node_id); @@ -522,8 +522,7 @@ void zero_estimators() { radfield::zero_estimators(); if constexpr (TRACK_ION_STATS) { for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - stats::reset_ion_stats(modelgridindex); + stats::reset_ion_stats(nonemptymgi); } } diff --git a/sn3d.h b/sn3d.h index d7431f563..bce2780d7 100644 --- a/sn3d.h +++ b/sn3d.h @@ -36,12 +36,6 @@ #ifdef STDPAR_ON #include -// #ifndef __cpp_lib_execution -// // homebrew llvm doesn't support execution policy yet, so brew install onedpl tbb -// #include -// #include -// #endif - #define EXEC_PAR_UNSEQ std::execution::par_unseq, #define EXEC_PAR std::execution::par, #else @@ -129,7 +123,7 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f #define __artis_assert(e) \ { \ const bool assertpass = static_cast(e); \ - if (!assertpass) { \ + if (!assertpass) [[unlikely]] { \ if (output_file) { \ output_file << "\n[rank " << globals::my_rank << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ @@ -137,10 +131,10 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f } \ std::cerr << "\n[rank " << globals::my_rank << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ - std::abort(); \ } \ assert(assertpass); \ } + #endif #define assert_always(e) __artis_assert(e) @@ -377,4 +371,11 @@ template return std::span(MPI_shared_malloc(num_allranks), num_allranks); } +template +void resize_exactly(std::vector &vec, const ptrdiff_t size) { + // just resizing can (only with libstdc++?) allocate a larger capacity than needed + vec.reserve(size); + vec.resize(size); +} + #endif // SN3D_H diff --git a/stats.cc b/stats.cc index 4784986aa..8c6d8a9b6 100644 --- a/stats.cc +++ b/stats.cc @@ -31,11 +31,11 @@ std::array eventstats{}; void init() { if constexpr (TRACK_ION_STATS) { - ionstats.resize(grid::get_npts_model() * get_includedions() * ION_STAT_COUNT, 0.); + ionstats.resize(static_cast(grid::get_nonempty_npts_model()) * get_includedions() * ION_STAT_COUNT, 0.); } } -void increment_ion_stats(const int modelgridindex, const int element, const int ion, enum ionstattypes ionstattype, +void increment_ion_stats(const int nonemptymgi, const int element, const int ion, enum ionstattypes ionstattype, const double increment) { if (ionstattype >= 18) { return; @@ -45,40 +45,40 @@ void increment_ion_stats(const int modelgridindex, const int element, const int assert_testmodeonly(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - atomicadd(ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + - ionstattype], + atomicadd(ionstats[(static_cast(nonemptymgi) * get_includedions() * ION_STAT_COUNT) + + (uniqueionindex * ION_STAT_COUNT) + ionstattype], increment); } -void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridindex, const int element, const int ion) { +void increment_ion_stats_contabsorption(const Packet &pkt, const int nonemptymgi, const int element, const int ion) { const double n_photons_absorbed = pkt.e_cmf / H / pkt.nu_cmf; - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION, n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION, n_photons_absorbed); const int et = pkt.emissiontype; if (et >= 0) { // r-packet is from bound-bound emission - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUND, n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUND, n_photons_absorbed); const int emissionelement = globals::linelist[et].elementindex; const int emissionion = globals::linelist[et].ionindex; - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_BOUNDBOUND_ABSORBED, n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_BOUNDBOUND_ABSORBED, n_photons_absorbed); if (emissionelement == element) { if (emissionion == ion + 1) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSONE, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSONE, n_photons_absorbed); } else if (emissionion == ion + 2) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTWO, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTWO, n_photons_absorbed); } else if (emissionion == ion + 3) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTHREE, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTHREE, n_photons_absorbed); } } } else if (et != EMTYPE_FREEFREE && et != EMTYPE_NOTSET) { // r-pkt is from bound-free emission (not free-free scattering) - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE, n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE, n_photons_absorbed); const int bfindex = (-1 * et) - 1; assert_always(bfindex >= 0); @@ -88,71 +88,67 @@ void increment_ion_stats_contabsorption(const Packet &pkt, const int modelgridin const int emissionupperion = emissionlowerion + 1; const int emissionlowerlevel = globals::bflist[bfindex].levelindex; - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_RADRECOMB_ABSORBED, n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_ABSORBED, n_photons_absorbed); if (emissionelement == element) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBFSAMEELEMENT, - n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFSAMEELEMENT, n_photons_absorbed); if (emissionupperion == ion + 1) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSONE, - n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSONE, n_photons_absorbed); } else if (emissionupperion == ion + 2) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTWO, - n_photons_absorbed); + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTWO, n_photons_absorbed); } else if (emissionupperion == ion + 3) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTHREE, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTHREE, n_photons_absorbed); } } if (level_isinsuperlevel(emissionelement, emissionlowerion, emissionlowerlevel)) { - stats::increment_ion_stats(modelgridindex, element, ion, stats::ION_PHOTOION_FROMBFLOWERSUPERLEVEL, + stats::increment_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFLOWERSUPERLEVEL, n_photons_absorbed); } } } -auto get_ion_stats(const int modelgridindex, const int element, const int ion, enum ionstattypes ionstattype) - -> double { +auto get_ion_stats(const int nonemptymgi, const int element, const int ion, enum ionstattypes ionstattype) -> double { assert_always(ion < get_nions(element)); assert_always(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - return ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + + return ionstats[(nonemptymgi * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + ionstattype]; } -void set_ion_stats(const int modelgridindex, const int element, const int ion, enum ionstattypes ionstattype, +void set_ion_stats(const int nonemptymgi, const int element, const int ion, enum ionstattypes ionstattype, const double newvalue) { assert_always(ion < get_nions(element)); assert_always(ionstattype < ION_STAT_COUNT); const int uniqueionindex = get_uniqueionindex(element, ion); - ionstats[(modelgridindex * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + ionstattype] = + ionstats[(nonemptymgi * get_includedions() * ION_STAT_COUNT) + (uniqueionindex * ION_STAT_COUNT) + ionstattype] = newvalue; } -void reset_ion_stats(int modelgridindex) { +void reset_ion_stats(int nonemptymgi) { for (int element = 0; element < get_nelements(); element++) { for (int ion = 0; ion < get_nions(element); ion++) { for (int i = 0; i < ION_STAT_COUNT; i++) { - set_ion_stats(modelgridindex, element, ion, static_cast(i), 0.); + set_ion_stats(nonemptymgi, element, ion, static_cast(i), 0.); } } } } -void normalise_ion_estimators(const int mgi, const double deltat, const double deltaV) { +void normalise_ion_estimators(const int nonemptymgi, const double deltat, const double deltaV) { for (int element = 0; element < get_nelements(); element++) { for (int ion = 0; ion < get_nions(element); ion++) { for (int i = 0; i < ION_STAT_COUNT; i++) { // energy or event count per volume per second - const double ratedensity = get_ion_stats(mgi, element, ion, static_cast(i)) / deltaV / - deltat / globals::nprocs; + const double ratedensity = get_ion_stats(nonemptymgi, element, ion, static_cast(i)) / + deltaV / deltat / globals::nprocs; if (i < nstatcounters_ratecoeff) { // convert photon event counters into rate coefficients - set_ion_stats(mgi, element, ion, static_cast(i), - ratedensity / get_nnion(mgi, element, ion)); + set_ion_stats(nonemptymgi, element, ion, static_cast(i), + ratedensity / get_nnion(nonemptymgi, element, ion)); } else { - set_ion_stats(mgi, element, ion, static_cast(i), ratedensity); + set_ion_stats(nonemptymgi, element, ion, static_cast(i), ratedensity); } } } diff --git a/stats.h b/stats.h index effff2caf..1bec08969 100644 --- a/stats.h +++ b/stats.h @@ -85,17 +85,17 @@ enum eventcounters { void init(); -void increment_ion_stats(int modelgridindex, int element, int ion, enum ionstattypes ionstattype, double increment); +void increment_ion_stats(int nonemptymgi, int element, int ion, enum ionstattypes ionstattype, double increment); -void increment_ion_stats_contabsorption(const Packet &pkt, int modelgridindex, int element, int ion); +void increment_ion_stats_contabsorption(const Packet &pkt, int nonemptymgi, int element, int ion); -[[nodiscard]] auto get_ion_stats(int modelgridindex, int element, int ion, enum ionstattypes ionstattype) -> double; +[[nodiscard]] auto get_ion_stats(int nonemptymgi, int element, int ion, enum ionstattypes ionstattype) -> double; -void set_ion_stats(int modelgridindex, int element, int ion, enum ionstattypes ionstattype, double newvalue); +void set_ion_stats(int nonemptymgi, int element, int ion, enum ionstattypes ionstattype, double newvalue); -void reset_ion_stats(int modelgridindex); +void reset_ion_stats(int nonemptymgi); -void normalise_ion_estimators(int mgi, double deltat, double deltaV); +void normalise_ion_estimators(int nonemptymgi, double deltat, double deltaV); void increment(enum eventcounters); diff --git a/thermalbalance.cc b/thermalbalance.cc index bbbae2675..3b7417bfe 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -25,16 +25,16 @@ namespace { -struct Te_solution_paras { +struct TeSolutionParams { double t_current; - int modelgridindex; + int nonemptymgi; HeatingCoolingRates *heatingcoolingrates; const std::vector *bfheatingcoeffs; }; -struct gsl_integral_paras_bfheating { +struct BFHeatingIntegralParams { double nu_edge; - int modelgridindex; + int nonemptymgi; float T_R; const float *photoion_xs; }; @@ -42,20 +42,20 @@ struct gsl_integral_paras_bfheating { auto integrand_bfheatingcoeff_custom_radfield(const double nu, void *const voidparas) -> double // Integrand to calculate the rate coefficient for bfheating using gsl integrators. { - const auto *const params = static_cast(voidparas); + const auto *const params = static_cast(voidparas); - const int modelgridindex = params->modelgridindex; + const int nonemptymgi = params->nonemptymgi; const double nu_edge = params->nu_edge; const float T_R = params->T_R; // const double Te_TR_factor = params->Te_TR_factor; // = sqrt(T_e/T_R) * sahafac(Te) / sahafac(TR) const float sigma_bf = photoionization_crosssection_fromtable(params->photoion_xs, nu_edge, nu); - // const auto T_e = grid::get_Te(modelgridindex); - // return sigma_bf * (1 - nu_edge/nu) * radfield::radfield(nu,modelgridindex) * (1 - Te_TR_factor * exp(-HOVERKB * nu + // const auto T_e = grid::get_Te(nonemptymgi); + // return sigma_bf * (1 - nu_edge/nu) * radfield::radfield(nu,nonemptymgi) * (1 - Te_TR_factor * exp(-HOVERKB * nu // / T_e)); - return sigma_bf * (1 - nu_edge / nu) * radfield::radfield(nu, modelgridindex) * (1 - exp(-HOVERKB * nu / T_R)); + return sigma_bf * (1 - nu_edge / nu) * radfield::radfield(nu, nonemptymgi) * (1 - exp(-HOVERKB * nu / T_R)); } auto calculate_bfheatingcoeff(const int element, const int ion, const int level, const int phixstargetindex, @@ -72,15 +72,15 @@ auto calculate_bfheatingcoeff(const int element, const int ion, const int level, const double nu_threshold = ONEOVERH * E_threshold; const double nu_max_phixs = nu_threshold * last_phixs_nuovernuedge; // nu of the uppermost point in the phixs table - // const auto T_e = grid::get_Te(modelgridindex); - // const double T_R = grid::get_TR(modelgridindex); + // const auto T_e = grid::get_Te(nonemptymgi); + // const double T_R = grid::get_TR(nonemptymgi); // const double sf_Te = calculate_sahafact(element,ion,level,upperionlevel,T_e,E_threshold); // const double sf_TR = calculate_sahafact(element,ion,level,upperionlevel,T_R,E_threshold); - - const gsl_integral_paras_bfheating intparas = {.nu_edge = nu_threshold, - .modelgridindex = modelgridindex, - .T_R = grid::get_TR(modelgridindex), - .photoion_xs = get_phixs_table(element, ion, level)}; + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const BFHeatingIntegralParams intparas = {.nu_edge = nu_threshold, + .nonemptymgi = nonemptymgi, + .T_R = grid::get_TR(nonemptymgi), + .photoion_xs = get_phixs_table(element, ion, level)}; // intparas.Te_TR_factor = sqrt(T_e/T_R) * sf_Te / sf_TR; @@ -105,13 +105,13 @@ auto calculate_bfheatingcoeff(const int element, const int ion, const int level, return bfheating; } -auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, const int ion, const double T_e, +auto get_heating_ion_coll_deexc(const int nonemptymgi, const int element, const int ion, const double T_e, const double nne) -> double { double C_deexc = 0.; const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); const double epsilon_level = epsilon(element, ion, level); // Collisional heating: deexcitation to same ionization stage @@ -132,7 +132,7 @@ auto get_heating_ion_coll_deexc(const int modelgridindex, const int element, con // Calculate the heating rates for a given cell. Results are returned via the elements of the heatingrates data // structure. -void calculate_heating_rates(const int modelgridindex, const double T_e, const double nne, +void calculate_heating_rates(const int nonemptymgi, const double T_e, const double nne, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { double C_deexc = 0.; @@ -144,7 +144,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d const int nions = get_nions(element); if constexpr (DIRECT_COL_HEAT) { for (int ion = 0; ion < nions; ion++) { - C_deexc += get_heating_ion_coll_deexc(modelgridindex, element, ion, T_e, nne); + C_deexc += get_heating_ion_coll_deexc(nonemptymgi, element, ion, T_e, nne); } } @@ -162,7 +162,7 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d for (int ion = 0; ion < nions - 1; ion++) { const int nbflevels = get_nlevels_ionising(element, ion); for (int level = 0; level < nbflevels; level++) { - const double nnlevel = get_levelpop(modelgridindex, element, ion, level); + const double nnlevel = get_levelpop(nonemptymgi, element, ion, level); bfheating += nnlevel * bfheatingcoeffs[get_uniquelevelindex(element, ion, level)]; } } @@ -170,7 +170,6 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d // Free-free heating (from estimators) - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); ffheating = globals::ffheatingestimator[nonemptymgi]; if constexpr (DIRECT_COL_HEAT) { @@ -186,39 +185,38 @@ void calculate_heating_rates(const int modelgridindex, const double T_e, const d // Thermal balance equation on which we have to iterate to get T_e auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { - const Te_solution_paras *const params = static_cast(paras); + const TeSolutionParams *const params = static_cast(paras); - const int modelgridindex = params->modelgridindex; + const auto nonemptymgi = params->nonemptymgi; const double t_current = params->t_current; auto *const heatingcoolingrates = params->heatingcoolingrates; // Set new T_e guess for the current cell and update populations - grid::set_Te(modelgridindex, T_e); + grid::set_Te(nonemptymgi, T_e); if constexpr (!USE_LUT_PHOTOION && !LTEPOP_EXCITATION_USE_TJ) { - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); for (int element = 0; element < get_nelements(); element++) { if (!elem_has_nlte_levels(element)) { // recalculate the Gammas using the current population estimates const int nions = get_nions(element); for (int ion = 0; ion < nions - 1; ion++) { globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] = - calculate_iongamma_per_gspop(modelgridindex, element, ion); + calculate_iongamma_per_gspop(nonemptymgi, element, ion); } } } } - calculate_ion_balance_nne(modelgridindex); - const auto nne = grid::get_nne(modelgridindex); + calculate_ion_balance_nne(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); // Then calculate heating and cooling rates - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); kpkt::calculate_cooling_rates(nonemptymgi, heatingcoolingrates); - calculate_heating_rates(modelgridindex, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); + calculate_heating_rates(nonemptymgi, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const auto ntlepton_frac_heating = nonthermal::get_nt_frac_heating(modelgridindex); - const auto ntlepton_dep = nonthermal::get_deposition_rate_density(modelgridindex); + const auto ntlepton_dep = nonthermal::get_deposition_rate_density(nonemptymgi); const auto ntalpha_frac_heating = 1.; const auto ntalpha_dep = heatingcoolingrates->dep_alpha; heatingcoolingrates->heating_dep = ntlepton_dep * ntlepton_frac_heating + ntalpha_dep * ntalpha_frac_heating; @@ -226,7 +224,7 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { (ntalpha_dep > 0) ? heatingcoolingrates->heating_dep / (ntlepton_dep + ntalpha_dep) : ntlepton_frac_heating; // Adiabatic cooling term - const double nntot = get_nnion_tot(modelgridindex) + nne; + const double nntot = get_nnion_tot(nonemptymgi) + nne; const double p = nntot * KB * T_e; // pressure in [erg/cm^3] const double volumetmin = grid::get_modelcell_assocvolume_tmin(modelgridindex); const double dV = 3 * volumetmin / pow(globals::tmin, 3) * pow(t_current, 2); // really dV/dt @@ -274,8 +272,8 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double minelfrac = 0.01; for (int element = 0; element < get_nelements(); element++) { - if (grid::get_elem_abundance(modelgridindex, element) <= minelfrac && !USE_LUT_BFHEATING) { - printout("skipping Z=%d X=%g, ", get_atomicnumber(element), grid::get_elem_abundance(modelgridindex, element)); + if (grid::get_elem_abundance(nonemptymgi, element) <= minelfrac && !USE_LUT_BFHEATING) { + printout("skipping Z=%d X=%g, ", get_atomicnumber(element), grid::get_elem_abundance(nonemptymgi, element)); } const int nions = get_nions(element); @@ -283,7 +281,7 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco const int nlevels = get_nlevels(element, ion); for (int level = 0; level < nlevels; level++) { double bfheatingcoeff = 0.; - if (grid::get_elem_abundance(modelgridindex, element) > minelfrac || USE_LUT_BFHEATING) { + if (grid::get_elem_abundance(nonemptymgi, element) > minelfrac || USE_LUT_BFHEATING) { const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { if constexpr (!USE_LUT_BFHEATING) { @@ -292,8 +290,8 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco // The correction factor for stimulated emission in gammacorr is set to its // LTE value. Because the T_e dependence of gammacorr is weak, this correction // correction may be evaluated at T_R! - const double T_R = grid::get_TR(modelgridindex); - const double W = grid::get_W(modelgridindex); + const double T_R = grid::get_TR(nonemptymgi); + const double W = grid::get_W(nonemptymgi); bfheatingcoeff += get_bfheatingcoeff_ana(element, ion, level, phixstargetindex, T_R, W); } } @@ -317,13 +315,13 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco void call_T_e_finder(const int nonemptymgi, const double t_current, const double T_min, const double T_max, HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const double T_e_old = grid::get_Te(modelgridindex); + const double T_e_old = grid::get_Te(nonemptymgi); printout("Finding T_e in cell %d at timestep %d...", modelgridindex, globals::timestep); - Te_solution_paras paras = {.t_current = t_current, - .modelgridindex = modelgridindex, - .heatingcoolingrates = heatingcoolingrates, - .bfheatingcoeffs = &bfheatingcoeffs}; + TeSolutionParams paras = {.t_current = t_current, + .nonemptymgi = nonemptymgi, + .heatingcoolingrates = heatingcoolingrates, + .bfheatingcoeffs = &bfheatingcoeffs}; gsl_function find_T_e_f = {.function = &T_e_eqn_heating_minus_cooling, .params = ¶s}; @@ -334,7 +332,7 @@ void call_T_e_finder(const int nonemptymgi, const double t_current, const double printout( "[abort request] call_T_e_finder: non-finite results in modelcell %d (T_R=%g, W=%g). T_e forced to be " "MINTEMP\n", - modelgridindex, grid::get_TR(modelgridindex), grid::get_W(modelgridindex)); + modelgridindex, grid::get_TR(nonemptymgi), grid::get_W(nonemptymgi)); thermalmax = thermalmin = -1; } @@ -376,14 +374,14 @@ void call_T_e_finder(const int nonemptymgi, const double t_current, const double printout( "[warning] call_T_e_finder: cooling bigger than heating at lower T_e boundary %g in modelcell %d " "(T_R=%g,W=%g). T_e forced to be MINTEMP\n", - MINTEMP, modelgridindex, grid::get_TR(modelgridindex), grid::get_W(modelgridindex)); + MINTEMP, modelgridindex, grid::get_TR(nonemptymgi), grid::get_W(nonemptymgi)); } else { // Thermal balance equation always negative ===> T_e = T_max T_e = MAXTEMP; printout( "[warning] call_T_e_finder: heating bigger than cooling over the whole T_e range [%g,%g] in modelcell %d " "(T_R=%g,W=%g). T_e forced to be MAXTEMP\n", - MINTEMP, MAXTEMP, modelgridindex, grid::get_TR(modelgridindex), grid::get_W(modelgridindex)); + MINTEMP, MAXTEMP, modelgridindex, grid::get_TR(nonemptymgi), grid::get_W(nonemptymgi)); } if (T_e > 2 * T_e_old) { @@ -396,7 +394,7 @@ void call_T_e_finder(const int nonemptymgi, const double t_current, const double T_e = std::max(T_e, MINTEMP); } - grid::set_Te(modelgridindex, T_e); + grid::set_Te(nonemptymgi, T_e); // this call with make sure heating/cooling rates and populations are updated for the final T_e // in case T_e got modified after the T_e solver finished diff --git a/update_grid.cc b/update_grid.cc index b302becc7..f11ace20e 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -49,8 +49,8 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti printout("writing to estimators file timestep %d cell %d...\n", timestep, mgi); - const auto T_e = grid::get_Te(mgi); - const auto nne = grid::get_nne(mgi); + const auto T_e = grid::get_Te(nonemptymgi); + const auto nne = grid::get_nne(nonemptymgi); const auto Y_e = grid::get_electronfrac(nonemptymgi); // fprintf(estimators_file,"%d %g %g %g %g %d // ",n,get_TR(n),grid::get_Te(n),get_W(n),get_TJ(n),grid::modelgrid[n].thick); fprintf(estimators_file,"%d %g %g %g @@ -58,18 +58,18 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti fprintf(estimators_file, "timestep %d modelgridindex %d titeration %d TR %g Te %g W %g TJ %g grey_depth %g thick %d nne %g Ye %g " "tdays %7.2f\n", - timestep, mgi, titer, grid::get_TR(mgi), T_e, grid::get_W(mgi), grid::get_TJ(mgi), - grid::modelgrid[mgi].grey_depth, grid::modelgrid[mgi].thick, nne, Y_e, + timestep, mgi, titer, grid::get_TR(nonemptymgi), T_e, grid::get_W(nonemptymgi), grid::get_TJ(nonemptymgi), + grid::modelgrid[nonemptymgi].grey_depth, grid::modelgrid[nonemptymgi].thick, nne, Y_e, globals::timesteps[timestep].mid / DAY); // fprintf(estimators_file,"%d %g %g %g %g %g %g %g //",n,get_TR(n),grid::get_Te(n),get_W(n),get_TJ(n),grey_optical_depth,grey_optical_deptha,compton_optical_depth); if (globals::total_nlte_levels > 0) { - nltepop_write_to_file(mgi, timestep); + nltepop_write_to_file(nonemptymgi, timestep); } for (int element = 0; element < get_nelements(); element++) { - if (grid::get_elem_abundance(mgi, element) <= 0.) { // skip elements with no abundance + if (grid::get_elem_abundance(nonemptymgi, element) <= 0.) { // skip elements with no abundance continue; } @@ -83,11 +83,11 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } double elpop = 0.; for (int ion = 0; ion < nions; ion++) { - elpop += get_nnion(mgi, element, ion); - fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), get_nnion(mgi, element, ion)); + elpop += get_nnion(nonemptymgi, element, ion); + fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), get_nnion(nonemptymgi, element, ion)); } if (nions == 0) { - elpop = grid::get_elem_numberdens(mgi, element); + elpop = grid::get_elem_numberdens(nonemptymgi, element); } fprintf(estimators_file, " SUM: %9.3e", elpop); @@ -142,7 +142,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } double ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_RADEXC); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_RADEXC); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -154,7 +154,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADDEEXC); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADDEEXC); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -166,7 +166,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLEXC); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLEXC); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -178,7 +178,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLDEEXC); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLDEEXC); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -190,7 +190,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_PHOTOION); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_PHOTOION); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -202,7 +202,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADRECOMB); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_RADRECOMB); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -214,7 +214,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLION); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_COLLION); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -226,7 +226,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLRECOMB); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_COLLRECOMB); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -238,7 +238,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_NTCOLLION); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_NTCOLLION); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -250,7 +250,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_in_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_TOTAL); + const double ma_in_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_TOTAL); ma_el += ma_in_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_in_ion); } @@ -262,7 +262,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_TOTAL); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -274,7 +274,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYIN_INTERNAL); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -286,7 +286,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } ma_el = 0.; for (int ion = 0; ion < nions; ion++) { - const double ma_ion = get_ion_stats(mgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL); + const double ma_ion = get_ion_stats(nonemptymgi, element, ion, stats::ION_MACROATOM_ENERGYOUT_INTERNAL); ma_el += ma_ion; fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), ma_ion); } @@ -332,7 +332,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // for (int ionstage = 1; ionstage < get_ionstage(element, 0); ionstage++) // fprintf(estimators_file, " "); // for (int ion = 0; ion < nions; ion++) { - // const double alpha_r_mc = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_MACROATOM); + // const double alpha_r_mc = get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_MACROATOM); // fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), alpha_r_mc); // } // fprintf(estimators_file, "\n"); @@ -343,7 +343,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // for (int ionstage = 1; ionstage < get_ionstage(element, 0); ionstage++) // fprintf(estimators_file, " "); // for (int ion = 0; ion < nions; ion++) { - // const double alpha_r_mc = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_KPKT); + // const double alpha_r_mc = get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_KPKT); // fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), alpha_r_mc); // } // fprintf(estimators_file, "\n"); @@ -355,8 +355,8 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti fprintf(estimators_file, " "); } for (int ion = 0; ion < nions; ion++) { - const double alpha_r_mc = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_MACROATOM) + - get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_KPKT); + const double alpha_r_mc = get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_MACROATOM) + + get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_KPKT); fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), alpha_r_mc); } fprintf(estimators_file, "\n"); @@ -366,9 +366,9 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti fprintf(estimators_file, " "); } for (int ion = 0; ion < nions; ion++) { - const double alpha_r_mc = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_MACROATOM) + - get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_KPKT); - const double alpha_r_mc_abs = get_ion_stats(mgi, element, ion, stats::ION_RADRECOMB_ABSORBED); + const double alpha_r_mc = get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_MACROATOM) + + get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_KPKT); + const double alpha_r_mc_abs = get_ion_stats(nonemptymgi, element, ion, stats::ION_RADRECOMB_ABSORBED); fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - (alpha_r_mc_abs / alpha_r_mc)); } fprintf(estimators_file, "\n"); @@ -378,8 +378,8 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti fprintf(estimators_file, " "); } for (int ion = 0; ion < nions; ion++) { - const double bb_emitted = get_ion_stats(mgi, element, ion, stats::ION_BOUNDBOUND_MACROATOM); - const double bb_abs = get_ion_stats(mgi, element, ion, stats::ION_BOUNDBOUND_ABSORBED); + const double bb_emitted = get_ion_stats(nonemptymgi, element, ion, stats::ION_BOUNDBOUND_MACROATOM); + const double bb_abs = get_ion_stats(nonemptymgi, element, ion, stats::ION_BOUNDBOUND_ABSORBED); fprintf(estimators_file, " %d: %9.3f", get_ionstage(element, ion), 1. - (bb_abs / bb_emitted)); } fprintf(estimators_file, "\n"); @@ -424,8 +424,8 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // const bool printdebug_gammar = false; // fprintf(estimators_file, " %d: %9.3e", // get_ionstage(element, ion), - // calculate_iongamma_per_ionpop(mgi, T_e, element, ion, assume_lte, false, printdebug_gammar, false, - // false)); + // calculate_iongamma_per_ionpop(nonemptymgi, T_e, element, ion, assume_lte, false, printdebug_gammar, + // false, false)); // } // fprintf(estimators_file, "\n"); // } @@ -438,9 +438,9 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti for (int ion = 0; ion < nions - 1; ion++) { // const bool printdebug_gammar = (get_atomicnumber(element) == 26 && get_ionstage(element, ion) == 2); const bool printdebug_gammar = false; - fprintf( - estimators_file, " %d: %9.3e", get_ionstage(element, ion), - calculate_iongamma_per_ionpop(mgi, T_e, element, ion, assume_lte, false, printdebug_gammar, false, true)); + fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), + calculate_iongamma_per_ionpop(nonemptymgi, T_e, element, ion, assume_lte, false, printdebug_gammar, + false, true)); } fprintf(estimators_file, "\n"); } @@ -454,9 +454,9 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // const bool printdebug_gammar = ((get_atomicnumber(element) == 26 || get_atomicnumber(element) == 28) && // get_ionstage(element, ion) >= 2); const bool printdebug_gammar = (get_atomicnumber(element) >= 26); const bool printdebug_gammar = false; - fprintf( - estimators_file, " %d: %9.3e", get_ionstage(element, ion), - calculate_iongamma_per_ionpop(mgi, T_e, element, ion, assume_lte, false, printdebug_gammar, true, false)); + fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), + calculate_iongamma_per_ionpop(nonemptymgi, T_e, element, ion, assume_lte, false, printdebug_gammar, + true, false)); } fprintf(estimators_file, "\n"); } @@ -468,7 +468,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION)); } fprintf(estimators_file, "\n"); } @@ -480,7 +480,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDFREE)); } fprintf(estimators_file, "\n"); } @@ -492,7 +492,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // { // fprintf(estimators_file, " %d: %9.3e", // get_ionstage(element, ion), - // get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBFSAMEELEMENT]); + // get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFSAMEELEMENT]); // } // fprintf(estimators_file, "\n"); @@ -503,7 +503,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSONE)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSONE)); } fprintf(estimators_file, "\n"); } @@ -515,7 +515,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTWO)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTWO)); } fprintf(estimators_file, "\n"); } @@ -527,7 +527,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTHREE)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFIONPLUSTHREE)); } fprintf(estimators_file, "\n"); } @@ -539,7 +539,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBFLOWERSUPERLEVEL)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBFLOWERSUPERLEVEL)); } fprintf(estimators_file, "\n"); } @@ -551,7 +551,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUND)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUND)); } fprintf(estimators_file, "\n"); } @@ -563,7 +563,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSONE)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSONE)); } fprintf(estimators_file, "\n"); } @@ -575,7 +575,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTWO)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTWO)); } fprintf(estimators_file, "\n"); } @@ -587,7 +587,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTHREE)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_PHOTOION_FROMBOUNDBOUNDIONPLUSTHREE)); } fprintf(estimators_file, "\n"); } @@ -599,7 +599,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // { // fprintf(estimators_file, " %d: %9.3e", // get_ionstage(element, ion), - // calculate_iongamma_per_ionpop(mgi, T_e, element, ion, assume_lte, true, + // calculate_iongamma_per_ionpop(nonemptymgi, T_e, element, ion, assume_lte, true, // printdebug)); // } // fprintf(estimators_file, "\n"); @@ -610,7 +610,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti fprintf(estimators_file, " "); } for (int ion = 0; ion < nions - 1; ion++) { - const double Y_nt = nonthermal::nt_ionization_ratecoeff(mgi, element, ion); + const double Y_nt = nonthermal::nt_ionization_ratecoeff(nonemptymgi, element, ion); fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), Y_nt); } fprintf(estimators_file, "\n"); @@ -622,7 +622,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } for (int ion = 0; ion < nions - 1; ion++) { fprintf(estimators_file, " %d: %9.3e", get_ionstage(element, ion), - get_ion_stats(mgi, element, ion, stats::ION_NTION)); + get_ion_stats(nonemptymgi, element, ion, stats::ION_NTION)); } fprintf(estimators_file, "\n"); } @@ -702,12 +702,12 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, const auto sys_time_start_partfuncs_or_gamma = std::time(nullptr); for (int element = 0; element < get_nelements(); element++) { if (!elem_has_nlte_levels(element)) { - calculate_cellpartfuncts(mgi, element); + calculate_cellpartfuncts(nonemptymgi, element); } } const int duration_solve_partfuncs_or_gamma = std::time(nullptr) - sys_time_start_partfuncs_or_gamma; - const double prev_T_e = grid::get_Te(mgi); + const double prev_T_e = grid::get_Te(nonemptymgi); const auto sys_time_start_Te = std::time(nullptr); // Find T_e as solution for thermal balance @@ -718,7 +718,7 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, if (globals::total_nlte_levels == 0) { const auto sys_time_start_pops = std::time(nullptr); - calculate_ion_balance_nne(mgi); + calculate_ion_balance_nne(nonemptymgi); const int duration_solve_pops = std::time(nullptr) - sys_time_start_pops; printout( @@ -729,7 +729,7 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, break; // no iteration is needed without nlte pops } - const double fracdiff_T_e = fabs((grid::get_Te(mgi) / prev_T_e) - 1); + const double fracdiff_T_e = fabs((grid::get_Te(nonemptymgi) / prev_T_e) - 1); const auto sys_time_start_nltepops = std::time(nullptr); // fractional difference between previous and current iteration's (nne or max(ground state // population change)) @@ -737,14 +737,14 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, for (int element = 0; element < get_nelements(); element++) { if (get_nions(element) > 0 && elem_has_nlte_levels(element)) { solve_nlte_pops_element(element, mgi, nts, nlte_iter); - calculate_cellpartfuncts(mgi, element); + calculate_cellpartfuncts(nonemptymgi, element); } } const int duration_solve_nltepops = std::time(nullptr) - sys_time_start_nltepops; - const double nne_prev = grid::get_nne(mgi); - calculate_ion_balance_nne(mgi); // sets nne - fracdiff_nne = fabs((grid::get_nne(mgi) / nne_prev) - 1); + const double nne_prev = grid::get_nne(nonemptymgi); + calculate_ion_balance_nne(nonemptymgi); // sets nne + fracdiff_nne = fabs((grid::get_nne(nonemptymgi) / nne_prev) - 1); printout( "NLTE solver cell %d timestep %d iteration %d: time spent on: Spencer-Fano %ds, T_e " "%ds, NLTE populations %ds\n", @@ -752,7 +752,8 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, printout( "NLTE (Spencer-Fano/Te/pops) solver cell %d timestep %d iteration %d: prev_iter nne " "%g, new nne is %g, fracdiff %g, prev T_e %g new T_e %g fracdiff %g\n", - mgi, nts, nlte_iter, nne_prev, grid::get_nne(mgi), fracdiff_nne, prev_T_e, grid::get_Te(mgi), fracdiff_T_e); + mgi, nts, nlte_iter, nne_prev, grid::get_nne(nonemptymgi), fracdiff_nne, prev_T_e, grid::get_Te(nonemptymgi), + fracdiff_T_e); if (fracdiff_nne <= convergence_tolerance && fracdiff_T_e <= convergence_tolerance) { printout( @@ -770,8 +771,7 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, } } -void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const double estimator_normfactor) { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); +void update_gamma_corrphotoionrenorm_bfheating_estimators(const int nonemptymgi, const double estimator_normfactor) { if constexpr (USE_LUT_PHOTOION) { for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); @@ -792,14 +792,15 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d #endif globals::corrphotoionrenorm[ionestimindex] = - globals::gammaestimator[ionestimindex] / get_corrphotoioncoeff_ana(element, ion, 0, 0, mgi); + globals::gammaestimator[ionestimindex] / get_corrphotoioncoeff_ana(element, ion, 0, 0, nonemptymgi); if (!std::isfinite(globals::corrphotoionrenorm[ionestimindex])) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout( "[fatal] about to set corrphotoionrenorm = NaN = gammaestimator / " "get_corrphotoioncoeff_ana(%d,%d,%d,%d,%d)=%g/%g", element, ion, 0, 0, mgi, globals::gammaestimator[ionestimindex], - get_corrphotoioncoeff_ana(element, ion, 0, 0, mgi)); + get_corrphotoioncoeff_ana(element, ion, 0, 0, nonemptymgi)); std::abort(); } } @@ -824,7 +825,7 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d const int ionestimindex = (nonemptymgi * globals::nbfcontinua_ground) + groundcontindex; if (!elem_has_nlte_levels(element)) { - globals::gammaestimator[ionestimindex] = calculate_iongamma_per_gspop(mgi, element, ion); + globals::gammaestimator[ionestimindex] = calculate_iongamma_per_gspop(nonemptymgi, element, ion); } if constexpr (USE_LUT_BFHEATING) { @@ -841,10 +842,11 @@ void update_gamma_corrphotoionrenorm_bfheating_estimators(const int mgi, const d // contributions are added up. const double bfheatingcoeff_ana = - get_bfheatingcoeff_ana(element, ion, 0, 0, grid::get_TR(mgi), grid::get_W(mgi)); + get_bfheatingcoeff_ana(element, ion, 0, 0, grid::get_TR(nonemptymgi), grid::get_W(nonemptymgi)); globals::bfheatingestimator[ionestimindex] = globals::bfheatingestimator[ionestimindex] / bfheatingcoeff_ana; if (!std::isfinite(globals::bfheatingestimator[ionestimindex])) { + const auto mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); printout( "[fatal] about to set bfheatingestimator = NaN = bfheatingestimator / " "get_bfheatingcoeff_ana(%d,%d,%d,%d,%d)=%g/%g", @@ -882,7 +884,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in printout("update_grid_cell: working on cell %d before timestep %d titeration %d...\n", mgi, nts, titer); // Update current mass density of cell - grid::set_rho(mgi, grid::get_rho_tmin(mgi) / pow(tratmid, 3)); + grid::set_rho(nonemptymgi, grid::get_rho_tmin(mgi) / pow(tratmid, 3)); // Update elemental abundances with radioactive decays decay::update_abundances(nonemptymgi, nts, globals::timesteps[nts].mid); @@ -897,14 +899,14 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in if (globals::opacity_case < 4) { // various forms of grey opacity - grid::modelgrid[mgi].thick = 1; + grid::modelgrid[nonemptymgi].thick = 1; if (globals::opacity_case == 3) { - if (grid::get_rho(mgi) > globals::rho_crit) { - grid::set_kappagrey(mgi, globals::opcase3_normal * (0.9 * grid::get_ffegrp(mgi) + 0.1) * globals::rho_crit / - grid::get_rho(mgi)); + if (grid::get_rho(nonemptymgi) > globals::rho_crit) { + grid::set_kappagrey(nonemptymgi, globals::opcase3_normal * (0.9 * grid::get_ffegrp(mgi) + 0.1) * + globals::rho_crit / grid::get_rho(nonemptymgi)); } else { - grid::set_kappagrey(mgi, globals::opcase3_normal * (0.9 * grid::get_ffegrp(mgi) + 0.1)); + grid::set_kappagrey(nonemptymgi, globals::opcase3_normal * (0.9 * grid::get_ffegrp(mgi) + 0.1)); } } } @@ -922,22 +924,22 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in // W == 1 indicates that this modelgrid cell was treated grey in the // last timestep. Therefore it has no valid Gamma estimators and must // be treated in LTE at restart. - if (grid::modelgrid[mgi].thick != 1 && grid::get_W(mgi) == 1) { + if (grid::modelgrid[nonemptymgi].thick != 1 && grid::get_W(nonemptymgi) == 1) { printout( "force modelgrid cell %d to grey/LTE thick = 1 for update grid since existing W == 1. (will not have " "gamma estimators)\n", mgi); - grid::modelgrid[mgi].thick = 1; + grid::modelgrid[nonemptymgi].thick = 1; } printout("lte_iteration %d\n", globals::lte_iteration ? 1 : 0); - printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, grid::modelgrid[mgi].thick); + printout("mgi %d modelgrid.thick: %d (during grid update)\n", mgi, grid::modelgrid[nonemptymgi].thick); for (int element = 0; element < get_nelements(); element++) { - calculate_cellpartfuncts(mgi, element); + calculate_cellpartfuncts(nonemptymgi, element); } if (!globals::simulation_continued_from_saved) { - calculate_ion_balance_nne(mgi); + calculate_ion_balance_nne(nonemptymgi); } } else { // For all other timesteps temperature corrections have to be applied @@ -950,7 +952,7 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in const auto sys_time_start_temperature_corrections = std::time(nullptr); - radfield::normalise_J(mgi, estimator_normfactor_over4pi); // this applies normalisation to the fullspec J + radfield::normalise_J(nonemptymgi, estimator_normfactor_over4pi); // this applies normalisation to the fullspec J // this stores the factor that will be applied later for the J bins but not fullspec J radfield::set_J_normfactor(nonemptymgi, estimator_normfactor_over4pi); @@ -959,18 +961,18 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in #endif if constexpr (TRACK_ION_STATS) { - stats::normalise_ion_estimators(mgi, deltat, deltaV); + stats::normalise_ion_estimators(nonemptymgi, deltat, deltaV); } // lte_iteration really means either ts 0 or nts < globals::num_lte_timesteps - if (globals::lte_iteration || grid::modelgrid[mgi].thick == 1) { + if (globals::lte_iteration || grid::modelgrid[nonemptymgi].thick == 1) { // LTE mode or grey mode (where temperature doesn't matter but is calculated anyway) - const double T_J = radfield::get_T_J_from_J(mgi); - grid::set_TR(mgi, T_J); - grid::set_Te(mgi, T_J); - grid::set_TJ(mgi, T_J); - grid::set_W(mgi, 1); + const double T_J = radfield::get_T_J_from_J(nonemptymgi); + grid::set_TR(nonemptymgi, T_J); + grid::set_Te(nonemptymgi, T_J); + grid::set_TJ(nonemptymgi, T_J); + grid::set_W(nonemptymgi, 1); if constexpr (USE_LUT_PHOTOION) { std::fill_n(globals::corrphotoionrenorm + (nonemptymgi * globals::nbfcontinua_ground), @@ -978,14 +980,14 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } for (int element = 0; element < get_nelements(); element++) { - calculate_cellpartfuncts(mgi, element); + calculate_cellpartfuncts(nonemptymgi, element); } - calculate_ion_balance_nne(mgi); + calculate_ion_balance_nne(nonemptymgi); } else { // not lte_iteration and not a thick cell - // non-LTE timesteps with T_e from heating/cooling + // non-pure-LTE timesteps with T_e from heating/cooling - radfield::normalise_nuJ(mgi, estimator_normfactor_over4pi); + radfield::normalise_nuJ(nonemptymgi, estimator_normfactor_over4pi); globals::ffheatingestimator[nonemptymgi] *= estimator_normfactor; globals::colheatingestimator[nonemptymgi] *= estimator_normfactor; @@ -995,11 +997,11 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in titer_average_estimators(mgi); #endif - update_gamma_corrphotoionrenorm_bfheating_estimators(mgi, estimator_normfactor); + update_gamma_corrphotoionrenorm_bfheating_estimators(nonemptymgi, estimator_normfactor); // Get radiation field parameters (T_J, T_R, W, and bins if enabled) out of the // full-spectrum and binned J and nuJ estimators - radfield::fit_parameters(mgi, nts); + radfield::fit_parameters(nonemptymgi, nts); solve_Te_nltepops(nonemptymgi, nts, nts_prev, heatingcoolingrates); } @@ -1007,45 +1009,46 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in std::time(nullptr) - sys_time_start_temperature_corrections); } - const float nne = grid::get_nne(mgi); + const float nne = grid::get_nne(nonemptymgi); const double compton_optical_depth = SIGMA_T * nne * grid::wid_init(mgi, 0) * tratmid; const int assoc_cells = grid::get_numpropcells(mgi); - const double radial_pos = grid::modelgrid[mgi].initial_radial_pos_sum * tratmid / assoc_cells; - const double grey_optical_deptha = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * grid::wid_init(mgi, 0) * tratmid; + const double radial_pos = grid::get_initial_radial_pos_sum(mgi) * tratmid / assoc_cells; + const double grey_optical_deptha = + grid::get_kappagrey(nonemptymgi) * grid::get_rho(nonemptymgi) * grid::wid_init(mgi, 0) * tratmid; // cube corners will have radial pos > rmax, so clamp to 0. const double dist_to_obs = std::max(0., (globals::rmax * tratmid) - radial_pos); - const double grey_optical_depth = grid::get_kappagrey(mgi) * grid::get_rho(mgi) * dist_to_obs; + const double grey_optical_depth = grid::get_kappagrey(nonemptymgi) * grid::get_rho(nonemptymgi) * dist_to_obs; printout( "modelgridcell %d, compton optical depth (/propgridcell) %g, grey optical depth " "(/propgridcell) %g\n", mgi, compton_optical_depth, grey_optical_deptha); printout("radial_pos %g, distance_to_obs %g, tau_dist %g\n", radial_pos, dist_to_obs, grey_optical_depth); - grid::modelgrid[mgi].grey_depth = grey_optical_depth; + grid::modelgrid[nonemptymgi].grey_depth = grey_optical_depth; // grey_optical_depth = compton_optical_depth; if ((grey_optical_depth >= globals::cell_is_optically_thick) && (nts < globals::num_grey_timesteps)) { printout("timestep %d cell %d is treated in grey approximation (chi_grey %g [cm2/g], tau %g >= %g)\n", nts, mgi, - grid::get_kappagrey(mgi), grey_optical_depth, globals::cell_is_optically_thick); - grid::modelgrid[mgi].thick = 1; + grid::get_kappagrey(nonemptymgi), grey_optical_depth, globals::cell_is_optically_thick); + grid::modelgrid[nonemptymgi].thick = 1; } else if (VPKT_ON && (grey_optical_depth > cell_is_optically_thick_vpkt)) { - grid::modelgrid[mgi].thick = 2; + grid::modelgrid[nonemptymgi].thick = 2; } else { - grid::modelgrid[mgi].thick = 0; + grid::modelgrid[nonemptymgi].thick = 0; } - if (grid::modelgrid[mgi].thick == 1) { + if (grid::modelgrid[nonemptymgi].thick == 1) { // cooling rates calculation can be skipped for thick cells // flag with negative numbers to indicate that the rates are invalid - grid::modelgrid[mgi].totalcooling = -1.; + grid::modelgrid[nonemptymgi].totalcooling = -1.; grid::ion_cooling_contribs_allcells[(nonemptymgi * get_includedions()) + 0] = -1.; } else if (globals::simulation_continued_from_saved && nts == globals::timestep_initial) { // cooling rates were read from the gridsave file for this timestep // make sure they are valid printout("cooling rates read from gridsave file for timestep %d cell %d...", nts, mgi); - assert_always(grid::modelgrid[mgi].totalcooling >= 0.); + assert_always(grid::modelgrid[nonemptymgi].totalcooling >= 0.); assert_always(grid::ion_cooling_contribs_allcells[(nonemptymgi * get_includedions()) + 0] >= 0.); } else { // Cooling rates depend only on cell properties, precalculate total cooling @@ -1062,8 +1065,8 @@ void update_grid_cell(const int mgi, const int nts, const int nts_prev, const in } if constexpr (EXPANSIONOPACITIES_ON || RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY > 0.) { - if (grid::modelgrid[mgi].thick != 1) { - calculate_expansion_opacities(mgi); + if (grid::modelgrid[nonemptymgi].thick != 1) { + calculate_expansion_opacities(nonemptymgi); } } @@ -1102,7 +1105,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const // nts_prev is the previous timestep, unless this is timestep zero const double deltat = globals::timesteps[nts_prev].width; - cellcache_change_cell(-99); + cellcache_change_cell(-1); // Do not use values which are saved in the cellcache within update_grid use_cellcache = false; @@ -1169,17 +1172,17 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const std::time(nullptr) - time_update_grid_end_thisrank, std::time(nullptr) - sys_time_start_update_grid); } -void cellcache_change_cell(const int modelgridindex) { +void cellcache_change_cell(const int nonemptymgi) { // All entries of the cellcache stack must be flagged as empty at the // onset of the new timestep. Also, boundary crossing? // Calculate the level populations for this cell, and flag the other entries // as empty. auto &cacheslot = globals::cellcache[cellcacheslotid]; - if (modelgridindex == cacheslot.cellnumber) { + if (nonemptymgi == cacheslot.nonemptymgi) { return; } - cacheslot.cellnumber = modelgridindex; + cacheslot.nonemptymgi = nonemptymgi; cacheslot.chi_ff_nnionpart = -1.; const int nelements = get_nelements(); @@ -1190,14 +1193,14 @@ void cellcache_change_cell(const int modelgridindex) { .cooling_contrib[kpkt::get_coolinglistoffset(element, ion) + kpkt::get_ncoolingterms_ion(element, ion) - 1] = COOLING_UNDEFINED; - if (modelgridindex >= 0) { + if (nonemptymgi >= 0) { const int nlevels = get_nlevels(element, ion); auto &chion = cacheslot.chelements[element].chions[ion]; #ifdef _OPENMP #pragma omp parallel for #endif for (int level = 0; level < nlevels; level++) { - chion.chlevels[level].population = calculate_levelpop(modelgridindex, element, ion, level); + chion.chlevels[level].population = calculate_levelpop(nonemptymgi, element, ion, level); } } } @@ -1221,17 +1224,17 @@ void cellcache_change_cell(const int modelgridindex) { } } - if (modelgridindex >= 0) { + if (nonemptymgi >= 0) { std::ranges::fill(cacheslot.ch_allcont_departureratios, -1.); - const auto nnetot = grid::get_nnetot(modelgridindex); + const auto nnetot = grid::get_nnetot(nonemptymgi); for (int i = 0; i < globals::nbfcontinua; i++) { const int element = globals::allcont[i].element; const int ion = globals::allcont[i].ion; const int level = globals::allcont[i].level; - const auto nnlevel = get_levelpop(modelgridindex, element, ion, level); + const auto nnlevel = get_levelpop(nonemptymgi, element, ion, level); cacheslot.ch_allcont_nnlevel[i] = nnlevel; - cacheslot.ch_keep_this_cont[i] = nnlevel > 0 && keep_this_cont(element, ion, level, modelgridindex, nnetot); + cacheslot.ch_keep_this_cont[i] = nnlevel > 0 && keep_this_cont(element, ion, level, nonemptymgi, nnetot); } } } diff --git a/update_grid.h b/update_grid.h index 76a0d5d50..69addd9a2 100644 --- a/update_grid.h +++ b/update_grid.h @@ -5,6 +5,6 @@ #include void update_grid(FILE *estimators_file, int nts, int nts_prev, int titer, time_t real_time_start); -void cellcache_change_cell(int modelgridindex); +void cellcache_change_cell(int nonemptymgi); #endif // UPDATE_GRID_H diff --git a/update_packets.cc b/update_packets.cc index c6529c676..46e56b337 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -59,7 +59,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { } else if constexpr (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::WOLLAEGER) { // particle thermalisation from Wollaeger+2018, similar to Barnes but using a slightly different expression const double A = (pkt.type == TYPE_NONTHERMAL_PREDEPOSIT_ALPHA) ? 1.2 * 1.e-11 : 1.3 * 1.e-11; - const double aux_term = 2 * A / (ts * grid::get_rho(mgi)); + const double aux_term = 2 * A / (ts * grid::get_rho(nonemptymgi)); // In Bulla 2023 (arXiv:2211.14348), the following line contains (<-> eq. 7) contains a typo. The way implemented // here is the original from Wollaeger paper without the typo const double f_p = std::log1p(aux_term) / aux_term; @@ -75,7 +75,7 @@ void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { } else { // ThermalisationScheme::DETAILED or ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS // local, detailed absorption following Shingles+2023 - const double rho = grid::get_rho(grid::get_cell_modelgridindex(pkt.where)); + const double rho = grid::get_rho(nonemptymgi); // endot is energy loss rate (positive) in [erg/s] // endot [erg/s] from Barnes et al. (2016). see their figure 6. @@ -256,7 +256,9 @@ void do_packet(Packet &pkt, const double t2, const int nts) } case TYPE_KPKT: { - if (grid::modelgrid[grid::get_cell_modelgridindex(pkt.where)].thick == 1 || + const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + if (grid::modelgrid[nonemptymgi].thick == 1 || (EXPANSIONOPACITIES_ON && RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.)) { kpkt::do_kpkt_blackbody(pkt); } else { @@ -305,8 +307,8 @@ auto std_compare_packets_bymodelgriddensity(const Packet &p1, const Packet &p2) // for both non-escaped packets, order by descending cell density const int mgi1 = grid::get_cell_modelgridindex(p1.where); const int mgi2 = grid::get_cell_modelgridindex(p2.where); - const auto rho1 = mgi1 < grid::get_npts_model() ? grid::get_rho(mgi1) : 0.0; - const auto rho2 = mgi2 < grid::get_npts_model() ? grid::get_rho(mgi2) : 0.0; + const auto rho1 = mgi1 < grid::get_npts_model() ? grid::get_rho(grid::get_nonemptymgi_of_mgi(mgi1)) : 0.0; + const auto rho2 = mgi2 < grid::get_npts_model() ? grid::get_rho(grid::get_nonemptymgi_of_mgi(mgi2)) : 0.0; if (rho1 > rho2) { return true; @@ -384,9 +386,10 @@ void update_packets(const int nts, std::span packets) { for (auto &pkt : packets) { if ((pkt.type != TYPE_ESCAPE && pkt.prop_time < ts_end)) { const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; const bool cellcache_change_cell_required = - (mgi != grid::get_npts_model() && globals::cellcache[cellcacheslotid].cellnumber != mgi && - grid::modelgrid[mgi].thick != 1); + (nonemptymgi >= 0 && globals::cellcache[cellcacheslotid].nonemptymgi != nonemptymgi && + grid::modelgrid[nonemptymgi].thick != 1); if (cellcache_change_cell_required) { if (packetgroupstart != &pkt) { @@ -398,7 +401,7 @@ void update_packets(const int nts, std::span packets) { #endif { stats::increment(stats::COUNTER_UPDATECELL); - cellcache_change_cell(mgi); + cellcache_change_cell(nonemptymgi); } packetgroupstart = &pkt; } diff --git a/vpkt.cc b/vpkt.cc index 3dadcea56..225fcd06f 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -261,7 +261,8 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar if (mgi == grid::get_npts_model()) { vpkt.next_trans = -1; } else { - calculate_chi_rpkt_cont(vpkt.nu_cmf, chi_vpkt_cont, mgi); + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + calculate_chi_rpkt_cont(vpkt.nu_cmf, chi_vpkt_cont, nonemptymgi); const double chi_cont = chi_vpkt_cont.total; @@ -327,8 +328,8 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar const double B_ul = CLIGHTSQUAREDOVERTWOH / pow(nutrans, 3) * A_ul; const double B_lu = stat_weight(element, ion, upper) / stat_weight(element, ion, lower) * B_ul; - const auto n_u = calculate_levelpop(mgi, element, ion, upper); - const auto n_l = calculate_levelpop(mgi, element, ion, lower); + const auto n_u = calculate_levelpop(nonemptymgi, element, ion, upper); + const auto n_l = calculate_levelpop(nonemptymgi, element, ion, lower); const double tau_line = std::max(0., (B_lu * n_l - B_ul * n_u) * HCLIGHTOVERFOURPI * t_line); // Check on the element to exclude (or -1 for no line opacity) @@ -357,10 +358,13 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar end_packet = (vpkt.type == TYPE_ESCAPE); mgi = grid::get_cell_modelgridindex(vpkt.where); + if (mgi < grid::get_npts_model()) { + const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); - // kill vpkt with pass through a thick cell - if (grid::modelgrid[mgi].thick != 0) { - return false; + // kill vpkt with pass through a thick cell + if (grid::modelgrid[nonemptymgi].thick != 0) { + return false; + } } } @@ -900,9 +904,9 @@ auto vpkt_call_estimators(const Packet &pkt, const enum packet_type type_before_ } // Cut on vpkts - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const auto nonemptymgi = grid::get_propcell_nonemptymgi(pkt.where); - if (grid::modelgrid[mgi].thick != 0) { + if (grid::modelgrid[nonemptymgi].thick != 0) { return; } From e672f456545e0ba86338ab8daaf9ae40f28ed449 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 5 Nov 2024 08:06:53 +0000 Subject: [PATCH 079/117] Fix typo --- input.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.cc b/input.cc index 43d432a12..9383216b6 100644 --- a/input.cc +++ b/input.cc @@ -79,7 +79,7 @@ constexpr std::array inputlinecomments = { "19: cell_is_optically_thick num_grey_timesteps", "20: UNUSED max_bf_continua: (>0: max bound-free continua per ion, <0 unlimited)", "21: nprocs_exspec: extract spectra for n MPI tasks. sn3d will set this on start of new sim.", - "22: do_emission_res: Extract line-of-sight dependent information of last emission for spectrum_res (1: yes, 2: " + "22: do_emission_res: Extract line-of-sight dependent information of last emission for spectrum_res (1: yes, 0: " "no)", "23: kpktdiffusion_timescale n_kpktdiffusion_timesteps: kpkts diffuse x of a time step's length for the first y " "time steps"}; From 59f4b4bad14519c83957e29167e9a3900b97d522 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 5 Nov 2024 12:19:21 +0000 Subject: [PATCH 080/117] Auto-detect model dimensions (#143) --- grid.cc | 102 +++++++++-------- grid.h | 2 +- input.cc | 12 +- spectrum_lightcurve.cc | 249 +++++++++++++++++------------------------ spectrum_lightcurve.h | 12 +- vectors.h | 4 +- 6 files changed, 164 insertions(+), 217 deletions(-) diff --git a/grid.cc b/grid.cc index 277e162ef..54c012542 100644 --- a/grid.cc +++ b/grid.cc @@ -16,6 +16,7 @@ #ifdef MPI_ON #include #endif +#include #include #include #include @@ -1857,6 +1858,7 @@ void calculate_kappagrey() { void read_ejecta_model() { auto fmodel = fstream_required("model.txt", std::ios::in); std::string line; + std::optional detected_dim{}; // two integers on the first line of the model file int npts_0 = 0; // total model points for 1D/3D, and number of points in r for 2D @@ -1864,22 +1866,48 @@ void read_ejecta_model() { assert_always(get_noncommentline(fmodel, line)); auto ssline = std::istringstream(line); ssline >> npts_0; - if (get_model_type() == GridType::SPHERICAL1D) { - ncoord_model[0] = npts_0; - ncoord_model[1] = 0; - ncoord_model[2] = 0; - } else if (get_model_type() == GridType::CYLINDRICAL2D) { + if (ssline >> npts_1) { + // second number on the line for 2D means the line was n_r n_z + detected_dim = GridType::CYLINDRICAL2D; + printout("Detected 2D model\n"); ssline >> npts_1; // r and z (cylindrical polar) - ncoord_model[0] = npts_0; - ncoord_model[1] = npts_1; - ncoord_model[2] = 0; - } else if (get_model_type() == GridType::CARTESIAN3D) { - ncoord_model[0] = static_cast(round(pow(npts_0, 1 / 3.))); - ncoord_model[1] = ncoord_model[0]; - ncoord_model[2] = ncoord_model[0]; - assert_always(ncoord_model[0] * ncoord_model[1] * ncoord_model[2] == npts_0); + npts_model = npts_0 * npts_1; + } else { + // for 1D and 3D, this was the total number of model cells + npts_model = npts_0; } - npts_model = std::max(1, ncoord_model[0]) * std::max(1, ncoord_model[1]) * std::max(1, ncoord_model[2]); + + // Now read the time (in days) at which the model is specified. + double t_model_days{NAN}; + assert_always(get_noncommentline(fmodel, line)); + std::istringstream(line) >> t_model_days; + t_model = t_model_days * DAY; + + const auto pos_after_t_model = fmodel.tellg(); + // if the next line is a single float, it is the vmax (so 2D or 3D) + // otherwise, it is the first line of the model or a header comment (so 1D) + std::getline(fmodel, line); + if (!line.starts_with("#")) { + double num_after_vmax{NAN}; + auto sslinevmax = std::istringstream(line); + if ((sslinevmax >> globals::vmax) && !(sslinevmax >> num_after_vmax)) { + // single value on the line is a vmax, so 2D or 3D + // if it's not already know to be 2D (based on n_r n_z line), then it's 3D + if (detected_dim != GridType::CYLINDRICAL2D) { + assert_always(!detected_dim.has_value()); + detected_dim = GridType::CARTESIAN3D; + printout("Detected 3D model\n"); + } + } + } + if (!detected_dim.has_value()) { + assert_always(!detected_dim.has_value()); + detected_dim = GridType::SPHERICAL1D; + printout("Detected 1D model\n"); + fmodel.seekg(pos_after_t_model); + } + + set_model_type(detected_dim.value()); assert_always(modelgrid_input.data() == nullptr); modelgrid_input = MPI_shared_malloc_span(npts_model + 1); @@ -1893,14 +1921,9 @@ void read_ejecta_model() { nonemptymgi_of_mgi.resize(npts_model + 1, -1); if (get_model_type() == GridType::SPHERICAL1D) { - printout("Read 1D model\n"); - - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - + ncoord_model[0] = npts_0; + ncoord_model[1] = 0; + ncoord_model[2] = 0; vout_model.resize(get_npts_model(), NAN); // Now read in the lines of the model. Each line has 5 entries: the @@ -1950,18 +1973,9 @@ void read_ejecta_model() { globals::vmax = vout_model[get_npts_model() - 1]; } else if (get_model_type() == GridType::CYLINDRICAL2D) { - printout("Read 2D model\n"); - - // Now read the time (in days) at which the model is specified. - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - - // Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; - + ncoord_model[0] = npts_0; + ncoord_model[1] = npts_1; + ncoord_model[2] = 0; const auto [colnames, nucindexlist, one_line_per_cell] = read_model_columns(fmodel); // Now read in the model. Each point in the model has two lines of input. @@ -2009,21 +2023,13 @@ void read_ejecta_model() { std::abort(); } } else if (get_model_type() == GridType::CARTESIAN3D) { - printout("Read 3D model\n"); - - double t_model_days{NAN}; - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> t_model_days; - t_model = t_model_days * DAY; - + ncoord_model[0] = static_cast(round(pow(npts_0, 1 / 3.))); + ncoord_model[1] = ncoord_model[0]; + ncoord_model[2] = ncoord_model[0]; // for a 3D input model, the propagation cells will match the input cells exactly ncoordgrid = ncoord_model; ngrid = npts_model; - // Now read in vmax for the model (in cm s^-1). - assert_always(get_noncommentline(fmodel, line)); - std::istringstream(line) >> globals::vmax; - const double xmax_tmodel = globals::vmax * t_model; // Now read in the lines of the model. @@ -2062,8 +2068,8 @@ void read_ejecta_model() { for (int axis = 0; axis < 3; axis++) { const double cellwidth = 2 * xmax_tmodel / ncoordgrid[axis]; const double cellpos_expected = -xmax_tmodel + (cellwidth * get_cellcoordpointnum(mgi, axis)); - // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d ncoordgrid - // %d\n", + // printout("mgi %d coord %d expected %g found %g or %g rmax %g get_cellcoordpointnum(mgi, axis) %d + // ncoordgrid %d\n", // mgi, axis, cellpos_expected, cellpos_in[axis], cellpos_in[2 - axis], xmax_tmodel, // get_cellcoordpointnum(mgi, axis), ncoordgrid[axis]); if (fabs(cellpos_expected - cellpos_in[axis]) > 0.5 * cellwidth) { @@ -2114,6 +2120,8 @@ void read_ejecta_model() { printout("min_den %g [g/cm3]\n", min_den); } + assert_always(get_npts_model() == + std::max(1, ncoord_model[0]) * std::max(1, ncoord_model[1]) * std::max(1, ncoord_model[2])); printout("npts_model: %d\n", get_npts_model()); globals::rmax = globals::vmax * globals::tmin; printout("vmax %g [cm/s] (%.2fc)\n", globals::vmax, globals::vmax / CLIGHT); diff --git a/grid.h b/grid.h index d086e6b0b..ce5116353 100644 --- a/grid.h +++ b/grid.h @@ -32,7 +32,7 @@ struct ModelGridCell { int thick = 0; }; -consteval auto get_ngriddimensions(const GridType gridtype) -> int { +constexpr auto get_ngriddimensions(const GridType gridtype) -> int { switch (gridtype) { case GridType::SPHERICAL1D: return 1; diff --git a/input.cc b/input.cc index 9383216b6..4fdf3c399 100644 --- a/input.cc +++ b/input.cc @@ -1669,16 +1669,7 @@ void read_parameterfile(int rank) { assert_always(get_noncommentline(file, line)); // UNUSED start and end times for synthesis - assert_always(get_noncommentline(file, line)); // model dimensions - int dum1 = 0; - std::istringstream(line) >> dum1; - if (dum1 == 1) { - grid::set_model_type(GridType::SPHERICAL1D); - } else if (dum1 == 2) { - grid::set_model_type(GridType::CYLINDRICAL2D); - } else if (dum1 == 3) { - grid::set_model_type(GridType::CARTESIAN3D); - } + assert_always(get_noncommentline(file, line)); // UNUSED model dimensions (now autodetected) assert_always(get_noncommentline(file, line)); // UNUSED compute the r-light curve? @@ -1789,6 +1780,7 @@ void read_parameterfile(int rank) { // Extract line-of-sight dependent information of last emission for spectrum_res assert_always(get_noncommentline(file, line)); + int dum1 = 0; std::istringstream(line) >> dum1; globals::do_emission_res = (dum1 != 0); diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index 755073176..fad7e71f1 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -175,8 +175,15 @@ auto columnindex_from_emissiontype(const int et) -> int { return (get_nelements() * get_max_nions()) + (element * get_max_nions()) + ion; } -void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, const Spectra *stokes_i, - const Spectra *stokes_q, const Spectra *stokes_u) +[[nodiscard]] auto get_absindex(const int nts, const int nnu_abs, const int element, const int ion) -> ptrdiff_t { + const auto nelements = get_nelements(); + const auto max_nions = get_max_nions(); + return (static_cast(nts) * MNUBINS * nelements * max_nions) + (nnu_abs * nelements * max_nions) + + (element * max_nions) + ion; +} + +void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, Spectra *stokes_i, Spectra *stokes_q, + Spectra *stokes_u) // Routine to add a packet to the outgoing spectrum. { // Need to (1) decide which time bin to put it in and (2) which frequency bin. @@ -189,24 +196,25 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co const double dlognu = (log(nu_max) - log(nu_min)) / MNUBINS; const double t_arrive = get_arrive_time(pkt); if (t_arrive > globals::tmin && t_arrive < globals::tmax && pkt.nu_rf > nu_min && pkt.nu_rf < nu_max) { - const int nt = get_timestep(t_arrive); + const int nts = get_timestep(t_arrive); const int nnu = static_cast((log(pkt.nu_rf) - log(nu_min)) / dlognu); assert_always(nnu < MNUBINS); - const double deltaE = pkt.e_rf / globals::timesteps[nt].width / spectra.delta_freq[nnu] / 4.e12 / PI / PARSEC / + const double deltaE = pkt.e_rf / globals::timesteps[nts].width / spectra.delta_freq[nnu] / 4.e12 / PI / PARSEC / PARSEC / globals::nprocs_exspec * anglefactor; - spectra.timesteps[nt].flux[nnu] += deltaE; + const ptrdiff_t fluxindex = (nts * MNUBINS) + nnu; + spectra.fluxalltimesteps[fluxindex] += deltaE; if (stokes_i != nullptr) { - stokes_i->timesteps[nt].flux[nnu] += pkt.stokes[0] * deltaE; + stokes_i->fluxalltimesteps[fluxindex] += pkt.stokes[0] * deltaE; } if (stokes_q != nullptr) { - stokes_q->timesteps[nt].flux[nnu] += pkt.stokes[1] * deltaE; + stokes_q->fluxalltimesteps[fluxindex] += pkt.stokes[1] * deltaE; } if (stokes_u != nullptr) { - stokes_u->timesteps[nt].flux[nnu] += pkt.stokes[2] * deltaE; + stokes_u->fluxalltimesteps[fluxindex] += pkt.stokes[2] * deltaE; } if (spectra.do_emission_res) { @@ -215,22 +223,24 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co const int truenproc = columnindex_from_emissiontype(pkt.trueemissiontype); assert_always(truenproc < proccount); if (truenproc >= 0) { - spectra.timesteps[nt].trueemission[(nnu * proccount) + truenproc] += deltaE; + const auto emindex = (static_cast(nts) * MNUBINS * proccount) + (nnu * proccount) + truenproc; + spectra.trueemissionalltimesteps[emindex] += deltaE; } const int nproc = columnindex_from_emissiontype(pkt.emissiontype); assert_always(nproc < proccount); if (nproc >= 0) { // -1 means not set - spectra.timesteps[nt].emission[(nnu * proccount) + nproc] += deltaE; + const auto emindex = (static_cast(nts) * MNUBINS * proccount) + (nnu * proccount) + nproc; + spectra.emissionalltimesteps[emindex] += deltaE; if (stokes_i != nullptr && stokes_i->do_emission_res) { - stokes_i->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[0] * deltaE; + stokes_i->emissionalltimesteps[emindex] += pkt.stokes[0] * deltaE; } if (stokes_q != nullptr && stokes_q->do_emission_res) { - stokes_q->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[1] * deltaE; + stokes_q->emissionalltimesteps[emindex] += pkt.stokes[1] * deltaE; } if (stokes_u != nullptr && stokes_u->do_emission_res) { - stokes_u->timesteps[nt].emission[(nnu * proccount) + nproc] += pkt.stokes[2] * deltaE; + stokes_u->emissionalltimesteps[emindex] += pkt.stokes[2] * deltaE; } } @@ -253,28 +263,24 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co ? static_cast((log(pkt.absorptionfreq) - log(nu_min)) / dlognu) : -1; if (nnu_abs >= 0 && nnu_abs < MNUBINS) { - const int ioncount = get_nelements() * get_max_nions(); - const double deltaE_absorption = pkt.e_rf / globals::timesteps[nt].width / spectra.delta_freq[nnu_abs] / 4.e12 / - PI / PARSEC / PARSEC / globals::nprocs_exspec * anglefactor; + const double deltaE_absorption = pkt.e_rf / globals::timesteps[nts].width / spectra.delta_freq[nnu_abs] / + 4.e12 / PI / PARSEC / PARSEC / globals::nprocs_exspec * anglefactor; const int at = pkt.absorptiontype; if (at >= 0) { // bb-emission const int element = globals::linelist[at].elementindex; const int ion = globals::linelist[at].ionindex; - spectra.timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += - deltaE_absorption; + const auto absindex = get_absindex(nts, nnu_abs, element, ion); + spectra.absorptionalltimesteps[absindex] += deltaE_absorption; if (stokes_i != nullptr && stokes_i->do_emission_res) { - stokes_i->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += - pkt.stokes[0] * deltaE_absorption; + stokes_i->absorptionalltimesteps[absindex] += pkt.stokes[0] * deltaE_absorption; } if (stokes_q != nullptr && stokes_q->do_emission_res) { - stokes_q->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += - pkt.stokes[1] * deltaE_absorption; + stokes_q->absorptionalltimesteps[absindex] += pkt.stokes[1] * deltaE_absorption; } if (stokes_u != nullptr && stokes_u->do_emission_res) { - stokes_u->timesteps[nt].absorption[(nnu_abs * ioncount) + (element * get_max_nions()) + ion] += - pkt.stokes[2] * deltaE_absorption; + stokes_u->absorptionalltimesteps[absindex] += pkt.stokes[2] * deltaE_absorption; } if (TRACE_EMISSION_ABSORPTION_REGION_ON && t_arrive >= traceemissabs_timemin && @@ -295,23 +301,47 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, co } #ifdef MPI_ON -void mpi_reduce_spectra(int my_rank, Spectra &spectra, const int numtimesteps) { - for (int n = 0; n < numtimesteps; n++) { - MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.timesteps[n].flux, spectra.timesteps[n].flux, MNUBINS, MPI_DOUBLE, - MPI_SUM, 0, MPI_COMM_WORLD); +void mpi_reduce_spectra(int my_rank, Spectra &spectra) { + MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.fluxalltimesteps.data(), spectra.fluxalltimesteps.data(), + spectra.fluxalltimesteps.size(), MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); + + if (spectra.do_emission_res) { + MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.absorptionalltimesteps.data(), + spectra.absorptionalltimesteps.data(), spectra.absorptionalltimesteps.size(), MPI_DOUBLE, MPI_SUM, 0, + MPI_COMM_WORLD); + + MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.emissionalltimesteps.data(), spectra.emissionalltimesteps.data(), + spectra.emissionalltimesteps.size(), MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); + MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.trueemissionalltimesteps.data(), + spectra.trueemissionalltimesteps.data(), spectra.trueemissionalltimesteps.size(), MPI_DOUBLE, MPI_SUM, 0, + MPI_COMM_WORLD); + } +} +#endif - if (spectra.do_emission_res) { - const int proccount = get_proccount(); - MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.timesteps[n].absorption, spectra.timesteps[n].absorption, - MNUBINS * get_nelements() * get_max_nions(), MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); - MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.timesteps[n].emission, spectra.timesteps[n].emission, - MNUBINS * proccount, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); - MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.timesteps[n].trueemission, spectra.timesteps[n].trueemission, - MNUBINS * proccount, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); +void write_specpol_param(FILE *specpol_file, FILE *emissionpol_file, FILE *absorptionpol_file, const Spectra &spec, + const int nnu, const bool do_emission_res) { + const int proccount = get_proccount(); + const int ioncount = get_nelements() * get_max_nions(); // may be higher than the true included ion count + // Stokes I, Q, or U + for (int nts = 0; nts < globals::ntimesteps; nts++) { + fprintf(specpol_file, "%g ", spec.fluxalltimesteps[(nts * MNUBINS) + nnu]); + + if (do_emission_res) { + for (int nproc = 0; nproc < proccount; nproc++) { + const auto emindex = (static_cast(nts) * MNUBINS * proccount) + (nnu * proccount) + nproc; + fprintf(emissionpol_file, "%g ", spec.emissionalltimesteps[emindex]); + } + fprintf(emissionpol_file, "\n"); + + for (int i = 0; i < ioncount; i++) { + const auto absindex = get_absindex(nts, nnu, 0, i); + fprintf(absorptionpol_file, "%g ", spec.absorptionalltimesteps[absindex]); + } + fprintf(absorptionpol_file, "\n"); } } } -#endif } // anonymous namespace @@ -357,20 +387,23 @@ void write_spectrum(const std::string &spec_filename, const std::string &emissio fprintf(spec_file, "%g ", ((spectra.lower_freq[nnu] + (spectra.delta_freq[nnu] / 2)))); for (int nts = 0; nts < numtimesteps; nts++) { - fprintf(spec_file, "%g ", spectra.timesteps[nts].flux[nnu]); + fprintf(spec_file, "%g ", spectra.fluxalltimesteps[(nts * MNUBINS) + nnu]); if (do_emission_res) { - for (int i = 0; i < proccount; i++) { - fprintf(emission_file, "%g ", spectra.timesteps[nts].emission[(nnu * proccount) + i]); + for (int nproc = 0; nproc < proccount; nproc++) { + const auto emindex = (static_cast(nts) * MNUBINS * proccount) + (nnu * proccount) + nproc; + fprintf(emission_file, "%g ", spectra.emissionalltimesteps[emindex]); } fprintf(emission_file, "\n"); - for (int i = 0; i < proccount; i++) { - fprintf(trueemission_file, "%g ", spectra.timesteps[nts].trueemission[(nnu * proccount) + i]); + for (int truenproc = 0; truenproc < proccount; truenproc++) { + const auto trueemindex = (static_cast(nts) * MNUBINS * proccount) + (nnu * proccount) + truenproc; + fprintf(trueemission_file, "%g ", spectra.trueemissionalltimesteps[trueemindex]); } fprintf(trueemission_file, "\n"); for (int i = 0; i < ioncount; i++) { - fprintf(absorption_file, "%g ", spectra.timesteps[nts].absorption[(nnu * ioncount) + i]); + const auto absindex = get_absindex(nts, nnu, 0, i); + fprintf(absorption_file, "%g ", spectra.absorptionalltimesteps[absindex]); } fprintf(absorption_file, "\n"); } @@ -414,62 +447,13 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss fprintf(specpol_file, "\n"); - const int proccount = get_proccount(); - const int ioncount = get_nelements() * get_max_nions(); assert_always(stokes_i->lower_freq.size() == stokes_i->delta_freq.size()); - for (ptrdiff_t m = 0; m < std::ssize(stokes_i->lower_freq); m++) { - fprintf(specpol_file, "%g ", ((stokes_i->lower_freq[m] + (stokes_i->delta_freq[m] / 2)))); - - // Stokes I - for (int p = 0; p < globals::ntimesteps; p++) { - fprintf(specpol_file, "%g ", stokes_i->timesteps[p].flux[m]); - - if (do_emission_res) { - for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_i->timesteps[p].emission[(m * proccount) + i]); - } - fprintf(emissionpol_file, "\n"); - - for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_i->timesteps[p].absorption[(m * ioncount) + i]); - } - fprintf(absorptionpol_file, "\n"); - } - } - - // Stokes Q - for (int p = 0; p < globals::ntimesteps; p++) { - fprintf(specpol_file, "%g ", stokes_q->timesteps[p].flux[m]); - - if (do_emission_res) { - for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_q->timesteps[p].emission[(m * proccount) + i]); - } - fprintf(emissionpol_file, "\n"); - - for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_q->timesteps[p].absorption[(m * ioncount) + i]); - } - fprintf(absorptionpol_file, "\n"); - } - } - - // Stokes U - for (int p = 0; p < globals::ntimesteps; p++) { - fprintf(specpol_file, "%g ", stokes_u->timesteps[p].flux[m]); + for (ptrdiff_t nnu = 0; nnu < std::ssize(stokes_i->lower_freq); nnu++) { + fprintf(specpol_file, "%g ", ((stokes_i->lower_freq[nnu] + (stokes_i->delta_freq[nnu] / 2)))); - if (do_emission_res) { - for (int i = 0; i < proccount; i++) { - fprintf(emissionpol_file, "%g ", stokes_u->timesteps[p].emission[(m * proccount) + i]); - } - fprintf(emissionpol_file, "\n"); - - for (int i = 0; i < ioncount; i++) { - fprintf(absorptionpol_file, "%g ", stokes_u->timesteps[p].absorption[(m * ioncount) + i]); - } - fprintf(absorptionpol_file, "\n"); - } - } + write_specpol_param(specpol_file, emissionpol_file, absorptionpol_file, *stokes_i, nnu, do_emission_res); + write_specpol_param(specpol_file, emissionpol_file, absorptionpol_file, *stokes_q, nnu, do_emission_res); + write_specpol_param(specpol_file, emissionpol_file, absorptionpol_file, *stokes_u, nnu, do_emission_res); fprintf(specpol_file, "\n"); } @@ -484,7 +468,7 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss void init_spectrum_trace() { if (TRACE_EMISSION_ABSORPTION_REGION_ON) { traceemission_totalenergy = 0.; - traceemissionabsorption.resize(globals::nlines); + resize_exactly(traceemissionabsorption, globals::nlines); traceabsorption_totalenergy = 0.; for (int i = 0; i < globals::nlines; i++) { traceemissionabsorption[i].energyemitted = 0.; @@ -496,10 +480,9 @@ void init_spectrum_trace() { } } +// resize and initialize the spectra object void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, const bool do_emission_res) { - // start by setting up the time and frequency bins. - // it is all done interms of a logarithmic spacing in both t and nu - get the - // step sizes first. + // setup the time and frequency bins using a logarithmic spacing in both t and nu assert_always(MNUBINS > 0); size_t mem_usage = 0; @@ -509,7 +492,7 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co spectra.nu_max = nu_max; spectra.do_emission_res = do_emission_res; const bool print_memusage = - (spectra.timesteps.empty() || (do_emission_res && spectra.absorptionalltimesteps.empty())); + (spectra.fluxalltimesteps.empty() || (do_emission_res && spectra.absorptionalltimesteps.empty())); for (ptrdiff_t nnu = 0; nnu < MNUBINS; nnu++) { spectra.lower_freq[nnu] = exp(log(nu_min) + (nnu * (dlognu))); @@ -518,50 +501,32 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co spectra.do_emission_res = do_emission_res; // might be set true later by alloc_emissionabsorption_spectra - spectra.timesteps.resize(globals::ntimesteps); - spectra.fluxalltimesteps.resize(globals::ntimesteps * MNUBINS); + resize_exactly(spectra.fluxalltimesteps, globals::ntimesteps * MNUBINS); std::ranges::fill(spectra.fluxalltimesteps, 0.0); mem_usage += globals::ntimesteps * sizeof(Spectra); - mem_usage += globals::ntimesteps * sizeof(TimeStepSpecrum); mem_usage += globals::ntimesteps * MNUBINS * sizeof(double); - for (int nts = 0; nts < globals::ntimesteps; nts++) { - spectra.timesteps[nts].flux = &spectra.fluxalltimesteps[nts * MNUBINS]; - } - if (do_emission_res) { const int proccount = get_proccount(); mem_usage += globals::ntimesteps * MNUBINS * get_nelements() * get_max_nions() * sizeof(double); mem_usage += 2 * globals::ntimesteps * MNUBINS * proccount * sizeof(double); - spectra.absorptionalltimesteps.resize(globals::ntimesteps * MNUBINS * get_nelements() * get_max_nions()); - spectra.emissionalltimesteps.resize(globals::ntimesteps * MNUBINS * proccount); - spectra.trueemissionalltimesteps.resize(globals::ntimesteps * MNUBINS * proccount); + resize_exactly(spectra.absorptionalltimesteps, globals::ntimesteps * MNUBINS * get_nelements() * get_max_nions()); + resize_exactly(spectra.emissionalltimesteps, globals::ntimesteps * MNUBINS * proccount); + resize_exactly(spectra.trueemissionalltimesteps, globals::ntimesteps * MNUBINS * proccount); std::ranges::fill(spectra.absorptionalltimesteps, 0.0); std::ranges::fill(spectra.emissionalltimesteps, 0.0); std::ranges::fill(spectra.trueemissionalltimesteps, 0.0); - for (ptrdiff_t nts = 0; nts < std::ssize(spectra.timesteps); nts++) { - spectra.timesteps[nts].absorption = - &spectra.absorptionalltimesteps[nts * MNUBINS * get_nelements() * get_max_nions()]; - spectra.timesteps[nts].emission = &spectra.emissionalltimesteps[nts * MNUBINS * proccount]; - spectra.timesteps[nts].trueemission = &spectra.trueemissionalltimesteps[nts * MNUBINS * proccount]; - } if (print_memusage) { printout("[info] mem_usage: set of emission/absorption spectra occupy %.3f MB (nnubins %d)\n", mem_usage / 1024. / 1024., MNUBINS); } } else { - for (int nts = 0; nts < globals::ntimesteps; nts++) { - spectra.timesteps[nts].absorption = nullptr; - spectra.timesteps[nts].emission = nullptr; - spectra.timesteps[nts].trueemission = nullptr; - } - spectra.absorptionalltimesteps.clear(); spectra.emissionalltimesteps.clear(); spectra.trueemissionalltimesteps.clear(); @@ -572,16 +537,9 @@ void init_spectra(Spectra &spectra, const double nu_min, const double nu_max, co } } -void add_to_spec_res(const Packet &pkt, const int current_abin, Spectra &spectra, const Spectra *stokes_i, - const Spectra *stokes_q, const Spectra *stokes_u) -// Routine to add a packet to the outgoing spectrum. -{ - // Need to (1) decide which time bin to put it in and (2) which frequency bin. - - // Time bin - we know that it escaped at "escape_time". However, we have to allow - // for travel time. Use the formula in Leon's paper. - // The extra distance to be travelled beyond the reference surface is ds = r_ref (1 - mu). - +// Add a packet to the outgoing spectrum. +void add_to_spec_res(const Packet &pkt, const int current_abin, Spectra &spectra, Spectra *stokes_i, Spectra *stokes_q, + Spectra *stokes_u) { if (current_abin == -1 || get_escapedirectionbin(pkt.dir, globals::syn_dir) == current_abin) { // either angle average spectrum or packet matches the selected angle bin add_to_spec(pkt, current_abin, spectra, stokes_i, stokes_q, stokes_u); @@ -625,7 +583,7 @@ void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Pa const auto time_mpireduction_start = std::time(nullptr); #ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); - mpi_reduce_spectra(my_rank, rpkt_spectra, numtimesteps); + mpi_reduce_spectra(my_rank, rpkt_spectra); MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : rpkt_light_curve_lum.data(), rpkt_light_curve_lum.data(), numtimesteps, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : rpkt_light_curve_lumcmf.data(), rpkt_light_curve_lumcmf.data(), numtimesteps, @@ -653,8 +611,6 @@ void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Pa time_mpireduction_end - time_mpireduction_start); } -// Routine to make a MC light curve from the r-packets. - void write_light_curve(const std::string &lc_filename, const int current_abin, const std::vector &light_curve_lum, const std::vector &light_curve_lumcmf, const int numtimesteps) { @@ -686,16 +642,15 @@ void write_light_curve(const std::string &lc_filename, const int current_abin, } } -void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector &light_curve_lum, - std::vector &light_curve_lumcmf) // add a packet to the outgoing light-curve. -{ +void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector &light_curve_lum, + std::vector &light_curve_lumcmf) { if (current_abin == -1) { // Put this into the time grid const double arrive_time = get_arrive_time(pkt); if (arrive_time > globals::tmin && arrive_time < globals::tmax) { - const int nt = get_timestep(arrive_time); - atomicadd(light_curve_lum[nt], pkt.e_rf / globals::timesteps[nt].width / globals::nprocs_exspec); + const int nts = get_timestep(arrive_time); + atomicadd(light_curve_lum[nts], pkt.e_rf / globals::timesteps[nts].width / globals::nprocs_exspec); } const double inverse_gamma = std::sqrt(1. - (globals::vmax * globals::vmax / CLIGHTSQUARED)); @@ -705,9 +660,9 @@ void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector globals::tmin && arrive_time_cmf < globals::tmax) { - const int nt = get_timestep(arrive_time_cmf); - atomicadd(light_curve_lumcmf[nt], - pkt.e_cmf / globals::timesteps[nt].width / globals::nprocs_exspec / inverse_gamma); + const int nts = get_timestep(arrive_time_cmf); + atomicadd(light_curve_lumcmf[nts], + pkt.e_cmf / globals::timesteps[nts].width / globals::nprocs_exspec / inverse_gamma); } return; @@ -716,8 +671,8 @@ void add_to_lc_res(const Packet &pkt, const int current_abin, std::vector globals::tmin && t_arrive < globals::tmax) { - const int nt = get_timestep(t_arrive); - atomicadd(light_curve_lum[nt], pkt.e_rf / globals::timesteps[nt].width * MABINS / globals::nprocs_exspec); + const int nts = get_timestep(t_arrive); + atomicadd(light_curve_lum[nts], pkt.e_rf / globals::timesteps[nts].width * MABINS / globals::nprocs_exspec); } } } diff --git a/spectrum_lightcurve.h b/spectrum_lightcurve.h index 3bcc36d44..919d3c539 100644 --- a/spectrum_lightcurve.h +++ b/spectrum_lightcurve.h @@ -7,13 +7,6 @@ #include "exspec.h" #include "packet.h" -struct TimeStepSpecrum { - double *flux{}; - double *absorption{}; - double *emission{}; - double *trueemission{}; -}; - struct Spectra { double nu_min = -1.; double nu_max = -1.; @@ -23,7 +16,6 @@ struct Spectra { std::vector absorptionalltimesteps; std::vector emissionalltimesteps; std::vector trueemissionalltimesteps; - std::vector timesteps; bool do_emission_res = false; }; @@ -35,8 +27,8 @@ void write_specpol(const std::string &specpol_filename, const std::string &emiss const std::string &absorption_filename, const Spectra *stokes_i, const Spectra *stokes_q, const Spectra *stokes_u); -void add_to_spec_res(const Packet &pkt, int current_abin, Spectra &spectra, const Spectra *stokes_i, - const Spectra *stokes_q, const Spectra *stokes_u); +void add_to_spec_res(const Packet &pkt, int current_abin, Spectra &spectra, Spectra *stokes_i, Spectra *stokes_q, + Spectra *stokes_u); void init_spectra(Spectra &spectra, double nu_min, double nu_max, bool do_emission_res); void init_spectrum_trace(); diff --git a/vectors.h b/vectors.h index 68616eca1..15e4b7a5c 100644 --- a/vectors.h +++ b/vectors.h @@ -158,11 +158,11 @@ constexpr auto move_pkt_withtime(Packet &pkt, const double distance) -> double { return move_pkt_withtime(pkt.pos, pkt.dir, pkt.prop_time, pkt.nu_rf, pkt.nu_cmf, pkt.e_rf, pkt.e_cmf, distance); } -[[nodiscard]] constexpr auto get_arrive_time(const Packet &pkt) -> double +// Get a packet's arrival time at the observer // We know that a packet escaped at "escape_time". However, we have // to allow for travel time. Use the formula in Leon's paper. The extra // distance to be travelled beyond the reference surface is ds = r_ref (1 - mu). -{ +[[nodiscard]] constexpr auto get_arrive_time(const Packet &pkt) -> double { return pkt.escape_time - (dot(pkt.pos, pkt.dir) / CLIGHT_PROP); } From dcd8a3f24097daa1f08003fc623890309f3883ee Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 5 Nov 2024 15:06:41 +0000 Subject: [PATCH 081/117] Always require MPI (#144) Non-MPI mode is not used anywhere, so the maintenance and CI costs of keeping it are not worthwhile. --- .clangd | 2 +- .github/workflows/ci-checks.yml | 56 +++++++++++++------------- .github/workflows/ci.yml | 2 +- Makefile | 20 +--------- decay.cc | 21 +--------- exspec.cc | 18 ++------- globals.h | 16 -------- grid.cc | 50 ++--------------------- input.cc | 33 +--------------- nonthermal.cc | 20 ++-------- packet.cc | 4 -- radfield.cc | 43 ++------------------ ratecoeff.cc | 11 +----- rpkt.cc | 15 ------- sn3d.cc | 70 ++------------------------------- sn3d.h | 12 +----- spectrum_lightcurve.cc | 12 +----- stats.cc | 4 -- update_grid.cc | 4 -- update_packets.cc | 4 -- 20 files changed, 57 insertions(+), 360 deletions(-) diff --git a/.clangd b/.clangd index 84021a87f..01adb0a32 100644 --- a/.clangd +++ b/.clangd @@ -2,4 +2,4 @@ CompileFlags: # to make the compilation database, pip install compiledb, then run: # compiledb -n --full-path make TESTMODE=ON CompilationDatabase: compile_commands.json - Add: [-DMPI_ON=true, -std=c++20, -DTESTMODE=true] + Add: [-std=c++20, -DTESTMODE=true] diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 08fba6c3c..884d5d7ce 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -55,7 +55,7 @@ jobs: - name: install llvm from brew run: | - brew install llvm || true + brew install llvm echo "/opt/homebrew/opt/llvm/bin" >> $GITHUB_PATH echo "LDFLAGS=-L/opt/homebrew/opt/llvm/lib" >> $GITHUB_ENV @@ -65,8 +65,7 @@ jobs: echo "LIBRARY_PATH=/opt/homebrew/opt/lib" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=/opt/homebrew/opt/lib" >> $GITHUB_ENV - - echo "CPATH=/opt/homebrew/opt/include" >> $GITHUB_ENV + echo "CPATH=$HOMEBREW_PREFIX/include:$CPATH" >> $GITHUB_ENV - name: Set up Python uses: actions/setup-python@v5 @@ -75,6 +74,7 @@ jobs: run: | brew update brew install openmpi gsl || true + brew link openmpi python3 -m pip install compiledb - name: Generate compile_commands.json @@ -100,11 +100,10 @@ jobs: {name: gcc, ver: 14}, {name: nvc++, ver: '24.7'}, ] - mpi: [ON, OFF] fail-fast: false runs-on: ubuntu-24.04 - name: ${{ matrix.compiler.name }} ${{ matrix.compiler.ver }}${{ matrix.mpi == 'ON' && ' MPI' || ''}} + name: ${{ matrix.compiler.name }} ${{ matrix.compiler.ver }} steps: - uses: actions/checkout@v4 @@ -155,7 +154,6 @@ jobs: sudo apt install libtbb-dev - name: install openmpi - if: matrix.mpi == 'ON' run: | sudo apt install -y openmpi-bin libopenmpi-dev @@ -168,19 +166,19 @@ jobs: $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile classic mode OPENMP=ON run: | make clean - make MPI=${{matrix.mpi}} OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile classic mode STDPAR=ON run: | $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile classic mode STDPAR=ON GPU=ON if: matrix.compiler.name == 'nvc++' @@ -188,45 +186,40 @@ jobs: $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode OPENMP=ON run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode STDPAR=ON if: matrix.compiler.name != 'nvc++' run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode STDPAR=ON GPU=ON if: matrix.compiler.name == 'nvc++' run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec mac-llvm: runs-on: macos-15 env: CXX: clang++ - strategy: - matrix: - mpi: [ON, OFF] - openmp: [ON, OFF] - fail-fast: false - name: macOS llvm clang ${{ matrix.mpi == 'ON' && ' MPI' || ''}}${{ matrix.openmp == 'ON' && ' OpenMP' || ''}} + name: macOS llvm clang steps: - uses: actions/checkout@v4 @@ -256,7 +249,6 @@ jobs: echo "CXX=clang++" >> $GITHUB_ENV - name: install OpenMP - if: matrix.openmp == 'ON' run: | brew install libomp || true brew link --force libomp @@ -265,7 +257,6 @@ jobs: echo "CXXFLAGS=-I/opt/homebrew/opt/libomp/include $CXXFLAGS" >> $GITHUB_ENV - name: install OpenMPI - if: matrix.mpi == 'ON' run: | brew install openmpi || true @@ -274,25 +265,34 @@ jobs: $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile classic mode OPENMP=ON + run: | + make clean + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile classic mode STDPAR=ON - if: matrix.openmp != 'ON' run: | $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} OPENMP=${{matrix.openmp}} -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode OPENMP=ON + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - name: Compile nebular mode STDPAR=ON - if: matrix.openmp != 'ON' run: | cp -v -p artisoptions_classic.h artisoptions.h make clean - make MPI=${{matrix.mpi}} STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb24e52de..00f393b10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: - name: Compile run: | - make REPRODUCIBLE=ON TESTMODE=${{ matrix.testmode }} MPI=ON MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec + make REPRODUCIBLE=ON TESTMODE=${{ matrix.testmode }} MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec cp sn3d tests/${{ matrix.testname }}_testrun/ cp exspec tests/${{ matrix.testname }}_testrun/ diff --git a/Makefile b/Makefile index d85da383c..75fc9937b 100644 --- a/Makefile +++ b/Makefile @@ -5,24 +5,8 @@ # place in architecture folder, e.g. build/arm64 BUILD_DIR = build/$(shell uname -m) -ifeq ($(MPI),) - # MPI option not specified. set to true if mpicxx exists - ifneq (, $(shell command -v mpicxx 2> /dev/null)) - MPI := ON - else - MPI := OFF - endif -endif - -ifeq ($(MPI),ON) - CXX := mpicxx - CXXFLAGS += -DMPI_ON=true - BUILD_DIR := $(BUILD_DIR)_mpi +CXX := mpicxx $(info mpicxx version: $(shell mpicxx --showme:version 2> /dev/null)) -else ifeq ($(MPI),OFF) -else - $(error bad value for MPI option. Should be ON or OFF) -endif ifeq ($(TESTMODE),ON) else ifeq ($(TESTMODE),OFF) @@ -40,7 +24,6 @@ else $(error bad value for REPRODUCIBLE option. Should be ON or OFF) endif - COMPILER_VERSION := $(shell $(CXX) --version) $(info $(COMPILER_VERSION)) ifneq '' '$(findstring clang,$(COMPILER_VERSION))' @@ -58,7 +41,6 @@ endif $(info detected compiler is $(COMPILER_NAME)) - ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -std=c++20 else diff --git a/decay.cc b/decay.cc index a9cf5b505..6326a684e 100644 --- a/decay.cc +++ b/decay.cc @@ -1,8 +1,6 @@ #include "decay.h" -#ifdef MPI_ON #include -#endif #include #include @@ -21,6 +19,7 @@ #include #include #include +#include #include #include @@ -133,9 +132,7 @@ std::vector decaypaths; // the index [mgi * num_decaypaths + i] will hold the decay energy per mass [erg/g] released by chain i in cell mgi // during the simulation time range std::span decaypath_energy_per_mass{}; -#ifdef MPI_ON MPI_Win win_decaypath_energy_per_mass{MPI_WIN_NULL}; -#endif [[nodiscard]] auto get_nuc_decaybranchprob(const int nucindex, const int decaytype) -> double { assert_testmodeonly(nucindex >= 0); @@ -1054,19 +1051,12 @@ void setup_decaypath_energy_per_mass() { "shared)...", nonempty_npts_model * get_num_decaypaths() * sizeof(double) / 1024. / 1024.); double *decaypath_energy_per_mass_data{nullptr}; -#ifdef MPI_ON std::tie(decaypath_energy_per_mass_data, win_decaypath_energy_per_mass) = MPI_shared_malloc_keepwin(nonempty_npts_model * get_num_decaypaths()); -#else - decaypath_energy_per_mass_data = - static_cast(malloc(nonempty_npts_model * get_num_decaypaths() * sizeof(double))); -#endif decaypath_energy_per_mass = std::span(decaypath_energy_per_mass_data, nonempty_npts_model * get_num_decaypaths()); printout("done.\n"); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif printout("Calculating decaypath_energy_per_mass for all cells..."); const ptrdiff_t num_decaypaths = get_num_decaypaths(); @@ -1081,24 +1071,15 @@ void setup_decaypath_energy_per_mass() { } printout("done.\n"); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif } void free_decaypath_energy_per_mass() { -#ifdef MPI_ON if (win_decaypath_energy_per_mass != MPI_WIN_NULL) { printout("[info] mem_usage: decaypath_energy_per_mass was freed\n"); MPI_Win_free(&win_decaypath_energy_per_mass); win_decaypath_energy_per_mass = MPI_WIN_NULL; } -#else - if (decaypath_energy_per_mass.data() != nullptr) { - printout("[info] mem_usage: decaypath_energy_per_mass was freed\n"); - free(decaypath_energy_per_mass.data()); - } -#endif decaypath_energy_per_mass = {}; } diff --git a/exspec.cc b/exspec.cc index 21d186877..83b25036d 100644 --- a/exspec.cc +++ b/exspec.cc @@ -1,13 +1,13 @@ #include "exspec.h" +#include +#include + #include #include #include #include #include -#ifdef MPI_ON -#include -#endif #ifndef GPU_ON #include #endif @@ -51,7 +51,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra const double nu_min_gamma = 0.05 * MEV / H; const double nu_max_gamma = 4. * MEV / H; init_spectra(gamma_spectra, nu_min_gamma, nu_max_gamma, false); - + assert_always(globals::nprocs_exspec > 0); for (int p = 0; p < globals::nprocs_exspec; p++) { Packet *pkts_start = load_allrank_packets ? &pkts[p * globals::npkts] : pkts; @@ -69,9 +69,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra } } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif if (p % globals::nprocs != globals::my_rank) { printout("skipping packets file %d %d\n", p + 1, globals::nprocs); @@ -164,9 +162,7 @@ void do_angle_bin(const int a, Packet *pkts, bool load_allrank_packets, Spectra auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) const auto sys_time_start = std::time(nullptr); -#ifdef MPI_ON MPI_Init(&argc, &argv); -#endif globals::setup_mpi_vars(); @@ -191,15 +187,11 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) printout("TESTMODE is ON\n"); #endif -#ifdef MPI_ON printout("process id (pid): %d\n", getpid()); printout("MPI enabled:\n"); printout(" rank_global %d of [0..%d] in MPI_COMM_WORLD\n", globals::my_rank, globals::nprocs - 1); printout(" rank_in_node %d of [0..%d] in node %d of [0..%d]\n", globals::rank_in_node, globals::node_nprocs - 1, globals::node_id, globals::node_count - 1); -#else - printout("MPI is disabled in this build\n"); -#endif // single rank only for now assert_always(globals::my_rank == 0); @@ -253,9 +245,7 @@ auto main(int argc, char *argv[]) -> int { // NOLINT(misc-unused-parameters) decay::cleanup(); printout("exspec finished at %ld (tstart + %ld seconds)\n", std::time(nullptr), std::time(nullptr) - sys_time_start); -#ifdef MPI_ON MPI_Finalize(); -#endif if (std::filesystem::exists("artis.pid")) { std::filesystem::remove("artis.pid"); diff --git a/globals.h b/globals.h index de5f32104..ee8a013e5 100644 --- a/globals.h +++ b/globals.h @@ -2,9 +2,7 @@ #ifndef GLOBALS_H #define GLOBALS_H -#ifdef MPI_ON #include -#endif #include #include @@ -216,9 +214,7 @@ inline int bfestimcount{0}; // for USE_LUT_PHOTOION = true inline double *corrphotoionrenorm{}; -#ifdef MPI_ON inline MPI_Win win_corrphotoionrenorm{MPI_WIN_NULL}; -#endif inline std::vector gammaestimator; @@ -283,10 +279,8 @@ inline double NPHIXSNUINCREMENT{-1}; inline std::vector cellcache{}; -#ifdef MPI_ON inline MPI_Comm mpi_comm_node{MPI_COMM_NULL}; inline MPI_Comm mpi_comm_internode{MPI_COMM_NULL}; -#endif inline int nprocs{-1}; inline int my_rank{-1}; @@ -327,7 +321,6 @@ inline bool lte_iteration; inline std::deque mutex_cellcachemacroatom; inline void setup_mpi_vars() { -#ifdef MPI_ON MPI_Comm_rank(MPI_COMM_WORLD, &globals::my_rank); MPI_Comm_size(MPI_COMM_WORLD, &globals::nprocs); @@ -366,15 +359,6 @@ inline void setup_mpi_vars() { MPI_Bcast(&globals::node_id, 1, MPI_INT, 0, globals::mpi_comm_node); MPI_Bcast(&globals::node_count, 1, MPI_INT, 0, globals::mpi_comm_node); - -#else - globals::my_rank = 0; - globals::nprocs = 1; - globals::rank_in_node = 0; - globals::node_nprocs = 1; - globals::node_id = 0; - globals::node_count = 0; -#endif } } // namespace globals diff --git a/grid.cc b/grid.cc index 54c012542..3d0867f33 100644 --- a/grid.cc +++ b/grid.cc @@ -1,5 +1,7 @@ #include "grid.h" +#include + #include #include #include @@ -13,9 +15,6 @@ #include #include #include -#ifdef MPI_ON -#include -#endif #include #include #include @@ -83,10 +82,8 @@ std::vector mgi_of_nonemptymgi; std::span totmassradionuclide{}; // total mass of each radionuclide in the ejecta -#ifdef MPI_ON MPI_Win win_nltepops_allcells = MPI_WIN_NULL; MPI_Win win_initnucmassfrac_allcells = MPI_WIN_NULL; -#endif float *initnucmassfrac_allcells{}; float *initmassfracuntrackedstable_allcells{}; @@ -132,19 +129,13 @@ void allocate_initradiobund() { const ptrdiff_t num_nuclides = decay::get_num_nuclides(); const size_t totalradioabundcount = (npts_model + 1) * num_nuclides; -#ifdef MPI_ON std::tie(initnucmassfrac_allcells, win_initnucmassfrac_allcells) = MPI_shared_malloc_keepwin(totalradioabundcount); -#else - initnucmassfrac_allcells = static_cast(malloc(totalradioabundcount * sizeof(float))); -#endif printout( "[info] mem_usage: radioabundance data for %td nuclides for %td cells occupies %.3f MB (node shared memory)\n", num_nuclides, npts_model, static_cast(totalradioabundcount * sizeof(float)) / 1024. / 1024.); -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif assert_always(initnucmassfrac_allcells != nullptr); @@ -153,9 +144,7 @@ void allocate_initradiobund() { std::fill_n(&initnucmassfrac_allcells[mgi * num_nuclides], num_nuclides, 0.); } } -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif } auto get_cell_r_inner(const int cellindex) -> double { @@ -275,13 +264,8 @@ void allocate_nonemptycells_composition_cooling() ion_cooling_contribs_allcells = MPI_shared_malloc(nonempty_npts_model_ptrdifft * get_includedions()); if (globals::total_nlte_levels > 0) { -#ifdef MPI_ON std::tie(nltepops_allcells, win_nltepops_allcells) = MPI_shared_malloc_keepwin(nonempty_npts_model_ptrdifft * globals::total_nlte_levels); -#else - nltepops_allcells = - static_cast(malloc(nonempty_npts_model * globals::total_nlte_levels * sizeof(double))); -#endif assert_always(nltepops_allcells != nullptr); } else { @@ -328,10 +312,7 @@ void allocate_nonemptymodelcells() { (mgi == get_npts_model())); } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - // find number of non-empty cells and allocate nonempty list nonempty_npts_model = 0; for (int mgi = 0; mgi < get_npts_model(); mgi++) { @@ -360,10 +341,7 @@ void allocate_nonemptymodelcells() { } } } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - for (int cellindex = 0; cellindex < ngrid; cellindex++) { const int mgi = get_cell_modelgridindex(cellindex); if (mgi >= get_npts_model()) { @@ -376,10 +354,7 @@ void allocate_nonemptymodelcells() { assert_always(modelgrid.data() == nullptr); modelgrid = MPI_shared_malloc_span(nonempty_npts_model); std::ranges::fill(modelgrid, ModelGridCell{}); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - allocate_nonemptycells_composition_cooling(); if constexpr (EXPANSIONOPACITIES_ON || RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY > 0.) { @@ -395,12 +370,8 @@ void allocate_nonemptymodelcells() { const auto ionestimsize = ionestimcount * sizeof(double); if (ionestimsize > 0) { -#ifdef MPI_ON std::tie(globals::corrphotoionrenorm, globals::win_corrphotoionrenorm) = MPI_shared_malloc_keepwin(ionestimcount); -#else - globals::corrphotoionrenorm = static_cast(malloc(ionestimsize)); -#endif globals::gammaestimator.resize(ionestimcount, 0.); #ifdef DO_TITER @@ -433,10 +404,8 @@ void allocate_nonemptymodelcells() { globals::colheatingestimator_save.resize(nonempty_npts_model, 0.); #endif -#ifdef MPI_ON // barrier to make sure node master has set abundance values to node shared memory MPI_Barrier(MPI_COMM_WORLD); -#endif printout("[info] mem_usage: the modelgrid array occupies %.3f MB\n", (get_npts_model() + 1) * sizeof(modelgrid[0]) / 1024. / 1024.); @@ -508,10 +477,8 @@ void map_modeltogrid_direct() { } void abundances_read() { -#ifdef MPI_ON // barrier to make sure node master has set values in node shared memory MPI_Barrier(MPI_COMM_WORLD); -#endif printout("reading abundances.txt..."); const bool threedimensional = (get_model_type() == GridType::CARTESIAN3D); @@ -575,10 +542,8 @@ void abundances_read() { } } -#ifdef MPI_ON // barrier to make sure node master has set values in node shared memory MPI_Barrier(MPI_COMM_WORLD); -#endif printout("done.\n"); } @@ -895,18 +860,13 @@ void read_grid_restart_data(const int timestep) { nonthermal::read_restart_data(gridsave_file); nltepop_read_restart_data(gridsave_file); } -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif fclose(gridsave_file); } // Assign temperatures to the grid cells at the start of the simulation void assign_initial_temperatures() { -#ifdef MPI_ON - MPI_Barrier(MPI_COMM_WORLD); -#endif - // For a simulation started from scratch we estimate the initial temperatures + MPI_Barrier(MPI_COMM_WORLD); // For a simulation started from scratch we estimate the initial temperatures // We assume that for early times the material is so optically thick, that // all the radiation is trapped in the cell it originates from. This @@ -1914,9 +1874,7 @@ void read_ejecta_model() { if (globals::rank_in_node == 0) { std::ranges::fill(modelgrid_input, ModelGridCellInput{}); } -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif mg_associated_cells.resize(npts_model + 1, 0); nonemptymgi_of_mgi.resize(npts_model + 1, -1); @@ -2343,9 +2301,7 @@ void grid_init(const int my_rank) { printout("Total grid-mapped mass: %9.3e [Msun] (%.1f%% of input mass)\n", mtot_mapped / MSUN, mtot_mapped / mtot_input * 100.); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif } auto get_totmassradionuclide(const int z, const int a) -> double { diff --git a/input.cc b/input.cc index 4fdf3c399..a25bf5b89 100644 --- a/input.cc +++ b/input.cc @@ -1,11 +1,8 @@ #include "input.h" -#ifdef MPI_ON -#include -#endif - #include #include +#include #include #include @@ -605,9 +602,7 @@ void add_transitions_to_unsorted_linelist(const int element, const int ion, cons } } } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif } auto calculate_nlevels_groundterm(const int element, const int ion) -> int { @@ -836,10 +831,8 @@ void read_phixs_data() { phixs_file_version_exists[1] = std::filesystem::exists(phixsdata_filenames[1]); phixs_file_version_exists[2] = std::filesystem::exists(phixsdata_filenames[2]); -#ifdef MPI_ON // just in case the file system was faulty and the ranks disagree on the existence of the files MPI_Allreduce(MPI_IN_PLACE, phixs_file_version_exists.data(), 3, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD); -#endif assert_always(phixs_file_version_exists[1] || phixs_file_version_exists[2]); // at least one must exist if (phixs_file_version_exists[1] && phixs_file_version_exists[2]) { printout( @@ -897,19 +890,14 @@ void read_phixs_data() { assert_always((nbftables * globals::NPHIXSPOINTS) == std::ssize(tmpallphixs)); // copy the photoionisation tables into one contiguous block of memory -#ifdef MPI_ON globals::allphixs = MPI_shared_malloc(tmpallphixs.size()); -#else - globals::allphixs = static_cast(malloc(tmpallphixs.size() * sizeof(float))); -#endif assert_always(globals::allphixs != nullptr); std::copy_n(tmpallphixs.cbegin(), tmpallphixs.size(), globals::allphixs); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif + tmpallphixs.clear(); tmpallphixs.shrink_to_fit(); } @@ -1175,13 +1163,9 @@ void read_atomicdata_files() { // create a shared all transitions list and then copy data across, freeing the local copy const auto totupdowntrans = totaluptrans + totaldowntrans; assert_always(totupdowntrans == static_cast(temp_alltranslist_size)); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); globals::alltrans = MPI_shared_malloc(totupdowntrans); -#else - globals::alltrans = static_cast(malloc(totupdowntrans * sizeof(LevelTransition))); -#endif if (globals::rank_in_node == 0) { std::copy_n(temp_alltranslist.data(), totupdowntrans, globals::alltrans); } @@ -1191,11 +1175,7 @@ void read_atomicdata_files() { // create a linelist shared on node and then copy data across, freeing the local copy TransitionLine *nonconstlinelist{}; -#ifdef MPI_ON nonconstlinelist = MPI_shared_malloc(globals::nlines); -#else - nonconstlinelist = static_cast(malloc(globals::nlines * sizeof(TransitionLine))); -#endif if (globals::rank_in_node == 0) { memcpy(static_cast(nonconstlinelist), temp_linelist.data(), globals::nlines * sizeof(TransitionLine)); @@ -1203,9 +1183,7 @@ void read_atomicdata_files() { temp_linelist.clear(); temp_alltranslist.shrink_to_fit(); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif globals::linelist = nonconstlinelist; nonconstlinelist = nullptr; printout("[info] mem_usage: linelist occupies %.3f MB (node shared memory)\n", @@ -1250,10 +1228,7 @@ void read_atomicdata_files() { } printout(" took %lds\n", std::time(nullptr) - time_start_establish_linelist_connections); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - for (int element = 0; element < get_nelements(); element++) { const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { @@ -1568,13 +1543,11 @@ void input(int rank) { read_atomicdata(); -#ifdef MPI_ON const auto time_before_barrier = std::time(nullptr); printout("barrier after read_atomicdata(): time before barrier %d, ", static_cast(time_before_barrier)); MPI_Barrier(MPI_COMM_WORLD); printout("time after barrier %d (waited %d seconds)\n", static_cast(time(nullptr)), static_cast(time(nullptr) - time_before_barrier)); -#endif grid::read_ejecta_model(); } @@ -1609,10 +1582,8 @@ void read_parameterfile(int rank) { #ifndef GPU_ON pre_zseed = std::random_device{}(); #endif -#ifdef MPI_ON // broadcast randomly-generated seed from rank 0 to all ranks MPI_Bcast(&pre_zseed, 1, MPI_INT64_T, 0, MPI_COMM_WORLD); -#endif printout("randomly-generated random number seed is %" PRId64 "\n", pre_zseed); #if defined REPRODUCIBLE && REPRODUCIBLE printout("ERROR: reproducible mode is on, so random number seed is required.\n"); diff --git a/nonthermal.cc b/nonthermal.cc index ebc92b75b..1a3038e88 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1,28 +1,24 @@ #include "nonthermal.h" -#include -#include -#include - -#ifdef MPI_ON -#include -#endif - #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -257,13 +253,9 @@ void read_shell_configs() { void read_binding_energies() { const bool binding_en_newformat_local = std::filesystem::exists("binding_energies_lotz_tab1and2.txt") || std::filesystem::exists("data/binding_energies_lotz_tab1and2.txt"); -#ifdef MPI_ON bool binding_en_newformat = binding_en_newformat_local; // just in case the file system was faulty and the ranks disagree on the existence of the files MPI_Allreduce(MPI_IN_PLACE, &binding_en_newformat, 1, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD); -#else - const bool binding_en_newformat = binding_en_newformat_local; -#endif int nshells = 0; // number of shell in binding energy file int n_z_binding = 0; // number of elements in binding energy file @@ -2138,9 +2130,7 @@ void init(const int my_rank, const int ndo_nonempty) { nt_solution[nonemptymgi].frac_excitations_list_size = 0; } } -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif double sourceintegral = 0.; // integral of S(e) dE for (int s = 0; s < SFPTS; s++) { @@ -2721,7 +2711,6 @@ void read_restart_data(FILE *gridsave_file) { } } -#ifdef MPI_ON void nt_MPI_Bcast(const int nonemptymgi, const int root_node_id) { MPI_Bcast(&deposition_rate_density_all_cells[nonemptymgi], 1, MPI_DOUBLE, root_node_id, globals::mpi_comm_internode); @@ -2751,7 +2740,6 @@ void nt_MPI_Bcast(const int nonemptymgi, const int root_node_id) { check_auger_probabilities(nonemptymgi); } } -#endif void nt_reset_stats() { nt_energy_deposited = 0.; } diff --git a/packet.cc b/packet.cc index 7901f8f7d..812da7e0b 100644 --- a/packet.cc +++ b/packet.cc @@ -1,8 +1,6 @@ #include "packet.h" -#ifdef MPI_ON #include -#endif #include #include @@ -88,9 +86,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac void packet_init(Packet *pkt) // Subroutine that initialises the packets if we start a new simulation. { -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif printout("UNIFORM_PELLET_ENERGIES is %s\n", (UNIFORM_PELLET_ENERGIES ? "true" : "false")); printout("INITIAL_PACKETS_ON is %s\n", (INITIAL_PACKETS_ON ? "on" : "off")); diff --git a/radfield.cc b/radfield.cc index 6cf4b1643..2e99d50b2 100644 --- a/radfield.cc +++ b/radfield.cc @@ -1,22 +1,19 @@ #include "radfield.h" -#include - -#ifdef MPI_ON -#include -#endif - #include #include #include #include #include +#include #include #include +#include #include #include #include +#include #include #include "artisoptions.h" @@ -53,10 +50,8 @@ constexpr double radfieldbins_delta_nu = RadFieldBin *radfieldbins{}; RadFieldBinSolution *radfieldbin_solutions{}; -#ifdef MPI_ON MPI_Win win_radfieldbin_solutions = MPI_WIN_NULL; MPI_Win win_prev_bfrate_normed = MPI_WIN_NULL; -#endif struct Jb_lu_estimator { double value = 0.; @@ -516,13 +511,8 @@ void init(const int my_rank, const int ndo_nonempty) { const size_t mem_usage_bin_solutions = nonempty_npts_model * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution); -#ifdef MPI_ON std::tie(radfieldbin_solutions, win_radfieldbin_solutions) = MPI_shared_malloc_keepwin(nonempty_npts_model * RADFIELDBINCOUNT); -#else - radfieldbin_solutions = static_cast( - malloc(nonempty_npts_model * RADFIELDBINCOUNT * sizeof(RadFieldBinSolution))); -#endif printout("[info] mem_usage: radiation field bin accumulators for non-empty cells occupy %.3f MB\n", mem_usage_bins / 1024. / 1024.); @@ -535,12 +525,8 @@ void init(const int my_rank, const int ndo_nonempty) { if constexpr (DETAILED_BF_ESTIMATORS_ON) { { -#ifdef MPI_ON std::tie(prev_bfrate_normed, win_prev_bfrate_normed) = MPI_shared_malloc_keepwin(nonempty_npts_model * globals::bfestimcount); -#else - prev_bfrate_normed = static_cast(malloc(nonempty_npts_model * globals::bfestimcount * sizeof(float))); -#endif } printout("[info] mem_usage: detailed bf estimators for non-empty cells occupy %.3f MB (node shared memory)\n", nonempty_npts_model * globals::bfestimcount * sizeof(float) / 1024. / 1024.); @@ -554,9 +540,7 @@ void init(const int my_rank, const int ndo_nonempty) { zero_estimators(); if constexpr (MULTIBIN_RADFIELD_MODEL_ON) { -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif if (globals::rank_in_node == 0) { for (ptrdiff_t nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { for (int binindex = 0; binindex < RADFIELDBINCOUNT; binindex++) { @@ -566,9 +550,7 @@ void init(const int my_rank, const int ndo_nonempty) { } } } -#ifdef MPI_ON MPI_Barrier(globals::mpi_comm_node); -#endif } } @@ -708,27 +690,15 @@ void close_file() { if (MULTIBIN_RADFIELD_MODEL_ON) { free(radfieldbins); -#ifdef MPI_ON if (win_radfieldbin_solutions != MPI_WIN_NULL) { MPI_Win_free(&win_radfieldbin_solutions); } -#else - if (radfieldbin_solutions != nullptr) { - free(radfieldbin_solutions); - } -#endif } if constexpr (DETAILED_BF_ESTIMATORS_ON) { -#ifdef MPI_ON if (win_radfieldbin_solutions != MPI_WIN_NULL) { MPI_Win_free(&win_prev_bfrate_normed); } -#else - if (prev_bfrate_normed != nullptr) { - free(prev_bfrate_normed); - } -#endif } } @@ -1033,7 +1003,6 @@ void titer_nuJ(const int modelgridindex) { } #endif -#ifdef MPI_ON void reduce_estimators() // reduce and broadcast (allreduce) the estimators for J and nuJ in all bins { @@ -1113,7 +1082,6 @@ void do_MPI_Bcast(const ptrdiff_t nonemptymgi, const int root, const int root_no MPI_Barrier(MPI_COMM_WORLD); } -#endif void write_restart_data(FILE *gridsave_file) { printout("binned radiation field and detailed lines, "); @@ -1276,10 +1244,7 @@ void read_restart_data(FILE *gridsave_file) { assert_always(fscanf(gridsave_file, "%la %la %a %a %d\n", &radfieldbins[mgibinindex].J_raw, &radfieldbins[mgibinindex].nuJ_raw, &W, &T_R, &radfieldbins[mgibinindex].contribcount) == 5); -#ifdef MPI_ON - if (globals::rank_in_node == 0) -#endif - { + if (globals::rank_in_node == 0) { radfieldbin_solutions[mgibinindex].W = W; radfieldbin_solutions[mgibinindex].T_R = T_R; } diff --git a/ratecoeff.cc b/ratecoeff.cc index 24e507d2e..ec2e9c583 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -1,8 +1,6 @@ #include "ratecoeff.h" -#ifdef MPI_ON #include -#endif #if !USE_SIMPSON_INTEGRATOR #include @@ -872,11 +870,7 @@ void setup_photoion_luts() { mem_usage_photoionluts += TABLESIZE * globals::nbfcontinua * sizeof(double); } -#ifdef MPI_ON bfcooling_coeffs = MPI_shared_malloc(TABLESIZE * globals::nbfcontinua); -#else - bfcooling_coeffs = static_cast(malloc(TABLESIZE * globals::nbfcontinua * sizeof(double))); -#endif printout( "[info] mem_usage: lookup tables derived from photoionisation (spontrecombcoeff, bfcooling and " @@ -1095,20 +1089,17 @@ void ratecoefficients_init() { printout("[info] ratecoefficients_init: ratecoeff.dat file not found. Creating a new one...\n"); } } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); // all node-rank 0 should agree, but to be sure, // world rank 0 will decide if we need to regenerate rate coefficient tables MPI_Bcast(&ratecoeff_match, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); -#endif if (!ratecoeff_match) { precalculate_rate_coefficient_integrals(); // And the master process writes them to file in a serial operation -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif + if (globals::my_rank == 0) { write_ratecoeff_dat(); } diff --git a/rpkt.cc b/rpkt.cc index d869b77fb..d824fbe61 100644 --- a/rpkt.cc +++ b/rpkt.cc @@ -1,8 +1,6 @@ #include "rpkt.h" -#ifdef MPI_ON #include -#endif #include #include @@ -43,10 +41,8 @@ std::span expansionopacities{}; // kappa times Planck function for each bin of each non-empty cell std::span expansionopacity_planck_cumulative{}; -#ifdef MPI_ON MPI_Win win_expansionopacities = MPI_WIN_NULL; MPI_Win win_expansionopacity_planck_cumulative = MPI_WIN_NULL; -#endif // get the frequency change per distance travelled assuming linear change to the abort distance // this is done is two parts to get identical results to do_rpkt_step() @@ -975,21 +971,12 @@ void allocate_expansionopacities() { float *expansionopacities_data{}; double *expansionopacity_planck_cumulative_data{}; -#ifdef MPI_ON std::tie(expansionopacities_data, win_expansionopacities) = MPI_shared_malloc_keepwin(nonempty_npts_model * expopac_nbins); -#else - expansionopacities_data = static_cast(malloc(nonempty_npts_model * expopac_nbins * sizeof(float))); -#endif if constexpr (RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.) { -#ifdef MPI_ON std::tie(expansionopacity_planck_cumulative_data, win_expansionopacity_planck_cumulative) = MPI_shared_malloc_keepwin(nonempty_npts_model * expopac_nbins); -#else - expansionopacity_planck_cumulative_data = - static_cast(malloc(nonempty_npts_model * expopac_nbins * sizeof(double))); -#endif } expansionopacities = std::span(expansionopacities_data, nonempty_npts_model * expopac_nbins); @@ -1125,7 +1112,6 @@ void calculate_chi_rpkt_cont(const double nu_cmf, Rpkt_continuum_absorptioncoeff } } -#ifdef MPI_ON void MPI_Bcast_binned_opacities(const ptrdiff_t nonemptymgi, const int root_node_id) { if constexpr (EXPANSIONOPACITIES_ON) { if (globals::rank_in_node == 0) { @@ -1140,7 +1126,6 @@ void MPI_Bcast_binned_opacities(const ptrdiff_t nonemptymgi, const int root_node } } } -#endif void calculate_expansion_opacities(const int nonemptymgi) { const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); diff --git a/sn3d.cc b/sn3d.cc index 3c08e6625..6c79d7935 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -12,11 +12,8 @@ #include "sn3d.h" -#ifdef MPI_ON -#include -#endif - #include +#include #include #include @@ -43,14 +40,12 @@ #include "grid.h" #include "input.h" #include "macroatom.h" -#ifdef MPI_ON -#include "rpkt.h" -#endif #include "nltepop.h" #include "nonthermal.h" #include "packet.h" #include "radfield.h" #include "ratecoeff.h" +#include "rpkt.h" #include "spectrum_lightcurve.h" #include "stats.h" #include "update_grid.h" @@ -153,20 +148,16 @@ void write_deposition_file() { } } -#ifdef MPI_ON - // in MPI mode, each process only calculated the contribution of a subset of cells + // each MPI rank only calculated the contribution of a subset of cells MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_positron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_electron_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].eps_alpha_ana_power, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_betaminus, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_alpha, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &globals::timesteps[nts].qdot_total, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -#endif -#ifdef MPI_ON MPI_Allreduce(MPI_IN_PLACE, &mtot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); -#endif if (my_rank == 0) { FILE *dep_file = fopen_required("deposition.out.tmp", "w"); @@ -209,7 +200,6 @@ void write_deposition_file() { std::time(nullptr) - time_write_deposition_file_start); } -#ifdef MPI_ON void mpi_communicate_grid_properties() { const ptrdiff_t nincludedions = get_includedions(); const ptrdiff_t nelements = get_nelements(); @@ -360,7 +350,6 @@ void mpi_reduce_estimators(const int nts) { MPI_Barrier(MPI_COMM_WORLD); } -#endif void write_temp_packetsfile(const int timestep, const int my_rank, const Packet *pkt) { // write packets binary file (and retry if the write fails) @@ -411,10 +400,7 @@ void remove_grid_restart_data(const int timestep) { } auto walltime_sufficient_to_continue(const int nts, const int nts_prev, const int walltimelimitseconds) -> bool { -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - // time is measured from just before packet propagation from one timestep to the next const int estimated_time_per_timestep = std::time(nullptr) - time_timestep_start; printout("TIME: time between timesteps is %d seconds (measured packet prop of ts %d and update grid of ts %d)\n", @@ -429,10 +415,8 @@ auto walltime_sufficient_to_continue(const int nts, const int nts_prev, const in // This flag being false will make it update_grid, and then exit do_this_full_loop = (wallclock_remaining_seconds >= (1.5 * estimated_time_per_timestep)); -#ifdef MPI_ON // communicate whatever decision the rank 0 process decided, just in case they differ MPI_Bcast(&do_this_full_loop, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); -#endif if (do_this_full_loop) { printout("TIMED_RESTARTS: Going to continue since remaining time %d s >= 1.5 * time_per_timestep\n", wallclock_remaining_seconds); @@ -445,9 +429,7 @@ auto walltime_sufficient_to_continue(const int nts, const int nts_prev, const in } void save_grid_and_packets(const int nts, const Packet *packets) { -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif const auto my_rank = globals::my_rank; bool write_successful = false; @@ -462,9 +444,8 @@ void save_grid_and_packets(const int nts, const Packet *packets) { const auto time_write_packets_finished_thisrank = std::time(nullptr); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif + const auto timenow = std::time(nullptr); printout("time after write temporary packets file %ld (took %lds, waited %lds, total %lds)\n", timenow, @@ -472,9 +453,7 @@ void save_grid_and_packets(const int nts, const Packet *packets) { timenow - time_write_packets_finished_thisrank, timenow - time_write_packets_file_start); if constexpr (VERIFY_WRITTEN_PACKETS_FILES) { -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif const auto time_readback_packets_start = std::time(nullptr); @@ -483,9 +462,7 @@ void save_grid_and_packets(const int nts, const Packet *packets) { // read packets file back to check that the disk write didn't fail write_successful = verify_temp_packetsfile(nts, my_rank, packets); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif printout("Verifying packets files for all ranks took %ld seconds.\n", std::time(nullptr) - time_readback_packets_start); @@ -501,9 +478,7 @@ void save_grid_and_packets(const int nts, const Packet *packets) { if (!KEEP_ALL_RESTART_FILES) { // ensure new packets files have been written by all processes before we remove the old set -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif if (my_rank == 0) { remove_grid_restart_data(nts - 1); @@ -516,9 +491,7 @@ void save_grid_and_packets(const int nts, const Packet *packets) { } void zero_estimators() { -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif radfield::zero_estimators(); if constexpr (TRACK_ION_STATS) { for (int nonemptymgi = 0; nonemptymgi < grid::get_nonempty_npts_model(); nonemptymgi++) { @@ -545,9 +518,7 @@ void zero_estimators() { } } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif } void normalise_deposition_estimators(int nts) { @@ -615,9 +586,7 @@ auto do_timestep(const int nts, const int titer, Packet *packets, const int wall const auto sys_time_start_communicate_grid = std::time(nullptr); // Each process has now updated its own set of cells. The results now need to be communicated between processes. -#ifdef MPI_ON mpi_communicate_grid_properties(); -#endif printout("timestep %d: time after grid properties have been communicated %ld (took %ld seconds)\n", nts, std::time(nullptr), std::time(nullptr) - sys_time_start_communicate_grid); @@ -636,27 +605,21 @@ auto do_timestep(const int nts, const int titer, Packet *packets, const int wall // and also the photoion and stimrecomb estimators zero_estimators(); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif if ((nts < globals::timestep_finish) && do_this_full_loop) { // Now process the packets. update_packets(nts, std::span{packets, static_cast(globals::npkts)}); -#ifdef MPI_ON // All the processes have their own versions of the estimators for this time step now. // Since these are going to be needed in the next time step, we will gather all the // estimators together now, sum them, and distribute the results const auto time_communicate_estimators_start = std::time(nullptr); mpi_reduce_estimators(nts); -#endif -#ifdef MPI_ON printout("timestep %d: time after estimators have been communicated %ld (took %ld seconds)\n", nts, std::time(nullptr), std::time(nullptr) - time_communicate_estimators_start); -#endif // The estimators have been summed across all processes and distributed. // They will now be normalised independently on all processes. @@ -738,9 +701,7 @@ auto main(int argc, char *argv[]) -> int { nvpkt_esc3 = 0; } -#ifdef MPI_ON MPI_Init(&argc, &argv); -#endif globals::setup_mpi_vars(); @@ -814,7 +775,6 @@ auto main(int argc, char *argv[]) -> int { printout("TESTMODE is ON\n"); #endif -#ifdef MPI_ON printout("process id (pid): %d\n", getpid()); printout("MPI enabled:\n"); printout(" rank %d of [0..%d] in MPI_COMM_WORLD\n", globals::my_rank, globals::nprocs - 1); @@ -826,9 +786,6 @@ auto main(int argc, char *argv[]) -> int { "present\n", MAX_NODE_SIZE); #endif -#else - printout("MPI is disabled in this build\n"); -#endif input(my_rank); if (globals::simulation_continued_from_saved) { @@ -851,11 +808,9 @@ auto main(int argc, char *argv[]) -> int { ratecoefficients_init(); -#ifdef MPI_ON printout("barrier after tabulation of rate coefficients: time before barrier %ld, ", std::time(nullptr)); MPI_Barrier(MPI_COMM_WORLD); printout("time after barrier %ld\n", std::time(nullptr)); -#endif stats::init(); @@ -902,10 +857,7 @@ auto main(int argc, char *argv[]) -> int { printout("\n"); } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - globals::timestep = globals::timestep_initial; macroatom_open_file(my_rank); @@ -923,13 +875,7 @@ auto main(int argc, char *argv[]) -> int { vpkt_init(globals::timestep, my_rank, globals::simulation_continued_from_saved); while (globals::timestep < globals::timestep_finish && !terminate_early) { -#ifdef MPI_ON - // const auto time_before_barrier = std::time(nullptr); MPI_Barrier(MPI_COMM_WORLD); - // const auto time_after_barrier = std::time(nullptr); - // printout("timestep %d: time before barrier %d, time after barrier %d\n", nts, time_before_barrier, - // time_after_barrier); -#endif // titer example: Do 3 iterations on timestep 0-6 // globals::n_titer = (nts < 6) ? 3: 1; @@ -954,10 +900,7 @@ auto main(int argc, char *argv[]) -> int { // Spectra and light curves are now extracted using exspec which is another make target of this // code. -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - if (linestat_file != nullptr) { fclose(linestat_file); } @@ -968,10 +911,7 @@ auto main(int argc, char *argv[]) -> int { printout("No need for restart\n"); } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - const auto real_time_end = std::time(nullptr); printout("sn3d finished at %ld (this job wallclock hours %.2f * %d processes * %d threads = %.1f core hours)\n", real_time_end, (real_time_end - real_time_start) / 3600., globals::nprocs, get_max_threads(), @@ -991,9 +931,7 @@ auto main(int argc, char *argv[]) -> int { decay::cleanup(); -#ifdef MPI_ON MPI_Finalize(); -#endif const std::filesystem::path pid_file_path("artis.pid"); if (std::filesystem::exists(pid_file_path)) { diff --git a/sn3d.h b/sn3d.h index bce2780d7..7045635b0 100644 --- a/sn3d.h +++ b/sn3d.h @@ -47,9 +47,7 @@ #include #endif -#ifdef MPI_ON #include -#endif #ifdef __NVCOMPILER_CUDA_ARCH__ #define THREADLOCALONHOST @@ -306,10 +304,8 @@ inline void check_already_running() { pidfile.close(); } -// make sure rank 0 checked for a pid file before we proceed -#ifdef MPI_ON + // make sure rank 0 checked for a pid file before we proceed MPI_Barrier(MPI_COMM_WORLD); -#endif } constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, const ptrdiff_t nchunk) @@ -328,7 +324,6 @@ constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, co return std::tuple{nstart, nsize}; } -#ifdef MPI_ON template [[nodiscard]] auto MPI_shared_malloc_keepwin(const ptrdiff_t num_allranks) -> std::tuple { if (num_allranks == 0) { @@ -350,18 +345,13 @@ template MPI_Barrier(globals::mpi_comm_node); return {ptr, mpiwin}; } -#endif template [[nodiscard]] auto MPI_shared_malloc(const ptrdiff_t num_allranks) -> T * { if (num_allranks == 0) { return nullptr; } -#ifdef MPI_ON T *ptr = std::get<0>(MPI_shared_malloc_keepwin(num_allranks)); -#else - T *ptr = static_cast(malloc(num_allranks * sizeof(T))); -#endif assert_always(ptr != nullptr); return ptr; } diff --git a/spectrum_lightcurve.cc b/spectrum_lightcurve.cc index fad7e71f1..38ce4db54 100644 --- a/spectrum_lightcurve.cc +++ b/spectrum_lightcurve.cc @@ -1,14 +1,13 @@ #include "spectrum_lightcurve.h" +#include + #include #include #include #include #include #include -#ifdef MPI_ON -#include -#endif #include #include #include @@ -300,7 +299,6 @@ void add_to_spec(const Packet &pkt, const int current_abin, Spectra &spectra, Sp } } -#ifdef MPI_ON void mpi_reduce_spectra(int my_rank, Spectra &spectra) { MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : spectra.fluxalltimesteps.data(), spectra.fluxalltimesteps.data(), spectra.fluxalltimesteps.size(), MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); @@ -317,7 +315,6 @@ void mpi_reduce_spectra(int my_rank, Spectra &spectra) { MPI_COMM_WORLD); } } -#endif void write_specpol_param(FILE *specpol_file, FILE *emissionpol_file, FILE *absorptionpol_file, const Spectra &spec, const int nnu, const bool do_emission_res) { @@ -581,7 +578,6 @@ void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Pa assert_always(numtimesteps <= globals::ntimesteps); const auto time_mpireduction_start = std::time(nullptr); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); mpi_reduce_spectra(my_rank, rpkt_spectra); MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : rpkt_light_curve_lum.data(), rpkt_light_curve_lum.data(), numtimesteps, @@ -593,7 +589,6 @@ void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Pa MPI_Reduce(my_rank == 0 ? MPI_IN_PLACE : gamma_light_curve_lumcmf.data(), gamma_light_curve_lumcmf.data(), numtimesteps, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); -#endif const auto time_mpireduction_end = std::time(nullptr); if (my_rank == 0) { @@ -602,10 +597,7 @@ void write_partial_lightcurve_spectra(const int my_rank, const int nts, const Pa write_spectrum("spec.out", "emission.out", "emissiontrue.out", "absorption.out", rpkt_spectra, numtimesteps); } -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif - printout("timestep %d: Saving partial light curves and %sspectra took %lds (%lds for MPI reduction)\n", nts, do_emission_res ? "emission/absorption " : "", std::time(nullptr) - time_func_start, time_mpireduction_end - time_mpireduction_start); diff --git a/stats.cc b/stats.cc index 8c6d8a9b6..f85473712 100644 --- a/stats.cc +++ b/stats.cc @@ -1,8 +1,6 @@ #include "stats.h" -#ifdef MPI_ON #include -#endif #include #include @@ -229,10 +227,8 @@ void pkt_action_counters_printout(const int nts) { } void reduce_estimators() { -#ifdef MPI_ON MPI_Allreduce(MPI_IN_PLACE, stats::ionstats.data(), grid::get_npts_model() * get_includedions() * stats::ION_STAT_COUNT, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -#endif } } // namespace stats diff --git a/update_grid.cc b/update_grid.cc index f11ace20e..cc83472b1 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1,8 +1,6 @@ #include "update_grid.h" -#ifdef MPI_ON #include -#endif #include #include @@ -1162,9 +1160,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const const auto time_update_grid_end_thisrank = std::time(nullptr); printout("finished update grid on this rank at time %ld\n", time_update_grid_end_thisrank); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); -#endif printout( "timestep %d: time after update grid for all processes %ld (rank %d took %lds, waited " "%lds, total %lds)\n", diff --git a/update_packets.cc b/update_packets.cc index 46e56b337..0dcb73a1c 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -1,8 +1,6 @@ #include "update_packets.h" -#ifdef MPI_ON #include -#endif #include #include @@ -429,9 +427,7 @@ void update_packets(const int nts, std::span packets) { const auto time_update_packets_end_thisrank = std::time(nullptr); printout("timestep %d: end of update_packets for this rank at time %ld\n", nts, time_update_packets_end_thisrank); -#ifdef MPI_ON MPI_Barrier(MPI_COMM_WORLD); // hold all processes once the packets are updated -#endif printout( "timestep %d: time after update packets for all processes %ld (rank %d took %lds, waited %lds, total %lds)\n", nts, std::time(nullptr), globals::my_rank, time_update_packets_end_thisrank - time_update_packets_start, From c7006acf8df95f5cf6ede24df9f1a039947d67db Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 5 Nov 2024 17:06:39 +0000 Subject: [PATCH 082/117] Don't save nonthermalspec files (#146) Spencer-Fano solution can be re-solved using ion populations in artistools. --- grid.cc | 2 +- nonthermal.cc | 55 +------------------ nonthermal.h | 2 +- .../results_md5_final.txt | 3 - .../results_md5_job0.txt | 3 - .../results_md5_final.txt | 3 - .../results_md5_job0.txt | 3 - 7 files changed, 3 insertions(+), 68 deletions(-) diff --git a/grid.cc b/grid.cc index 3d0867f33..1a7907601 100644 --- a/grid.cc +++ b/grid.cc @@ -2255,7 +2255,7 @@ void grid_init(const int my_rank) { const int ndo_nonempty = grid::get_ndo_nonempty(my_rank); radfield::init(my_rank, ndo_nonempty); - nonthermal::init(my_rank, ndo_nonempty); + nonthermal::init(); // and assign a temperature to the cells if (globals::simulation_continued_from_saved) { diff --git a/nonthermal.cc b/nonthermal.cc index 1a3038e88..46c59d5de 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -88,8 +87,6 @@ struct collionrow { std::vector colliondata; -FILE *nonthermalfile{}; - static_assert(SF_EMIN > 0.); constexpr double DELTA_E = (SF_EMAX - SF_EMIN) / (SFPTS - 1); @@ -793,40 +790,6 @@ void zero_all_effionpot(const int nonemptymgi) { // return yfunc[index]; } -void nt_write_to_file(const int modelgridindex, const int timestep, const int iteration, - const std::array &yfunc) { -#ifdef _OPENMP -#pragma omp critical(nonthermal_out_file) - { -#endif - assert_always(nonthermalfile != nullptr); - - static int64_t nonthermalfile_offset_iteration_zero = 0; -#ifdef _OPENMP -#pragma omp threadprivate(nonthermalfile_offset_iteration_zero) -#endif - { - if (iteration == 0) { - nonthermalfile_offset_iteration_zero = ftell(nonthermalfile); - } else { - // overwrite the non-thermal spectrum of a previous iteration of the same timestep and gridcell - assert_always(fseek(nonthermalfile, nonthermalfile_offset_iteration_zero, SEEK_SET) == 0); - } - } - - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); - const double yscalefactor = get_deposition_rate_density(nonemptymgi) / (E_init_ev * EV); - - for (int s = 0; s < SFPTS; s++) { - fprintf(nonthermalfile, "%d %d %d %.5e %.5e %.5e\n", timestep, modelgridindex, s, engrid(s), sourcevec(s), - yscalefactor * yfunc[s]); - } - fflush(nonthermalfile); -#ifdef _OPENMP - } -#endif -} - auto xs_ionization_lotz(const double en_erg, const collionrow &colliondata_ion) -> double { const double ionpot_ev = colliondata_ion.ionpot_ev; if (en_erg < (ionpot_ev * EV)) { @@ -2061,7 +2024,7 @@ auto sfmatrix_solve(const std::vector &sfmatrix) -> std::array(nonempty_npts_model); @@ -2093,14 +2056,6 @@ void init(const int my_rank, const int ndo_nonempty) { printout(" SF_AUGER_CONTRIBUTION %s\n", SF_AUGER_CONTRIBUTION_ON ? "on" : "off"); printout(" SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN %s\n", SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN ? "on" : "off"); - if (ndo_nonempty > 0) { - char filename[MAXFILENAMELENGTH]; - snprintf(filename, MAXFILENAMELENGTH, "nonthermalspec_%.4d.out", my_rank); - nonthermalfile = fopen_required(filename, "w"); - fprintf(nonthermalfile, "timestep modelgridindex index energy_ev source y\n"); - fflush(nonthermalfile); - } - if (NT_EXCITATION_ON) { nt_excitations_stored = std::min(MAX_NT_EXCITATIONS_STORED, get_possible_nt_excitation_count()); printout("[info] mem_usage: storing %d non-thermal excitations for non-empty cells occupies %.3f MB\n", @@ -2195,10 +2150,6 @@ void close_file() { return; } - if (nonthermalfile != nullptr) { - fclose(nonthermalfile); - nonthermalfile = nullptr; - } colliondata.clear(); } @@ -2604,10 +2555,6 @@ void solve_spencerfano(const int nonemptymgi, const int timestep, const int iter decompactify_triangular_matrix(sfmatrix); const auto yfunc = sfmatrix_solve(sfmatrix); - if (timestep % 10 == 0) { - nt_write_to_file(modelgridindex, timestep, iteration, yfunc); - } - analyse_sf_solution(nonemptymgi, timestep, enable_sfexcitation, yfunc); } diff --git a/nonthermal.h b/nonthermal.h index fd54a1dcf..fd15a04d4 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -7,7 +7,7 @@ #include "thermalbalance.h" namespace nonthermal { -void init(int my_rank, int ndo_nonempty); +void init(); void close_file(); void solve_spencerfano(int nonemptymgi, int timestep, int iteration); [[nodiscard]] auto nt_ionization_ratecoeff(int nonemptymgi, int element, int ion) -> double; diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt index 379a55f10..0e2093a66 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_final.txt @@ -22,9 +22,6 @@ fb7cd3f5a650f7fd327bb881fa309e56 job1/estimators_0001.out 7c7f8384eb6ffdc73439d8255444761b job1/nlte_0000.out 2955bcccd9ff1744d5cc635463f92f74 job1/nlte_0001.out f6dfc69e1ecbe5e4838160c94eae4390 job1/nlte_0002.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out 6cefe0c0f4f344ae0fe215479ff702c0 job1/radfield_0000.out 3ac6a500599048c09861ae54d838d551 job1/radfield_0001.out 0ae4c4599d3caf162e94e1c81ba6f47c job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt index aede92c2c..2855e7c50 100644 --- a/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -21,9 +21,6 @@ ce6db00706ebfd0ffd47a42b06dd63f9 packets00_0003.out db7b6f001f5b1115a36a9e5e99a7b8d1 job0/nlte_0000.out 065e80e98b641952bce2db500aa8f8c0 job0/nlte_0001.out 38f8a173a5c4e2acb4c6dc18fe6c2aac job0/nlte_0002.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out 3eb872041047a946222d9e8896a3140f job0/radfield_0000.out d364314ae61b485d9a05907342706167 job0/radfield_0001.out d33aa4018ec2f1adda99e9891562f002 job0/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt index 1fbcbbc01..7fdd80a99 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_final.txt @@ -22,9 +22,6 @@ abb88431c718b2898e817ad76e8a099b job1/estimators_0002.out 7fad386c6c6ad93e558954325e0a3b27 job1/nlte_0000.out af22d7b135926c5ddecab95db3be05c6 job1/nlte_0001.out 6ddb80fd4753109834df1ac4ea15f44b job1/nlte_0002.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0000.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0001.out -098fc87f14a17287756a3a4f2cadc922 job1/nonthermalspec_0002.out 9b775cd0c4a0ec68188ba6eb9395766e job1/radfield_0000.out 2f140f78ac85f4eca187c713c6a9b120 job1/radfield_0001.out 966a4ad7b86bd21abc07064dde2a337c job1/radfield_0002.out diff --git a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt index 2cc983afc..2b64363db 100644 --- a/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt +++ b/tests/nebular_1d_3dgrid_limitbfest_inputfiles/results_md5_job0.txt @@ -21,9 +21,6 @@ bc6393b0fa989162a19cb6a8e45d369f job0/estimators_0001.out 293a0481beead6b266c51ef55813abd4 job0/nlte_0000.out 212fd9d5a9a09c0da30be8fd54584e48 job0/nlte_0001.out 22f4dfabcb46ecfb742e43d66e9d7c8e job0/nlte_0002.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0000.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0001.out -098fc87f14a17287756a3a4f2cadc922 job0/nonthermalspec_0002.out 82c5527878531c8cd0ed309ac4e6411b job0/radfield_0000.out 714469b7b7094e4847ddea178529a378 job0/radfield_0001.out f81c683aeee7965f09b112d398c77b15 job0/radfield_0002.out From d89b4211131fdea34524ec4b60cf3cde1502638b Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 6 Nov 2024 08:23:52 +0000 Subject: [PATCH 083/117] Auto disable resume from saved when starting from timestep zero --- input.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/input.cc b/input.cc index a25bf5b89..53ab10dfe 100644 --- a/input.cc +++ b/input.cc @@ -1684,11 +1684,14 @@ void read_parameterfile(int rank) { assert_always(get_noncommentline(file, line)); std::istringstream(line) >> continue_flag; globals::simulation_continued_from_saved = (continue_flag == 1); + if (globals::timestep_initial == 0) { + // it's not possible to resume from a saved point if we start from timestep zero, so override the flag + globals::simulation_continued_from_saved = false; + } if (globals::simulation_continued_from_saved) { printout("input: resuming simulation from saved point\n"); } else { printout("input: starting a new simulation\n"); - assert_always(globals::timestep_initial == 0); } // Wavelength (in Angstroms) at which the parameterisation of the radiation field From 6911fd3f0ed080bd0d7a4ad230bd983a8101f9f7 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 6 Nov 2024 08:18:40 +0000 Subject: [PATCH 084/117] Makefile: Enable extra warnings --- Makefile | 7 ++++--- decay.cc | 10 +++++++--- ratecoeff.cc | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 75fc9937b..18cc60f56 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,6 @@ # place in architecture folder, e.g. build/arm64 BUILD_DIR = build/$(shell uname -m) -CXX := mpicxx $(info mpicxx version: $(shell mpicxx --showme:version 2> /dev/null)) ifeq ($(TESTMODE),ON) @@ -18,12 +17,14 @@ endif ifeq ($(REPRODUCIBLE),ON) CXXFLAGS += -DREPRODUCIBLE=true -ffp-contract=off BUILD_DIR := $(BUILD_DIR)_reproducible + FASTMATH := OFF else ifeq ($(REPRODUCIBLE),OFF) else ifeq ($(REPRODUCIBLE),) else $(error bad value for REPRODUCIBLE option. Should be ON or OFF) endif +CXX := mpicxx COMPILER_VERSION := $(shell $(CXX) --version) $(info $(COMPILER_VERSION)) ifneq '' '$(findstring clang,$(COMPILER_VERSION))' @@ -44,7 +45,7 @@ $(info detected compiler is $(COMPILER_NAME)) ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -std=c++20 else - CXXFLAGS += -std=c++23 -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -MD -MP -ftrivial-auto-var-init=pattern + CXXFLAGS += -std=c++23 -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -Wno-error=cast-function-type -MD -MP -ftrivial-auto-var-init=pattern endif CXXFLAGS += -fstrict-aliasing @@ -226,7 +227,7 @@ else endif endif -CXXFLAGS += -Winline -Wall -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow +CXXFLAGS += -Winline -Wall -Wextra -pedantic -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow # sn3d.cc and exspec.cc have main() defined common_files := $(filter-out sn3d.cc exspec.cc, $(wildcard *.cc)) diff --git a/decay.cc b/decay.cc index 6326a684e..55d3ba88b 100644 --- a/decay.cc +++ b/decay.cc @@ -384,7 +384,9 @@ void find_decaypaths(const std::vector &custom_zlist, const std::vector(1, z), .a = std::vector(1, a), .nucindex = std::vector(1, startnucindex), - .decaytypes = std::vector(1, decaytype)}); + .decaytypes = std::vector(1, decaytype), + .lambdas = {}, + .branchproduct = 0.}); extend_lastdecaypath(); // take this single step chain and find all descendants } @@ -549,7 +551,8 @@ auto get_nuc_massfrac(const int nonemptymgi, const int z, const int a, const dou // Get the mass fraction of a nuclide accounting for all decays including those of its parent and grandparent. // e.g., Co56 abundance may first increase with time due to Ni56 decays, then decease due to Co56 decay // Can be called for stable nuclides that are one daughters of the radioactive nuclide list e.g., Fe56 -// For stable nuclides, abundance returned only comes from other decays (some could be included in init model elem frac) +// For stable nuclides, abundance returned only comes from other decays (some could be included in init model elem +// frac) { const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); assert_always(time >= 0.); @@ -650,7 +653,8 @@ auto get_endecay_to_tinf_per_ejectamass_at_time(const int modelgridindex, const return endecay; } -// Simple Euler integration as a check on the analytic result from get_endecay_per_ejectamass_t0_to_time_withexpansion() +// Simple Euler integration as a check on the analytic result from +// get_endecay_per_ejectamass_t0_to_time_withexpansion() auto get_endecay_per_ejectamass_t0_to_time_withexpansion_chain_numerical(const int nonemptymgi, const int decaypathindex, const double tstart) -> double { diff --git a/ratecoeff.cc b/ratecoeff.cc index ec2e9c583..17cf90071 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -690,6 +690,7 @@ auto calculate_stimrecombcoeff_integral(const int element, const int lowerion, c const auto T_e = grid::get_Te(nonemptymgi); const auto intparas = GSLIntegralParasGammaCorr{ .nu_edge = nu_threshold, + .departure_ratio = 1., // not used, but must be set to something .photoion_xs = get_phixs_table(element, lowerion, level), .T_e = T_e, .nonemptymgi = nonemptymgi, From f7f5d70d2253a484276600569e7fe3f3d37c86ec Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 6 Nov 2024 09:44:33 +0000 Subject: [PATCH 085/117] Check working directory matched as well as pid running to prevent multiple sn3d running in same directory (#147) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ple sn3d per folder --- sn3d.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sn3d.h b/sn3d.h index 7045635b0..021dc25f4 100644 --- a/sn3d.h +++ b/sn3d.h @@ -27,6 +27,7 @@ #include #include #include +#include #ifndef GPU_ON #include #endif @@ -288,9 +289,16 @@ inline void check_already_running() { if (std::filesystem::exists("artis.pid")) { auto pidfile = std::fstream("artis.pid", std::ios::in); pid_t artispid_in = 0; - pidfile >> artispid_in; + std::string line; + std::getline(pidfile, line); + std::istringstream ssline1(line); + ssline1 >> artispid_in; + std::getline(pidfile, line); + std::istringstream ssline2(line); + std::string working_directory; + ssline2 >> working_directory; pidfile.close(); - if (is_pid_running(artispid_in)) { + if (is_pid_running(artispid_in) && std::filesystem::current_path().generic_string() == working_directory) { fprintf(stderr, "\nERROR: artis or exspec is already running in this folder with existing pid %d. Refusing to start. " "(delete artis.pid if you are sure this is incorrect)\n", @@ -300,7 +308,8 @@ inline void check_already_running() { } auto pidfile = std::fstream("artis.pid", std::ofstream::out | std::ofstream::trunc); - pidfile << artispid; + pidfile << artispid << '\n'; + pidfile << std::filesystem::current_path().generic_string() << '\n'; pidfile.close(); } From 44c7d50adfbfe3d914d84c7f4089f920de20a194 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 6 Nov 2024 22:25:48 +0000 Subject: [PATCH 086/117] Speed up hybrid NLTE mode when LTEPOP_EXCITATION_USE_TJ = false (#148) Only update the ion gammas (for ion balance) for the new T_e if T_e changes by more than 10% --- .github/workflows/ci-checks.yml | 1 - Makefile | 2 +- gammapkt.cc | 10 +-- grid.cc | 145 ++++++++++++++++---------------- grid.h | 6 +- ltepop.cc | 34 ++++---- nltepop.cc | 21 ++--- nltepop.h | 4 +- nonthermal.cc | 2 +- packet.cc | 6 +- ratecoeff.cc | 2 +- thermalbalance.cc | 35 ++++---- update_grid.cc | 2 +- update_packets.cc | 14 +-- vpkt.cc | 4 +- 15 files changed, 143 insertions(+), 145 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 884d5d7ce..f39c5df40 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -74,7 +74,6 @@ jobs: run: | brew update brew install openmpi gsl || true - brew link openmpi python3 -m pip install compiledb - name: Generate compile_commands.json diff --git a/Makefile b/Makefile index 18cc60f56..7a047e0d0 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ endif ifeq ($(REPRODUCIBLE),ON) CXXFLAGS += -DREPRODUCIBLE=true -ffp-contract=off BUILD_DIR := $(BUILD_DIR)_reproducible - FASTMATH := OFF + FASTMATH := OFF else ifeq ($(REPRODUCIBLE),OFF) else ifeq ($(REPRODUCIBLE),) else diff --git a/gammapkt.cc b/gammapkt.cc index 56893e361..9f39edc33 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -460,7 +460,7 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { double chi_cmf{NAN}; // Start by working out the x-section in the co-moving frame. - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); if (mgi >= grid::get_npts_model()) { return 0.; // empty cell @@ -554,7 +554,7 @@ auto get_chi_photo_electric_rf(const Packet &pkt) -> double { // calculate the absorption coefficient [cm^-1] for pair production in the observer reference frame auto get_chi_pair_prod_rf(const Packet &pkt) -> double { - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); if (mgi >= grid::get_npts_model()) { return 0.; // empty cell } @@ -891,7 +891,7 @@ void wollaeger_thermalisation(Packet &pkt) { const auto [sdist, snext] = grid::boundary_distance(pkt_copy.dir, pkt_copy.pos, pkt_copy.prop_time, pkt_copy.where, &pkt_copy.last_cross); const double s_cont = sdist * t_current * t_current * t_current / std::pow(pkt_copy.prop_time, 3); - const int mgi = grid::get_cell_modelgridindex(pkt_copy.where); + const int mgi = grid::get_propcell_modelgridindex(pkt_copy.where); if (mgi != grid::get_npts_model()) { const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); tau += grid::get_rho(nonemptymgi) * s_cont * mean_gamma_opac; // contribution to the integral @@ -953,7 +953,7 @@ void guttman_thermalisation(Packet &pkt) { const auto [sdist, snext] = grid::boundary_distance(pkt_copy.dir, pkt_copy.pos, pkt_copy.prop_time, pkt_copy.where, &pkt_copy.last_cross); const double s_cont = sdist * std::pow(t, 3.) / std::pow(pkt_copy.prop_time, 3.); - const int mgi = grid::get_cell_modelgridindex(pkt_copy.where); + const int mgi = grid::get_propcell_modelgridindex(pkt_copy.where); if (mgi != grid::get_npts_model()) { column_densities[i] += grid::get_rho_tmin(mgi) * s_cont; // contribution to the integral } @@ -1077,7 +1077,7 @@ __host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { if constexpr (GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILED && GAMMA_THERMALISATION_SCHEME != ThermalisationScheme::DETAILEDWITHGAMMAPRODUCTS) { // no transport, so the path-based gamma deposition estimator won't get updated unless we do it here - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); atomicadd(globals::dep_estimator_gamma[nonemptymgi], pkt.e_cmf); } diff --git a/grid.cc b/grid.cc index 1a7907601..17df9be54 100644 --- a/grid.cc +++ b/grid.cc @@ -67,16 +67,15 @@ double mfegroup = 0.; // Total mass of Fe group elements in ejecta int first_cellindex = -1; // auto-determine first cell index in model.txt (usually 1 or 0) -struct PropGridCell { - std::array pos_min{}; // Initial co-ordinates of inner most corner of cell. - int modelgridindex{-1}; -}; - -std::vector cell{}; +// Initial co-ordinates of inner most corner of cell. +std::vector> propcell_pos_min{}; +// associate each propagation cell with a model grid cell, or not, if the cell is empty (or doesn't get mapped to +// anything such as 1D/2D to 3D) +std::vector mgi_of_propcell; std::vector nonemptymgi_of_propcell; -std::vector mg_associated_cells; +std::vector modelgrid_numassociated_propcells; std::vector nonemptymgi_of_mgi; std::vector mgi_of_nonemptymgi; @@ -95,6 +94,8 @@ std::vector ranks_ndo; std::vector ranks_ndo_nonempty; inline std::span modelgrid_input{}; +constexpr auto NDIM = grid::get_ngriddimensions(GRID_TYPE); + void set_rho_tmin(const int modelgridindex, const float x) { modelgrid_input[modelgridindex].rhoinit = x; } void set_initelectronfrac(const int modelgridindex, const double electronfrac) { @@ -181,10 +182,12 @@ void set_ffegrp(const int modelgridindex, float x) { modelgrid_input[modelgridindex].ffegrp = x; } -void set_cell_modelgridindex(const int cellindex, const int new_modelgridindex) { +void set_propcell_modelgridindex(const int cellindex, const int new_modelgridindex) { + assert_testmodeonly(cellindex >= 0); assert_testmodeonly(cellindex < ngrid); + assert_testmodeonly(new_modelgridindex >= 0); assert_testmodeonly(new_modelgridindex <= get_npts_model()); - cell[cellindex].modelgridindex = new_modelgridindex; + mgi_of_propcell[cellindex] = new_modelgridindex; } void set_modelinitnucmassfrac(const int modelgridindex, const int nucindex, float abund) { @@ -284,7 +287,7 @@ void allocate_nonemptycells_composition_cooling() void allocate_nonemptymodelcells() { // Determine the number of simulation cells associated with the model cells - std::ranges::fill(mg_associated_cells, 0); + std::ranges::fill(modelgrid_numassociated_propcells, 0); if (globals::rank_in_node == 0) { for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { modelgrid_input[mgi].initial_radial_pos_sum = 0.; @@ -296,19 +299,19 @@ void allocate_nonemptymodelcells() { if (FORCE_SPHERICAL_ESCAPE_SURFACE && radial_pos_mid > globals::vmax * globals::tmin) { // for 1D models, the final shell outer v should already be at vmax - assert_always(model_type != GridType::SPHERICAL1D || cell[cellindex].modelgridindex == get_npts_model()); - cell[cellindex].modelgridindex = get_npts_model(); + assert_always(model_type != GridType::SPHERICAL1D || mgi_of_propcell[cellindex] == get_npts_model()); + set_propcell_modelgridindex(cellindex, get_npts_model()); } - const int mgi = get_cell_modelgridindex(cellindex); + const int mgi = get_propcell_modelgridindex(cellindex); assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); - mg_associated_cells[mgi] += 1; + modelgrid_numassociated_propcells[mgi] += 1; if (globals::rank_in_node == 0) { modelgrid_input[mgi].initial_radial_pos_sum += radial_pos_mid; } - assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (mg_associated_cells[mgi] == 1) || + assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (modelgrid_numassociated_propcells[mgi] == 1) || (mgi == get_npts_model())); } @@ -343,7 +346,7 @@ void allocate_nonemptymodelcells() { } MPI_Barrier(MPI_COMM_WORLD); for (int cellindex = 0; cellindex < ngrid; cellindex++) { - const int mgi = get_cell_modelgridindex(cellindex); + const int mgi = get_propcell_modelgridindex(cellindex); if (mgi >= get_npts_model()) { nonemptymgi_of_propcell[cellindex] = -1; } else { @@ -426,13 +429,13 @@ void map_1dmodelto3dgrid() const int mgi = static_cast(std::ranges::lower_bound(vout_model, cellvmid) - vout_model.begin()); if (mgi < get_npts_model() && modelgrid_input[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); + set_propcell_modelgridindex(cellindex, mgi); assert_always(vout_model[mgi] >= cellvmid); assert_always((mgi > 0 ? vout_model[mgi - 1] : 0.0) <= cellvmid); } else { // corner cells outside of the outermost model shell are empty // and so are any shells with zero density - set_cell_modelgridindex(cellindex, get_npts_model()); + set_propcell_modelgridindex(cellindex, get_npts_model()); } } } @@ -457,12 +460,12 @@ void map_2dmodelto3dgrid() const int mgi = (n_z * ncoord_model[0]) + n_rcyl; if (modelgrid_input[mgi].rhoinit > 0) { - set_cell_modelgridindex(cellindex, mgi); + set_propcell_modelgridindex(cellindex, mgi); } else { - set_cell_modelgridindex(cellindex, get_npts_model()); + set_propcell_modelgridindex(cellindex, get_npts_model()); } } else { - set_cell_modelgridindex(cellindex, get_npts_model()); + set_propcell_modelgridindex(cellindex, get_npts_model()); } } } @@ -472,7 +475,7 @@ void map_2dmodelto3dgrid() void map_modeltogrid_direct() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const int mgi = (modelgrid_input[cellindex].rhoinit > 0) ? cellindex : get_npts_model(); - set_cell_modelgridindex(cellindex, mgi); + set_propcell_modelgridindex(cellindex, mgi); } } @@ -1019,14 +1022,14 @@ void setup_grid_cartesian_3d() { assert_always(ncoordgrid[0] == ncoordgrid[2]); ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell.resize(ngrid, {}); + propcell_pos_min.resize(ngrid, {}); coordlabel = {'X', 'Y', 'Z'}; std::array nxyz = {0, 0, 0}; for (int n = 0; n < ngrid; n++) { for (int axis = 0; axis < 3; axis++) { assert_always(nxyz[axis] == get_cellcoordpointnum(n, axis)); - cell[n].pos_min[axis] = -globals::rmax + (2 * nxyz[axis] * globals::rmax / ncoordgrid[axis]); + propcell_pos_min[n][axis] = -globals::rmax + (2 * nxyz[axis] * globals::rmax / ncoordgrid[axis]); } assert_always(n == nxyz[2] * ncoordgrid[1] * ncoordgrid[2] + nxyz[1] * ncoordgrid[0] + nxyz[0]); @@ -1050,12 +1053,12 @@ void setup_grid_spherical1d() { ncoordgrid = {get_npts_model(), 1, 1}; ngrid = ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]; - cell.resize(ngrid, {}); + propcell_pos_min.resize(ngrid, {}); for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { const int mgi = cellindex; // interchangeable in this mode const double v_inner = mgi > 0 ? vout_model[mgi - 1] : 0.; - cell[cellindex].pos_min = {v_inner * globals::tmin, 0., 0.}; + propcell_pos_min[cellindex] = {v_inner * globals::tmin, 0., 0.}; } } @@ -1070,14 +1073,14 @@ void setup_grid_cylindrical_2d() { ncoordgrid = ncoord_model; ngrid = ncoordgrid[0] * ncoordgrid[1]; - cell.resize(ngrid, {}); + propcell_pos_min.resize(ngrid, {}); for (int cellindex = 0; cellindex < get_npts_model(); cellindex++) { const int n_rcyl = get_cellcoordpointnum(cellindex, 0); const int n_z = get_cellcoordpointnum(cellindex, 1); - cell[cellindex].pos_min = {n_rcyl * globals::rmax / ncoord_model[0], - globals::rmax * (-1 + n_z * 2. / ncoord_model[1]), 0.}; + propcell_pos_min[cellindex] = {n_rcyl * globals::rmax / ncoord_model[0], + globals::rmax * (-1 + n_z * 2. / ncoord_model[1]), 0.}; } } @@ -1095,9 +1098,9 @@ auto get_grid_type_name(const GridType gridtype) -> std::string { } } +// Get the discrete index of the coordinate value (where pos must be position in grid coordinate system, not necessarily +// xyz) auto get_poscoordpointnum(const double pos, const double time, const int axis) -> int { - // pos must be position in grid coordinate system, not necessarily xyz - if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { return static_cast((pos / time + globals::vmax) / 2 / globals::vmax * ncoordgrid[axis]); } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { @@ -1121,33 +1124,34 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - return -1; } -constexpr auto get_gridcoords_from_xyz(const std::array &pos_xyz) -> std::array { +// Convert a position in Cartesian xyz to the grid coordinate system (which might the same, or 2D cylindrical or 1D +// spherical) +constexpr auto get_gridcoords_from_xyz(const std::array &pos_xyz) { if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { - return pos_xyz; + return std::array{pos_xyz[0], pos_xyz[1], pos_xyz[2]}; } if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { - return {std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)), pos_xyz[2], 0.}; + return std::array{std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)), pos_xyz[2]}; } if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { - return {vec_len(pos_xyz), 0., 0.}; + return std::array{vec_len(pos_xyz)}; } assert_always(false); - return {0., 0., 0.}; + return std::array{}; } +// find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are +// 2-vectors or 3-vectors) or expanding circle (2D vectors) +// returns -1 if there are no forward intersections (or if the intersection +// is tangential to the shell) template [[nodiscard]] constexpr auto expanding_shell_intersection(const std::array &pos, const std::array &dir, const double speed, const double shellradiuststart, const bool isinnerboundary, - const double tstart) -> double -// find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are -// 3-vectors) or expanding circle (2D vectors) -// returns -1 if there are no forward intersections (or if the intersection -// is tangential to the shell) -{ + const double tstart) -> double { static_assert(S1 == 2 || S1 == 3); assert_always(shellradiuststart > 0); @@ -1238,15 +1242,15 @@ template auto get_coordboundary_distances_cylindrical2d(const std::array &pkt_pos, const std::array &pkt_dir, - const std::array &pktposgridcoord, - const std::array &pktvelgridcoord, const int cellindex, - const double tstart, const std::array &cellcoordmax) - -> std::tuple, std::array> { + const std::array &pktposgridcoord, + const std::array &pktvelgridcoord, const int cellindex, + const double tstart, const std::array &cellcoordmax) + -> std::tuple, std::array> { // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the // propagation speed set to the xy component of the 3-velocity - std::array d_coordminboundary{}; - std::array d_coordmaxboundary{}; + std::array d_coordminboundary{}; + std::array d_coordmaxboundary{}; const std::array posnoz = {pkt_pos[0], pkt_pos[1]}; @@ -1308,7 +1312,7 @@ auto wid_init(const int cellindex, const int axis) -> double } if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { - const int modelgridindex = get_cell_modelgridindex(cellindex); + const int modelgridindex = get_propcell_modelgridindex(cellindex); const double v_inner = modelgridindex > 0 ? vout_model[modelgridindex - 1] : 0.; return (vout_model[modelgridindex] - v_inner) * globals::tmin; } @@ -1336,7 +1340,7 @@ auto get_modelcell_assocvolume_tmin(const int modelgridindex) -> double { assert_always(false); } -auto get_gridcell_volume_tmin(const int cellindex) -> double +auto get_propcell_volume_tmin(const int cellindex) -> double // return the propagation cell volume at globals::tmin // for a spherical grid, the cell index is required (and should be equivalent to a modelgridindex) { @@ -1345,7 +1349,7 @@ auto get_gridcell_volume_tmin(const int cellindex) -> double } // 2D and 1D with direct mapping to propagation cells - const int mgi = get_cell_modelgridindex(cellindex); + const int mgi = get_propcell_modelgridindex(cellindex); return get_modelcell_assocvolume_tmin(mgi); } @@ -1373,7 +1377,7 @@ auto get_cellcoordmax(const int cellindex, const int axis) -> double // get the minimum value of a coordinate at globals::tmin (xyz or radial coords) of a propagation cell // e.g., the minimum x position in xyz coords, or the minimum radius auto get_cellcoordmin(const int cellindex, const int axis) -> double { - return cell[cellindex].pos_min[axis]; + return propcell_pos_min[cellindex][axis]; // return - coordmax[axis] + (2 * get_cellcoordpointnum(cellindex, axis) * coordmax[axis] / ncoordgrid[axis]); } @@ -1573,10 +1577,10 @@ auto get_t_model() -> double { return t_model; } -[[nodiscard]] __host__ __device__ auto get_cell_modelgridindex(const int cellindex) -> int { +[[nodiscard]] __host__ __device__ auto get_propcell_modelgridindex(const int cellindex) -> int { assert_testmodeonly(cellindex >= 0); assert_testmodeonly(cellindex < ngrid); - const auto mgi = cell[cellindex].modelgridindex; + const auto mgi = mgi_of_propcell[cellindex]; assert_testmodeonly(mgi >= 0); assert_testmodeonly(mgi < (get_npts_model() + 1)); return mgi; @@ -1592,7 +1596,7 @@ auto get_t_model() -> double { // number of propagation cells associated with each modelgrid cell __host__ __device__ auto get_numpropcells(const int modelgridindex) -> int { assert_testmodeonly(modelgridindex <= get_npts_model()); - return mg_associated_cells[modelgridindex]; + return modelgrid_numassociated_propcells[modelgridindex]; } // get the index in the list of non-empty cells for a given model grid cell @@ -1692,8 +1696,7 @@ auto get_cellradialposmid(const int cellindex) -> double { return vec_len(dcen); } -[[nodiscard]] auto get_elements_uppermost_ion(const int modelgridindex, const int element) -> int { - const ptrdiff_t nonemptymgi = get_nonemptymgi_of_mgi(modelgridindex); +[[nodiscard]] auto get_elements_uppermost_ion(const int nonemptymgi, const int element) -> int { return elements_uppermost_ion_allcells[(nonemptymgi * get_nelements()) + element]; } @@ -1875,7 +1878,7 @@ void read_ejecta_model() { std::ranges::fill(modelgrid_input, ModelGridCellInput{}); } MPI_Barrier(globals::mpi_comm_node); - mg_associated_cells.resize(npts_model + 1, 0); + modelgrid_numassociated_propcells.resize(npts_model + 1, 0); nonemptymgi_of_mgi.resize(npts_model + 1, -1); if (get_model_type() == GridType::SPHERICAL1D) { @@ -2199,6 +2202,7 @@ void grid_init(const int my_rank) { printout("[fatal] grid_init: Error: Unknown grid type. Abort."); std::abort(); } + mgi_of_propcell.resize(ngrid, -1); printout("propagation grid: %d-dimensional %s\n", get_ngriddimensions(GRID_TYPE), get_grid_type_name(GRID_TYPE).c_str()); @@ -2240,7 +2244,7 @@ void grid_init(const int my_rank) { if (globals::my_rank == 0) { FILE *grid_file = fopen_required("grid.out", "w"); for (int n = 0; n < ngrid; n++) { - const int mgi = get_cell_modelgridindex(n); + const int mgi = get_propcell_modelgridindex(n); if (mgi != get_npts_model()) { fprintf(grid_file, "%d %d\n", n, mgi); // write only non-empty cells to grid file } @@ -2339,20 +2343,19 @@ auto get_totmassradionuclide(const int z, const int a) -> double { auto last_cross = *pkt_last_cross; // d is used to loop over the coordinate indicies 0,1,2 for x,y,z - // the following four vectors are in grid coordinates, so either x,y,z or r - const int ndim = grid::get_ngriddimensions(GRID_TYPE); - assert_testmodeonly(ndim <= 3); - auto cellcoordmax = std::array{0}; - auto pktvelgridcoord = std::array{0}; // dir * CLIGHT_PROP converted from xyz to grid coordinates + // the following vector are in grid coordinates, so either x,y,z (3D) or r (1D), or r_xy, z (2D) + assert_testmodeonly(NDIM <= 3); + auto cellcoordmax = std::array{0}; + auto pktvelgridcoord = std::array{0}; // dir * CLIGHT_PROP converted from xyz to grid coordinates const auto pktposgridcoord = get_gridcoords_from_xyz(pos); - for (int d = 0; d < ndim; d++) { + for (int d = 0; d < NDIM; d++) { cellcoordmax[d] = grid::get_cellcoordmax(cellindex, d); } if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { // keep xyz Cartesian coordinates - for (int d = 0; d < ndim; d++) { + for (int d = 0; d < NDIM; d++) { pktvelgridcoord[d] = dir[d] * CLIGHT_PROP; } } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { @@ -2372,7 +2375,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { const auto negdirections = std::array{COORD0_MIN, COORD1_MIN, COORD2_MIN}; const auto posdirections = std::array{COORD0_MAX, COORD1_MAX, COORD2_MAX}; - for (int d = 0; d < ndim; d++) { + for (int d = 0; d < NDIM; d++) { // flip is either zero or one to indicate +ve and -ve boundaries along the selected axis for (int flip = 0; flip < 2; flip++) { enum cell_boundary const direction = flip != 0 ? posdirections[d] : negdirections[d]; @@ -2428,10 +2431,10 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } // distance to reach the cell's upper boundary on each coordinate - auto d_coordmaxboundary = std::array{-1}; + auto d_coordmaxboundary = std::array{-1}; // distance to reach the cell's lower boundary on each coordinate - auto d_coordminboundary = std::array{-1}; + auto d_coordminboundary = std::array{-1}; if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { last_cross = BOUNDARY_NONE; // handle this separately by setting d_inner and d_outer negative for invalid direction @@ -2487,7 +2490,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { enum cell_boundary choice = BOUNDARY_NONE; double distance = std::numeric_limits::max(); int snext = 0; - for (int d = 0; d < ndim; d++) { + for (int d = 0; d < NDIM; d++) { // upper d coordinate of the current cell if ((d_coordmaxboundary[d] > 0) && (d_coordmaxboundary[d] < distance) && (last_cross != negdirections[d])) { choice = posdirections[d]; @@ -2524,7 +2527,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { printout("coord %d: initpos %g dir %g\n", d2, pos[d2], dir[d2]); } printout("|initpos| %g |dir| %g |pos.dir| %g\n", vec_len(pos), vec_len(dir), dot(pos, dir)); - for (int d2 = 0; d2 < ndim; d2++) { + for (int d2 = 0; d2 < NDIM; d2++) { printout("coord %d: dist_posmax %g dist_posmin %g\n", d2, d_coordmaxboundary[d2], d_coordminboundary[d2]); printout("coord %d: cellcoordmin %g cellcoordmax %g\n", d2, grid::get_cellcoordmin(cellindex, d2) * tstart / globals::tmin, diff --git a/grid.h b/grid.h index ce5116353..cdc2eb7bc 100644 --- a/grid.h +++ b/grid.h @@ -60,11 +60,11 @@ inline float *ion_groundlevelpops_allcells{}; inline float *ion_partfuncts_allcells{}; inline double *ion_cooling_contribs_allcells{}; -[[nodiscard]] auto get_elements_uppermost_ion(int modelgridindex, int element) -> int; +[[nodiscard]] auto get_elements_uppermost_ion(int nonemptymgi, int element) -> int; void set_elements_uppermost_ion(int nonemptymgi, int element, int newvalue); [[nodiscard]] auto wid_init(int cellindex, int axis) -> double; [[nodiscard]] auto get_modelcell_assocvolume_tmin(int modelgridindex) -> double; -[[nodiscard]] auto get_gridcell_volume_tmin(int cellindex) -> double; +[[nodiscard]] auto get_propcell_volume_tmin(int cellindex) -> double; [[nodiscard]] auto get_cellcoordmax(int cellindex, int axis) -> double; [[nodiscard]] auto get_cellcoordmin(int cellindex, int axis) -> double; [[nodiscard]] auto get_cellcoordpointnum(int cellindex, int axis) -> int; @@ -108,7 +108,7 @@ void set_model_type(GridType model_type_value); [[nodiscard]] auto get_npts_model() -> int; [[nodiscard]] auto get_nonempty_npts_model() -> int; [[nodiscard]] auto get_t_model() -> double; -[[nodiscard]] auto get_cell_modelgridindex(int cellindex) -> int; +[[nodiscard]] auto get_propcell_modelgridindex(int cellindex) -> int; [[nodiscard]] auto get_propcell_nonemptymgi(int cellindex) -> int; [[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, double time) -> int; void read_ejecta_model(); diff --git a/ltepop.cc b/ltepop.cc index 1e87463df..49b08ea7d 100644 --- a/ltepop.cc +++ b/ltepop.cc @@ -46,8 +46,7 @@ auto interpolate_ions_spontrecombcoeff(const int uniqueionindex, const double T) } // use Saha equation for LTE ionization balance -auto phi_lte(const int element, const int ion, const int modelgridindex) -> double { - const int nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); +auto phi_lte(const int element, const int ion, const int nonemptymgi) -> double { const int uniqueionindex = get_uniqueionindex(element, ion); const auto partfunc_ion = grid::ion_partfuncts_allcells[(static_cast(nonemptymgi) * get_includedions()) + uniqueionindex]; @@ -62,8 +61,7 @@ auto phi_lte(const int element, const int ion, const int modelgridindex) -> doub // Calculate population ratio (a saha factor) of two consecutive ionisation stages in nebular approximation phi_j,k* = // N_j,k*/(N_j+1,k* * nne) -auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const int nonemptymgi) -> double { - assert_testmodeonly(modelgridindex < grid::get_npts_model()); +auto phi_rate_balance(const int element, const int ion, const int nonemptymgi) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -92,7 +90,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, const double gamma_nt = NT_ON ? nonthermal::nt_ionization_ratecoeff(nonemptymgi, element, ion) : 0.; - if ((Gamma + gamma_nt) == 0) { + if ((Gamma_ion + gamma_nt) == 0) { printout("Fatal: Gamma = 0 for element %d, ion %d in phi ... abort\n", element, ion); std::abort(); } @@ -108,7 +106,7 @@ auto phi_ion_equilib(const int element, const int ion, const int modelgridindex, "[fatal] phi: phi %g exceeds numerically possible range for element %d, ion %d, T_e %g ... remove higher or " "lower ionisation stages\n", phi, element, ion, T_e); - printout("[fatal] phi: Alpha_sp %g, Gamma %g, partfunct %g, stat_weight %g\n", Alpha_sp, Gamma, partfunc_ion, + printout("[fatal] phi: Alpha_sp %g, Gamma %g, partfunct %g, stat_weight %g\n", Alpha_sp, Gamma_ion, partfunc_ion, stat_weight(element, ion, 0)); printout("[fatal] phi: upperionpartfunct %g, upperionstatweight %g\n", partfunc_upperion, stat_weight(element, ion + 1, 0)); @@ -176,7 +174,6 @@ auto calculate_levelpop_nominpop(const int nonemptymgi, const int element, const assert_testmodeonly(level < get_nlevels(element, ion)); double nn{NAN}; - const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if (level == 0) { nn = get_groundlevelpop(nonemptymgi, element, ion); @@ -210,7 +207,7 @@ auto calculate_levelpop_nominpop(const int nonemptymgi, const int element, const nn = calculate_levelpop_lte(nonemptymgi, element, ion, level); } else { nn = superlevelpop_over_rho * grid::get_rho(nonemptymgi) * - superlevel_boltzmann(modelgridindex, element, ion, level); + superlevel_boltzmann(nonemptymgi, element, ion, level); if (!std::isfinite(nn)) { printout("[fatal] NLTE population failure.\n"); printout("element %d ion %d level %d\n", element, ion, level); @@ -288,11 +285,11 @@ auto find_uppermost_ion(const int nonemptymgi, const int element, const double n return nions - 1; } const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const bool use_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); + const bool use_phi_lte = force_lte || FORCE_SAHA_ION_BALANCE(get_atomicnumber(element)); int uppermost_ion = 0; uppermost_ion = nions - 1; - if (!use_lte) { + if (!use_phi_lte) { for (int ion = 0; ion < nions - 1; ion++) { if (iongamma_is_zero(nonemptymgi, element, ion) && (!NT_ON || ((globals::dep_estimator_gamma[nonemptymgi] == 0.) && @@ -308,7 +305,7 @@ auto find_uppermost_ion(const int nonemptymgi, const int element, const double n int ion = 0; for (ion = 0; ion < uppermost_ion; ion++) { const auto phifactor = - use_lte ? phi_lte(element, ion, modelgridindex) : phi_ion_equilib(element, ion, modelgridindex, nonemptymgi); + use_phi_lte ? phi_lte(element, ion, nonemptymgi) : phi_rate_balance(element, ion, nonemptymgi); factor *= nne_hi * phifactor; if (!std::isfinite(factor)) { @@ -378,14 +375,13 @@ auto find_converged_nne(const int nonemptymgi, double nne_hi, const bool force_l printout("nne@x_hi %g\n", nne_solution_f(nne_hi, f.params)); for (int element = 0; element < get_nelements(); element++) { - printout("cell %d, element %d, uppermost_ion is %d\n", modelgridindex, element, - grid::get_elements_uppermost_ion(modelgridindex, element)); + printout("modelgridindex %d, element %d, uppermost_ion is %d\n", modelgridindex, element, + grid::get_elements_uppermost_ion(nonemptymgi, element)); if constexpr (USE_LUT_PHOTOION) { - for (int ion = 0; ion <= grid::get_elements_uppermost_ion(modelgridindex, element); ion++) { + for (int ion = 0; ion <= grid::get_elements_uppermost_ion(nonemptymgi, element); ion++) { printout("element %d, ion %d, gammaionest %g\n", element, ion, - globals::gammaestimator[get_ionestimindex_nonemptymgi(grid::get_nonemptymgi_of_mgi(modelgridindex), - element, ion)]); + globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)]); } } } @@ -426,7 +422,7 @@ auto find_converged_nne(const int nonemptymgi, double nne_hi, const bool force_l [[nodiscard]] auto calculate_ionfractions(const int element, const int nonemptymgi, const double nne, const bool use_phi_lte) -> std::vector { const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); - const int uppermost_ion = grid::get_elements_uppermost_ion(modelgridindex, element); + const int uppermost_ion = grid::get_elements_uppermost_ion(nonemptymgi, element); assert_testmodeonly(element < get_nelements()); assert_testmodeonly(uppermost_ion <= std::max(0, get_nions(element) - 1)); @@ -440,8 +436,8 @@ auto find_converged_nne(const int nonemptymgi, double nne_hi, const bool force_l double normfactor = 1.; for (int ion = uppermost_ion - 1; ion >= 0; ion--) { - const auto phifactor = use_phi_lte ? phi_lte(element, ion, modelgridindex) - : phi_ion_equilib(element, ion, modelgridindex, nonemptymgi); + const auto phifactor = + use_phi_lte ? phi_lte(element, ion, nonemptymgi) : phi_rate_balance(element, ion, nonemptymgi); ionfractions[ion] = ionfractions[ion + 1] * nne * phifactor; normfactor += ionfractions[ion]; } diff --git a/nltepop.cc b/nltepop.cc index 43820f6dc..69d4165d5 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -393,7 +393,7 @@ void nltepop_reset_element(const int nonemptymgi, const int element) { } } -auto get_element_superlevelpartfuncs(const int modelgridindex, const int element) -> std::vector { +auto get_element_superlevelpartfuncs(const int nonemptymgi, const int element) -> std::vector { const int nions = get_nions(element); auto superlevel_partfuncs = std::vector(nions, 0.); for (int ion = 0; ion < nions; ion++) { @@ -401,7 +401,7 @@ auto get_element_superlevelpartfuncs(const int modelgridindex, const int element const int nlevels_nlte = get_nlevels_nlte(element, ion); const int nlevels = get_nlevels(element, ion); for (int level = nlevels_nlte + 1; level < nlevels; level++) { - superlevel_partfuncs[ion] += superlevel_boltzmann(modelgridindex, element, ion, level); + superlevel_partfuncs[ion] += superlevel_boltzmann(nonemptymgi, element, ion, level); } } } @@ -794,12 +794,12 @@ void set_element_pops_lte(const int nonemptymgi, const int element) { } // anonymous namespace -void solve_nlte_pops_element(const int element, const int modelgridindex, const int timestep, const int nlte_iter) +void solve_nlte_pops_element(const int element, const int nonemptymgi, const int timestep, const int nlte_iter) // solves the statistical balance equations to find NLTE level populations for all ions of an element // (ionisation balance follows from this too) { const int atomic_number = get_atomicnumber(element); - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); + const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); if (grid::get_elem_abundance(nonemptymgi, element) <= 0.) { // abundance of this element is zero, so do not store any NLTE populations @@ -831,7 +831,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const "nnelement %.2e cm^-3)\n", modelgridindex, timestep, nlte_iter, atomic_number, grid::get_elem_abundance(nonemptymgi, element), nnelement); - const auto superlevel_partfunc = get_element_superlevelpartfuncs(modelgridindex, element); + const auto superlevel_partfunc = get_element_superlevelpartfuncs(nonemptymgi, element); const int nlte_dimension = get_element_nlte_dimension(element); // printout("NLTE: the vector dimension is %d", nlte_dimension); @@ -905,7 +905,7 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const std::fill_n(s_renorm.begin(), nlevels_nlte + 1, 1.); for (int level = (nlevels_nlte + 1); level < nlevels; level++) { - s_renorm[level] = superlevel_boltzmann(modelgridindex, element, ion, level) / superlevel_partfunc[ion]; + s_renorm[level] = superlevel_boltzmann(nonemptymgi, element, ion, level) / superlevel_partfunc[ion]; } nltepop_matrix_add_boundbound(nonemptymgi, element, ion, t_mid, s_renorm, &rate_matrix_rad_bb, &rate_matrix_coll_bb, @@ -1099,10 +1099,11 @@ void solve_nlte_pops_element(const int element, const int modelgridindex, const } } -__host__ __device__ auto superlevel_boltzmann(const int modelgridindex, const int element, const int ion, - const int level) -> double { +// Get a Boltzman factor for a level within the super level (combined Non-LTE level) +__host__ __device__ auto superlevel_boltzmann(const int nonemptymgi, const int element, const int ion, const int level) + -> double { + assert_testmodeonly(level_isinsuperlevel(element, ion, level)); const int superlevel_index = get_nlevels_nlte(element, ion) + 1; - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const double T_exc = LTEPOP_EXCITATION_USE_TJ ? grid::get_TJ(nonemptymgi) : grid::get_Te(nonemptymgi); const double E_level = epsilon(element, ion, level); const double E_superlevel = epsilon(element, ion, superlevel_index); @@ -1173,7 +1174,7 @@ void nltepop_write_to_file(const int nonemptymgi, const int timestep) { fprintf(nlte_file, "%d ", -1); for (int level_sl = nlevels_nlte + 1; level_sl < get_nlevels(element, ion); level_sl++) { nnlevellte += calculate_levelpop_lte(nonemptymgi, element, ion, level_sl); - superlevel_partfunc += superlevel_boltzmann(modelgridindex, element, ion, level_sl); + superlevel_partfunc += superlevel_boltzmann(nonemptymgi, element, ion, level_sl); } nnlevelnlte = slpopfactor * superlevel_partfunc; diff --git a/nltepop.h b/nltepop.h index edd565722..4640b1e7b 100644 --- a/nltepop.h +++ b/nltepop.h @@ -3,8 +3,8 @@ #include -void solve_nlte_pops_element(int element, int modelgridindex, int timestep, int nlte_iter); -[[nodiscard]] auto superlevel_boltzmann(int modelgridindex, int element, int ion, int level) -> double; +void solve_nlte_pops_element(int element, int nonemptymgi, int timestep, int nlte_iter); +[[nodiscard]] auto superlevel_boltzmann(int nonemptymgi, int element, int ion, int level) -> double; [[nodiscard]] auto get_nlte_levelpop_over_rho(int nonemptymgi, int element, int ion, int level) -> double; [[nodiscard]] auto get_nlte_superlevelpop_over_rho(int nonemptymgi, int element, int ion) -> double; void set_nlte_levelpop_over_rho(int nonemptymgi, int element, int ion, int level, double value); diff --git a/nonthermal.cc b/nonthermal.cc index 46c59d5de..dd3da81aa 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2321,7 +2321,7 @@ __host__ __device__ void do_ntalpha_deposit(Packet &pkt) { __host__ __device__ void do_ntlepton_deposit(Packet &pkt) { atomicadd(nt_energy_deposited, pkt.e_cmf); - const int modelgridindex = grid::get_cell_modelgridindex(pkt.where); + const int modelgridindex = grid::get_propcell_modelgridindex(pkt.where); const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); // macroatom should not be activated in thick cells diff --git a/packet.cc b/packet.cc index 812da7e0b..ba13ddd27 100644 --- a/packet.cc +++ b/packet.cc @@ -66,7 +66,7 @@ void place_pellet(const double e0, const int cellindex, const int pktnumber, Pac // ensure that the random position was inside the cell we selected assert_always(grid::get_cellindex_from_pos(pkt.pos, pkt.prop_time) == cellindex); - const int mgi = grid::get_cell_modelgridindex(cellindex); + const int mgi = grid::get_propcell_modelgridindex(cellindex); decay::setup_radioactive_pellet(e0, mgi, pkt); @@ -107,7 +107,7 @@ void packet_init(Packet *pkt) double norm = 0.; for (int m = 0; m < grid::ngrid; m++) { - const int mgi = grid::get_cell_modelgridindex(m); + const int mgi = grid::get_propcell_modelgridindex(m); if (mgi < grid::get_npts_model() && grid::get_numpropcells(mgi) > 0) // some grid cells are empty { const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); @@ -116,7 +116,7 @@ void packet_init(Packet *pkt) q += grid::get_initenergyq(mgi); } - norm += grid::get_gridcell_volume_tmin(m) * grid::get_rho_tmin(mgi) * q; + norm += grid::get_propcell_volume_tmin(m) * grid::get_rho_tmin(mgi) * q; } en_cumulative[m] = norm; } diff --git a/ratecoeff.cc b/ratecoeff.cc index 17cf90071..dca8b153f 100644 --- a/ratecoeff.cc +++ b/ratecoeff.cc @@ -1249,7 +1249,7 @@ auto iongamma_is_zero(const int nonemptymgi, const int element, const int ion) - return true; } - if (USE_LUT_PHOTOION || !elem_has_nlte_levels(element)) { + if (!elem_has_nlte_levels(element)) { return (globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] == 0); } diff --git a/thermalbalance.cc b/thermalbalance.cc index 3b7417bfe..c94060cd4 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -59,7 +59,7 @@ auto integrand_bfheatingcoeff_custom_radfield(const double nu, void *const voidp } auto calculate_bfheatingcoeff(const int element, const int ion, const int level, const int phixstargetindex, - const int modelgridindex) -> double { + const int nonemptymgi) -> double { double error = 0.; const double epsrel = 1e-3; const double epsrelwarning = 1e-1; @@ -76,7 +76,6 @@ auto calculate_bfheatingcoeff(const int element, const int ion, const int level, // const double T_R = grid::get_TR(nonemptymgi); // const double sf_Te = calculate_sahafact(element,ion,level,upperionlevel,T_e,E_threshold); // const double sf_TR = calculate_sahafact(element,ion,level,upperionlevel,T_R,E_threshold); - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(modelgridindex); const BFHeatingIntegralParams intparas = {.nu_edge = nu_threshold, .nonemptymgi = nonemptymgi, .T_R = grid::get_TR(nonemptymgi), @@ -95,8 +94,8 @@ auto calculate_bfheatingcoeff(const int element, const int ion, const int level, printout( "bf_heating integrator gsl warning %d. modelgridindex %d Z=%d ionstage %d lower %d phixstargetindex %d " "integral %g error %g\n", - status, modelgridindex, get_atomicnumber(element), get_ionstage(element, ion), level, phixstargetindex, - bfheating, error); + status, grid::get_mgi_of_nonemptymgi(nonemptymgi), get_atomicnumber(element), get_ionstage(element, ion), level, + phixstargetindex, bfheating, error); } gsl_set_error_handler(previous_handler); @@ -190,22 +189,23 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const auto nonemptymgi = params->nonemptymgi; const double t_current = params->t_current; auto *const heatingcoolingrates = params->heatingcoolingrates; - - // Set new T_e guess for the current cell and update populations - grid::set_Te(nonemptymgi, T_e); - - if constexpr (!USE_LUT_PHOTOION && !LTEPOP_EXCITATION_USE_TJ) { - for (int element = 0; element < get_nelements(); element++) { - if (!elem_has_nlte_levels(element)) { - // recalculate the Gammas using the current population estimates - const int nions = get_nions(element); - for (int ion = 0; ion < nions - 1; ion++) { - globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] = - calculate_iongamma_per_gspop(nonemptymgi, element, ion); + if constexpr (!LTEPOP_EXCITATION_USE_TJ) { + if (std::abs((T_e / grid::get_Te(nonemptymgi)) - 1.) > 0.1) { + grid::set_Te(nonemptymgi, T_e); + for (int element = 0; element < get_nelements(); element++) { + if (!elem_has_nlte_levels(element)) { + // recalculate the Gammas using the current level populations + const int nions = get_nions(element); + for (int ion = 0; ion < nions - 1; ion++) { + globals::gammaestimator[get_ionestimindex_nonemptymgi(nonemptymgi, element, ion)] = + calculate_iongamma_per_gspop(nonemptymgi, element, ion); + } } } } } + // Set new T_e guess for the current cell and update populations + grid::set_Te(nonemptymgi, T_e); calculate_ion_balance_nne(nonemptymgi); const auto nne = grid::get_nne(nonemptymgi); @@ -269,7 +269,6 @@ auto get_bfheatingcoeff_ana(const int element, const int ion, const int level, c // depends only the radiation field - no dependence on T_e or populations void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingcoeffs) { bfheatingcoeffs.resize(get_includedlevels()); - const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double minelfrac = 0.01; for (int element = 0; element < get_nelements(); element++) { if (grid::get_elem_abundance(nonemptymgi, element) <= minelfrac && !USE_LUT_BFHEATING) { @@ -285,7 +284,7 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco const auto nphixstargets = get_nphixstargets(element, ion, level); for (int phixstargetindex = 0; phixstargetindex < nphixstargets; phixstargetindex++) { if constexpr (!USE_LUT_BFHEATING) { - bfheatingcoeff += calculate_bfheatingcoeff(element, ion, level, phixstargetindex, modelgridindex); + bfheatingcoeff += calculate_bfheatingcoeff(element, ion, level, phixstargetindex, nonemptymgi); } else { // The correction factor for stimulated emission in gammacorr is set to its // LTE value. Because the T_e dependence of gammacorr is weak, this correction diff --git a/update_grid.cc b/update_grid.cc index cc83472b1..8cdc95a08 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -734,7 +734,7 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, double fracdiff_nne = 0.; for (int element = 0; element < get_nelements(); element++) { if (get_nions(element) > 0 && elem_has_nlte_levels(element)) { - solve_nlte_pops_element(element, mgi, nts, nlte_iter); + solve_nlte_pops_element(element, nonemptymgi, nts, nlte_iter); calculate_cellpartfuncts(nonemptymgi, element); } } diff --git a/update_packets.cc b/update_packets.cc index 0dcb73a1c..22fe90716 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -27,7 +27,7 @@ namespace { void do_nonthermal_predeposit(Packet &pkt, const int nts, const double t2) { double en_deposited = pkt.e_cmf; - const auto mgi = grid::get_cell_modelgridindex(pkt.where); + const auto mgi = grid::get_propcell_modelgridindex(pkt.where); const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const auto priortype = pkt.type; const double ts = pkt.prop_time; @@ -254,7 +254,7 @@ void do_packet(Packet &pkt, const double t2, const int nts) } case TYPE_KPKT: { - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); const int nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); if (grid::modelgrid[nonemptymgi].thick == 1 || (EXPANSIONOPACITIES_ON && RPKT_BOUNDBOUND_THERMALISATION_PROBABILITY >= 0.)) { @@ -303,8 +303,8 @@ auto std_compare_packets_bymodelgriddensity(const Packet &p1, const Packet &p2) // } // for both non-escaped packets, order by descending cell density - const int mgi1 = grid::get_cell_modelgridindex(p1.where); - const int mgi2 = grid::get_cell_modelgridindex(p2.where); + const int mgi1 = grid::get_propcell_modelgridindex(p1.where); + const int mgi2 = grid::get_propcell_modelgridindex(p2.where); const auto rho1 = mgi1 < grid::get_npts_model() ? grid::get_rho(grid::get_nonemptymgi_of_mgi(mgi1)) : 0.0; const auto rho2 = mgi2 < grid::get_npts_model() ? grid::get_rho(grid::get_nonemptymgi_of_mgi(mgi2)) : 0.0; @@ -331,11 +331,11 @@ auto std_compare_packets_bymodelgriddensity(const Packet &p1, const Packet &p2) void do_cell_packet_updates(std::span packets, const int nts, const double ts_end) { auto update_packet = [ts_end, nts](auto &pkt) { - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); int newmgi = mgi; while (pkt.prop_time < ts_end && pkt.type != TYPE_ESCAPE && (newmgi == mgi || newmgi == grid::get_npts_model())) { do_packet(pkt, ts_end, nts); - newmgi = grid::get_cell_modelgridindex(pkt.where); + newmgi = grid::get_propcell_modelgridindex(pkt.where); } }; @@ -383,7 +383,7 @@ void update_packets(const int nts, std::span packets) { for (auto &pkt : packets) { if ((pkt.type != TYPE_ESCAPE && pkt.prop_time < ts_end)) { - const int mgi = grid::get_cell_modelgridindex(pkt.where); + const int mgi = grid::get_propcell_modelgridindex(pkt.where); const int nonemptymgi = (mgi < grid::get_npts_model()) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; const bool cellcache_change_cell_required = (nonemptymgi >= 0 && globals::cellcache[cellcacheslotid].nonemptymgi != nonemptymgi && diff --git a/vpkt.cc b/vpkt.cc index 225fcd06f..b27852408 100644 --- a/vpkt.cc +++ b/vpkt.cc @@ -249,7 +249,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar // compute the optical depth to boundary - mgi = grid::get_cell_modelgridindex(vpkt.where); + mgi = grid::get_propcell_modelgridindex(vpkt.where); Rpkt_continuum_absorptioncoeffs chi_vpkt_cont{}; while (!end_packet) { @@ -357,7 +357,7 @@ auto rlc_emiss_vpkt(const Packet &pkt, const double t_current, const double t_ar grid::change_cell(vpkt, snext); end_packet = (vpkt.type == TYPE_ESCAPE); - mgi = grid::get_cell_modelgridindex(vpkt.where); + mgi = grid::get_propcell_modelgridindex(vpkt.where); if (mgi < grid::get_npts_model()) { const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); From fde3637d49efd2494e5a1cdc5d79386e0bf1ccf0 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 7 Nov 2024 00:58:55 +0000 Subject: [PATCH 087/117] Update nvc++ to 24.9 (#149) --- .github/workflows/ci-checks.yml | 2 +- .github/workflows/ci.yml | 1 + CMakeLists.txt | 9 ++-- atomic.h | 2 + gammapkt.cc | 1 + grid.cc | 78 +++++++++++++++++++-------------- grid.h | 14 ------ 7 files changed, 54 insertions(+), 53 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index f39c5df40..45a9146f4 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -97,7 +97,7 @@ jobs: {name: gcc, ver: 12}, {name: gcc, ver: 13}, {name: gcc, ver: 14}, - {name: nvc++, ver: '24.7'}, + {name: nvc++, ver: '24.9'}, ] fail-fast: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00f393b10..e1ed42227 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,7 @@ jobs: - os: self-hosted testmode: ON fail-fast: false + max-parallel: 10 runs-on: ${{ matrix.os }} timeout-minutes: 120 diff --git a/CMakeLists.txt b/CMakeLists.txt index 386de86d2..e3ca05ab7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,12 +63,9 @@ vpkt.cc) add_executable(exspec ${EXSPEC_SOURCES}) -#if(UNIX AND NOT APPLE) -if(UNIX AND NOT APPLE) - find_package(MPI) - include_directories(SYSTEM ${MPI_INCLUDE_PATH}) - target_link_libraries(sn3d MPI_CXX) -endif() +find_package(MPI) +include_directories(SYSTEM ${MPI_INCLUDE_PATH}) +target_link_libraries(sn3d MPI_CXX) add_compile_options("-Wall" "-Wextra") diff --git a/atomic.h b/atomic.h index bb0e90706..ab5d47f07 100644 --- a/atomic.h +++ b/atomic.h @@ -332,6 +332,7 @@ inline auto get_includedlevels() -> int { return includedlevels; } } } assert_always(false); // allionsindex too high to be valid + return {-1, -1}; } // Get an index for level of an ionstage of an element that is unique across every ion of every element @@ -361,6 +362,7 @@ inline auto get_includedlevels() -> int { return includedlevels; } } } assert_always(false); // alllevelsindex too high to be valid + return {-1, -1, -1}; } [[nodiscard]] inline auto ion_has_superlevel(const int element, const int ion) -> bool { diff --git a/gammapkt.cc b/gammapkt.cc index 9f39edc33..6d78e8531 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -249,6 +249,7 @@ __host__ __device__ auto choose_gamma_ray(const int nucindex) -> double { printout("Failure to choose line (pellet_nucindex %d). Abort. zrand %g runtot %g\n", nucindex, zrand, runtot); assert_always(false); + return NAN; } constexpr auto sigma_compton_partial(const double x, const double f_max) -> double diff --git a/grid.cc b/grid.cc index 17df9be54..a450cf008 100644 --- a/grid.cc +++ b/grid.cc @@ -94,7 +94,20 @@ std::vector ranks_ndo; std::vector ranks_ndo_nonempty; inline std::span modelgrid_input{}; -constexpr auto NDIM = grid::get_ngriddimensions(GRID_TYPE); +// Get number of dimensions +constexpr auto get_ndim(const GridType gridtype) -> int { + switch (gridtype) { + case GridType::SPHERICAL1D: + return 1; + case GridType::CYLINDRICAL2D: + return 2; + case GridType::CARTESIAN3D: + return 3; + default: + assert_always(false); + return -1; + } +} void set_rho_tmin(const int modelgridindex, const float x) { modelgrid_input[modelgridindex].rhoinit = x; } @@ -746,6 +759,7 @@ auto get_inputcellvolume(const int mgi) -> double { return pow((2 * globals::vmax * globals::tmin), 3.) / (ncoordgrid[0] * ncoordgrid[1] * ncoordgrid[2]); } assert_always(false); + return NAN; } void calc_modelinit_totmassradionuclides() { @@ -1126,21 +1140,22 @@ auto get_poscoordpointnum(const double pos, const double time, const int axis) - // Convert a position in Cartesian xyz to the grid coordinate system (which might the same, or 2D cylindrical or 1D // spherical) -constexpr auto get_gridcoords_from_xyz(const std::array &pos_xyz) { - if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { - return std::array{pos_xyz[0], pos_xyz[1], pos_xyz[2]}; +template +[[nodiscard]] constexpr auto get_gridcoords_from_xyz(const std::array &pos_xyz) -> std::array { + if constexpr (grid_type == GridType::CARTESIAN3D) { + return {pos_xyz[0], pos_xyz[1], pos_xyz[2]}; } - if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { - return std::array{std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)), pos_xyz[2]}; + if constexpr (grid_type == GridType::CYLINDRICAL2D) { + return {std::sqrt(std::pow(pos_xyz[0], 2) + std::pow(pos_xyz[1], 2)), pos_xyz[2], 0.}; } - if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { - return std::array{vec_len(pos_xyz)}; + if constexpr (grid_type == GridType::SPHERICAL1D) { + return {vec_len(pos_xyz), 0., 0.}; } assert_always(false); - return std::array{}; + return {NAN, NAN, NAN}; } // find the closest forward distance to the intersection of a ray with an expanding spherical shell (pos and dir are @@ -1242,15 +1257,15 @@ template auto get_coordboundary_distances_cylindrical2d(const std::array &pkt_pos, const std::array &pkt_dir, - const std::array &pktposgridcoord, - const std::array &pktvelgridcoord, const int cellindex, - const double tstart, const std::array &cellcoordmax) - -> std::tuple, std::array> { + const std::array &pktposgridcoord, + const std::array &pktvelgridcoord, const int cellindex, + const double tstart, const std::array &cellcoordmax) + -> std::tuple, std::array> { // to get the cylindrical intersection, get the spherical intersection with Z components set to zero, and the // propagation speed set to the xy component of the 3-velocity - std::array d_coordminboundary{}; - std::array d_coordmaxboundary{}; + std::array d_coordminboundary{}; + std::array d_coordmaxboundary{}; const std::array posnoz = {pkt_pos[0], pkt_pos[1]}; @@ -2204,10 +2219,9 @@ void grid_init(const int my_rank) { } mgi_of_propcell.resize(ngrid, -1); - printout("propagation grid: %d-dimensional %s\n", get_ngriddimensions(GRID_TYPE), - get_grid_type_name(GRID_TYPE).c_str()); + printout("propagation grid: %d-dimensional %s\n", get_ndim(GRID_TYPE), get_grid_type_name(GRID_TYPE).c_str()); - for (int d = 0; d < get_ngriddimensions(GRID_TYPE); d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { printout(" coordinate %d '%c': cells have %d position values\n", d, coordlabel[d], ncoordgrid[d]); } printout(" total propagation cells: %d\n", ngrid); @@ -2314,15 +2328,15 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // identify the cell index from an (x,y,z) position and a time. [[nodiscard]] auto get_cellindex_from_pos(const std::array &pos, const double time) -> int { - auto posgridcoords = get_gridcoords_from_xyz(pos); + auto posgridcoords = get_gridcoords_from_xyz(pos); int cellindex = 0; - for (int d = 0; d < get_ngriddimensions(GRID_TYPE); d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { cellindex += get_coordcellindexincrement(d) * get_poscoordpointnum(posgridcoords[d], time, d); } // do a check that the position is within the cell const double trat = time / globals::tmin; - for (int n = 0; n < grid::get_ngriddimensions(GRID_TYPE); n++) { + for (int n = 0; n < get_ndim(GRID_TYPE); n++) { assert_always(posgridcoords[n] >= grid::get_cellcoordmin(cellindex, n) * trat); assert_always(posgridcoords[n] <= grid::get_cellcoordmax(cellindex, n) * trat); } @@ -2344,18 +2358,18 @@ auto get_totmassradionuclide(const int z, const int a) -> double { // d is used to loop over the coordinate indicies 0,1,2 for x,y,z // the following vector are in grid coordinates, so either x,y,z (3D) or r (1D), or r_xy, z (2D) - assert_testmodeonly(NDIM <= 3); - auto cellcoordmax = std::array{0}; - auto pktvelgridcoord = std::array{0}; // dir * CLIGHT_PROP converted from xyz to grid coordinates + assert_testmodeonly(get_ndim(GRID_TYPE) <= 3); + auto cellcoordmax = std::array{0}; + auto pktvelgridcoord = std::array{0}; // dir * CLIGHT_PROP converted from xyz to grid coordinates - const auto pktposgridcoord = get_gridcoords_from_xyz(pos); + const auto pktposgridcoord = get_gridcoords_from_xyz(pos); - for (int d = 0; d < NDIM; d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { cellcoordmax[d] = grid::get_cellcoordmax(cellindex, d); } if constexpr (GRID_TYPE == GridType::CARTESIAN3D) { // keep xyz Cartesian coordinates - for (int d = 0; d < NDIM; d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { pktvelgridcoord[d] = dir[d] * CLIGHT_PROP; } } else if constexpr (GRID_TYPE == GridType::CYLINDRICAL2D) { @@ -2375,7 +2389,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { const auto negdirections = std::array{COORD0_MIN, COORD1_MIN, COORD2_MIN}; const auto posdirections = std::array{COORD0_MAX, COORD1_MAX, COORD2_MAX}; - for (int d = 0; d < NDIM; d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { // flip is either zero or one to indicate +ve and -ve boundaries along the selected axis for (int flip = 0; flip < 2; flip++) { enum cell_boundary const direction = flip != 0 ? posdirections[d] : negdirections[d]; @@ -2431,10 +2445,10 @@ auto get_totmassradionuclide(const int z, const int a) -> double { } // distance to reach the cell's upper boundary on each coordinate - auto d_coordmaxboundary = std::array{-1}; + auto d_coordmaxboundary = std::array{-1}; // distance to reach the cell's lower boundary on each coordinate - auto d_coordminboundary = std::array{-1}; + auto d_coordminboundary = std::array{-1}; if constexpr (GRID_TYPE == GridType::SPHERICAL1D) { last_cross = BOUNDARY_NONE; // handle this separately by setting d_inner and d_outer negative for invalid direction @@ -2490,7 +2504,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { enum cell_boundary choice = BOUNDARY_NONE; double distance = std::numeric_limits::max(); int snext = 0; - for (int d = 0; d < NDIM; d++) { + for (int d = 0; d < get_ndim(GRID_TYPE); d++) { // upper d coordinate of the current cell if ((d_coordmaxboundary[d] > 0) && (d_coordmaxboundary[d] < distance) && (last_cross != negdirections[d])) { choice = posdirections[d]; @@ -2527,7 +2541,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { printout("coord %d: initpos %g dir %g\n", d2, pos[d2], dir[d2]); } printout("|initpos| %g |dir| %g |pos.dir| %g\n", vec_len(pos), vec_len(dir), dot(pos, dir)); - for (int d2 = 0; d2 < NDIM; d2++) { + for (int d2 = 0; d2 < get_ndim(GRID_TYPE); d2++) { printout("coord %d: dist_posmax %g dist_posmin %g\n", d2, d_coordmaxboundary[d2], d_coordminboundary[d2]); printout("coord %d: cellcoordmin %g cellcoordmax %g\n", d2, grid::get_cellcoordmin(cellindex, d2) * tstart / globals::tmin, diff --git a/grid.h b/grid.h index cdc2eb7bc..a2b8220f6 100644 --- a/grid.h +++ b/grid.h @@ -32,20 +32,6 @@ struct ModelGridCell { int thick = 0; }; -constexpr auto get_ngriddimensions(const GridType gridtype) -> int { - switch (gridtype) { - case GridType::SPHERICAL1D: - return 1; - case GridType::CYLINDRICAL2D: - return 2; - case GridType::CARTESIAN3D: - return 3; - default: - assert_always(false); - return -1; - } -} - inline std::span modelgrid{}; inline int ngrid{0}; From 9212281492c0a93bc5464733f3b085ddaff0c6e2 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 7 Nov 2024 10:36:21 +0000 Subject: [PATCH 088/117] Enable more clangd/clang-tidy warnings (#150) --- .clang-tidy | 5 +++-- .clangd | 22 +++++++++++++++++++++- atomic.h | 5 +++++ decay.h | 1 + globals.h | 1 - grid.cc | 32 ++++++++++++++++---------------- grid.h | 5 +++-- input.h | 2 ++ md5.h | 3 ++- nonthermal.cc | 8 ++++---- radfield.h | 5 +++++ ratecoeff.h | 1 + rpkt.h | 5 +++++ sn3d.h | 10 +++++++++- spectrum_lightcurve.h | 1 + stats.h | 2 -- vectors.h | 2 ++ 17 files changed, 80 insertions(+), 30 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index b927c18ce..1be73aa59 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -72,5 +72,6 @@ CheckOptions: value: lower_case - key: bugprone-reserved-identifier.AllowedIdentifiers value: '__host__;__device__' - - key: misc-include-cleaner.IgnoreHeaders - value: '.*(ranges).*' + - key: misc-include-cleaner.IgnoreHeaders # std::ranges::upper_bound is triggering warning to include a private libc++ header __algorithm/ranges_upper_bound.h + # value: '.*(ranges).*' + value: '.*(__algorithm).*' diff --git a/.clangd b/.clangd index 01adb0a32..16adac4c8 100644 --- a/.clangd +++ b/.clangd @@ -2,4 +2,24 @@ CompileFlags: # to make the compilation database, pip install compiledb, then run: # compiledb -n --full-path make TESTMODE=ON CompilationDatabase: compile_commands.json - Add: [-std=c++20, -DTESTMODE=true] + Add: [-xc++, -std=c++20, -DTESTMODE=true] + +Diagnostics: + ClangTidy: + FastCheckFilter: None + UnusedIncludes: Strict + MissingIncludes: Strict + Includes: + # std::ranges::upper_bound is triggering warning to include a private libc++ header __algorithm/ranges_upper_bound.h + # IgnoreHeader: '.*(ranges).*' + IgnoreHeader: '.*(__algorithm).*' + +Completion: + AllScopes: true + #ArgumentListsPolicy: None # added to LLVM 20? + +InlayHints: + BlockEnd: true + Designators: true + Enabled: true + ParameterNames: true diff --git a/atomic.h b/atomic.h index ab5d47f07..c0f265d38 100644 --- a/atomic.h +++ b/atomic.h @@ -3,8 +3,13 @@ #include #include +#include +#include #include +#include "artisoptions.h" +#include "constants.h" +#include "globals.h" #include "grid.h" #include "ltepop.h" #include "sn3d.h" diff --git a/decay.h b/decay.h index b511d3183..b7e38f071 100644 --- a/decay.h +++ b/decay.h @@ -2,6 +2,7 @@ #define DECAY_H #include +#include #include #include #include diff --git a/globals.h b/globals.h index ee8a013e5..b25a7207e 100644 --- a/globals.h +++ b/globals.h @@ -1,4 +1,3 @@ -#include #ifndef GLOBALS_H #define GLOBALS_H diff --git a/grid.cc b/grid.cc index a450cf008..d9a051832 100644 --- a/grid.cc +++ b/grid.cc @@ -72,10 +72,10 @@ std::vector> propcell_pos_min{}; // associate each propagation cell with a model grid cell, or not, if the cell is empty (or doesn't get mapped to // anything such as 1D/2D to 3D) -std::vector mgi_of_propcell; -std::vector nonemptymgi_of_propcell; +std::vector propcell_mgi; +std::vector propcell_nonemptymgi; -std::vector modelgrid_numassociated_propcells; +std::vector modelgrid_numpropcells; std::vector nonemptymgi_of_mgi; std::vector mgi_of_nonemptymgi; @@ -200,7 +200,7 @@ void set_propcell_modelgridindex(const int cellindex, const int new_modelgridind assert_testmodeonly(cellindex < ngrid); assert_testmodeonly(new_modelgridindex >= 0); assert_testmodeonly(new_modelgridindex <= get_npts_model()); - mgi_of_propcell[cellindex] = new_modelgridindex; + propcell_mgi[cellindex] = new_modelgridindex; } void set_modelinitnucmassfrac(const int modelgridindex, const int nucindex, float abund) { @@ -300,7 +300,7 @@ void allocate_nonemptycells_composition_cooling() void allocate_nonemptymodelcells() { // Determine the number of simulation cells associated with the model cells - std::ranges::fill(modelgrid_numassociated_propcells, 0); + std::ranges::fill(modelgrid_numpropcells, 0); if (globals::rank_in_node == 0) { for (int mgi = 0; mgi < (get_npts_model() + 1); mgi++) { modelgrid_input[mgi].initial_radial_pos_sum = 0.; @@ -312,19 +312,19 @@ void allocate_nonemptymodelcells() { if (FORCE_SPHERICAL_ESCAPE_SURFACE && radial_pos_mid > globals::vmax * globals::tmin) { // for 1D models, the final shell outer v should already be at vmax - assert_always(model_type != GridType::SPHERICAL1D || mgi_of_propcell[cellindex] == get_npts_model()); + assert_always(model_type != GridType::SPHERICAL1D || propcell_mgi[cellindex] == get_npts_model()); set_propcell_modelgridindex(cellindex, get_npts_model()); } const int mgi = get_propcell_modelgridindex(cellindex); assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (get_rho_tmin(mgi) > 0) || (mgi == get_npts_model())); - modelgrid_numassociated_propcells[mgi] += 1; + modelgrid_numpropcells[mgi] += 1; if (globals::rank_in_node == 0) { modelgrid_input[mgi].initial_radial_pos_sum += radial_pos_mid; } - assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (modelgrid_numassociated_propcells[mgi] == 1) || + assert_always(!(get_model_type() == GridType::CARTESIAN3D) || (modelgrid_numpropcells[mgi] == 1) || (mgi == get_npts_model())); } @@ -339,7 +339,7 @@ void allocate_nonemptymodelcells() { assert_always(nonempty_npts_model > 0); mgi_of_nonemptymgi.resize(nonempty_npts_model, -2); - nonemptymgi_of_propcell.resize(ngrid, -1); + propcell_nonemptymgi.resize(ngrid, -1); int nonemptymgi = 0; // index within list of non-empty modelgrid cells @@ -361,9 +361,9 @@ void allocate_nonemptymodelcells() { for (int cellindex = 0; cellindex < ngrid; cellindex++) { const int mgi = get_propcell_modelgridindex(cellindex); if (mgi >= get_npts_model()) { - nonemptymgi_of_propcell[cellindex] = -1; + propcell_nonemptymgi[cellindex] = -1; } else { - nonemptymgi_of_propcell[cellindex] = get_nonemptymgi_of_mgi(mgi); + propcell_nonemptymgi[cellindex] = get_nonemptymgi_of_mgi(mgi); } } @@ -1595,14 +1595,14 @@ auto get_t_model() -> double { [[nodiscard]] __host__ __device__ auto get_propcell_modelgridindex(const int cellindex) -> int { assert_testmodeonly(cellindex >= 0); assert_testmodeonly(cellindex < ngrid); - const auto mgi = mgi_of_propcell[cellindex]; + const auto mgi = propcell_mgi[cellindex]; assert_testmodeonly(mgi >= 0); assert_testmodeonly(mgi < (get_npts_model() + 1)); return mgi; } [[nodiscard]] __host__ __device__ auto get_propcell_nonemptymgi(const int cellindex) -> int { - const auto nonemptymgi = nonemptymgi_of_propcell[cellindex]; + const auto nonemptymgi = propcell_nonemptymgi[cellindex]; assert_testmodeonly(nonemptymgi >= -1); assert_testmodeonly(nonemptymgi < get_nonempty_npts_model()); return nonemptymgi; @@ -1611,7 +1611,7 @@ auto get_t_model() -> double { // number of propagation cells associated with each modelgrid cell __host__ __device__ auto get_numpropcells(const int modelgridindex) -> int { assert_testmodeonly(modelgridindex <= get_npts_model()); - return modelgrid_numassociated_propcells[modelgridindex]; + return modelgrid_numpropcells[modelgridindex]; } // get the index in the list of non-empty cells for a given model grid cell @@ -1893,7 +1893,7 @@ void read_ejecta_model() { std::ranges::fill(modelgrid_input, ModelGridCellInput{}); } MPI_Barrier(globals::mpi_comm_node); - modelgrid_numassociated_propcells.resize(npts_model + 1, 0); + modelgrid_numpropcells.resize(npts_model + 1, 0); nonemptymgi_of_mgi.resize(npts_model + 1, -1); if (get_model_type() == GridType::SPHERICAL1D) { @@ -2217,7 +2217,7 @@ void grid_init(const int my_rank) { printout("[fatal] grid_init: Error: Unknown grid type. Abort."); std::abort(); } - mgi_of_propcell.resize(ngrid, -1); + propcell_mgi.resize(ngrid, -1); printout("propagation grid: %d-dimensional %s\n", get_ndim(GRID_TYPE), get_grid_type_name(GRID_TYPE).c_str()); diff --git a/grid.h b/grid.h index a2b8220f6..c185fc806 100644 --- a/grid.h +++ b/grid.h @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -6,7 +8,6 @@ #include -#include "artisoptions.h" #include "constants.h" #include "globals.h" #include "packet.h" @@ -132,7 +133,7 @@ inline auto get_ejecta_kinetic_energy() { for (int nonemptymgi = 0; nonemptymgi < get_nonempty_npts_model(); nonemptymgi++) { const int mgi = get_mgi_of_nonemptymgi(nonemptymgi); const int assoc_cells = get_numpropcells(mgi); - double M_cell = get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); + double const M_cell = get_rho_tmin(mgi) * grid::get_modelcell_assocvolume_tmin(mgi); const double radial_pos = get_initial_radial_pos_sum(mgi) / assoc_cells; E_kin += 0.5 * M_cell * std::pow(radial_pos / globals::tmin, 2); } diff --git a/input.h b/input.h index 6e53d730c..d63ae1c7d 100644 --- a/input.h +++ b/input.h @@ -1,7 +1,9 @@ #ifndef INPUT_H #define INPUT_H +#include #include +#include void input(int rank); void read_parameterfile(int rank); diff --git a/md5.h b/md5.h index 4b014a789..3f4114c0d 100644 --- a/md5.h +++ b/md5.h @@ -11,6 +11,7 @@ /*************************** HEADER FILES ***************************/ #include +#include /****************************** MACROS ******************************/ constexpr int MD5_BLOCK_SIZE = 16; // MD5 outputs a 16 byte digest @@ -22,7 +23,7 @@ using WORD = unsigned int; // 32-bit word, change to "long" for 16-bit machine using MD5_CTX = struct { BYTE data[64]; WORD datalen; - unsigned long long bitlen; + std::uint64_t bitlen; WORD state[4]; }; diff --git a/nonthermal.cc b/nonthermal.cc index dd3da81aa..c63f7a49d 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -642,9 +642,9 @@ void read_collion_data() { const int Z = get_atomicnumber(element); for (int ion = 0; ion < get_nions(element); ion++) { const int ionstage = get_ionstage(element, ion); - const bool any_data_matched = std::any_of( - colliondata.cbegin(), colliondata.cend(), - [Z, ionstage](const collionrow &collionrow) { return collionrow.Z == Z && collionrow.ionstage == ionstage; }); + const bool any_data_matched = std::ranges::any_of(colliondata, [Z, ionstage](const collionrow &collionrow) { + return collionrow.Z == Z && collionrow.ionstage == ionstage; + }); if (!any_data_matched) { const double ionpot_ev = globals::elements[element].ions[ion].ionpot / EV; printout("No collisional ionisation data for Z=%d ionstage %d. Using Lotz approximation with ionpot = %g eV\n", @@ -1704,7 +1704,7 @@ void analyse_sf_solution(const int nonemptymgi, const int timestep, const bool e } nt_solution[nonemptymgi].frac_excitations_list_size = tmp_excitation_list.size(); - std::copy(tmp_excitation_list.begin(), tmp_excitation_list.end(), get_cell_ntexcitations(nonemptymgi).begin()); + std::ranges::copy(tmp_excitation_list, get_cell_ntexcitations(nonemptymgi).begin()); printout("[info] mem_usage: non-thermal excitations for cell %d at this timestep occupy %.3f MB\n", modelgridindex, nt_solution[nonemptymgi].frac_excitations_list_size * sizeof(NonThermalExcitation) / 1024. / 1024.); diff --git a/radfield.h b/radfield.h index b29f0d66c..7e32eb8c2 100644 --- a/radfield.h +++ b/radfield.h @@ -1,4 +1,9 @@ +#include + +#include #include + +#include "constants.h" #ifndef RADFIELD_H #define RADFIELD_H diff --git a/ratecoeff.h b/ratecoeff.h index 3bf607815..012a6fe49 100644 --- a/ratecoeff.h +++ b/ratecoeff.h @@ -3,6 +3,7 @@ #include +#include "globals.h" #include "sn3d.h" #if !USE_SIMPSON_INTEGRATOR #include diff --git a/rpkt.h b/rpkt.h index bf0465702..bf03581c8 100644 --- a/rpkt.h +++ b/rpkt.h @@ -6,6 +6,11 @@ #include #include +#include "globals.h" +#include "ltepop.h" +#include "packet.h" +#include "sn3d.h" + struct Phixslist { std::span groundcont_gamma_contr; // for either USE_LUT_PHOTOION = true or !USE_LUT_BFHEATING = false std::span chi_bf_sum; diff --git a/sn3d.h b/sn3d.h index 021dc25f4..1d81bb393 100644 --- a/sn3d.h +++ b/sn3d.h @@ -1,7 +1,12 @@ #ifndef SN3D_H #define SN3D_H +#include +#include #include +#include + +#include "artisoptions.h" #ifndef __host__ #define __host__ #endif @@ -15,7 +20,6 @@ #include #include -#include #include #include #include @@ -154,6 +158,10 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f #define SORT_OR_STABLE_SORT sort #endif +#if defined(STDPAR_ON) && defined(__cpp_lib_atomic_ref) +#include +#endif + template inline void atomicadd(T &var, const T &val) { #ifdef _OPENMP diff --git a/spectrum_lightcurve.h b/spectrum_lightcurve.h index 919d3c539..79b81ace3 100644 --- a/spectrum_lightcurve.h +++ b/spectrum_lightcurve.h @@ -1,6 +1,7 @@ #ifndef SPECTRUM_H #define SPECTRUM_H +#include #include #include diff --git a/stats.h b/stats.h index 1bec08969..e5367a9e7 100644 --- a/stats.h +++ b/stats.h @@ -2,8 +2,6 @@ #ifndef STATS_H #define STATS_H -#include - #include "packet.h" namespace stats { diff --git a/vectors.h b/vectors.h index 15e4b7a5c..68fccc6f8 100644 --- a/vectors.h +++ b/vectors.h @@ -4,9 +4,11 @@ #include #include #include +#include #include #include +#include "artisoptions.h" #include "constants.h" #include "exspec.h" #include "packet.h" From dfbc96d74c8331045fc6e4c3f45b0379ce0a2e70 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 8 Nov 2024 11:21:54 +0000 Subject: [PATCH 089/117] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1ed42227..f7f20f7ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - os: self-hosted testmode: ON fail-fast: false - max-parallel: 10 + max-parallel: 12 runs-on: ${{ matrix.os }} timeout-minutes: 120 From ebf7895794eeb646c03b0b42d9cfa401066898a6 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 11 Nov 2024 13:08:57 +0000 Subject: [PATCH 090/117] CI: split slow test mode into separate workflow (#152) --- .github/workflows/ci-checks.yml | 3 -- .github/workflows/ci.yml | 44 +++++++++++++--------------- .github/workflows/cislowtestmode.yml | 18 ++++++++++++ 3 files changed, 39 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/cislowtestmode.yml diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 45a9146f4..141d5197f 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -6,9 +6,6 @@ on: branches-ignore: - classic* workflow_dispatch: - # pull_request: - # branches-ignore: - # - classic* jobs: cppcheck: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7f20f7ed..92cc6faa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,10 +8,13 @@ on: schedule: - cron: 0 13 * * 1 workflow_dispatch: - # pull_request: - # branches-ignore: - # - classic* - + workflow_call: # for triggering the full test mode + inputs: + # test mode enables the santizers and additional assertions + testmode: + required: false + default: 'OFF' + type: string env: ASAN_OPTIONS: detect_stack_use_after_return=1:detect_leaks=0 @@ -20,7 +23,6 @@ jobs: strategy: matrix: os: [ubuntu-24.04] - testmode: [OFF, ON] testname: [ classicmode_1d_3dgrid, @@ -35,15 +37,11 @@ jobs: nebular_1d_3dgrid, nebular_1d_3dgrid_limitbfest, ] - exclude: - - os: self-hosted - testmode: ON fail-fast: false - max-parallel: 12 runs-on: ${{ matrix.os }} timeout-minutes: 120 - name: ${{ matrix.testname }}${{ matrix.testmode == 'ON' && ' testmode ON' || ''}} + name: ${{ matrix.testname }} steps: - uses: actions/checkout@v4 @@ -110,7 +108,7 @@ jobs: - name: Compile run: | - make REPRODUCIBLE=ON TESTMODE=${{ matrix.testmode }} MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec + make REPRODUCIBLE=ON TESTMODE=${{ inputs.testmode }} MAX_NODE_SIZE=2 FASTMATH=OFF -j${{ steps.cpu-count.outputs.count }} sn3d exspec cp sn3d tests/${{ matrix.testname }}_testrun/ cp exspec tests/${{ matrix.testname }}_testrun/ @@ -173,7 +171,7 @@ jobs: run: cat job1/output_0-0.txt - name: show deposition.out - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' working-directory: tests/${{ matrix.testname }}_testrun/ run: | cat deposition.out @@ -210,61 +208,61 @@ jobs: - name: Upload output files uses: actions/upload-artifact@v4 - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' with: name: test-${{ matrix.testname }}-output path: tests/${{ matrix.testname }}_testrun - name: Upload checksum files uses: actions/upload-artifact@v4 - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' with: name: ${{ matrix.testname }}_inputfiles path: tests/${{ matrix.testname }}_inputfiles/results_md5* - name: Set up Python - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' uses: actions/setup-python@v5 - name: Install artistools - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' run: | python3 -m pip install --upgrade pip uv uv pip install --system -U artistools - name: Plot light curve - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' working-directory: tests/ run: | at plotlightcurves ${{ matrix.testname }}_testrun at plotlightcurves --frompackets ${{ matrix.testname }}_testrun - name: Plot spectrum nebular - if: always() && matrix.testmode == 'OFF' && startsWith(matrix.testname, 'nebular') + if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'nebular') working-directory: tests/ run: | at plotspectra --frompackets -ts 8 ${{ matrix.testname }}_testrun - name: Plot spectrum classicmode - if: always() && matrix.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_') + if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_') working-directory: tests/ run: | at plotspectra --frompackets -t 4-6 ${{ matrix.testname }}_testrun - name: Plot virtual packet spectrum classicmode_1d - if: always() && matrix.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_1d') + if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_1d') working-directory: tests/ run: | at plotspectra -t 4-6 -plotvspecpol 0 1 2 3 12 13 14 --frompackets ${{ matrix.testname }}_testrun - name: Plot spectrum kilonova - if: always() && matrix.testmode == 'OFF' && startsWith(matrix.testname, 'kilonova') + if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'kilonova') working-directory: tests/ run: | at plotspectra --frompackets -t 2 ${{ matrix.testname }}_testrun - name: Upload plot files - if: always() && matrix.testmode == 'OFF' + if: always() && inputs.testmode == 'OFF' uses: actions/upload-artifact@v4 with: name: test-${{ matrix.testname }}-output-pdf @@ -272,7 +270,7 @@ jobs: combine_checksums: needs: testmodels - if: always() + if: always() && inputs.testmode == 'OFF' runs-on: ubuntu-24.04 steps: - name: Download test output diff --git a/.github/workflows/cislowtestmode.yml b/.github/workflows/cislowtestmode.yml new file mode 100644 index 000000000..2a19682f0 --- /dev/null +++ b/.github/workflows/cislowtestmode.yml @@ -0,0 +1,18 @@ +--- +name: CI Slow + +on: + push: + branches: + - main + - develop + workflow_dispatch: + pull_request: + +jobs: + citestmode: + name: testmode ON + uses: ./.github/workflows/ci.yml + with: + testmode: ON + secrets: inherit From 8e01c64ceff3027b82d8c67e1703c26417b8ae0a Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 11 Nov 2024 15:51:03 +0000 Subject: [PATCH 091/117] Concurrency group slow tests per branch/PR --- .github/workflows/ci.yml | 7 ++----- .github/workflows/cislowtestmode.yml | 12 ++++++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92cc6faa2..c671971a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,6 @@ jobs: testmodels: strategy: matrix: - os: [ubuntu-24.04] testname: [ classicmode_1d_3dgrid, @@ -37,9 +36,9 @@ jobs: nebular_1d_3dgrid, nebular_1d_3dgrid_limitbfest, ] - fail-fast: false + fail-fast: ${{ inputs.testmode == 'ON' }} - runs-on: ${{ matrix.os }} + runs-on: ubuntu-24.04 timeout-minutes: 120 name: ${{ matrix.testname }} @@ -138,7 +137,6 @@ jobs: run: cat job0/output_0-0.txt - name: Checksum job0 output files - #if: always() if: always() working-directory: tests/${{ matrix.testname }}_testrun run: | @@ -192,7 +190,6 @@ jobs: cat exspec.txt - name: Checksum job1 output files - #if: always() if: always() working-directory: tests/${{ matrix.testname }}_testrun run: | diff --git a/.github/workflows/cislowtestmode.yml b/.github/workflows/cislowtestmode.yml index 2a19682f0..055297cdb 100644 --- a/.github/workflows/cislowtestmode.yml +++ b/.github/workflows/cislowtestmode.yml @@ -3,11 +3,15 @@ name: CI Slow on: push: - branches: - - main - - develop + branches-ignore: + - classic* workflow_dispatch: - pull_request: + +concurrency: + # Use github.run_id on main or develop branch (unlimited concurrency) + # Use github.ref otherwise, so that it's unique per branch or PR + group: ${{ github.workflow }}-${{ github.ref_protected && github.run_id || github.ref }} + cancel-in-progress: false jobs: citestmode: From 81ead5a1bbc942e46d9988c21d6f4c78bff013a0 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 12 Nov 2024 08:46:32 +0000 Subject: [PATCH 092/117] Add STACKTRACE=ON for assertion failures (C++23 feature supported by gcc >= 14) (#151) --- .clangd | 7 ++++++- Makefile | 39 +++++++++++++++++++++++++-------------- decay.cc | 2 +- input.cc | 2 +- sn3d.h | 11 +++++++++-- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/.clangd b/.clangd index 16adac4c8..2cea2fc80 100644 --- a/.clangd +++ b/.clangd @@ -12,7 +12,8 @@ Diagnostics: Includes: # std::ranges::upper_bound is triggering warning to include a private libc++ header __algorithm/ranges_upper_bound.h # IgnoreHeader: '.*(ranges).*' - IgnoreHeader: '.*(__algorithm).*' + IgnoreHeader: 'signal.h|(_).*(.h)|.*(__algorithm).*' + AnalyzeAngledIncludes: true Completion: AllScopes: true @@ -23,3 +24,7 @@ InlayHints: Designators: true Enabled: true ParameterNames: true + DeducedTypes: false + +Hover: + ShowAKA: Yes diff --git a/Makefile b/Makefile index 7a047e0d0..e8e5632e7 100644 --- a/Makefile +++ b/Makefile @@ -26,21 +26,31 @@ endif CXX := mpicxx COMPILER_VERSION := $(shell $(CXX) --version) +COMPILER_VERSION_NUMBER := $(shell $(CXX) -dumpversion -dumpfullversion) +COMPILER_VERSION_NUMBER_MAJOR := $(shell echo $(COMPILER_VERSION_NUMBER) | cut -f1 -d.) $(info $(COMPILER_VERSION)) ifneq '' '$(findstring clang,$(COMPILER_VERSION))' - COMPILER_NAME := CLANG - CXXFLAGS += -flto=thin + COMPILER_NAME := CLANG + CXXFLAGS += -flto=thin else ifneq '' '$(findstring g++,$(COMPILER_VERSION))' - COMPILER_NAME := GCC - CXXFLAGS += -flto=auto + COMPILER_NAME := GCC + CXXFLAGS += -flto=auto + # std::stacktrace is available in GCC 14 and later + # but it is not enabled by default because it slowed down the GitHub CI by > 2x + ifeq ($(shell expr $(COMPILER_VERSION_NUMBER_MAJOR) \>= 14),1) + ifeq ($(STACKTRACE),ON) + CXXFLAGS += -DSTACKTRACE_ON=true -rdynamic + LDFLAGS += -lstdc++exp + endif + endif else ifneq '' '$(findstring nvc++,$(COMPILER_VERSION))' - COMPILER_NAME := NVHPC + COMPILER_NAME := NVHPC else - $(warning Unknown compiler) - COMPILER_NAME := unknown + $(warning Unknown compiler) + COMPILER_NAME := unknown endif -$(info detected compiler is $(COMPILER_NAME)) +$(info detected compiler is $(COMPILER_NAME) major version $(COMPILER_VERSION_NUMBER_MAJOR)) ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -std=c++20 @@ -192,15 +202,16 @@ ifneq ($(MAX_NODE_SIZE),) endif ifeq ($(TESTMODE),ON) - CXXFLAGS += -DTESTMODE=true -D_LIBCPP_DEBUG=0 + CXXFLAGS += -DTESTMODE=true - CXXFLAGS += -D_GLIBCXX_ASSERTIONS - # CXXFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_BACKTRACE=1 + CXXFLAGS += -fno-omit-frame-pointer -g - CXXFLAGS += -fno-omit-frame-pointer -g + CXXFLAGS += -D_GLIBCXX_ASSERTIONS + # CXXFLAGS += -D_GLIBCXX_DEBUG + # CXXFLAGS += -D_GLIBCXX_DEBUG_BACKTRACE - # CXXFLAGS += -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE CXXFLAGS += -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG + # CXXFLAGS += -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE CXXFLAGS += -fsanitize=undefined,address @@ -227,7 +238,7 @@ else endif endif -CXXFLAGS += -Winline -Wall -Wextra -pedantic -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow +CXXFLAGS += -Winline -Wall -Wextra -pedantic -Wpedantic -Wredundant-decls -Wno-unused-parameter -Wno-unused-function -Wno-inline -Wsign-compare -Wshadow # sn3d.cc and exspec.cc have main() defined common_files := $(filter-out sn3d.cc exspec.cc, $(wildcard *.cc)) diff --git a/decay.cc b/decay.cc index 55d3ba88b..af34ef139 100644 --- a/decay.cc +++ b/decay.cc @@ -475,7 +475,7 @@ void filter_unused_nuclides(const std::vector &custom_zlist, const std::vec }); nuclides.shrink_to_fit(); - // update the nuclide indicies in the decay paths after we possibly removed some nuclides + // update the nuclide indices in the decay paths after we possibly removed some nuclides for (auto &decaypath : decaypaths) { std::ranges::transform(decaypath.z, decaypath.a, decaypath.nucindex.begin(), [](const auto z, const auto a) { return get_nucindex(z, a); }); diff --git a/input.cc b/input.cc index 53ab10dfe..f9a1114d9 100644 --- a/input.cc +++ b/input.cc @@ -780,7 +780,7 @@ void setup_phixs_list() { globals::bfestimcount = 0; if (nbfcontinua > 0) { - // indicies above were temporary only. continuum index should be to the sorted list + // indices above were temporary only. continuum index should be to the sorted list std::ranges::SORT_OR_STABLE_SORT(std::span(nonconstallcont, nbfcontinua), std::ranges::less{}, &FullPhotoionTransition::nu_edge); diff --git a/sn3d.h b/sn3d.h index 1d81bb393..743724e72 100644 --- a/sn3d.h +++ b/sn3d.h @@ -14,7 +14,6 @@ #define __device__ #endif -#include #include #include #include @@ -38,6 +37,13 @@ #include #include +#ifdef STACKTRACE_ON +#include +#define STACKTRACEIFSUPPORTED << std::stacktrace::current() +#else +#define STACKTRACEIFSUPPORTED +#endif + #ifdef STDPAR_ON #include @@ -133,7 +139,7 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f output_file.flush(); \ } \ std::cerr << "\n[rank " << globals::my_rank << "] " << __FILE__ << ":" << __LINE__ << ": failed assertion `" \ - << #e << "` in function " << __PRETTY_FUNCTION__ << "\n"; \ + << #e << "` in function " << __PRETTY_FUNCTION__ << "\n" STACKTRACEIFSUPPORTED; \ } \ assert(assertpass); \ } @@ -218,6 +224,7 @@ inline void gsl_error_handler_printout(const char *reason, const char *file, int } return file; } + #include "globals.h" [[nodiscard]] inline auto get_bflutindex(const int tempindex, const int element, const int ion, const int level, From 1c3be6cf3a98c6db9f0764aa0ccdd495ed68138f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 12 Nov 2024 08:47:53 +0000 Subject: [PATCH 093/117] Fix checksum upload --- .github/workflows/ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c671971a4..95a45196d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,7 +169,7 @@ jobs: run: cat job1/output_0-0.txt - name: show deposition.out - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' working-directory: tests/${{ matrix.testname }}_testrun/ run: | cat deposition.out @@ -205,61 +205,61 @@ jobs: - name: Upload output files uses: actions/upload-artifact@v4 - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' with: name: test-${{ matrix.testname }}-output path: tests/${{ matrix.testname }}_testrun - name: Upload checksum files uses: actions/upload-artifact@v4 - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' with: name: ${{ matrix.testname }}_inputfiles path: tests/${{ matrix.testname }}_inputfiles/results_md5* - name: Set up Python - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' uses: actions/setup-python@v5 - name: Install artistools - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' run: | python3 -m pip install --upgrade pip uv uv pip install --system -U artistools - name: Plot light curve - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' working-directory: tests/ run: | at plotlightcurves ${{ matrix.testname }}_testrun at plotlightcurves --frompackets ${{ matrix.testname }}_testrun - name: Plot spectrum nebular - if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'nebular') + if: always() && inputs.testmode != 'ON' && startsWith(matrix.testname, 'nebular') working-directory: tests/ run: | at plotspectra --frompackets -ts 8 ${{ matrix.testname }}_testrun - name: Plot spectrum classicmode - if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_') + if: always() && inputs.testmode != 'ON' && startsWith(matrix.testname, 'classicmode_') working-directory: tests/ run: | at plotspectra --frompackets -t 4-6 ${{ matrix.testname }}_testrun - name: Plot virtual packet spectrum classicmode_1d - if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'classicmode_1d') + if: always() && inputs.testmode != 'ON' && startsWith(matrix.testname, 'classicmode_1d') working-directory: tests/ run: | at plotspectra -t 4-6 -plotvspecpol 0 1 2 3 12 13 14 --frompackets ${{ matrix.testname }}_testrun - name: Plot spectrum kilonova - if: always() && inputs.testmode == 'OFF' && startsWith(matrix.testname, 'kilonova') + if: always() && inputs.testmode != 'ON' && startsWith(matrix.testname, 'kilonova') working-directory: tests/ run: | at plotspectra --frompackets -t 2 ${{ matrix.testname }}_testrun - name: Upload plot files - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' uses: actions/upload-artifact@v4 with: name: test-${{ matrix.testname }}-output-pdf @@ -267,7 +267,7 @@ jobs: combine_checksums: needs: testmodels - if: always() && inputs.testmode == 'OFF' + if: always() && inputs.testmode != 'ON' runs-on: ubuntu-24.04 steps: - name: Download test output From e95fc5104e246ff61503fddb0873c4c7ffc68c14 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 15 Nov 2024 13:00:20 +0000 Subject: [PATCH 094/117] Update to nvc++ 24.11 and compile as c++23 (#153) --- .github/workflows/ci-checks.yml | 2 +- .vscode/settings.json | 16 ++++++++++------ Makefile | 9 ++++----- decay.cc | 2 +- nonthermal.cc | 6 +++--- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 141d5197f..11f7add75 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -94,7 +94,7 @@ jobs: {name: gcc, ver: 12}, {name: gcc, ver: 13}, {name: gcc, ver: 14}, - {name: nvc++, ver: '24.9'}, + {name: nvc++, ver: '24.11'}, ] fail-fast: false diff --git a/.vscode/settings.json b/.vscode/settings.json index 2b419c5aa..c9ec07b28 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,22 @@ { "[cpp]": { - "editor.tabSize": 2, "editor.codeActionsOnSave": { "source.fixAll": "always" }, - "editor.formatOnSave": true + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd", + "editor.formatOnSave": true, + "editor.semanticHighlighting.enabled": true, + "editor.suggest.insertMode": "replace", + "editor.tabSize": 2, + "editor.wordBasedSuggestions": "off" }, "[yaml]": { "editor.tabSize": 4 }, + "editor.formatOnSave": true, + "editor.formatOnType": true, "files.eol": "\n", - "files.trimFinalNewlines": true, "files.insertFinalNewline": true, - "files.trimTrailingWhitespace": true, - "editor.formatOnType": true, - "editor.formatOnSave": true + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true } diff --git a/Makefile b/Makefile index e8e5632e7..2406f9352 100644 --- a/Makefile +++ b/Makefile @@ -52,13 +52,12 @@ endif $(info detected compiler is $(COMPILER_NAME) major version $(COMPILER_VERSION_NUMBER_MAJOR)) -ifeq ($(COMPILER_NAME),NVHPC) - CXXFLAGS += -std=c++20 -else - CXXFLAGS += -std=c++23 -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -Wno-error=cast-function-type -MD -MP -ftrivial-auto-var-init=pattern +CXXFLAGS += -std=c++23 -fstrict-aliasing + +ifneq ($(COMPILER_NAME),NVHPC) + CXXFLAGS += -ftree-vectorize -Wunused-macros -Werror -Wno-error=unknown-pragmas -Wno-error=cast-function-type -MD -MP -ftrivial-auto-var-init=pattern endif -CXXFLAGS += -fstrict-aliasing # CXXFLAGS += -DUSE_SIMPSON_INTEGRATOR=true # profile-guided optimisation diff --git a/decay.cc b/decay.cc index af34ef139..6ae1f59e3 100644 --- a/decay.cc +++ b/decay.cc @@ -37,7 +37,7 @@ namespace decay { namespace { -const std::array elsymbols{ +constexpr std::array elsymbols{ "n", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", diff --git a/nonthermal.cc b/nonthermal.cc index c63f7a49d..0ff349320 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -51,9 +51,9 @@ constexpr double MINDEPRATE = 0.; // Bohr radius squared in cm^2 constexpr double A_naught_squared = 2.800285203e-17; -const std::array shellnames{"K ", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5", "N1", - "N2", "N3", "N4", "N5", "N6", "N7", "O1", "O2", "O3", "O4", - "O5", "O6", "O7", "P1", "P2", "P3", "P4", "Q1"}; +constexpr std::array shellnames{"K ", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5", "N1", + "N2", "N3", "N4", "N5", "N6", "N7", "O1", "O2", "O3", "O4", + "O5", "O6", "O7", "P1", "P2", "P3", "P4", "Q1"}; std::vector> elements_electron_binding; std::vector> elements_shells_q; From 7b94bbccce7b11e398de91293511c4aba0149b5e Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 15 Nov 2024 15:52:21 +0000 Subject: [PATCH 095/117] Set clangd, clang-tidy and cppcheck to c++23 mode (#154) --- .clang-tidy | 5 +++-- .clangd | 4 +++- .github/workflows/ci-checks.yml | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 1be73aa59..2351c5023 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -41,6 +41,7 @@ Checks: > -misc-no-recursion, -misc-non-private-member-variables-in-classes, -modernize-use-ranges, + -modernize-use-std-print, # replace printout macro with a function when we want to autofix to use std::format gcc >=13 -performance-enum-size, -readability-identifier-length, -readability-function-cognitive-complexity, @@ -48,7 +49,7 @@ Checks: > WarningsAsErrors: > *, FormatStyle: file -ExtraArgs: [-std=c++20] +ExtraArgs: [-std=c++23] CheckOptions: - key: modernize-deprecated-headers.CheckHeaderFile value: 'true' @@ -56,7 +57,7 @@ CheckOptions: value: google - key: cppcoreguidelines-init-variables.MathHeader value: - - key: modernize-use-std-print.PrintfLikeFunctions # replace printout macro with a function when we want to autofix to use std::format gcc >=13 + - key: modernize-use-std-print.PrintfLikeFunctions value: printf; absl::PrintF; printout - key: modernize-use-std-print.FprintfLikeFunctions value: fprintf; absl::FPrintF diff --git a/.clangd b/.clangd index 2cea2fc80..c92409e82 100644 --- a/.clangd +++ b/.clangd @@ -2,11 +2,13 @@ CompileFlags: # to make the compilation database, pip install compiledb, then run: # compiledb -n --full-path make TESTMODE=ON CompilationDatabase: compile_commands.json - Add: [-xc++, -std=c++20, -DTESTMODE=true] + Add: [-xc++, -std=c++23, -DTESTMODE=true] Diagnostics: ClangTidy: FastCheckFilter: None + Remove: + performance-enum-size UnusedIncludes: Strict MissingIncludes: Strict Includes: diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 11f7add75..5209bb225 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -23,7 +23,7 @@ jobs: - name: run cppcheck run: | cppcheck --version - cppcheck --force --error-exitcode=1 --language=c++ --std=c++20 --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . + cppcheck --force --error-exitcode=1 --language=c++ --enable=all --inconclusive --suppress=knownConditionTrueFalse --suppress=constParameterCallback --suppress=redundantAssignment --suppress=knownArgument --suppress=missingIncludeSystem --suppress=unusedFunction --check-level=exhaustive . clang-format: runs-on: macos-15 From 10a306839650f6ab4b2dc4ee34168822b71549ca Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Fri, 15 Nov 2024 23:51:34 +0000 Subject: [PATCH 096/117] Add Apple clang compile check (#155) --- .github/workflows/ci-checks.yml | 77 ++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 5209bb225..ef6b930c2 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -85,8 +85,6 @@ jobs: xcrun run-clang-tidy compile: - env: - CXX: g++ strategy: matrix: compiler: @@ -159,7 +157,6 @@ jobs: - name: Compile classic mode run: | - $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean make -j${{ steps.cpu-count.outputs.count}} sn3d exspec @@ -171,7 +168,6 @@ jobs: - name: Compile classic mode STDPAR=ON run: | - $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec @@ -179,7 +175,6 @@ jobs: - name: Compile classic mode STDPAR=ON GPU=ON if: matrix.compiler.name == 'nvc++' run: | - $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean make STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec @@ -210,11 +205,8 @@ jobs: make clean make STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec - mac-llvm: + mac-llvm-clang: runs-on: macos-15 - env: - CXX: clang++ - name: macOS llvm clang steps: @@ -241,9 +233,72 @@ jobs: run: | brew install llvm || true echo "/opt/homebrew/opt/llvm/bin" >> $GITHUB_PATH - echo "LDFLAGS=-L/opt/homebrew/opt/llvm/lib/c++ -Wl,-rpath,/opt/homebrew/opt/llvm/lib/c++ $LDFLAGS" >> $GITHUB_ENV + echo "LDFLAGS=-L/opt/homebrew/opt/llvm/lib -L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind" >> $GITHUB_ENV + echo "CPPFLAGS=-I/opt/homebrew/opt/llvm/include" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV + - name: install OpenMPI + run: | + brew install openmpi || true + + - name: Compile classic mode + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile classic mode OPENMP=ON + run: | + make clean + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile classic mode STDPAR=ON + run: | + clang++ -v + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode OPENMP=ON + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make OPENMP=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile nebular mode STDPAR=ON + run: | + cp -v -p artisoptions_classic.h artisoptions.h + make clean + make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + mac-apple-clang: + runs-on: macos-15 + name: macOS Apple clang + + steps: + - uses: actions/checkout@v4 + + - name: CPU core count + id: cpu-count + run: | + python3 -c 'import multiprocessing; print(f"CPU count: {multiprocessing.cpu_count()}")' + echo "count=$(python3 -c 'import multiprocessing; print(multiprocessing.cpu_count())')" >> $GITHUB_OUTPUT + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 'latest-stable' + + - name: install dependencies + run: | + brew update + brew install gsl || true + - name: install OpenMP run: | brew install libomp || true @@ -258,7 +313,6 @@ jobs: - name: Compile classic mode run: | - $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean make -j${{ steps.cpu-count.outputs.count}} sn3d exspec @@ -270,7 +324,6 @@ jobs: - name: Compile classic mode STDPAR=ON run: | - $CXX -v cp -v -p artisoptions_classic.h artisoptions.h make clean make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec From 12c7abe864b4cb806e9185657a977b6f36b56102 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 18 Nov 2024 09:38:45 +0000 Subject: [PATCH 097/117] Switch __builtin_unreachable to std::unreachable() (#156) --- .clang-tidy | 100 +++++++++++++++++++++++----------------------- .clangd | 2 - atomic.h | 3 +- gammapkt.cc | 3 +- grid.cc | 6 +-- kpkt.cc | 3 +- macroatom.cc | 3 +- sn3d.h | 22 +++++----- update_packets.cc | 7 ++-- 9 files changed, 77 insertions(+), 72 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 2351c5023..156e8490b 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,53 +1,53 @@ --- InheritParentConfig: true -Checks: > - *, - -*static-assert*, - -*avoid-c-arrays, - -cert-dcl03-c, - -abseil-*, - -android-*, - -altera-*, - -bugprone-casting-through-void, - -bugprone-easily-swappable-parameters, - -bugprone-exception-escape, - -bugprone-implicit-widening-of-multiplication-result, - -bugprone-multi-level-implicit-pointer-conversion, - -bugprone-narrowing-conversions, - -boost-use-ranges, - -llvmlibc-*, - -cert-dcl50-cpp, - -cert-err33-c, - -cert-err34-c, - -cert-err58-cpp, - -clang-analyzer-deadcode.DeadStores, - -cppcoreguidelines-avoid-magic-numbers, - -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-macro-usage, - -cppcoreguidelines-no-malloc, - -cppcoreguidelines-owning-memory, - -cppcoreguidelines-pro-bounds-array-to-pointer-decay, - -cppcoreguidelines-pro-bounds-constant-array-index, - -cppcoreguidelines-pro-bounds-pointer-arithmetic, - -cppcoreguidelines-pro-type-cstyle-cast, - -cppcoreguidelines-pro-type-vararg, - -fuchsia-*, - -google-objc*, - -google-readability-todo, - -hicpp-vararg, - -hicpp-no-array-decay, - -hicpp-no-malloc, - -hicpp-signed-bitwise, - -misc-no-recursion, - -misc-non-private-member-variables-in-classes, - -modernize-use-ranges, - -modernize-use-std-print, # replace printout macro with a function when we want to autofix to use std::format gcc >=13 - -performance-enum-size, - -readability-identifier-length, - -readability-function-cognitive-complexity, - -readability-magic-numbers, -WarningsAsErrors: > - *, +Checks: [ + '*', + -*static-assert*, + -*avoid-c-arrays, + -cert-dcl03-c, + -abseil-*, + -android-*, + -altera-*, + -bugprone-casting-through-void, + -bugprone-easily-swappable-parameters, + -bugprone-exception-escape, + -bugprone-implicit-widening-of-multiplication-result, + -bugprone-multi-level-implicit-pointer-conversion, + -bugprone-narrowing-conversions, + -boost-use-ranges, + -llvmlibc-*, + -cert-dcl50-cpp, + -cert-err33-c, + -cert-err34-c, + -cert-err58-cpp, + -clang-analyzer-deadcode.DeadStores, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-cstyle-cast, + -cppcoreguidelines-pro-type-vararg, + -fuchsia-*, + -google-objc*, + -google-readability-todo, + -hicpp-vararg, + -hicpp-no-array-decay, + -hicpp-no-malloc, + -hicpp-signed-bitwise, + -misc-no-recursion, + -misc-non-private-member-variables-in-classes, + -modernize-use-ranges, # things like sort and for_each don't support parallel execution policies + -modernize-use-std-print, # replace printout macro with a function when we want to autofix to use std::format gcc >=13 + -performance-enum-size, + -readability-identifier-length, + -readability-function-cognitive-complexity, + -readability-magic-numbers, + ] +WarningsAsErrors: '*' FormatStyle: file ExtraArgs: [-std=c++23] CheckOptions: @@ -73,6 +73,6 @@ CheckOptions: value: lower_case - key: bugprone-reserved-identifier.AllowedIdentifiers value: '__host__;__device__' - - key: misc-include-cleaner.IgnoreHeaders # std::ranges::upper_bound is triggering warning to include a private libc++ header __algorithm/ranges_upper_bound.h - # value: '.*(ranges).*' + - key: misc-include-cleaner.IgnoreHeaders # std::ranges::upper_bound is triggering warning to include a private libc++ header __algorithm/ranges_upper_bound.h + # value: '.*(ranges).*' value: '.*(__algorithm).*' diff --git a/.clangd b/.clangd index c92409e82..0cff95fb0 100644 --- a/.clangd +++ b/.clangd @@ -7,8 +7,6 @@ CompileFlags: Diagnostics: ClangTidy: FastCheckFilter: None - Remove: - performance-enum-size UnusedIncludes: Strict MissingIncludes: Strict Includes: diff --git a/atomic.h b/atomic.h index c0f265d38..4c0c58124 100644 --- a/atomic.h +++ b/atomic.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "artisoptions.h" #include "constants.h" @@ -431,7 +432,7 @@ inline void set_nuptrans(const int element, const int ion, const int level, cons } assert_testmodeonly(false); if constexpr (!TESTMODE) { - __builtin_unreachable(); + std::unreachable(); } return -1; } diff --git a/gammapkt.cc b/gammapkt.cc index 6d78e8531..e57977e20 100644 --- a/gammapkt.cc +++ b/gammapkt.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "artisoptions.h" @@ -1067,7 +1068,7 @@ __host__ __device__ void do_gamma(Packet &pkt, const int nts, const double t2) { } else if constexpr (GAMMA_THERMALISATION_SCHEME == ThermalisationScheme::GUTTMAN) { guttman_thermalisation(pkt); } else { - __builtin_unreachable(); + std::unreachable(); } if (pkt.type != TYPE_GAMMA && pkt.type != TYPE_ESCAPE) { diff --git a/grid.cc b/grid.cc index d9a051832..0ccd60289 100644 --- a/grid.cc +++ b/grid.cc @@ -1414,7 +1414,7 @@ auto get_coordcellindexincrement(const int axis) -> int { printout("invalid coordinate index %d", axis); assert_testmodeonly(false); } else { - __builtin_unreachable(); + std::unreachable(); } } } @@ -1439,7 +1439,7 @@ auto get_cellcoordpointnum(const int cellindex, const int axis) -> int { printout("invalid coordinate index %d", axis); assert_testmodeonly(false); } else { - __builtin_unreachable(); + std::unreachable(); } } } @@ -2551,7 +2551,7 @@ auto get_totmassradionuclide(const int z, const int a) -> double { assert_always(false); } else { - __builtin_unreachable(); + std::unreachable(); } } diff --git a/kpkt.cc b/kpkt.cc index b7a4ee4ec..796a3b831 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "artisoptions.h" @@ -642,7 +643,7 @@ __host__ __device__ void do_kpkt(Packet &pkt, const double t2, const int nts) { } else if constexpr (TESTMODE) { assert_always(false); } else { - __builtin_unreachable(); + std::unreachable(); } } diff --git a/macroatom.cc b/macroatom.cc index 0521e419b..b9a5e01f1 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -5,6 +5,7 @@ #include #include #include +#include #if defined(STDPAR_ON) || defined(_OPENMP_ON) #include #endif @@ -602,7 +603,7 @@ __host__ __device__ void do_macroatom(Packet &pkt, const MacroAtomState &pktmast printout("ERROR: Unknown macroatom selected_action type %d\n", selected_action); assert_testmodeonly(false); } else { - __builtin_unreachable(); + std::unreachable(); } } } diff --git a/sn3d.h b/sn3d.h index 743724e72..45819c220 100644 --- a/sn3d.h +++ b/sn3d.h @@ -168,25 +168,27 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f #include #endif -template -inline void atomicadd(T &var, const T &val) { #ifdef _OPENMP -#pragma omp atomic update - var += val; +#define atomicadd(var, val) \ + { \ + _Pragma("omp atomic update") var += val; \ + } + #else #ifdef STDPAR_ON + #ifdef __cpp_lib_atomic_ref - static_assert(std::atomic::is_always_lock_free); - std::atomic_ref(var).fetch_add(val, std::memory_order_relaxed); +#define atomicadd(var, val) \ + std::atomic_ref::type>(var).fetch_add(val, std::memory_order_relaxed); #else - // this works on clang but not gcc for doubles. - __atomic_fetch_add(&var, val, __ATOMIC_RELAXED); +// needed for Apple clang +#define atomicadd(var, val) __atomic_fetch_add(&var, val, __ATOMIC_RELAXED); #endif + #else - var += val; +#define atomicadd(var, val) var += (val); #endif #endif -} inline void gsl_error_handler_printout(const char *reason, const char *file, int line, int gsl_errno) { if (gsl_errno != 18) // roundoff error diff --git a/update_packets.cc b/update_packets.cc index 22fe90716..6e07f79f0 100644 --- a/update_packets.cc +++ b/update_packets.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "artisoptions.h" #include "constants.h" @@ -178,7 +179,7 @@ void update_pellet(Packet &pkt, const int nts, const double t2) { pkt.pellet_decaytype); std::abort(); } else { - __builtin_unreachable(); + std::unreachable(); } pkt.em_time = pkt.prop_time; pkt.absorptiontype = -10; @@ -204,7 +205,7 @@ void update_pellet(Packet &pkt, const int nts, const double t2) { printout("ERROR: Something wrong with decaying pellets. tdecay %g ts %g (ts + tw) %g\n", tdecay, ts, t2); assert_testmodeonly(false); } else { - __builtin_unreachable(); + std::unreachable(); } } @@ -270,7 +271,7 @@ void do_packet(Packet &pkt, const double t2, const int nts) printout("ERROR: Unknown packet type %d\n", pkt.type); assert_testmodeonly(false); } else { - __builtin_unreachable(); + std::unreachable(); } } } From 3276e3f5a9a451d16aeccd37cae6149bcf29a253 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 18 Nov 2024 11:17:58 +0000 Subject: [PATCH 098/117] Fix false positive error: non-void function does not return a value in all control paths --- macroatom.cc | 1 + nonthermal.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/macroatom.cc b/macroatom.cc index b9a5e01f1..2bdc75ee4 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -300,6 +300,7 @@ void do_macroatom_raddeexcitation(Packet &pkt, const int element, const int ion, } assert_always(false); + return -1; } } // anonymous namespace diff --git a/nonthermal.cc b/nonthermal.cc index 0ff349320..1632d4735 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -1504,6 +1504,7 @@ auto select_nt_ionization(const int modelgridindex) -> std::tuple { } } assert_always(false); + return {-1, -1}; } auto get_uptransindex(const int element, const int ion, const int lower, const int upper) { From 2f5f3622e0e9c013f71cc25e3b4291e10a5d9ca3 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 14:25:53 +0000 Subject: [PATCH 099/117] Use ptrdiff_t literal suffix Z --- nonthermal.cc | 4 ++-- sn3d.h | 4 ++-- stats.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index 1632d4735..a01303d2e 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -393,7 +393,7 @@ void read_auger_data() { float n_auger_elec_avg = 0; double prob_num_auger[NT_MAX_AUGER_ELECTRONS + 1]; for (int a = 0; a < 9; a++) { - linepos = line + static_cast(26 + (a * 5)); + linepos = line + 26 + (a * 5); // have to read out exactly 5 characters at a time because the columns are sometimes not separated by a space char strprob[6] = "00000"; assert_always(sscanf(linepos, "%5c%n", strprob, &offset) == 1); @@ -485,7 +485,7 @@ auto get_approx_shell_occupancies(const int nbound, const int ioncharge) { assert_always(ioncharge >= 0); const int Z = nbound + ioncharge; std::vector q; - q.resize(std::max(static_cast(10), elements_electron_binding[Z - 1].size()), 0); + q.resize(std::max(10UZ, elements_electron_binding[Z - 1].size()), 0); for (int electron_loop = 0; electron_loop < nbound; electron_loop++) { if (q[0] < 2) { diff --git a/sn3d.h b/sn3d.h index 45819c220..155895b17 100644 --- a/sn3d.h +++ b/sn3d.h @@ -341,8 +341,8 @@ constexpr auto get_range_chunk(const ptrdiff_t size, const ptrdiff_t nchunks, co assert_always(nchunk >= 0); const auto minchunksize = size / nchunks; // integer division, minimum non-empty cells per process const auto n_remainder = size % nchunks; - const auto nstart = ((minchunksize + 1) * std::min(n_remainder, nchunk)) + - (minchunksize * std::max(static_cast(0), nchunk - n_remainder)); + const auto nstart = + ((minchunksize + 1) * std::min(n_remainder, nchunk)) + (minchunksize * std::max(0Z, nchunk - n_remainder)); const auto nsize = (nchunk < n_remainder) ? minchunksize + 1 : minchunksize; assert_testmodeonly(nstart >= 0); assert_testmodeonly(nsize >= 0); diff --git a/stats.cc b/stats.cc index f85473712..7b1991a96 100644 --- a/stats.cc +++ b/stats.cc @@ -156,7 +156,7 @@ void normalise_ion_estimators(const int nonemptymgi, const double deltat, const __host__ __device__ void increment(enum eventcounters i) { assert_testmodeonly(i >= 0); assert_testmodeonly(i < COUNTER_COUNT); - atomicadd(eventstats[i], static_cast(1)); + atomicadd(eventstats[i], 1Z); } void pkt_action_counters_reset() { From fc1028dda6a25807a8ab55a042558159db60456f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 15:44:02 +0000 Subject: [PATCH 100/117] Update .clangd --- .clangd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.clangd b/.clangd index 0cff95fb0..5d597e322 100644 --- a/.clangd +++ b/.clangd @@ -1,6 +1,8 @@ CompileFlags: # to make the compilation database, pip install compiledb, then run: - # compiledb -n --full-path make TESTMODE=ON + # make clean && compiledb -n --full-path make TESTMODE=ON + # or brew install bear, then: + # make clean && bear -- make TESTMODE=ON CompilationDatabase: compile_commands.json Add: [-xc++, -std=c++23, -DTESTMODE=true] From 8739f3a916be7bd3385069f93ea5dc317fc8a5a2 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 16:06:31 +0000 Subject: [PATCH 101/117] Update update_grid.cc --- update_grid.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/update_grid.cc b/update_grid.cc index 8cdc95a08..214fc635c 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -29,6 +29,7 @@ #include "vpkt.h" namespace { +std::vector heatingcoolingrates_thisrankcells; void write_to_estimators_file(FILE *estimators_file, const int mgi, const int timestep, const int titer, const HeatingCoolingRates *heatingcoolingrates) { @@ -1114,6 +1115,8 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const const int nstart = grid::get_nstart(my_rank); const int ndo = grid::get_ndo(my_rank); + heatingcoolingrates_thisrankcells.resize(ndo); + std::ranges::fill(heatingcoolingrates_thisrankcells, HeatingCoolingRates{}); #ifdef _OPENMP #pragma omp parallel #endif @@ -1126,10 +1129,9 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const for (int mgi = nstart; mgi < nstart + ndo; mgi++) { // Check if this task should work on the current model grid cell. // If yes, update the cell and write out the estimators - HeatingCoolingRates heatingcoolingrates{}; - const int assoc_cells = grid::get_numpropcells(mgi); - if (assoc_cells > 0) { - update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, &heatingcoolingrates); + if (grid::get_numpropcells(mgi) > 0) { + update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, + &heatingcoolingrates_thisrankcells.at(mgi - nstart)); } // maybe want to add omp ordered here if the modelgrid cells should be output in order @@ -1137,7 +1139,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #pragma omp critical(estimators_file) #endif { - write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates); + write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates_thisrankcells.at(mgi - nstart)); } } // end parallel for loop over all modelgrid cells From ca13c3fb2d709181e7772cc108ef68519e8314bb Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 16:24:25 +0000 Subject: [PATCH 102/117] Pass heatingcoolingrates as reference --- nonthermal.cc | 27 +++++++++++++-------------- nonthermal.h | 2 +- thermalbalance.cc | 36 ++++++++++++++++++------------------ thermalbalance.h | 2 +- update_grid.cc | 30 ++++++++++++++---------------- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/nonthermal.cc b/nonthermal.cc index a01303d2e..e790ecc45 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -2104,8 +2104,8 @@ void init() { // set total non-thermal deposition rate from individual gamma/positron/electron/alpha rates. This should be called // after packet propagation is finished for this timestep and normalise_deposition_estimators() has been done void calculate_deposition_rate_density(const int nonemptymgi, const int timestep, - HeatingCoolingRates *heatingcoolingrates) { - heatingcoolingrates->dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; + HeatingCoolingRates &heatingcoolingrates) { + heatingcoolingrates.dep_gamma = globals::dep_estimator_gamma[nonemptymgi]; const double tmid = globals::timesteps[timestep].mid; const double rho = grid::get_rho(nonemptymgi); @@ -2113,31 +2113,30 @@ void calculate_deposition_rate_density(const int nonemptymgi, const int timestep // if INSTANT_PARTICLE_DEPOSITION, use the analytic rate at t_mid since it will have no Monte Carlo noise (although // strictly, it should be an integral from the timestep start to the end) // with time-dependent deposition, we don't have an analytic rate, so we use the Monte Carlo rate - assert_always(heatingcoolingrates != nullptr); - heatingcoolingrates->eps_gamma_ana = rho * decay::get_gamma_emission_rate(nonemptymgi, tmid); + heatingcoolingrates.eps_gamma_ana = rho * decay::get_gamma_emission_rate(nonemptymgi, tmid); - heatingcoolingrates->eps_positron_ana = + heatingcoolingrates.eps_positron_ana = rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_BETAPLUS); - heatingcoolingrates->eps_electron_ana = + heatingcoolingrates.eps_electron_ana = (rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_BETAMINUS)); - heatingcoolingrates->eps_alpha_ana = + heatingcoolingrates.eps_alpha_ana = rho * decay::get_particle_injection_rate(nonemptymgi, tmid, decay::DECAYTYPE_ALPHA); if (PARTICLE_THERMALISATION_SCHEME == ThermalisationScheme::INSTANT) { - heatingcoolingrates->dep_positron = heatingcoolingrates->eps_positron_ana; - heatingcoolingrates->dep_electron = heatingcoolingrates->eps_electron_ana; - heatingcoolingrates->dep_alpha = heatingcoolingrates->eps_alpha_ana; + heatingcoolingrates.dep_positron = heatingcoolingrates.eps_positron_ana; + heatingcoolingrates.dep_electron = heatingcoolingrates.eps_electron_ana; + heatingcoolingrates.dep_alpha = heatingcoolingrates.eps_alpha_ana; } else { - heatingcoolingrates->dep_positron = globals::dep_estimator_positron[nonemptymgi]; - heatingcoolingrates->dep_electron = globals::dep_estimator_electron[nonemptymgi]; - heatingcoolingrates->dep_alpha = globals::dep_estimator_alpha[nonemptymgi]; + heatingcoolingrates.dep_positron = globals::dep_estimator_positron[nonemptymgi]; + heatingcoolingrates.dep_electron = globals::dep_estimator_electron[nonemptymgi]; + heatingcoolingrates.dep_alpha = globals::dep_estimator_alpha[nonemptymgi]; } deposition_rate_density_all_cells[nonemptymgi] = - (heatingcoolingrates->dep_gamma + heatingcoolingrates->dep_positron + heatingcoolingrates->dep_electron); + (heatingcoolingrates.dep_gamma + heatingcoolingrates.dep_positron + heatingcoolingrates.dep_electron); } // get non-thermal deposition rate density in erg / s / cm^3 previously stored by calculate_deposition_rate_density() diff --git a/nonthermal.h b/nonthermal.h index fd15a04d4..cb5455996 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -15,7 +15,7 @@ void solve_spencerfano(int nonemptymgi, int timestep, int iteration); bool energyweighted) -> double; [[nodiscard]] auto nt_ionisation_maxupperion(int element, int lowerion) -> int; [[nodiscard]] auto nt_random_upperion(int nonemptymgi, int element, int lowerion, bool energyweighted) -> int; -void calculate_deposition_rate_density(int nonemptymgi, int timestep, HeatingCoolingRates *heatingcoolingrates); +void calculate_deposition_rate_density(int nonemptymgi, int timestep, HeatingCoolingRates &heatingcoolingrates); [[nodiscard]] auto get_deposition_rate_density(int nonemptymgi) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; #pragma omp declare simd diff --git a/thermalbalance.cc b/thermalbalance.cc index c94060cd4..04185e31c 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -132,7 +132,7 @@ auto get_heating_ion_coll_deexc(const int nonemptymgi, const int element, const // Calculate the heating rates for a given cell. Results are returned via the elements of the heatingrates data // structure. void calculate_heating_rates(const int nonemptymgi, const double T_e, const double nne, - HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { + HeatingCoolingRates &heatingcoolingrates, const std::vector &bfheatingcoeffs) { double C_deexc = 0.; // double C_recomb = 0.; @@ -172,14 +172,14 @@ void calculate_heating_rates(const int nonemptymgi, const double T_e, const doub ffheating = globals::ffheatingestimator[nonemptymgi]; if constexpr (DIRECT_COL_HEAT) { - heatingcoolingrates->heating_collisional = C_deexc; + heatingcoolingrates.heating_collisional = C_deexc; } else { // Collisional heating (from estimators) - heatingcoolingrates->heating_collisional = globals::colheatingestimator[nonemptymgi]; // C_deexc + C_recomb; + heatingcoolingrates.heating_collisional = globals::colheatingestimator[nonemptymgi]; // C_deexc + C_recomb; } - heatingcoolingrates->heating_bf = bfheating; - heatingcoolingrates->heating_ff = ffheating; + heatingcoolingrates.heating_bf = bfheating; + heatingcoolingrates.heating_ff = ffheating; } // Thermal balance equation on which we have to iterate to get T_e @@ -188,7 +188,7 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const auto nonemptymgi = params->nonemptymgi; const double t_current = params->t_current; - auto *const heatingcoolingrates = params->heatingcoolingrates; + auto &heatingcoolingrates = *params->heatingcoolingrates; if constexpr (!LTEPOP_EXCITATION_USE_TJ) { if (std::abs((T_e / grid::get_Te(nonemptymgi)) - 1.) > 0.1) { grid::set_Te(nonemptymgi, T_e); @@ -211,17 +211,17 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const auto nne = grid::get_nne(nonemptymgi); // Then calculate heating and cooling rates - kpkt::calculate_cooling_rates(nonemptymgi, heatingcoolingrates); + kpkt::calculate_cooling_rates(nonemptymgi, &heatingcoolingrates); calculate_heating_rates(nonemptymgi, T_e, nne, heatingcoolingrates, *params->bfheatingcoeffs); const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const auto ntlepton_frac_heating = nonthermal::get_nt_frac_heating(modelgridindex); const auto ntlepton_dep = nonthermal::get_deposition_rate_density(nonemptymgi); const auto ntalpha_frac_heating = 1.; - const auto ntalpha_dep = heatingcoolingrates->dep_alpha; - heatingcoolingrates->heating_dep = ntlepton_dep * ntlepton_frac_heating + ntalpha_dep * ntalpha_frac_heating; - heatingcoolingrates->dep_frac_heating = - (ntalpha_dep > 0) ? heatingcoolingrates->heating_dep / (ntlepton_dep + ntalpha_dep) : ntlepton_frac_heating; + const auto ntalpha_dep = heatingcoolingrates.dep_alpha; + heatingcoolingrates.heating_dep = ntlepton_dep * ntlepton_frac_heating + ntalpha_dep * ntalpha_frac_heating; + heatingcoolingrates.dep_frac_heating = + (ntalpha_dep > 0) ? heatingcoolingrates.heating_dep / (ntlepton_dep + ntalpha_dep) : ntlepton_frac_heating; // Adiabatic cooling term const double nntot = get_nnion_tot(nonemptymgi) + nne; @@ -229,12 +229,12 @@ auto T_e_eqn_heating_minus_cooling(const double T_e, void *paras) -> double { const double volumetmin = grid::get_modelcell_assocvolume_tmin(modelgridindex); const double dV = 3 * volumetmin / pow(globals::tmin, 3) * pow(t_current, 2); // really dV/dt const double V = volumetmin * pow(t_current / globals::tmin, 3); - heatingcoolingrates->cooling_adiabatic = p * dV / V; + heatingcoolingrates.cooling_adiabatic = p * dV / V; - const double total_heating_rate = heatingcoolingrates->heating_ff + heatingcoolingrates->heating_bf + - heatingcoolingrates->heating_collisional + heatingcoolingrates->heating_dep; - const double total_coolingrate = heatingcoolingrates->cooling_ff + heatingcoolingrates->cooling_fb + - heatingcoolingrates->cooling_collisional + heatingcoolingrates->cooling_adiabatic; + const double total_heating_rate = heatingcoolingrates.heating_ff + heatingcoolingrates.heating_bf + + heatingcoolingrates.heating_collisional + heatingcoolingrates.heating_dep; + const double total_coolingrate = heatingcoolingrates.cooling_ff + heatingcoolingrates.cooling_fb + + heatingcoolingrates.cooling_collisional + heatingcoolingrates.cooling_adiabatic; return total_heating_rate - total_coolingrate; } @@ -312,14 +312,14 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco } void call_T_e_finder(const int nonemptymgi, const double t_current, const double T_min, const double T_max, - HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs) { + HeatingCoolingRates &heatingcoolingrates, const std::vector &bfheatingcoeffs) { const int modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double T_e_old = grid::get_Te(nonemptymgi); printout("Finding T_e in cell %d at timestep %d...", modelgridindex, globals::timestep); TeSolutionParams paras = {.t_current = t_current, .nonemptymgi = nonemptymgi, - .heatingcoolingrates = heatingcoolingrates, + .heatingcoolingrates = &heatingcoolingrates, .bfheatingcoeffs = &bfheatingcoeffs}; gsl_function find_T_e_f = {.function = &T_e_eqn_heating_minus_cooling, .params = ¶s}; diff --git a/thermalbalance.h b/thermalbalance.h index a95a7ade9..ffd97060e 100644 --- a/thermalbalance.h +++ b/thermalbalance.h @@ -25,7 +25,7 @@ struct HeatingCoolingRates { }; void call_T_e_finder(int nonemptymgi, double t_current, double T_min, double T_max, - HeatingCoolingRates *heatingcoolingrates, const std::vector &bfheatingcoeffs); + HeatingCoolingRates &heatingcoolingrates, const std::vector &bfheatingcoeffs); [[nodiscard]] auto get_bfheatingcoeff_ana(int element, int ion, int level, int phixstargetindex, double T_R, double W) -> double; void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingcoeffs); diff --git a/update_grid.cc b/update_grid.cc index 214fc635c..c90d043df 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -32,7 +32,7 @@ namespace { std::vector heatingcoolingrates_thisrankcells; void write_to_estimators_file(FILE *estimators_file, const int mgi, const int timestep, const int titer, - const HeatingCoolingRates *heatingcoolingrates) { + const HeatingCoolingRates &heatingcoolingrates) { // return; disable for better performance (if estimators files are not needed) if (grid::get_numpropcells(mgi) < 1) { @@ -653,17 +653,17 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti // ana means analytical at t_mid, i.e. the rates calculated from the nuclear abundances and decay data, not from // Monte Carlo fprintf(estimators_file, "emission_ana: gamma %11.5e positron %11.5e electron %11.5e alpha %11.5e\n", - heatingcoolingrates->eps_gamma_ana, heatingcoolingrates->eps_positron_ana, - heatingcoolingrates->eps_electron_ana, heatingcoolingrates->eps_alpha_ana); + heatingcoolingrates.eps_gamma_ana, heatingcoolingrates.eps_positron_ana, heatingcoolingrates.eps_electron_ana, + heatingcoolingrates.eps_alpha_ana); fprintf(estimators_file, "deposition: gamma %11.5e positron %11.5e electron %11.5e alpha %11.5e\n", - heatingcoolingrates->dep_gamma, heatingcoolingrates->dep_positron, heatingcoolingrates->dep_electron, - heatingcoolingrates->dep_alpha); + heatingcoolingrates.dep_gamma, heatingcoolingrates.dep_positron, heatingcoolingrates.dep_electron, + heatingcoolingrates.dep_alpha); fprintf(estimators_file, "heating: ff %11.5e bf %11.5e coll %11.5e dep %11.5e heating_dep/total_dep %.3f\n", - heatingcoolingrates->heating_ff, heatingcoolingrates->heating_bf, heatingcoolingrates->heating_collisional, - heatingcoolingrates->heating_dep, heatingcoolingrates->dep_frac_heating); + heatingcoolingrates.heating_ff, heatingcoolingrates.heating_bf, heatingcoolingrates.heating_collisional, + heatingcoolingrates.heating_dep, heatingcoolingrates.dep_frac_heating); fprintf(estimators_file, "cooling: ff %11.5e fb %11.5e coll %11.5e adiabatic %11.5e\n", - heatingcoolingrates->cooling_ff, heatingcoolingrates->cooling_fb, heatingcoolingrates->cooling_collisional, - heatingcoolingrates->cooling_adiabatic); + heatingcoolingrates.cooling_ff, heatingcoolingrates.cooling_fb, heatingcoolingrates.cooling_collisional, + heatingcoolingrates.cooling_adiabatic); fprintf(estimators_file, "\n"); @@ -676,7 +676,7 @@ void write_to_estimators_file(FILE *estimators_file, const int mgi, const int ti } void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, - HeatingCoolingRates *heatingcoolingrates) + HeatingCoolingRates &heatingcoolingrates) // nts is the timestep number { const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); @@ -873,7 +873,7 @@ static void titer_average_estimators(const int nonemptymgi) { #endif void update_grid_cell(const int mgi, const int nts, const int nts_prev, const int titer, const double tratmid, - const double deltat, HeatingCoolingRates *heatingcoolingrates) { + const double deltat, HeatingCoolingRates &heatingcoolingrates) { const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); const double deltaV = @@ -1127,11 +1127,9 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #endif for (int mgi = nstart; mgi < nstart + ndo; mgi++) { - // Check if this task should work on the current model grid cell. - // If yes, update the cell and write out the estimators + auto &heatingcoolingrates = heatingcoolingrates_thisrankcells.at(mgi - nstart); if (grid::get_numpropcells(mgi) > 0) { - update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, - &heatingcoolingrates_thisrankcells.at(mgi - nstart)); + update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, heatingcoolingrates); } // maybe want to add omp ordered here if the modelgrid cells should be output in order @@ -1139,7 +1137,7 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const #pragma omp critical(estimators_file) #endif { - write_to_estimators_file(estimators_file, mgi, nts, titer, &heatingcoolingrates_thisrankcells.at(mgi - nstart)); + write_to_estimators_file(estimators_file, mgi, nts, titer, heatingcoolingrates); } } // end parallel for loop over all modelgrid cells From d0a23de83cc96ca1205813f8cea9bbc654ff755b Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 16:38:41 +0000 Subject: [PATCH 103/117] Initialise prev_bfrate_normed to zero --- radfield.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radfield.cc b/radfield.cc index 2e99d50b2..1cd03f81d 100644 --- a/radfield.cc +++ b/radfield.cc @@ -527,6 +527,9 @@ void init(const int my_rank, const int ndo_nonempty) { { std::tie(prev_bfrate_normed, win_prev_bfrate_normed) = MPI_shared_malloc_keepwin(nonempty_npts_model * globals::bfestimcount); + if (globals::rank_in_node == 0) { + std::ranges::fill_n(prev_bfrate_normed, nonempty_npts_model * globals::bfestimcount, 0.); + } } printout("[info] mem_usage: detailed bf estimators for non-empty cells occupy %.3f MB (node shared memory)\n", nonempty_npts_model * globals::bfestimcount * sizeof(float) / 1024. / 1024.); From 10fa884a328d9b9eb9574ea9f697b0aca8f93792 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 16:48:14 +0000 Subject: [PATCH 104/117] Make prev_bfrate_normed a std::span --- radfield.cc | 9 +++++---- sn3d.h | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/radfield.cc b/radfield.cc index 1cd03f81d..3b114c4d8 100644 --- a/radfield.cc +++ b/radfield.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -66,8 +67,8 @@ std::vector detailed_lineindicies; std::vector> prev_Jb_lu_normed{}; // value from the previous timestep std::vector> Jb_lu_raw{}; // unnormalised estimator for the current timestep -float *prev_bfrate_normed{}; // values from the previous timestep -std::vector bfrate_raw; // unnormalised estimators for the current timestep +std::span prev_bfrate_normed{}; // values from the previous timestep +std::vector bfrate_raw; // unnormalised estimators for the current timestep // expensive debugging mode to track the contributions to each bound-free rate estimator @@ -526,9 +527,9 @@ void init(const int my_rank, const int ndo_nonempty) { if constexpr (DETAILED_BF_ESTIMATORS_ON) { { std::tie(prev_bfrate_normed, win_prev_bfrate_normed) = - MPI_shared_malloc_keepwin(nonempty_npts_model * globals::bfestimcount); + MPI_shared_malloc_keepwin_span(nonempty_npts_model * globals::bfestimcount); if (globals::rank_in_node == 0) { - std::ranges::fill_n(prev_bfrate_normed, nonempty_npts_model * globals::bfestimcount, 0.); + std::ranges::fill(prev_bfrate_normed, 0.); } } printout("[info] mem_usage: detailed bf estimators for non-empty cells occupy %.3f MB (node shared memory)\n", diff --git a/sn3d.h b/sn3d.h index 155895b17..61e99616b 100644 --- a/sn3d.h +++ b/sn3d.h @@ -372,6 +372,12 @@ template return {ptr, mpiwin}; } +template +[[nodiscard]] auto MPI_shared_malloc_keepwin_span(const ptrdiff_t num_allranks) -> std::tuple, MPI_Win> { + auto [ptr, mpiwin] = MPI_shared_malloc_keepwin(num_allranks); + return {std::span(ptr, num_allranks), mpiwin}; +} + template [[nodiscard]] auto MPI_shared_malloc(const ptrdiff_t num_allranks) -> T * { if (num_allranks == 0) { From 913a85f40656d3773dc4e164a9eb46afda72cd2f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 19 Nov 2024 16:53:33 +0000 Subject: [PATCH 105/117] Write estimators: replace mutex with single thread loop after update grid cells Simplifies parallelisation of update_grid --- update_grid.cc | 68 +++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/update_grid.cc b/update_grid.cc index c90d043df..bf15cf6df 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -31,18 +31,10 @@ namespace { std::vector heatingcoolingrates_thisrankcells; -void write_to_estimators_file(FILE *estimators_file, const int mgi, const int timestep, const int titer, +void write_to_estimators_file(FILE *estimators_file, const int nonemptymgi, const int timestep, const int titer, const HeatingCoolingRates &heatingcoolingrates) { // return; disable for better performance (if estimators files are not needed) - - if (grid::get_numpropcells(mgi) < 1) { - // modelgrid cells that are not represented in the simulation grid - fprintf(estimators_file, "timestep %d modelgridindex %d EMPTYCELL\n\n", timestep, mgi); - fflush(estimators_file); - return; - } - - const auto nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); const auto sys_time_start_write_estimators = std::time(nullptr); @@ -872,9 +864,9 @@ static void titer_average_estimators(const int nonemptymgi) { } #endif -void update_grid_cell(const int mgi, const int nts, const int nts_prev, const int titer, const double tratmid, +void update_grid_cell(const int nonemptymgi, const int nts, const int nts_prev, const int titer, const double tratmid, const double deltat, HeatingCoolingRates &heatingcoolingrates) { - const ptrdiff_t nonemptymgi = grid::get_nonemptymgi_of_mgi(mgi); + const int mgi = grid::get_mgi_of_nonemptymgi(nonemptymgi); const double deltaV = grid::get_modelcell_assocvolume_tmin(mgi) * pow(globals::timesteps[nts_prev].mid / globals::tmin, 3); @@ -1117,43 +1109,35 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const const int ndo = grid::get_ndo(my_rank); heatingcoolingrates_thisrankcells.resize(ndo); std::ranges::fill(heatingcoolingrates_thisrankcells, HeatingCoolingRates{}); -#ifdef _OPENMP -#pragma omp parallel -#endif - { -// Updating cell information -#ifdef _OPENMP -#pragma omp for schedule(dynamic) -#endif - for (int mgi = nstart; mgi < nstart + ndo; mgi++) { - auto &heatingcoolingrates = heatingcoolingrates_thisrankcells.at(mgi - nstart); - if (grid::get_numpropcells(mgi) > 0) { - update_grid_cell(mgi, nts, nts_prev, titer, tratmid, deltat, heatingcoolingrates); - } - - // maybe want to add omp ordered here if the modelgrid cells should be output in order #ifdef _OPENMP -#pragma omp critical(estimators_file) +#pragma omp parallel for schedule(dynamic) #endif - { - write_to_estimators_file(estimators_file, mgi, nts, titer, heatingcoolingrates); - } - } // end parallel for loop over all modelgrid cells - - } // end OpenMP parallel section + for (int mgi = nstart; mgi < nstart + ndo; mgi++) { + const auto nonemptymgi = (grid::get_numpropcells(mgi) > 0) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + if (nonemptymgi >= 0) { + update_grid_cell(nonemptymgi, nts, nts_prev, titer, tratmid, deltat, + heatingcoolingrates_thisrankcells.at(mgi - nstart)); + } + } // end parallel for loop over all modelgrid cells + + // serial output of estimator data to this ranks estimator file cell by cell + for (int mgi = nstart; mgi < nstart + ndo; mgi++) { + const auto nonemptymgi = (grid::get_numpropcells(mgi) > 0) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; + if (nonemptymgi >= 0) { + write_to_estimators_file(estimators_file, nonemptymgi, nts, titer, + heatingcoolingrates_thisrankcells.at(mgi - nstart)); + } else { + // modelgrid cells that are not represented in the simulation grid + fprintf(estimators_file, "timestep %d modelgridindex %d EMPTYCELL\n\n", nts, mgi); + fflush(estimators_file); + } + } // Now after all the relevant tasks of update_grid have been finished activate - // the use of the cellcache for all OpenMP tasks, in what follows (update_packets) + // the use of the cellcache for what follows (update_packets) use_cellcache = true; - // alternative way to write out estimators. this keeps the modelgrid cells in order but - // heatingrates are not valid. #ifdef _OPENMP for (int n = nstart; n < nstart+nblock; n++) - // { - // write_to_estimators_file(n,nts); - // } - // #endif - globals::max_path_step = std::min(1.e35, globals::rmax / 10.); printout("max_path_step %g\n", globals::max_path_step); From c9a64baf3fd49d25c61e9cb4be4fe4c647b7c6f1 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 20 Nov 2024 16:37:34 +0000 Subject: [PATCH 106/117] Fix artisoptions_christinenonthermal.h and add check for compilation of all option files (#158) --- .github/workflows/ci-checks.yml | 12 ++++++++++++ artisoptions_christinenonthermal.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index ef6b930c2..fb1e76868 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -205,6 +205,10 @@ jobs: make clean make STDPAR=ON GPU=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + - name: Compile all remaining option files + run: | + find . -name "artisoptions_*.h" ! -name "artisoptions_classic.h" ! -name "artisoptions_nebular.h" -exec sh -c 'cp -v -p {} artisoptions.h && make sn3d' \; + mac-llvm-clang: runs-on: macos-15 name: macOS llvm clang @@ -277,6 +281,10 @@ jobs: make clean make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + - name: Compile all remaining option files + run: | + find . -name "artisoptions_*.h" ! -name "artisoptions_classic.h" ! -name "artisoptions_nebular.h" -exec sh -c 'cp -v -p {} artisoptions.h && make sn3d' \; + mac-apple-clang: runs-on: macos-15 name: macOS Apple clang @@ -345,3 +353,7 @@ jobs: cp -v -p artisoptions_classic.h artisoptions.h make clean make STDPAR=ON -j${{ steps.cpu-count.outputs.count}} sn3d exspec + + - name: Compile all remaining option files + run: | + find . -name "artisoptions_*.h" ! -name "artisoptions_classic.h" ! -name "artisoptions_nebular.h" -exec sh -c 'cp -v -p {} artisoptions.h && make sn3d' \; diff --git a/artisoptions_christinenonthermal.h b/artisoptions_christinenonthermal.h index 77c574bcf..aa646dc34 100644 --- a/artisoptions_christinenonthermal.h +++ b/artisoptions_christinenonthermal.h @@ -62,6 +62,8 @@ constexpr double MINPOP = 1e-40; constexpr double NU_MIN_R = 1e13; constexpr double NU_MAX_R = 5e16; +constexpr bool PHIXS_CLASSIC_NO_INTERPOLATION = false; + constexpr bool MULTIBIN_RADFIELD_MODEL_ON = true; constexpr int RADFIELDBINCOUNT = 64; @@ -118,6 +120,8 @@ constexpr bool SF_AUGER_CONTRIBUTION_ON = true; constexpr bool SF_AUGER_CONTRIBUTION_DISTRIBUTE_EN = false; +constexpr bool NT_WORKFUNCTION_USE_SHELL_OCCUPANCY_FILE = false; + constexpr double TEMPERATURE_SOLVER_ACCURACY = 1e-3; constexpr double CONTINUUM_NU_INTEGRAL_ACCURACY = 1e-3; From fbad3559f333d819e0492d82eba4346f022c19e2 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 21 Nov 2024 11:59:27 +0000 Subject: [PATCH 107/117] STDPAR parallelise update_grid components (#157) in STDPAR mode, cells are processed one at a time using multiple threads for accelerating various solvers (compare to OpenMP mode in which each thread updates a different cell). --- Makefile | 2 +- atomic.h | 4 +-- grid.cc | 1 + kpkt.cc | 7 +++-- ltepop.h | 6 ++-- macroatom.cc | 14 ++++----- macroatom.h | 12 +++----- nltepop.cc | 75 ++++++++++++++++++++++++++--------------------- nonthermal.cc | 13 ++++---- nonthermal.h | 2 +- packet.cc | 4 +-- radfield.cc | 4 +-- sn3d.cc | 25 +++++++++------- sn3d.h | 9 ++++-- thermalbalance.cc | 6 ++-- update_grid.cc | 26 ++++++++-------- 16 files changed, 116 insertions(+), 94 deletions(-) diff --git a/Makefile b/Makefile index 2406f9352..7f5c4d68a 100644 --- a/Makefile +++ b/Makefile @@ -232,7 +232,7 @@ else ifeq ($(COMPILER_NAME),NVHPC) CXXFLAGS += -fast else - CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only -fopenmp-simd + CXXFLAGS += -ffast-math -funsafe-math-optimizations -fno-finite-math-only endif endif endif diff --git a/atomic.h b/atomic.h index 4c0c58124..a4a86d613 100644 --- a/atomic.h +++ b/atomic.h @@ -58,7 +58,7 @@ inline auto get_nlevels(const int element, const int ion) -> int { } // Return the energy of (element,ion,level). -#pragma omp declare simd + [[nodiscard]] inline auto epsilon(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); @@ -120,7 +120,7 @@ inline auto get_nphixstargets(const int element, const int ion, const int level) } // Return the statistical weight of (element,ion,level). -#pragma omp declare simd + [[nodiscard]] inline auto stat_weight(const int element, const int ion, const int level) -> double { assert_testmodeonly(element < get_nelements()); assert_testmodeonly(ion < get_nions(element)); diff --git a/grid.cc b/grid.cc index 0ccd60289..89351198a 100644 --- a/grid.cc +++ b/grid.cc @@ -1005,6 +1005,7 @@ void setup_nstart_ndo() { assert_always(fileout.is_open()); fileout << "#rank nstart ndo ndo_nonempty\n"; for (int r = 0; r < nprocesses; r++) { + assert_always(ranks_ndo_nonempty[r] <= ranks_ndo[r]); fileout << r << " " << ranks_nstart[r] << " " << ranks_ndo[r] << " " << ranks_ndo_nonempty[r] << "\n"; } } diff --git a/kpkt.cc b/kpkt.cc index 796a3b831..d8b195cc7 100644 --- a/kpkt.cc +++ b/kpkt.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -262,12 +263,14 @@ void calculate_cooling_rates(const int nonemptymgi, HeatingCoolingRates *heating double C_fb_all = 0.; // free-bound creation of rpkt double C_exc_all = 0.; // collisional excitation of macroatoms double C_ionization_all = 0.; // collisional ionisation of macroatoms - for (int allionindex = 0; allionindex < get_includedions(); allionindex++) { + + const auto allionindices = std::ranges::iota_view{0, get_includedions()}; + std::for_each(EXEC_PAR allionindices.begin(), allionindices.end(), [&](const int allionindex) { const auto [element, ion] = get_ionfromuniqueionindex(allionindex); grid::ion_cooling_contribs_allcells[(static_cast(nonemptymgi) * get_includedions()) + allionindex] = calculate_cooling_rates_ion(nonemptymgi, element, ion, -1, cellcacheslotid, &C_ff_all, &C_fb_all, &C_exc_all, &C_ionization_all); - } + }); // this loop is made separate for future parallelisation of upper loop. // the ion contributions must be added in this exact order diff --git a/ltepop.h b/ltepop.h index 9d7d1c8e6..08dbe26ae 100644 --- a/ltepop.h +++ b/ltepop.h @@ -4,11 +4,11 @@ #include [[nodiscard]] auto get_groundlevelpop(int nonemptymgi, int element, int ion) -> double; -#pragma omp declare simd + [[nodiscard]] auto calculate_levelpop(int nonemptymgi, int element, int ion, int level) -> double; -#pragma omp declare simd + [[nodiscard]] auto calculate_levelpop_lte(int nonemptymgi, int element, int ion, int level) -> double; -#pragma omp declare simd + [[nodiscard]] auto get_levelpop(int nonemptymgi, int element, int ion, int level) -> double; [[nodiscard]] auto calculate_sahafact(int element, int ion, int level, int upperionlevel, double T, double E_threshold) -> double; diff --git a/macroatom.cc b/macroatom.cc index 2bdc75ee4..c30766e5c 100644 --- a/macroatom.cc +++ b/macroatom.cc @@ -646,7 +646,7 @@ void macroatom_close_file() { // radiative deexcitation rate: paperII 3.5.2 // multiply by upper level population to get a rate per second -#pragma omp declare simd + auto rad_deexcitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lower, const double epsilon_trans, const float A_ul, const double upperstatweight, const double nnlevelupper, const double t_current) -> double { @@ -690,7 +690,7 @@ auto rad_deexcitation_ratecoeff(const int nonemptymgi, const int element, const // radiative excitation rate: paperII 3.5.2 // multiply by lower level population to get a rate per second -#pragma omp declare simd + auto rad_excitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double nnlevel_lower, const int lineindex, const double t_current) -> double { @@ -732,7 +732,7 @@ auto rad_excitation_ratecoeff(const int nonemptymgi, const int element, const in // radiative recombination rate: paperII 3.5.2 // multiply by upper level population to get a rate per second -#pragma omp declare simd + auto rad_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, const int upperionlevel, const int lowerionlevel, const int nonemptymgi) -> double { // it's probably faster to only check this condition outside this function @@ -777,7 +777,7 @@ auto stim_recombination_ratecoeff(const float nne, const int element, const int } // multiply by upper level population to get a rate per second -#pragma omp declare simd + auto col_recombination_ratecoeff(const float T_e, const float nne, const int element, const int upperion, const int upper, const int lower, const double epsilon_trans) -> double { // it's probably faster to only check this condition outside this function @@ -818,7 +818,7 @@ auto col_recombination_ratecoeff(const float T_e, const float nne, const int ele // collisional ionization rate: paperII 3.5.1 // multiply by lower level population to get a rate per second -#pragma omp declare simd + auto col_ionization_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int phixstargetindex, const double epsilon_trans) -> double { assert_testmodeonly(phixstargetindex >= 0); @@ -850,7 +850,7 @@ auto col_ionization_ratecoeff(const float T_e, const float nne, const int elemen } // multiply by upper level population to get a rate per second -#pragma omp declare simd + auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double epsilon_trans, const int element, const int ion, const int upper, const LevelTransition &downtransition) -> double { const int lower = downtransition.targetlevelindex; @@ -901,7 +901,7 @@ auto col_deexcitation_ratecoeff(const float T_e, const float nne, const double e } // multiply by lower level population to get a rate per second -#pragma omp declare simd + auto col_excitation_ratecoeff(const float T_e, const float nne, const int element, const int ion, const int lower, const int uptransindex, const double epsilon_trans, const double lowerstatweight) -> double { diff --git a/macroatom.h b/macroatom.h index bee0939cc..69e13f6da 100644 --- a/macroatom.h +++ b/macroatom.h @@ -9,33 +9,29 @@ void macroatom_close_file(); void do_macroatom(Packet &pkt, const MacroAtomState &pktmastate); -#pragma omp declare simd [[nodiscard]] auto rad_deexcitation_ratecoeff(int nonemptymgi, int element, int ion, int lower, double epsilon_trans, float A_ul, double upperstatweight, double nnlevelupper, double t_current) -> double; -#pragma omp declare simd [[nodiscard]] auto rad_excitation_ratecoeff(int nonemptymgi, int element, int ion, int lower, int uptransindex, double epsilon_trans, double nnlevel_lower, int lineindex, double t_current) -> double; -#pragma omp declare simd [[nodiscard]] auto rad_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upperionlevel, int lowerionlevel, int nonemptymgi) -> double; -#pragma omp declare simd + [[nodiscard]] auto stim_recombination_ratecoeff(float nne, int element, int upperion, int upper, int lower, int nonemptymgi) -> double; -#pragma omp declare simd [[nodiscard]] auto col_recombination_ratecoeff(float T_e, float nne, int element, int upperion, int upper, int lower, double epsilon_trans) -> double; -#pragma omp declare simd + [[nodiscard]] auto col_ionization_ratecoeff(float T_e, float nne, int element, int ion, int lower, int phixstargetindex, double epsilon_trans) -> double; -#pragma omp declare simd + [[nodiscard]] auto col_deexcitation_ratecoeff(float T_e, float nne, double epsilon_trans, int element, int ion, int upper, const LevelTransition &downtransition) -> double; -#pragma omp declare simd + [[nodiscard]] auto col_excitation_ratecoeff(float T_e, float nne, int element, int ion, int lower, int uptransindex, double epsilon_trans, double lowerstatweight) -> double; diff --git a/nltepop.cc b/nltepop.cc index 69d4165d5..168518b89 100644 --- a/nltepop.cc +++ b/nltepop.cc @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -441,7 +443,8 @@ void nltepop_matrix_add_boundbound(const int nonemptymgi, const int element, con const auto T_e = grid::get_Te(nonemptymgi); const float nne = grid::get_nne(nonemptymgi); const int nlevels = get_nlevels(element, ion); - for (int level = 0; level < nlevels; level++) { + const auto levels = std::ranges::iota_view{0, nlevels}; + std::for_each(levels.begin(), levels.end(), [&](const auto level) { const int level_index = get_nlte_vector_index(element, ion, level); const double epsilon_level = epsilon(element, ion, level); const double statweight = stat_weight(element, ion, level); @@ -449,9 +452,8 @@ void nltepop_matrix_add_boundbound(const int nonemptymgi, const int element, con // de-excitation const int ndowntrans = get_ndowntrans(element, ion, level); - const auto *const leveldowntranslist = get_downtranslist(element, ion, level); - for (int i = 0; i < ndowntrans; i++) { - const auto &downtransition = leveldowntranslist[i]; + const auto leveldowntrans = std::span(get_downtranslist(element, ion, level), ndowntrans); + std::for_each(leveldowntrans.begin(), leveldowntrans.end(), [&](const auto &downtransition) { const double A_ul = downtransition.einstein_A; const int lower = downtransition.targetlevelindex; @@ -466,20 +468,21 @@ void nltepop_matrix_add_boundbound(const int nonemptymgi, const int element, con const int upper_index = level_index; const int lower_index = get_nlte_vector_index(element, ion, lower); - *gsl_matrix_ptr(rate_matrix_rad_bb, upper_index, upper_index) -= R; - *gsl_matrix_ptr(rate_matrix_rad_bb, lower_index, upper_index) += R; - *gsl_matrix_ptr(rate_matrix_coll_bb, upper_index, upper_index) -= C; - *gsl_matrix_ptr(rate_matrix_coll_bb, lower_index, upper_index) += C; + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bb, upper_index, upper_index), -R); + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bb, lower_index, upper_index), R); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bb, upper_index, upper_index), -C); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bb, lower_index, upper_index), C); if ((R < 0) || (C < 0)) { printout(" WARNING: Negative de-excitation rate from ionstage %d level %d to level %d\n", get_ionstage(element, ion), level, lower); } - } + }); // excitation const int nuptrans = get_nuptrans(element, ion, level); const auto *const leveluptranslist = get_uptranslist(element, ion, level); - for (int i = 0; i < nuptrans; i++) { + const auto nuptransindices = std::ranges::iota_view{0, nuptrans}; + std::for_each(nuptransindices.begin(), nuptransindices.end(), [&](const auto i) { const int lineindex = leveluptranslist[i].lineindex; const int upper = leveluptranslist[i].targetlevelindex; const double epsilon_trans = epsilon(element, ion, upper) - epsilon_level; @@ -501,18 +504,19 @@ void nltepop_matrix_add_boundbound(const int nonemptymgi, const int element, con const int lower_index = level_index; const int upper_index = get_nlte_vector_index(element, ion, upper); - *gsl_matrix_ptr(rate_matrix_rad_bb, lower_index, lower_index) -= R; - *gsl_matrix_ptr(rate_matrix_rad_bb, upper_index, lower_index) += R; - *gsl_matrix_ptr(rate_matrix_coll_bb, lower_index, lower_index) -= C; - *gsl_matrix_ptr(rate_matrix_coll_bb, upper_index, lower_index) += C; - *gsl_matrix_ptr(rate_matrix_ntcoll_bb, lower_index, lower_index) -= NTC; - *gsl_matrix_ptr(rate_matrix_ntcoll_bb, upper_index, lower_index) += NTC; + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bb, lower_index, lower_index), -R); + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bb, upper_index, lower_index), R); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bb, lower_index, lower_index), -C); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bb, upper_index, lower_index), C); + atomicadd(*gsl_matrix_ptr(rate_matrix_ntcoll_bb, lower_index, lower_index), -NTC); + atomicadd(*gsl_matrix_ptr(rate_matrix_ntcoll_bb, upper_index, lower_index), NTC); + if ((R < 0) || (C < 0)) { printout(" WARNING: Negative excitation rate from ion %d level %d to level %d\n", get_ionstage(element, ion), level, upper); } - } - } + }); + }); } void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const int ion, @@ -525,7 +529,8 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const int nionisinglevels = get_nlevels_ionising(element, ion); const int maxrecombininglevel = get_maxrecombininglevel(element, ion + 1); - for (int level = 0; level < nionisinglevels; level++) { + const auto levels = std::ranges::iota_view{0, nionisinglevels}; + std::for_each(EXEC_PAR levels.begin(), levels.end(), [&](const auto level) { const int lower_index = get_nlte_vector_index(element, ion, level); // thermal collisional ionization, photoionisation and recombination processes @@ -544,10 +549,10 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const double C_ionisation = col_ionization_ratecoeff(T_e, nne, element, ion, level, phixstargetindex, epsilon_trans); - *gsl_matrix_ptr(rate_matrix_rad_bf, lower_index, lower_index) -= R_ionisation * s_renorm[level]; - *gsl_matrix_ptr(rate_matrix_rad_bf, upper_index, lower_index) += R_ionisation * s_renorm[level]; - *gsl_matrix_ptr(rate_matrix_coll_bf, lower_index, lower_index) -= C_ionisation * s_renorm[level]; - *gsl_matrix_ptr(rate_matrix_coll_bf, upper_index, lower_index) += C_ionisation * s_renorm[level]; + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bf, lower_index, lower_index), -R_ionisation * s_renorm[level]); + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bf, upper_index, lower_index), R_ionisation * s_renorm[level]); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bf, lower_index, lower_index), -C_ionisation * s_renorm[level]); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bf, upper_index, lower_index), C_ionisation * s_renorm[level]); if ((R_ionisation < 0) || (C_ionisation < 0)) { printout(" WARNING: Negative ionization rate from ionstage %d level %d phixstargetindex %d\n", @@ -560,10 +565,10 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, const double R_recomb = rad_recombination_ratecoeff(T_e, nne, element, ion + 1, upper, level, nonemptymgi); const double C_recomb = col_recombination_ratecoeff(T_e, nne, element, ion + 1, upper, level, epsilon_trans); - *gsl_matrix_ptr(rate_matrix_rad_bf, upper_index, upper_index) -= R_recomb * s_renorm[upper]; - *gsl_matrix_ptr(rate_matrix_rad_bf, lower_index, upper_index) += R_recomb * s_renorm[upper]; - *gsl_matrix_ptr(rate_matrix_coll_bf, upper_index, upper_index) -= C_recomb * s_renorm[upper]; - *gsl_matrix_ptr(rate_matrix_coll_bf, lower_index, upper_index) += C_recomb * s_renorm[upper]; + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bf, upper_index, upper_index), -R_recomb * s_renorm[upper]); + atomicadd(*gsl_matrix_ptr(rate_matrix_rad_bf, lower_index, upper_index), R_recomb * s_renorm[upper]); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bf, upper_index, upper_index), -C_recomb * s_renorm[upper]); + atomicadd(*gsl_matrix_ptr(rate_matrix_coll_bf, lower_index, upper_index), C_recomb * s_renorm[upper]); if ((R_recomb < 0) || (C_recomb < 0)) { printout(" WARNING: Negative recombination rate to ionstage %d level %d phixstargetindex %d\n", @@ -571,7 +576,7 @@ void nltepop_matrix_add_ionisation(const int modelgridindex, const int element, } } } - } + }); } void nltepop_matrix_add_nt_ionisation(const int nonemptymgi, const int element, const int ion, @@ -595,9 +600,10 @@ void nltepop_matrix_add_nt_ionisation(const int nonemptymgi, const int element, for (int level = 0; level < nlevels; level++) { const int lower_index = get_nlte_vector_index(element, ion, level); - *gsl_matrix_ptr(rate_matrix_ntcoll_bf, lower_index, lower_index) -= Y_nt_thisupperion * s_renorm[level]; - *gsl_matrix_ptr(rate_matrix_ntcoll_bf, upper_groundstate_index, lower_index) += - Y_nt_thisupperion * s_renorm[level]; + atomicadd(*gsl_matrix_ptr(rate_matrix_ntcoll_bf, lower_index, lower_index), + -Y_nt_thisupperion * s_renorm[level]); + atomicadd(*gsl_matrix_ptr(rate_matrix_ntcoll_bf, upper_groundstate_index, lower_index), + Y_nt_thisupperion * s_renorm[level]); } } } @@ -894,7 +900,8 @@ void solve_nlte_pops_element(const int element, const int nonemptymgi, const int } // printout(" Adding rates for ion stages:"); - for (int ion = 0; ion < nions; ion++) { + const auto ions = std::ranges::iota_view{0, nions}; + std::for_each(EXEC_PAR ions.begin(), ions.end(), [&](const auto ion) { // const int ionstage = get_ionstage(element, ion); // printout(" %d", ionstage); @@ -911,14 +918,14 @@ void solve_nlte_pops_element(const int element, const int nonemptymgi, const int nltepop_matrix_add_boundbound(nonemptymgi, element, ion, t_mid, s_renorm, &rate_matrix_rad_bb, &rate_matrix_coll_bb, &rate_matrix_ntcoll_bb); - if (ion < nions - 1) { + if (ion < (nions - 1)) { // this is the slowest component nltepop_matrix_add_ionisation(modelgridindex, element, ion, s_renorm, &rate_matrix_rad_bf, &rate_matrix_coll_bf); if (NT_ON) { nltepop_matrix_add_nt_ionisation(nonemptymgi, element, ion, s_renorm, &rate_matrix_ntcoll_bf); } } - } + }); // printout("\n"); if (individual_process_matrices) { diff --git a/nonthermal.cc b/nonthermal.cc index e790ecc45..120fc0503 100644 --- a/nonthermal.cc +++ b/nonthermal.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1800,7 +1801,8 @@ void sfmatrix_add_excitation(std::vector &sfmatrixuppertri, const int mo const int nlevels_all = get_nlevels(element, ion); const int nlevels = (nlevels_all > NTEXCITATION_MAXNLEVELS_LOWER) ? NTEXCITATION_MAXNLEVELS_LOWER : nlevels_all; - for (int lower = 0; lower < nlevels; lower++) { + const auto lowers = std::ranges::iota_view{0, nlevels}; + std::for_each(lowers.begin(), lowers.end(), [&](const int lower) { const double statweight_lower = stat_weight(element, ion, lower); const double nnlevel = get_levelpop(nonemptymgi, element, ion, lower); const double epsilon_lower = epsilon(element, ion, lower); @@ -1829,17 +1831,17 @@ void sfmatrix_add_excitation(std::vector &sfmatrixuppertri, const int mo const int startindex = std::max(i, xsstartindex); for (int j = startindex; j < stopindex; j++) { - sfmatrixuppertri[rowoffset + j] += nnlevel * vec_xs_excitation_deltae[j]; + atomicadd(sfmatrixuppertri[rowoffset + j], nnlevel * vec_xs_excitation_deltae[j]); } // do the last bit separately because we're not using the full delta_e interval const double delta_en_actual = (en + epsilon_trans_ev - engrid(stopindex)); - sfmatrixuppertri[rowoffset + stopindex] += - nnlevel * vec_xs_excitation_deltae[stopindex] * delta_en_actual / DELTA_E; + atomicadd(sfmatrixuppertri[rowoffset + stopindex], + nnlevel * vec_xs_excitation_deltae[stopindex] * delta_en_actual / DELTA_E); } } } - } + }); } void sfmatrix_add_ionization(std::vector &sfmatrixuppertri, const int Z, const int ionstage, const double nnion) @@ -2280,7 +2282,6 @@ __host__ __device__ auto nt_ionization_ratecoeff(const int nonemptymgi, const in return nt_ionization_ratecoeff_wfapprox(modelgridindex, element, ion); } -#pragma omp declare simd __host__ __device__ auto nt_excitation_ratecoeff(const int nonemptymgi, const int element, const int ion, const int lowerlevel, const int uptransindex, const int lineindex) -> double { diff --git a/nonthermal.h b/nonthermal.h index cb5455996..5218feb98 100644 --- a/nonthermal.h +++ b/nonthermal.h @@ -18,7 +18,7 @@ void solve_spencerfano(int nonemptymgi, int timestep, int iteration); void calculate_deposition_rate_density(int nonemptymgi, int timestep, HeatingCoolingRates &heatingcoolingrates); [[nodiscard]] auto get_deposition_rate_density(int nonemptymgi) -> double; [[nodiscard]] auto get_nt_frac_heating(int modelgridindex) -> float; -#pragma omp declare simd + [[nodiscard]] auto nt_excitation_ratecoeff(int nonemptymgi, int element, int ion, int lowerlevel, int uptransindex, int lineindex) -> double; void do_ntalpha_deposit(Packet &pkt); diff --git a/packet.cc b/packet.cc index ba13ddd27..91dfcbf8d 100644 --- a/packet.cc +++ b/packet.cc @@ -132,8 +132,8 @@ void packet_init(Packet *pkt) // Now place the pellets in the ejecta and decide at what time they will decay. printout("Placing pellets...\n"); - auto allpkts = std::ranges::iota_view{0, globals::npkts}; - std::ranges::for_each(allpkts, [&, norm, e0](const int n) { + const auto allpkts = std::ranges::iota_view{0, globals::npkts}; + std::for_each(EXEC_PAR allpkts.begin(), allpkts.end(), [&, norm, e0](const int n) { pkt[n] = Packet{}; const double targetval = rng_uniform() * norm; diff --git a/radfield.cc b/radfield.cc index 3b114c4d8..d834c3302 100644 --- a/radfield.cc +++ b/radfield.cc @@ -112,7 +112,7 @@ constexpr auto get_bin_nu_lower(const int binindex) -> double { } // find the left-closed bin [nu_lower, nu_upper) that nu belongs to -#pragma omp declare simd + constexpr auto select_bin(const double nu) -> int { if (nu < nu_lower_first_initial) { return -2; // out of range, nu lower than lowest bin's lower boundary @@ -224,7 +224,7 @@ void update_bfestimators(const int nonemptymgi, const double distance_e_cmf, con globals::bfestim_nu_edge.data(); const auto bfestimcount = globals::bfestimcount; -#pragma omp simd + for (auto bfestimindex = bfestimbegin; bfestimindex < bfestimend; bfestimindex++) { atomicadd(bfrate_raw[(nonemptymgi * bfestimcount) + bfestimindex], phixslist.gamma_contr[bfestimindex] * distance_e_cmf_over_nu); diff --git a/sn3d.cc b/sn3d.cc index 6c79d7935..fbe10e0e2 100644 --- a/sn3d.cc +++ b/sn3d.cc @@ -29,7 +29,7 @@ #endif #include #ifdef STDPAR_ON -#include +#include #endif #include "artisoptions.h" @@ -689,7 +689,6 @@ auto do_timestep(const int nts, const int titer, Packet *packets, const int wall auto main(int argc, char *argv[]) -> int { real_time_start = std::time(nullptr); - char filename[MAXFILENAMELENGTH]; // if DETAILED_BF_ESTIMATORS_ON is true, USE_LUT_PHOTOION must be false assert_always(!DETAILED_BF_ESTIMATORS_ON || !USE_LUT_PHOTOION); @@ -709,15 +708,25 @@ auto main(int argc, char *argv[]) -> int { const int my_rank = globals::my_rank; +#ifdef STDPAR_ON + printout("C++ standard parallelism (stdpar) is enabled with %d hardware threads\n", get_max_threads()); + for (int t = 1; t < get_max_threads(); t++) { + char outputfilename[MAXFILENAMELENGTH]; + snprintf(outputfilename, MAXFILENAMELENGTH, "output_%d-%d.txt", my_rank, t); + std::filesystem::remove(outputfilename); + } +#endif + #if defined(_OPENMP) && !defined(GPU_ON) // Explicitly turn off dynamic threads because we use the threadprivate directive!!! omp_set_dynamic(0); -#pragma omp parallel private(filename) +#pragma omp parallel #endif { // initialise the thread and rank specific output file - snprintf(filename, MAXFILENAMELENGTH, "output_%d-%d.txt", my_rank, get_thread_num()); - output_file = std::ofstream(filename); + char outputfilename[MAXFILENAMELENGTH]; + snprintf(outputfilename, MAXFILENAMELENGTH, "output_%d-%d.txt", my_rank, get_thread_num()); + output_file = std::ofstream(outputfilename); assert_always(output_file.is_open()); #ifdef _OPENMP @@ -727,11 +736,6 @@ auto main(int argc, char *argv[]) -> int { #endif } -#ifdef STDPAR_ON - printout("C++ standard parallelism (stdpar) is enabled with %d hardware threads\n", - std::thread::hardware_concurrency()); -#endif - #ifdef GPU_ON printout("GPU_ON is enabled\n"); #endif @@ -863,6 +867,7 @@ auto main(int argc, char *argv[]) -> int { macroatom_open_file(my_rank); if (ndo > 0) { assert_always(estimators_file == nullptr); + char filename[MAXFILENAMELENGTH]; snprintf(filename, MAXFILENAMELENGTH, "estimators_%.4d.out", my_rank); estimators_file = fopen_required(filename, "w"); diff --git a/sn3d.h b/sn3d.h index 61e99616b..037ac5740 100644 --- a/sn3d.h +++ b/sn3d.h @@ -46,6 +46,7 @@ #ifdef STDPAR_ON #include +#include #define EXEC_PAR_UNSEQ std::execution::par_unseq, #define EXEC_PAR std::execution::par, @@ -179,7 +180,7 @@ __attribute__((__format__(__printf__, 1, 2))) inline auto printout(const char *f #ifdef __cpp_lib_atomic_ref #define atomicadd(var, val) \ - std::atomic_ref::type>(var).fetch_add(val, std::memory_order_relaxed); + std::atomic_ref::type>(var).fetch_add(val, std::memory_order_relaxed); #else // needed for Apple clang #define atomicadd(var, val) __atomic_fetch_add(&var, val, __ATOMIC_RELAXED); @@ -254,11 +255,15 @@ inline void gsl_error_handler_printout(const char *reason, const char *file, int } [[nodiscard]] inline auto get_max_threads() -> int { -#if defined _OPENMP +#ifdef STDPAR_ON + return static_cast(std::thread::hardware_concurrency()); +#else +#ifdef _OPENMP return omp_get_max_threads(); #else return 1; #endif +#endif } [[nodiscard]] inline auto get_thread_num() -> int { diff --git a/thermalbalance.cc b/thermalbalance.cc index 04185e31c..871b84bab 100644 --- a/thermalbalance.cc +++ b/thermalbalance.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include "artisoptions.h" @@ -278,7 +279,8 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco const int nions = get_nions(element); for (int ion = 0; ion < nions; ion++) { const int nlevels = get_nlevels(element, ion); - for (int level = 0; level < nlevels; level++) { + const auto levels = std::ranges::iota_view{0, nlevels}; + std::for_each(EXEC_PAR levels.begin(), levels.end(), [&](const int level) { double bfheatingcoeff = 0.; if (grid::get_elem_abundance(nonemptymgi, element) > minelfrac || USE_LUT_BFHEATING) { const auto nphixstargets = get_nphixstargets(element, ion, level); @@ -306,7 +308,7 @@ void calculate_bfheatingcoeffs(int nonemptymgi, std::vector &bfheatingco } } bfheatingcoeffs[get_uniquelevelindex(element, ion, level)] = bfheatingcoeff; - } + }); } } } diff --git a/update_grid.cc b/update_grid.cc index bf15cf6df..d4a5fdec8 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -1105,28 +1105,30 @@ void update_grid(FILE *estimators_file, const int nts, const int nts_prev, const radfield::normalise_bf_estimators(nts, nts_prev, titer, deltat); } - const int nstart = grid::get_nstart(my_rank); - const int ndo = grid::get_ndo(my_rank); - heatingcoolingrates_thisrankcells.resize(ndo); + const auto ndo_nonempty = grid::get_ndo_nonempty(my_rank); + heatingcoolingrates_thisrankcells.resize(ndo_nonempty); std::ranges::fill(heatingcoolingrates_thisrankcells, HeatingCoolingRates{}); + const auto nstart_nonempty = grid::get_nstart_nonempty(my_rank); + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) #endif - for (int mgi = nstart; mgi < nstart + ndo; mgi++) { - const auto nonemptymgi = (grid::get_numpropcells(mgi) > 0) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; - if (nonemptymgi >= 0) { - update_grid_cell(nonemptymgi, nts, nts_prev, titer, tratmid, deltat, - heatingcoolingrates_thisrankcells.at(mgi - nstart)); - } - } // end parallel for loop over all modelgrid cells + for (int nonemptymgi = nstart_nonempty; nonemptymgi < (nstart_nonempty + ndo_nonempty); nonemptymgi++) { + update_grid_cell(nonemptymgi, nts, nts_prev, titer, tratmid, deltat, + heatingcoolingrates_thisrankcells.at(nonemptymgi - nstart_nonempty)); + } // serial output of estimator data to this ranks estimator file cell by cell - for (int mgi = nstart; mgi < nstart + ndo; mgi++) { + const auto nstart = grid::get_nstart(my_rank); + const auto ndo = grid::get_ndo(my_rank); + for (int mgi = nstart; mgi < (nstart + ndo); mgi++) { const auto nonemptymgi = (grid::get_numpropcells(mgi) > 0) ? grid::get_nonemptymgi_of_mgi(mgi) : -1; if (nonemptymgi >= 0) { + assert_always(nonemptymgi >= nstart_nonempty); + assert_always(nonemptymgi < (nstart_nonempty + ndo_nonempty)); write_to_estimators_file(estimators_file, nonemptymgi, nts, titer, - heatingcoolingrates_thisrankcells.at(mgi - nstart)); + heatingcoolingrates_thisrankcells.at(nonemptymgi - nstart_nonempty)); } else { // modelgrid cells that are not represented in the simulation grid fprintf(estimators_file, "timestep %d modelgridindex %d EMPTYCELL\n\n", nts, mgi); From 5eba15bb1ebd2311ebc0276e0ef5a3bec021feb5 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 26 Nov 2024 16:13:24 +0000 Subject: [PATCH 108/117] Fix comment typo --- decay.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/decay.cc b/decay.cc index 6ae1f59e3..1ba0acfbc 100644 --- a/decay.cc +++ b/decay.cc @@ -1014,8 +1014,8 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector nucdecayenergytotal(25, 52) / MEV); } -// calculate the decay energy per unit mass [erg/g] released from time t_model to tstart, accounting for -// the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) +// calculate the decay energy per unit mass [erg/g] released from time t_model (can be before tmin) to tstart, +// accounting for the photon energy loss due to expansion between time of decays and tstart (equation 18 of Lucy 2005) auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int nonemptymgi, const double tstart) -> double { const auto modelgridindex = grid::get_mgi_of_nonemptymgi(nonemptymgi); double tot_endecay = 0.; @@ -1039,7 +1039,7 @@ auto get_endecay_per_ejectamass_t0_to_time_withexpansion(const int nonemptymgi, return tot_endecay; } -// get the density at time tmin of decay energy that will be released during the simulation time range [erg/cm3] +// get the decay energy that will be released during the simulation time range [erg/g] auto get_modelcell_simtime_endecay_per_mass(const int nonemptymgi) -> double { double endecay_per_mass = 0.; for (int decaypathindex = 0; decaypathindex < get_num_decaypaths(); decaypathindex++) { From e5fb0f906e26219a3d35403c4ffe59d4d1710a3e Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Thu, 5 Dec 2024 16:47:42 +0000 Subject: [PATCH 109/117] Update alphadecays.txt --- data/alphadecays.txt | 302 +++++++++++++++++++++---------------------- 1 file changed, 151 insertions(+), 151 deletions(-) diff --git a/data/alphadecays.txt b/data/alphadecays.txt index c0a4f1eff..05c6bc596 100644 --- a/data/alphadecays.txt +++ b/data/alphadecays.txt @@ -1,187 +1,187 @@ # Data source: Evaluated Nuclear Data File library (ENDF/B-VII.1; Chadwick et al. 2011) # via Hotokezaka et al. https://github.com/hotokezaka/HeatingRate # A, Z, branch_alpha, branch_beta, halflife[s], Q_total_alphadec[MeV], Q_total_betadec[MeV], E_alpha[MeV], E_gamma[MeV], E_beta[MeV] -# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -209 80 0 1 36.5 0 5.292 0.0000000000000000 1.7640000000000000 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 +# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +209 80 0 1 36.5 0 5.292 0.0000000000000000 1.7640000000000000 0.0000000000000000 +209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 +209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 209 83 0 0 0 0 0 0 0 0 -210 80 0 1 146 0 3.88 0.0000000000000000 1.2929999999999999 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 +210 80 0 1 146 0 3.88 0.0000000000000000 1.2929999999999999 0.0000000000000000 +210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 210 82 0 0 0 0 0 0 0 0 -211 81 0 1 60 0 4.55 0.0000000000000000 1.5160000000000000 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 +211 81 0 1 60 0 4.55 0.0000000000000000 1.5160000000000000 0.0000000000000000 +211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 +211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 +211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 +207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 207 82 0 0 0 0 0 0 0 0 -212 81 0 1 67 0 6.1 0.0000000000000000 2.0329999999999999 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.55950000000000000 +212 81 0 1 67 0 6.1 0.0000000000000000 2.0329999999999999 0.0000000000000000 +212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 +212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 +212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 +208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.55950000000000000 208 82 0 0 0 0 0 0 0 0 -213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 +213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 +213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 +213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 +209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 +209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 209 83 0 0 0 0 0 0 0 0 -214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 -214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 -214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 +214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 +214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 +214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 +210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 210 82 0 0 0 0 0 0 0 0 -215 82 0 1 36 0 2.9 0.0000000000000000 0.96699999999999997 0.0000000000000000 -215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 -215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 +215 82 0 1 36 0 2.9 0.0000000000000000 0.96699999999999997 0.0000000000000000 +215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 +215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 +211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 +211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 +211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 +207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 207 82 0 0 0 0 0 0 0 0 -216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 -216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.55950000000000000 +216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 +216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 +212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 +212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 +212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 +208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.55950000000000000 208 82 0 0 0 0 0 0 0 0 -217 83 0 1 98.5 0 2.92 0.0000000000000000 0.97333329999999996 0.0000000000000000 +217 83 0 1 98.5 0 2.92 0.0000000000000000 0.97333329999999996 0.0000000000000000 217 84 1 0 1.53 6.66022 0 6.66022 0.0 0.0 -213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 +213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 +213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 +213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 +209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 +209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 209 83 0 0 0 0 0 0 0 0 -218 83 0 1 33 0 4.819 0.0000000000000000 1.2965430000000000 1.3470000000000000 -218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 -214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 -214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 -214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 +218 83 0 1 33 0 4.819 0.0000000000000000 1.2965430000000000 1.3470000000000000 +218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 +214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 +214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 +214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 +210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 210 82 0 0 0 0 0 0 0 0 -219 84 0 1 3e-07 0 2.405 0.0000000000000000 0.80166669999999995 0.0000000000000000 -219 85 0.97 0.03 56 6.324 1.566 6.0220000000000002 0.0000000000000000 1.6410000000000001E-002 -219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 -215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 -215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 +219 84 0 1 3e-07 0 2.405 0.0000000000000000 0.80166669999999995 0.0000000000000000 +219 85 0.97 0.03 56 6.324 1.566 6.0220000000000002 0.0000000000000000 1.6410000000000001E-002 +219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 +215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 +215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 +211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 +211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 +211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 +207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 207 82 0 0 0 0 0 0 0 0 -220 84 0 1 3e-07 0 1.113 0.0000000000000000 0.37100000000000000 0.0000000000000000 -220 85 0.08 0.92 222.6 6.05 3.74 0.47539999999999999 0.37246040000000002 1.1679999999999999 -220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 -216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 -216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 +220 84 0 1 3e-07 0 1.113 0.0000000000000000 0.37100000000000000 0.0000000000000000 +220 85 0.08 0.92 222.6 6.05 3.74 0.47539999999999999 0.37246040000000002 1.1679999999999999 +220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 +216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 +216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 +212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 +212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 +212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 +208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 208 82 0 0 0 0 0 0 0 0 -221 85 0 1 138 0 2.341 0.0000000000000000 0.78033330000000001 0.0000000000000000 -221 86 0.22 0.78 1542 6.148 1.194 1.1980000000000000 0.11954239999999999 0.25009999999999999 -221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 +221 85 0 1 138 0 2.341 0.0000000000000000 0.78033330000000001 0.0000000000000000 +221 86 0.22 0.78 1542 6.148 1.194 1.1980000000000000 0.11954239999999999 0.25009999999999999 +221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 217 85 1 0 3.230000e-2 7.201300 0 7.0629999999999997 0.0 0.0 217 84 1 0 1.53 6.66022 0 6.66022 0.0 0.0 -213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.1974000000000000 +213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 +213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 +213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 +209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 +209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.1974000000000000 209 83 0 0 0 0 0 0 0 0 -222 85 0 1 54 0 4.427 0.0000000000000000 1.4756669999999998 0.0000000000000000 -222 86 1 0 330350 5.5903 0 5.4889999999999999 3.8892149999999998E-004 0.0000000000000000 -218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 -214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 -214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 -214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 +222 85 0 1 54 0 4.427 0.0000000000000000 1.4756669999999998 0.0000000000000000 +222 86 1 0 330350 5.5903 0 5.4889999999999999 3.8892149999999998E-004 0.0000000000000000 +218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 +214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 +214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 +214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 +210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 210 82 0 0 0 0 0 0 0 0 -223 85 0 1 50 0 3.167 0.0000000000000000 1.0556669999999999 0.0000000000000000 -223 86 0 1 1458 0 2.012 0.0000000000000000 0.30934079999999997 0.52660000000000007 -223 87 6e-05 0.99994 1320 5.562 1.1492 3.2770000000000000E-004 4.8698349999999994E-002 0.34560000000000002 -223 88 1 0 987552 5.9793 0 5.6650000000000000 0.13356070000000000 0.0000000000000000 -219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 -215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 +223 85 0 1 50 0 3.167 0.0000000000000000 1.0556669999999999 0.0000000000000000 +223 86 0 1 1458 0 2.012 0.0000000000000000 0.30934079999999997 0.52660000000000007 +223 87 6e-05 0.99994 1320 5.562 1.1492 3.2770000000000000E-004 4.8698349999999994E-002 0.34560000000000002 +223 88 1 0 987552 5.9793 0 5.6650000000000000 0.13356070000000000 0.0000000000000000 +219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 +215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 +211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 +211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 +211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 +207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 207 82 0 0 0 0 0 0 0 0 -224 86 0 1 6420 0 0.783 0.0000000000000000 0.26100000000000001 0.0000000000000000 -224 87 0 1 199.8 0 2.83 0.0000000000000000 0.53339530000000002 0.83460000000000001 -224 88 1 0 316224 5.78887 0 5.6730000000000000 1.0388479999999999E-002 0.000000000000000 -220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 -216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 +224 86 0 1 6420 0 0.783 0.0000000000000000 0.26100000000000001 0.0000000000000000 +224 87 0 1 199.8 0 2.83 0.0000000000000000 0.53339530000000002 0.83460000000000001 +224 88 1 0 316224 5.78887 0 5.6730000000000000 1.0388479999999999E-002 0.000000000000000 +220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 +216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 +212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 +212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 +212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 +208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 208 82 0 0 0 0 0 0 0 0 -225 86 0 1 279.6 0 2.74 0.0000000000000000 0.57196979999999997 0.75570000000000004 -225 87 0 1 237 0 1.82 0.0000000000000000 0.60666669999999989 0.0000000000000000 -225 88 0 1 1.28736e+06 0 0.357 0.0000000000000000 1.3983770000000000E-002 9.2390000000000000E-002 -225 89 1 0 864000 5.9351 0 5.7759999999999998 1.5370379999999998E-002 0.0000000000000000 -221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 -217 85 1 0 3.230000e-2 7.201300 0 7.0629999999999997 2.1010950000000000E-004 1.6039999999999999E-005 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 +225 86 0 1 279.6 0 2.74 0.0000000000000000 0.57196979999999997 0.75570000000000004 +225 87 0 1 237 0 1.82 0.0000000000000000 0.60666669999999989 0.0000000000000000 +225 88 0 1 1.28736e+06 0 0.357 0.0000000000000000 1.3983770000000000E-002 9.2390000000000000E-002 +225 89 1 0 864000 5.9351 0 5.7759999999999998 1.5370379999999998E-002 0.0000000000000000 +221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 +217 85 1 0 3.230000e-2 7.201300 0 7.0629999999999997 2.1010950000000000E-004 1.6039999999999999E-005 +213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 +213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 +209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 +209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 209 83 0 0 0 0 0 0 0 0 -226 86 0 1 444 0 1.401 0.0000000000000000 0.46699999999999997 0.0000000000000000 -226 87 0 1 49 0 3.671 0.0000000000000000 0.43404640000000000 1.1910000000000001 +226 86 0 1 444 0 1.401 0.0000000000000000 0.46699999999999997 0.0000000000000000 +226 87 0 1 49 0 3.671 0.0000000000000000 0.43404640000000000 1.1910000000000001 226 88 0 0 0 0 0 0 0 0 -227 86 0 1 20.8 0 3.326 0.0000000000000000 1.1086669999999998 0.0000000000000000 -227 87 0 1 148.2 0 2.477 0.0000000000000000 0.43496089999999998 0.70070000000000010 -227 88 0 1 2532 0 1.3273 0.0000000000000000 0.13790569999999999 0.3975000000000000 +227 86 0 1 20.8 0 3.326 0.0000000000000000 1.1086669999999998 0.0000000000000000 +227 87 0 1 148.2 0 2.477 0.0000000000000000 0.43496089999999998 0.70070000000000010 +227 88 0 1 2532 0 1.3273 0.0000000000000000 0.13790569999999999 0.3975000000000000 227 89 0 0 0 0 0 0 0 0 -228 86 0 1 65 0 2.102 0.0000000000000000 0.70066669999999998 0.0000000000000000 -228 87 0 1 38 0 4.34 0.0000000000000000 0.66961380000000004 1.3780000000000001 +228 86 0 1 65 0 2.102 0.0000000000000000 0.70066669999999998 0.0000000000000000 +228 87 0 1 38 0 4.34 0.0000000000000000 0.66961380000000004 1.3780000000000001 228 88 0 0 0 0 0 0 0 0 -229 87 0 1 50.2 0 3.26 0.0000000000000000 0.55985900000000000 0.88039999999999996 -229 88 0 1 240 0 1.81 0.0000000000000000 0.0000000000000000 0.62679999999999991 -229 89 0 1 3762 0 1.16 0.0000000000000000 5.9103660000000002E-002 0.35610000000000003 +229 87 0 1 50.2 0 3.26 0.0000000000000000 0.55985900000000000 0.88039999999999996 +229 88 0 1 240 0 1.81 0.0000000000000000 0.0000000000000000 0.62679999999999991 +229 89 0 1 3762 0 1.16 0.0000000000000000 5.9103660000000002E-002 0.35610000000000003 229 90 0 0 0 0 0 0 0 0 -230 87 0 1 19.1 0 4.987 0.0000000000000000 0.85936789999999996 1.6440000000000001 -230 88 0 1 5580 0 0.71 0.0000000000000000 0.23666670000000001 0.0000000000000000 -230 89 0 1 122 0 2.9 0.0000000000000000 0.50942829999999995 0.86450000000000005 +230 87 0 1 19.1 0 4.987 0.0000000000000000 0.85936789999999996 1.6440000000000001 +230 88 0 1 5580 0 0.71 0.0000000000000000 0.23666670000000001 0.0000000000000000 +230 89 0 1 122 0 2.9 0.0000000000000000 0.50942829999999995 0.86450000000000005 230 90 0 0 0 0 0 0 0 0 -231 87 0 1 17.6 0 3.9 0.0000000000000000 0.44763829999999999 1.3129999999999999 -231 88 0 1 103 0 2.479 0.0000000000000000 0.82633330000000005 0.000000000000000 -231 89 0 1 450 0 2.1 0.0000000000000000 0.41319939999999999 0.54379999999999995 -231 90 0 1 91872 0 0.3907 0.0000000000000000 2.3437949999999999E-002 7.9219999999999999E-002 +231 87 0 1 17.6 0 3.9 0.0000000000000000 0.44763829999999999 1.3129999999999999 +231 88 0 1 103 0 2.479 0.0000000000000000 0.82633330000000005 0.000000000000000 +231 89 0 1 450 0 2.1 0.0000000000000000 0.41319939999999999 0.54379999999999995 +231 90 0 1 91872 0 0.3907 0.0000000000000000 2.3437949999999999E-002 7.9219999999999999E-002 231 91 0 0 0 0 0 0 0 0 -232 87 0 1 5.5 0 5.604 0.0000000000000000 0.23674289999999998 2.0960000000000001 -232 88 0 1 252 0 1.5 0.0000000000000000 0.50000000000000000 0.0000000000000000 -232 89 0 1 119 0 3.7 0.0000000000000000 1.1488259999999999 0.93460000000000010 +232 87 0 1 5.5 0 5.604 0.0000000000000000 0.23674289999999998 2.0960000000000001 +232 88 0 1 252 0 1.5 0.0000000000000000 0.50000000000000000 0.0000000000000000 +232 89 0 1 119 0 3.7 0.0000000000000000 1.1488259999999999 0.93460000000000010 232 90 0 0 0 0 0 0 0 0 -233 88 0 1 30 0 3.269 0.0000000000000000 1.0896669999999999 0.0000000000000000 -233 89 0 1 145 0 2.8 0.0000000000000000 0.49858390000000002 0.83150000000000002 -233 90 0 1 1338 0 1.2431 0.0000000000000000 3.6983019999999998E-002 0.40450000000000003 -233 91 0 1 2.33064e+06 0 0.5701 0.0000000000000000 0.21756379999999997 6.6470000000000001E-002 +233 88 0 1 30 0 3.269 0.0000000000000000 1.0896669999999999 0.0000000000000000 +233 89 0 1 145 0 2.8 0.0000000000000000 0.49858390000000002 0.83150000000000002 +233 90 0 1 1338 0 1.2431 0.0000000000000000 3.6983019999999998E-002 0.40450000000000003 +233 91 0 1 2.33064e+06 0 0.5701 0.0000000000000000 0.21756379999999997 6.6470000000000001E-002 233 92 0 0 0 0 0 0 0 0 -234 88 0 1 30 0 2.128 0.0000000000000000 0.70933330000000006 0.0000000000000000 -234 89 0 1 44 0 4.489 0.0000000000000000 1.4963329999999999 0.0000000000000000 -234 90 0 1 2.08224e+06 0 0.199 0.0000000000000000 7.5724059999999994E-003 4.7810000000000005E-002 -234 91 0 1 24120 0 2.194 0.0000000000000000 1.4820449999999998 0.22240000000000001 +234 88 0 1 30 0 2.128 0.0000000000000000 0.70933330000000006 0.0000000000000000 +234 89 0 1 44 0 4.489 0.0000000000000000 1.4963329999999999 0.0000000000000000 +234 90 0 1 2.08224e+06 0 0.199 0.0000000000000000 7.5724059999999994E-003 4.7810000000000005E-002 +234 91 0 1 24120 0 2.194 0.0000000000000000 1.4820449999999998 0.22240000000000001 234 92 0 0 0 0 0 0 0 0 -235 89 0 1 60 0 3.467 0.0000000000000000 1.1556670000000000 0.0000000000000000 -235 90 0 1 426 0 1.92 0.0000000000000000 5.2376619999999999E-002 0.66279999999999994 -235 91 0 1 1466.4 0 1.41 0.0000000000000000 0.46999999999999997 0.000000000000000 +235 89 0 1 60 0 3.467 0.0000000000000000 1.1556670000000000 0.0000000000000000 +235 90 0 1 426 0 1.92 0.0000000000000000 5.2376619999999999E-002 0.66279999999999994 +235 91 0 1 1466.4 0 1.41 0.0000000000000000 0.46999999999999997 0.000000000000000 235 92 0 0 0 0 0 0 0 0 -236 89 0 1 120 0 4.81 0.0000000000000000 1.6033320000000000 0.0000000000000000 -236 90 0 1 2238 0 1.1 0.0000000000000000 3.2532939999999996E-002 0.33850000000000002 -236 91 0 1 546 0 2.9 0.0000000000000000 0.80315979999999998 0.72570000000000001 +236 89 0 1 120 0 4.81 0.0000000000000000 1.6033320000000000 0.0000000000000000 +236 90 0 1 2238 0 1.1 0.0000000000000000 3.2532939999999996E-002 0.33850000000000002 +236 91 0 1 546 0 2.9 0.0000000000000000 0.80315979999999998 0.72570000000000001 236 92 0 0 0 0 0 0 0 0 -237 90 0 1 282 0 2.56 0.0000000000000000 0.85333329999999996 0.0000000000000000 -237 91 0 1 522 0 2.25 0.0000000000000000 0.60763209999999990 0.56479999999999997 -237 92 0 1 583200 0 0.5186 0.0000000000000000 0.13527069999999999 6.7860000000000004E-002 +237 90 0 1 282 0 2.56 0.0000000000000000 0.85333329999999996 0.0000000000000000 +237 91 0 1 522 0 2.25 0.0000000000000000 0.60763209999999990 0.56479999999999997 +237 92 0 1 583200 0 0.5186 0.0000000000000000 0.13527069999999999 6.7860000000000004E-002 237 93 0 0 0 0 0 0 0 0 -238 90 0 1 564 0 1.856 0.0000000000000000 0.61866669999999990 0.0000000000000000 -238 91 0 1 136.2 0 3.46 0.0000000000000000 1.1533329999999999 0.0000000000000000 +238 90 0 1 564 0 1.856 0.0000000000000000 0.61866669999999990 0.0000000000000000 +238 91 0 1 136.2 0 3.46 0.0000000000000000 1.1533329999999999 0.0000000000000000 238 92 0 0 0 0 0 0 0 0 From acad155b5fdb4e87bdc7d6106af4b8a9fae34f1c Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sat, 7 Dec 2024 17:15:01 +0000 Subject: [PATCH 110/117] Fixup call to solve_spencerfano() --- update_grid.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update_grid.cc b/update_grid.cc index d4a5fdec8..c2b7d7a0b 100644 --- a/update_grid.cc +++ b/update_grid.cc @@ -686,7 +686,7 @@ void solve_Te_nltepops(const int nonemptymgi, const int nts, const int nts_prev, const auto sys_time_start_spencerfano = std::time(nullptr); if (NT_ON && NT_SOLVE_SPENCERFANO) { // SF solution depends on the ionization balance, and weakly on nne - nonthermal::solve_spencerfano(mgi, nts, nlte_iter); + nonthermal::solve_spencerfano(nonemptymgi, nts, nlte_iter); } const int duration_solve_spencerfano = std::time(nullptr) - sys_time_start_spencerfano; From 30f7bdc1b5c77440d995006b6c1672483aa98955 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Sun, 8 Dec 2024 10:35:37 +0000 Subject: [PATCH 111/117] Ignore spurious gamma emission from nuclear de-excitations included in betaminusdecays.txt (#160) These appear to be related to nuclear excited-state transitions, which are not handled by artis. Ignoring these gives good agreement with the total energy release rates (Qdot) from the network calculation. Should not be significant for the published model, since (with uranium data fixed as it was) the abnormally high gamma emission is only seen after one day when gamma ray thermalisation is very inefficient. Will be more significant for higher-mass models. ![beta_release_ratios_tot_Hotokezaka_Yeall_uraniumfix](https://github.com/user-attachments/assets/66028a32-a3a6-45d6-b08e-8e49d2112319) --- decay.cc | 21 +- .../results_md5_final.txt | 34 +- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 34 +- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 634 ++++++++--------- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 234 +++---- .../results_md5_job0.txt | 28 +- .../results_md5_final.txt | 638 +++++++++--------- .../results_md5_job0.txt | 26 +- .../results_md5_final.txt | 638 +++++++++--------- .../results_md5_job0.txt | 32 +- .../results_md5_final.txt | 638 +++++++++--------- .../results_md5_job0.txt | 26 +- 15 files changed, 1537 insertions(+), 1536 deletions(-) diff --git a/decay.cc b/decay.cc index 1ba0acfbc..1ccc3ca5f 100644 --- a/decay.cc +++ b/decay.cc @@ -925,20 +925,21 @@ void init_nuclides(const std::vector &custom_zlist, const std::vector // columns: # A, Z, Q[MeV], E_gamma[MeV], E_elec[MeV], E_neutrino[MeV], meanlife[s] int a = -1; int z = -1; - double q_mev = 0.; + double q_beta_mev = 0.; double e_gamma_mev = 0.; double e_elec_mev = 0.; double e_neutrino = 0.; double tau_sec = 0.; - std::stringstream(line) >> a >> z >> q_mev >> e_gamma_mev >> e_elec_mev >> e_neutrino >> tau_sec; - - assert_always(!nuc_exists(z, a)); - nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec}); - nuclides.back().branchprobs[DECAYTYPE_BETAMINUS] = 1.; - nuclides.back().endecay_q[DECAYTYPE_BETAMINUS] = q_mev * MEV; - nuclides.back().endecay_electron = e_elec_mev * MEV; - nuclides.back().endecay_gamma = e_gamma_mev * MEV; - assert_always(e_elec_mev >= 0.); + std::stringstream(line) >> a >> z >> q_beta_mev >> e_gamma_mev >> e_elec_mev >> e_neutrino >> tau_sec; + if (q_beta_mev > 0.) { + assert_always(!nuc_exists(z, a)); + nuclides.push_back({.z = z, .a = a, .meanlife = tau_sec}); + nuclides.back().branchprobs[DECAYTYPE_BETAMINUS] = 1.; + nuclides.back().endecay_q[DECAYTYPE_BETAMINUS] = q_beta_mev * MEV; + nuclides.back().endecay_electron = e_elec_mev * MEV; + nuclides.back().endecay_gamma = e_gamma_mev * MEV; + assert_always(e_elec_mev >= 0.); + } } auto falpha = fstream_required("alphadecays.txt", std::ios::in); diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt index 5c2d18786..68b807e16 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -a68ab8919d91afb5c3a4b28bb98b75b8 absorption.out +5e70840457d3ebb1a70aae91797bf12d absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -f0db52c346ffcba95d1d8812475f8c34 deposition.out -065c01cd760d54a888a939dfe00378c4 emission.out -f345c0a8d5ae60ec17b7bfa78d61abb9 emissiontrue.out -dd314f8317220adaee8b48aa1b60f2a3 gamma_light_curve.out -9148bc2382bb01fe9ffa140ff86a5707 gamma_spec.out -4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out +57d70ef50670042f0aee39838696b6f4 deposition.out +bb04fc3f2022fcfe6a6333266b9e5ff2 emission.out +0d933b1cbf641c1e5662269be44b572d emissiontrue.out +abda1035e92b327aa5c331fbf52df955 gamma_light_curve.out +7dd1e0c57f597e664960f19f50da8ab7 gamma_spec.out +cfe0877961d7651ddab7826c45ba6770 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -f0b726a4dfbbbe17d71e182cfc251e72 light_curve.out +bdd30c2ea4f997d076b10a62cee55631 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -8c3d21a3d8646afef626a7adeb0feee8 packets00_0000.out -67239f5faf43336b8bd4a175553763ee packets00_0001.out -b4828c6463ba397ce993bf75488a2a33 packets00_0002.out -ddfded7dcd44bb1469432977052eca4b packets00_0003.out -5bc66d0e2f639e2cd2d2a8d9a6487c3b spec.out +f5b542810e6f3fc8a9c2272531c9bc75 packets00_0000.out +95d2bc8b85d49d64e69d7054efe261dd packets00_0001.out +a6b7fc332a6a8c05d77156764d3a7c90 packets00_0002.out +e6c8d10f260c3007350beeae0d8fc398 packets00_0003.out +381f8187e7b05d03b62e6d1b38a6b585 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -ea174eff24f41e70b1d28e9775e7dfd3 job1/estimators_0000.out -0690d0264e69496e2a43cfe86bdc9e01 job1/estimators_0001.out -4c2fa51eabca21c4680661d0db01f811 job1/estimators_0002.out -fef640281337a9f404fc72a269a20406 job1/estimators_0003.out +3cab5d3d4e763334d57beaad05cdd867 job1/estimators_0000.out +db98cbc7fc195bfa9944289927d15c2b job1/estimators_0001.out +fedc7856d170715d4e5e3c6037b73521 job1/estimators_0002.out +e03ce33dc0f2227dbb5cf65ce2dd969c job1/estimators_0003.out diff --git a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt index f6525158b..666d43a10 100644 --- a/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_1dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -9b6e08da1a7ff4bb095586408e58c0bc absorption.out +2900c3409f983192e778095ee3522780 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -a37e9be6c23303199deccfe9a8704b90 deposition.out -da000c6330f226464a3fc2ba16eb8beb emission.out -851560ece3b6630497d362ad8c69a127 emissiontrue.out -a65c34c5069444d22e04c7efb8bd0d69 gamma_light_curve.out -4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out +d78ef9529cf1a41661d26b5a59651659 deposition.out +2f412c22d3207dc01a4e9c971c61d6e5 emission.out +ca9e41bb0a16abecf97c2650a59d8cdd emissiontrue.out +61619cbe363c8daf005aa8aebfbd0c2a gamma_light_curve.out +cfe0877961d7651ddab7826c45ba6770 gammalinelist.out 7db21c856b5d2784b14eabfd22e5b837 grid.out -ba3d39bcb52c8f2f4bb30666cec29607 light_curve.out +e981746ff85b8b009e833d80aef76cc2 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -f267baafef20bacbaf44ac66b4de90d5 packets00_0000.out -01c4d1d02b822f05d6a0b1a19ae0f6aa packets00_0001.out -04fca0a55fde00a2a3b31cf49d611a9b packets00_0002.out -54a3b60f3de31e59d9d046f1e133d7ef packets00_0003.out -d90011df9b26a1b201891122b690b7e9 spec.out +57f07070abe7318fbd3add00609d0141 packets00_0000.out +d57addd2505c8c0a9df15a9f2d43e568 packets00_0001.out +fe15be88234899aecdad1ae65c8f997a packets00_0002.out +14053d099f9bd07041f5c1e5a91da0b3 packets00_0003.out +5b508166a80f8c15bf7ae775d83d86d0 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -59b9ddad12a7142035a8a14a66772533 job0/estimators_0000.out -914fb771d6a47c19c2902a35f2b31b8a job0/estimators_0001.out -2fc6ed25172ee06c660042cc2bd4bb79 job0/estimators_0002.out -903bf6890de8671b082f96627469ab5e job0/estimators_0003.out +485d5556f68c4212629973fcd4c6a988 job0/estimators_0000.out +ea2e10760b34e985f68aba4bb2a5ec8a job0/estimators_0001.out +3ba602640206bbfa1ccecb7a4944e2b1 job0/estimators_0002.out +95bb5ce9a7be73d10471187f6f60c3e7 job0/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt index d5471ecb5..86aa09d93 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_final.txt @@ -1,22 +1,22 @@ -f06170f48efc0e06240668b75fc209ab absorption.out +fb55532ef3cdabf21d284fa99e15faf0 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -b0408ab41fc6af31a67b83db2d30995a deposition.out -8809f7f9b0de8b9f340bbfcfd74c8971 emission.out -99b1de21168c8370d1f503eaf46ba252 emissiontrue.out -7d05408c2969bcf5e2776f3b51716ef1 gamma_light_curve.out -ea2528ae1d42dce5f7c8eef94b948c86 gamma_spec.out -4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out +2436cfa7755a3ba39f09239b0e240b2f deposition.out +26c7e7dba34b728615d4c61d499b2b98 emission.out +a08f83670a94876559ed4e8e264edaa6 emissiontrue.out +df82df31e3640085f64404e2979abdf2 gamma_light_curve.out +fd5c890bd2adb9aab8a88fb8efa9b848 gamma_spec.out +cfe0877961d7651ddab7826c45ba6770 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -c61ea3b7b9fc33359366cb32edf7ad74 light_curve.out +4b2f02e7353e423eb8d429178c88ddba light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -7e330e3a09784fdf8026ef2b81efc0d9 packets00_0000.out -59947bdab37695bb5c41b233e9644a59 packets00_0001.out -08ea133f3dd4ef8b99fd51aa7a23eb01 packets00_0002.out -7ae9a0fe5fc4b76b418fd95e41659f35 packets00_0003.out -dbb89cf92f157e3519a95ee53a28320f spec.out +5fe2ffbcc73c82afb34bc7efe7932579 packets00_0000.out +dabc4d7274f5acd54a466693446d4a98 packets00_0001.out +7c6a07640f1cd8e7f86122429cf80e2c packets00_0002.out +69bedebc77a18ce2e8d338378fa2a731 packets00_0003.out +f4044fe30b9c779900b4392584de9f96 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -bb94370d18931aa66b2679ca2f9d0a68 job1/estimators_0000.out -b3a3eb895f42b0d30e6defe5b82a50b3 job1/estimators_0001.out -a99083e8902291ec9eaa8762c5d185de job1/estimators_0002.out -adbe958740bf9170186c9b9a325353cc job1/estimators_0003.out +8e3851012e39d0e0368c6d274344b938 job1/estimators_0000.out +a0f9957f953cfb61583ad2af8baf3308 job1/estimators_0001.out +95fda81770d98c011a0c4800dee12032 job1/estimators_0002.out +d7bc707bd99035443bbc12e1f939354b job1/estimators_0003.out diff --git a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt index 1b868dbd6..dac63a3ec 100644 --- a/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_1d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -5cc44fdb5a61e3462dbdbc69df162192 absorption.out +0d77d38c20ad3326e3dc5d2a4d0fcc05 absorption.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -2f58b4c57f01595ff2039430f6b93e7c deposition.out -ac5639d46649923f4d6962a640ca309f emission.out -682041787c0270df66edc5aa01a9a7dc emissiontrue.out -5099680a2dd8f2b9b0054fa4316dd6cb gamma_light_curve.out -4af36569cc2db94b41cdadbc03354ac4 gammalinelist.out +9c5675dd091196401a9989c214a3a930 deposition.out +e637d1f193a40c71d0fd798630ec9606 emission.out +0fabab432e7b3584c4ecd15d4900f1da emissiontrue.out +06bb26de9606e8d41b828dfd32149664 gamma_light_curve.out +cfe0877961d7651ddab7826c45ba6770 gammalinelist.out 17cf657837d7df2969e3e1540b183cfe grid.out -c4e3d0aa48ca1a45d08d6b06c4087666 light_curve.out +958a863d22eab86ef5a2e22f6cdc784d light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out bc40edd64676f86b6ac2df0934e2ce9a modelgridrankassignments.out -3dca38a2a4a7610f384725664209a2f6 packets00_0000.out -2c29214bc02476969918f550375e613d packets00_0001.out -08a3134596ed9a4bf7eed265acdf3d1d packets00_0002.out -6cb7f23fe871e1e174e941850084f3bb packets00_0003.out -2ebdb99d551f71d619b45c09bdd354cb spec.out +de600f22a8d0cc3d29e4e6a408fedfa2 packets00_0000.out +31355be9a2b9a24e9cb2f395e02c9478 packets00_0001.out +e49fb69915383efd008f6f3c7798c157 packets00_0002.out +bb25f506c49db920c8a45cb65b7bb672 packets00_0003.out +320634d14a0734ca961e2ea9c3346ecc spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -2889a013b8d2c36925d8e5d96f486703 job0/estimators_0000.out -78abe66049a2de616aae8947d708077a job0/estimators_0001.out -610f067f46a2e965dc439051379c6f40 job0/estimators_0002.out -a917473083f7d971dfc6277426369d4d job0/estimators_0003.out +f319fbbe5a1c66b5414e40583819224e job0/estimators_0000.out +d74aab46725dc027a8d729fd8e431a80 job0/estimators_0001.out +ea26af36aac9b11279d4686d1c7f8430 job0/estimators_0002.out +3a29be4f442b4e218cc80060fab8608a job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt index 92881013c..fd1f39ee3 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -f9e8c462e7ef8bd0c0fade07bb715f3b absorption.out -274f502b0c431c87692eedaf5919ce4d absorption_res_00.out -1b23e9efcf255979d6e8dc1c9830e520 absorption_res_01.out -8f2d66054dd29553336e6b8a5491bbb6 absorption_res_02.out -e386c3bcbe983401a17bd95dc3d121d0 absorption_res_03.out -6a329922993d5f74dd860dbed3212635 absorption_res_04.out -4c73b13c528ea23c57bce1a988690cfb absorption_res_05.out -89efb4289fe1d9d399128d41a6642a05 absorption_res_06.out -18139fddb12924162c061157f9747207 absorption_res_07.out -c361a8425799dc3c16444f04fc197dcd absorption_res_08.out -24b714a39d7728e2e39c091a35e6241c absorption_res_09.out -acbca6ff80b948fa1c04ccab4037000f absorption_res_10.out -339b7c36dda10cf55418f2cacc59107f absorption_res_11.out -fabaefc81410ade72b31a9e6111af0e8 absorption_res_12.out -5ba48c6fced17fa5c84ba19ceb2c987e absorption_res_13.out -0899f426f6940ead33ef8c672f1fde00 absorption_res_14.out -f0ec41e87d648be6c2734d81e9b2a131 absorption_res_15.out -6e2cbfdb33a712025e11fec3ef58430a absorption_res_16.out -78cdb5e1399efa97c2cf87b5f30cb3d6 absorption_res_17.out -2bb07657b2a766dee543d3da2d154e41 absorption_res_18.out -39f1391db15fcd364f74689c05fae1d1 absorption_res_19.out -25f676d65df111740bee8deca71996b6 absorption_res_20.out -563a11129d764a915c89a9550b79408a absorption_res_21.out -d8d9d0df34288fef286dc46689a9ee03 absorption_res_22.out -516083a4ac583d51efca3e9b4bd6109a absorption_res_23.out -955163e7185855887b69ccacb553dddb absorption_res_24.out -8246b28aacb57b55aec1413793412344 absorption_res_25.out -2b481d6c113c632ddf7bbc15e4aecf8a absorption_res_26.out -99f5de348249be74f8cd4922927666a4 absorption_res_27.out -dd75e3b757da769ce06ea9ab3f854f90 absorption_res_28.out -af8da6bb3e95edd423441c817e1dc37d absorption_res_29.out -27c62988f57b5d905939782bfb3b0efe absorption_res_30.out -9371d71de8c01d9699811f29fb8a85c4 absorption_res_31.out -6e36bcef06a0605acfc3707604f36014 absorption_res_32.out -65c7ffbc0002be87c56bab4d797dfe19 absorption_res_33.out -67409a5ecea0880828b8a7234c8f3bf7 absorption_res_34.out -f10c90f165eec7bcba64ad9121989011 absorption_res_35.out -fbcd7f2ab65c0c535a657e72cc7edb3e absorption_res_36.out -635a99eaffd5d9f94b793e6f7ec73048 absorption_res_37.out -060b661d3a2e3ef001b2f9aeeffe10cb absorption_res_38.out -0863ed003882654f41655ad1665c20d5 absorption_res_39.out -1358786cd5a80c38f6b92b99e6b557f7 absorption_res_40.out -4caa8b9dbae91dc0c1882234b4ec0274 absorption_res_41.out -db49da7c14b3d32a62fabed98bb9c9c2 absorption_res_42.out -7d97f8989a5db571735d1a7b3f5b37bd absorption_res_43.out -ef4d0a36fec4da1705a10f98fa7a69c4 absorption_res_44.out -18cad46ac655c6cfafb9824fd2e5dfb2 absorption_res_45.out -2ffee6d7cb0c23e5ffb65db38d8a79af absorption_res_46.out -e8fec2be24fd7c1fe2c60941e74c990b absorption_res_47.out -89970ea8b3d5f85c069a7850f603e2ed absorption_res_48.out -a153dcd23cbd0e575579f5530bf0feb5 absorption_res_49.out -19dec21ea4ca6d122d4e6402e413e239 absorption_res_50.out -e2690942c3b57a50ced741027c94fb0a absorption_res_51.out -dc28aeb8509b183139472d242eb705f7 absorption_res_52.out -d4105a99be3e63e6351a077dd4e611f0 absorption_res_53.out -077e591ad2a1acb81412826e93a7b46b absorption_res_54.out -24035fc228f793f64cfcd1d96f0c6e23 absorption_res_55.out -471a08a1da666ae13f1f687ae868fa25 absorption_res_56.out -f6c6ef61dc942b2ad9735f67b528b4ac absorption_res_57.out -b857a70faa8d869c165d08763b85225c absorption_res_58.out -ae4d59c2630ca6b8ab8dd696dfc25fd4 absorption_res_59.out -bfd97c4e5495dffa84b2747896497e1f absorption_res_60.out -8db139458bb9280d9191540feb7f22aa absorption_res_61.out -23678df0058e7b136d548447c9247a5a absorption_res_62.out -1746f4b528f81b64f8c5ce789430d76a absorption_res_63.out -17b01b01353c695793e7956663dbaaf9 absorption_res_64.out -8700cba4ae77d530a3622c0ce5bbc8a8 absorption_res_65.out -67a9bdf952985811e14f60c8aadde0e5 absorption_res_66.out -528f8be97188ed25e32e3b3258ac5856 absorption_res_67.out -3eb4717018783c3aed3f298fb31583f7 absorption_res_68.out -6ad940791b99711306d5b3d5b947ee19 absorption_res_69.out -9d583ed1e8372c45f90a671df0e4dcb0 absorption_res_70.out -30fba9edf8484101009db72700fc3718 absorption_res_71.out -9c3332a1a4bc7d4ebbba1b6212e14d6c absorption_res_72.out -2e5b57f4f1adf29f21a0af09d7ee20d0 absorption_res_73.out -bd587ea7ccabea5c061acb24a62db797 absorption_res_74.out -14003f97741c6e428dba2ab2ee61aa9b absorption_res_75.out -f380a1f5f10e23a9eae4ddc860fec4b0 absorption_res_76.out -b9af5fe86e7e4601cb9ab0b5537e7303 absorption_res_77.out -e35b607f63d833a39e2936ca0528be1f absorption_res_78.out -b3d003d76facde4842f80b373cfe67aa absorption_res_79.out -54755075322b22a6f9014cc52c1145d5 absorption_res_80.out -ef297f2cca47bb00bf977a8053e15081 absorption_res_81.out -1b8fd6e037b3f508c08e814a4bb3f1ef absorption_res_82.out -357b5a10e02e415648c4f6bed251ba5d absorption_res_83.out -fc1cae8802aa49f3ee6111f8d8cfe287 absorption_res_84.out -5ca5d9d11fe1ef510f67c1e0eb073568 absorption_res_85.out -dedf1b98f85b928daad12bef4c373681 absorption_res_86.out -3aaa4d6ca5732a9536035e3559170e6c absorption_res_87.out -06fefa329cde29f5d86e77c0fa8d4c5c absorption_res_88.out -39d74ef9cc6c92c23200e6d400c28762 absorption_res_89.out -f7135992bb8a81787479ba759007d411 absorption_res_90.out -0bd9fdf583d626000f5d25aff31d071e absorption_res_91.out -a9c2a4462385ab0555d801ea431f5562 absorption_res_92.out -4bd91060043c8f96553bfd5a0ba6ec1a absorption_res_93.out -f52b5597e3d1f0f8e2a9b03e8d71e349 absorption_res_94.out -f8efb652b3b62df30d6490bbfdaf42fe absorption_res_95.out -4af3a8bbe04cd83ffca6201705ded960 absorption_res_96.out -6f63b6cbff3c903c64e7e6ecdea50c4c absorption_res_97.out -e62dba7cbb6826d15f6cb2fdde45c69b absorption_res_98.out -eb05e3560a97e99403464e9c79845341 absorption_res_99.out +2411c1a626b92cb3ef015455c8d1fe26 absorption.out +0cbe595c4a5db6cae834773da51f5bab absorption_res_00.out +9295c2560af5af03e7cff5b2c6b8e4de absorption_res_01.out +0f89cf3d27a7fedf419ecab1bbc11f0c absorption_res_02.out +d32b4deae960c291ad3bbf3e85437a95 absorption_res_03.out +59f714d22d81d9d9de35c05944af5690 absorption_res_04.out +24f79b551bb7b5d456b91221ed7d1b62 absorption_res_05.out +4c10968fc039b8d950d425514f2cc5b9 absorption_res_06.out +edc29f1265076240dedf2f57520518f7 absorption_res_07.out +b538530f34b86bdd20f7a14a281d38d6 absorption_res_08.out +9920ceafbbfdda03f76f496b6db72513 absorption_res_09.out +730f86df8280b8ad33ff65aa48ded3e0 absorption_res_10.out +bb26c45c27a8b27b9cd99757950e8235 absorption_res_11.out +1490098188ae4c367a6e2451844e9a7e absorption_res_12.out +eed4b56fe77926fb7bc906d3002587c9 absorption_res_13.out +6ac0d9ceb2b20fe0d39b39424ecdece6 absorption_res_14.out +c2db7711b9abe77ed1bb703c0b34379a absorption_res_15.out +e601c9d665bb0dbe30bc111d26b56a5b absorption_res_16.out +fb21dc94659e2d4e6bc54193d5b11a79 absorption_res_17.out +6b8639055b9c6162caea331b9a0c48e6 absorption_res_18.out +41324c33bf7a12e92c211f8fe764cd78 absorption_res_19.out +040fc1339c771478c0c343b75d04aecb absorption_res_20.out +e6e505c4c4120ff9e4e98289933c4e86 absorption_res_21.out +a10198bb8be6741fe792203f04a7f42f absorption_res_22.out +ef73deab1d890134f7b9af665c3513de absorption_res_23.out +d4857af34eac0172c00165eee8e67072 absorption_res_24.out +a6eab45b294b277e9776030ac4fab597 absorption_res_25.out +86c6ca74477064e700760fce72021bfd absorption_res_26.out +f0f7cd01c57123f140a06ae45ca9d808 absorption_res_27.out +8c272309f38b1ccbd252d5fe69566f28 absorption_res_28.out +20d041411eb43118c8cf9efde6de848f absorption_res_29.out +249c2c03c94bd4f8fa20de46ffe38ed3 absorption_res_30.out +90979047442da886286383d2749d6db0 absorption_res_31.out +a595ed8816652934c76e608060b57cb3 absorption_res_32.out +6ccb84cc525e8e59fa504324f897b7dd absorption_res_33.out +924a7ccaef5c34dcfcad9020809196ed absorption_res_34.out +051034109e0d0112d8972125f3060b69 absorption_res_35.out +4953d058ca077e941a72d1d64803c3d4 absorption_res_36.out +2c50ffa2943b8052aef34b7712c7ef89 absorption_res_37.out +dfb8b2cd7baa32777797fdbb6f785c06 absorption_res_38.out +6248b5667da37a3213313cbedffd15b0 absorption_res_39.out +50c4ae7edd9d84de99bf64d7e4cddd7c absorption_res_40.out +23d896921cb707685c1f7a716fe7484c absorption_res_41.out +bf1e2b0ed46ffa83944bcc22f801a0ee absorption_res_42.out +7476f94af2030206dc65648245cda0a5 absorption_res_43.out +0f499e64e105aa922688f90c69545766 absorption_res_44.out +e9b93a67a6e71e805a60b97337d32727 absorption_res_45.out +efe5531d7c7dc66ffcdc3dae40127acf absorption_res_46.out +69b537d5168f4521ee46d5c1b8451e73 absorption_res_47.out +0eb40941b8fc5a655d3b82ff0a878b00 absorption_res_48.out +e091cc75b1a4e2da0660a9ff12bdb055 absorption_res_49.out +eb7598f41c7e9d82499617aabd6ab85a absorption_res_50.out +3b24a189322c1d91f4f5ec1786e190cf absorption_res_51.out +e091e5bd08f0df7e635b4279be3bd80d absorption_res_52.out +4e78a64082b5df1ddebc025985821cf7 absorption_res_53.out +22d82de1b80a444346be96fc7b92ce62 absorption_res_54.out +b37aee915ab9c17e21df15d62e8e5730 absorption_res_55.out +c02184ef77a8929499fd63fce0dd1f00 absorption_res_56.out +18e32e7f8d9064a87f993046ad4e5424 absorption_res_57.out +091d25fd6878c37efb3a711bf66de5b2 absorption_res_58.out +8f84395cdd16b932cdc0e770564fca1a absorption_res_59.out +3a86392499caff2af91a72fc489217c2 absorption_res_60.out +f638d7c4403819d82aafc3e9fb62a28a absorption_res_61.out +0f6c3fbc58d6c8f65548280eae3a460d absorption_res_62.out +2ad8a20e110fbf7b18b0068b0368e5cc absorption_res_63.out +8037e10b12586a633e848532b2f7c446 absorption_res_64.out +e9eb2e5c3865b24f065fd81bdcaf06d1 absorption_res_65.out +b3e69e9e981fdd6bfaa38a10b447203b absorption_res_66.out +3523c62d6376a0cb15c8b221ff0ba3e5 absorption_res_67.out +e0586e5d0d6cb433b40cae1a31422ddf absorption_res_68.out +d1b4607e1ecef935ec1b99fd0a3c7b4a absorption_res_69.out +9de15fc18942e3c742739d624d02ffe9 absorption_res_70.out +fd86c96d9ddbd5723d8791e6a3050791 absorption_res_71.out +0dadb2b210ec23babd3ff3be59d2ae84 absorption_res_72.out +3a272863e0dcbf09522e153333fecdd7 absorption_res_73.out +5392945b2ce7bdd58b2d777df4a24330 absorption_res_74.out +fd2458e5bd7464abf206716ee0b84eda absorption_res_75.out +971861c75a1fb6da8fd55925c83118d2 absorption_res_76.out +0f311ecfd1674fd5fa2e809e147e6577 absorption_res_77.out +ffebd1d74851b9417267950881731ea9 absorption_res_78.out +179612fcdeb64fda26e083709f97f22c absorption_res_79.out +84369dded2347e8c06e484296fb62097 absorption_res_80.out +d884cd0cb3210ebd3494fa1e007dbaf4 absorption_res_81.out +938045b95f3c60026f4a170749b8b17d absorption_res_82.out +b07a77698d5f442a16687e45b0fcefbc absorption_res_83.out +9a8f10598e22569cceced4de8fa5102b absorption_res_84.out +471e9ccceb628a94d1039f780017434b absorption_res_85.out +64538fcb68f44a3cc442e4cdc5ebc666 absorption_res_86.out +39646af8a8c9aab4bf14ef5b8b86acd9 absorption_res_87.out +16478b9e9551a4a9e5b0c66553af8fab absorption_res_88.out +f70bf00ca7479a3c46a71b4edad54d86 absorption_res_89.out +9646f1ca854ae244993d12e79d3c1ff2 absorption_res_90.out +3c85424bd278572621ad60a1fba0ffe9 absorption_res_91.out +405000a2e77100d73c055d929fba001a absorption_res_92.out +3aa15f4ea4fbdbdd7232cd3d2f0b81a2 absorption_res_93.out +10d7d8dfd1b723eb4d85f9efc1b096d3 absorption_res_94.out +a1fb072d3b0e8f29bf66ef44e2b0fea5 absorption_res_95.out +70ff4cccad02460d6c3969f2f82f2c99 absorption_res_96.out +f9fc2d03e0119ceecf2774af9cc65f6c absorption_res_97.out +ebfb61646c5db7a6ab4870879375db33 absorption_res_98.out +70271dd0dfa0f7644e6948f72bcaf0a1 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -3e606137299da9ff0d407802b98206a2 deposition.out -94e7893f4d16eaedf276ca3bb09408e2 emission.out -802067a4cd06e68099ae5d93d3e29773 emission_res_00.out -e885f6a4f62b14a6b45dd9423c20a98a emission_res_01.out -96dec81fc301a72fb5c7e08dc3637429 emission_res_02.out -3d95332d326b8ac4af0adf5af879543a emission_res_03.out -8a1f1252089b7f18d86b5738f3e37ab8 emission_res_04.out -3f7585082f3b3ebe844ceaa89863aedb emission_res_05.out -1d1555ab1c568793fcd362e9c5050d31 emission_res_06.out -57f31f3962ce4a18463d74841ff1b210 emission_res_07.out -0773ad2f6294f67ee91af110e7c64bd0 emission_res_08.out -f72ed64f15567c2317a4bbe238f31501 emission_res_09.out -064c28ace251811bdb07a9b7df383509 emission_res_10.out -06da84c944e866d0a85f292f799da601 emission_res_11.out -b98e07714fd362a755f3f12f35bb5084 emission_res_12.out -bc65982be583d84728ee39fdba1fda8b emission_res_13.out -95c634859bbc07187da5b7ae438fedd6 emission_res_14.out -1ee4dc26615d50737cc1c13c0811fcce emission_res_15.out -a21463ef64bfcccaf4f598cfbb6afae1 emission_res_16.out -0a6a79c5a0115fd3b331e45d8e242668 emission_res_17.out -3bdba3c4db9aeb5ada76d6198a911bdc emission_res_18.out -82ed3b9a44cbeab1e15c6c24967de7ff emission_res_19.out -e12b0df30e35686164792e078070f3ab emission_res_20.out -2d642d0d278d4b691187b7265b744610 emission_res_21.out -6c6389ec62f9aa14ef953772290b2d00 emission_res_22.out -84975687d246f6f7c78d6f2d04fd88ad emission_res_23.out -c6aa79e2280c41e13ff8461be02c0bb0 emission_res_24.out -2f92a55f470fb77669cf43f1e77dab89 emission_res_25.out -0d06fd2b501b740e876e72da835420e8 emission_res_26.out -ebed62e732f039a9b693f0271febc89e emission_res_27.out -f62e2aa4c4258a0379e95de144a8f694 emission_res_28.out -3e03b1bc7eedc9ac11fab9b362ac7ba4 emission_res_29.out -f95fce0026987aa1e2d45e9f42601799 emission_res_30.out -c44d05f443a167a9dbfbc12022fcf9f0 emission_res_31.out -4a106ace1b7bcc45ad4b0c985b704747 emission_res_32.out -6fddeaa911102604cb08a60922f518dc emission_res_33.out -de38fed5e2488f1cf5c8c67231135eab emission_res_34.out -b6450142bfeeeba4d8d9fb4546b8e00d emission_res_35.out -13f2b982cdf2c17e58b1128522637a27 emission_res_36.out -8a390b9d14dd186ea99117252ba69866 emission_res_37.out -bc9cab540155a5051fa9c72a9bde4904 emission_res_38.out -2cd6b2c4bd210424c75a0845a3bcb865 emission_res_39.out -6a462299b5a9556071a015616e735b22 emission_res_40.out -04bed39cfdda981d226aaf52a3f14446 emission_res_41.out -d8119b704c3c756907158cae1599b50b emission_res_42.out -180c543799c8222f5eb65eab46703390 emission_res_43.out -319e422dc7d67d5302c0af46031fa2ff emission_res_44.out -de9ff223f750723829be02852fcebe2c emission_res_45.out -ea6adaa69ef43bf3f77a5ddb02b9923b emission_res_46.out -e7251578e966a3d7411f45dd9ec7bcf0 emission_res_47.out -f7bfe17e81549093e7c1a55c6c41a8f6 emission_res_48.out -1d630e5b44474b813f4658b810dd1c51 emission_res_49.out -c96e48f5d4c22ed6795bf3c97634d478 emission_res_50.out -1a99b5727cba51bbb5579679c3c35e7a emission_res_51.out -08fb4109b9d80434bff19f74156dab93 emission_res_52.out -ad14b7efa870245ca7930cbbfd485f59 emission_res_53.out -16508a2eddfe4378122804eb08417ced emission_res_54.out -4e9ef3ddc1bad58af3ed46d353f10086 emission_res_55.out -6868217b5d9dd93da1193113416a8366 emission_res_56.out -2bee3ffecd99642130f792e6ad682253 emission_res_57.out -0446b4f5f267c6961811fb69f59fa250 emission_res_58.out -b1e4645cd0b8f29a6257a2adc07b8274 emission_res_59.out -435336fbabef2041315ca3005194cc4f emission_res_60.out -fb4cbb5640c27518f4f17a848d6a69c5 emission_res_61.out -f981fffabb8bc6d0f748a7316e3b0952 emission_res_62.out -2194689ac46a015e6909ff65892b011c emission_res_63.out -cc07bf8459f2e7d6875e2d179c7a0106 emission_res_64.out -1d5ae514e4fc6282201e78fe85484669 emission_res_65.out -d675c2588fc42731145a1d3c0b5c687b emission_res_66.out -2cf76193138ce584e31cadc9f5b3bd84 emission_res_67.out -8affb443ca4d8b0a77e7c88733debb94 emission_res_68.out -bc854df639f68c8b149124f1ea61c6bb emission_res_69.out -21517ada149c5cf22e13a74d2d0863a8 emission_res_70.out -2da4e995d536c0e54696515aff752e46 emission_res_71.out -cc0c3b1680328bc927c0f54482126c5b emission_res_72.out -8613f32cf8d3e29f5b8edd894c659f73 emission_res_73.out -c1994baf84849f372662843412c5de68 emission_res_74.out -52e5fa9e3717b0fb3dde8ba471b49bbb emission_res_75.out -1ea14b097540b319a03e199df3611e11 emission_res_76.out -a98f6a81be8953903c1086eb0a5be8c6 emission_res_77.out -9cebab17a7dd36b1c6d3ad384ad63225 emission_res_78.out -07890efda1402d7ca57e036986bb94e0 emission_res_79.out -402cabe1089be744674d03177da02bb5 emission_res_80.out -53e829019a110181ce49443a2a456c60 emission_res_81.out -3259348d2c75947f90d850a5f7edeebb emission_res_82.out -d2b3a5952c3070ba7022190ee1e01b3a emission_res_83.out -ace32f45b7f9acfe5bda96d10bd6a39c emission_res_84.out -fc3f2ffb314a2c36853f242d8afd2f18 emission_res_85.out -9c89eeab349e729d247aa103dc91e48a emission_res_86.out -7fc3cb5d79a61059025fb5ab94d5be0e emission_res_87.out -f3211188c037e359c947d69eb68fc855 emission_res_88.out -308f7883bc6b64f625dd0d177d5168f0 emission_res_89.out -fbfd42a65e22751bcbf42bfa2aca3b40 emission_res_90.out -1a1a8172c8907f9a615c2d6cbdbdcc25 emission_res_91.out -f0853330612ec6644947aa0cab728b1c emission_res_92.out -45f17ebf98700b22aaaf2534948f3739 emission_res_93.out -8e20cb52ecb1ada6dce9db0a1bdefca3 emission_res_94.out -5c99bbb14897b0d0228aded66a96c022 emission_res_95.out -d03f934f750cf063cfdcde6b7e1f274c emission_res_96.out -81168b09e51669a848901263b9b0d69f emission_res_97.out -f603c942ee34d4b4b12a910141e8f9cc emission_res_98.out -0e86758a606793c97614e61fa00e18bd emission_res_99.out -ddc4ce928abab65d46d480f89c2e574b emissiontrue.out -e86a156efcfe3b34f7436f4477868ccd emissiontrue_res_00.out -4f12e1ee9d7e764268d832470b6c3ae8 emissiontrue_res_01.out -03e5b5b9bb711cd002734e843e462ee9 emissiontrue_res_02.out -7ac89cf9180ffb2fca31007892a2138e emissiontrue_res_03.out -6d39ca494abf5e58f3c042d1eab6e8ac emissiontrue_res_04.out -57d913d72de624546786fd1adc6936d5 emissiontrue_res_05.out -b3a7774e7f90432cfd5041465f58c41a emissiontrue_res_06.out -46a2dd8ed093b86abbb33ab716b8fda3 emissiontrue_res_07.out -e8bf23ffd98fa0e4efc0fa44ec3ebc86 emissiontrue_res_08.out -2d495595ae8d7ce2798c69e61d70215f emissiontrue_res_09.out -fc9badf3dbf024782155aa3b15e88034 emissiontrue_res_10.out -647f4d3acea36b412dd3db484d0b7db1 emissiontrue_res_11.out -9d57d4aace7f6239b4998511bc31b2c4 emissiontrue_res_12.out -917648be6892d25b44b4f1024bd19901 emissiontrue_res_13.out -2d92697892551d8ff8831c2ea394164c emissiontrue_res_14.out -29a9d87a2ea0032ed40eff83e84bd91f emissiontrue_res_15.out -194129d693d005005aa5c022a2091693 emissiontrue_res_16.out -7adcd28f45232f7550a7e778e66ba17f emissiontrue_res_17.out -625a21043483d85de186ebd65173dfca emissiontrue_res_18.out -401ca73df0574e3460786f1bbdbb0886 emissiontrue_res_19.out -58e83e9a97c1cc581adf5d2b19c40ec3 emissiontrue_res_20.out -8501ad496eec2760c0ef67135767de2b emissiontrue_res_21.out -6083024a98dcd371bff283c80a6bfea5 emissiontrue_res_22.out -a3813332e1739c2613bc8469861550b2 emissiontrue_res_23.out -c7dd72feff75b0289389681471b35cfd emissiontrue_res_24.out -8372c7921bdf58199ac416677ac71573 emissiontrue_res_25.out -398f16256b356464e5511726e64114ef emissiontrue_res_26.out -7f7c72d10636e797c3dc6a019aaac7fc emissiontrue_res_27.out -bb8a2cc7f83d38a4aa5d04611df7c6bf emissiontrue_res_28.out -7a188814bf3c63160a0afcfcf046d250 emissiontrue_res_29.out -b2f7d4744092b5779876f8823e12e963 emissiontrue_res_30.out -e76d94d9cbb15be8af6e5007cfebf489 emissiontrue_res_31.out -98c07bcc9786a6f03bc15242cfc079f8 emissiontrue_res_32.out -351b911335c672f627b2e090c968bf16 emissiontrue_res_33.out -96bc46d50765b98ce3ee870ef9df4b52 emissiontrue_res_34.out -4460994748a4394f0f8ac79d59d177bd emissiontrue_res_35.out -cf31f73fcb64cdda5167507e0346e4f3 emissiontrue_res_36.out -4a502cd7f1881388589c122258265536 emissiontrue_res_37.out -e6336332dc88919f38ff742f37fb0a21 emissiontrue_res_38.out -804069802c8fde481bc95ce84fe82b4c emissiontrue_res_39.out -46bb77b2b0c2ae15dd0e91bdd9003fbd emissiontrue_res_40.out -a50a6600d9bdc78939539033a7d09106 emissiontrue_res_41.out -052f0eb5db6423d69887704483ba032e emissiontrue_res_42.out -4ba6bec99680742ade65c6690c4aaeaf emissiontrue_res_43.out -22b0143252ea8bcb364dcb93362ad735 emissiontrue_res_44.out -0c9847e9d43702a168f3dae685345e4d emissiontrue_res_45.out -be7ad75e02dd55a1c3ef0b5c0ef73aa7 emissiontrue_res_46.out -c9cad8ef312b13a8d4b44dba6f6c80f5 emissiontrue_res_47.out -a5496f4ed80af479e4bfeda1cf0edada emissiontrue_res_48.out -5ac17a32ed4d81f7ec3a21cd441761d6 emissiontrue_res_49.out -1e6243408c1397667bc52d08aab3fdc5 emissiontrue_res_50.out -573ba7e8afb89e8396b846cfdcfbe6f0 emissiontrue_res_51.out -e0dcc6d7cfa1e8917cbf5231b4f2470e emissiontrue_res_52.out -c71ef5e51679b446458b8c15d614ab80 emissiontrue_res_53.out -1c93d9ab3e6746f37bb284da3df685a0 emissiontrue_res_54.out -d5062a8c2c2ab51956ca2cb7e0cd847b emissiontrue_res_55.out -e550cb7d9b3c5144d82cc594b6ba8ae4 emissiontrue_res_56.out -54d230e990bfea095231c3010ee914fe emissiontrue_res_57.out -4694877ebf8197a4480552b953db45b9 emissiontrue_res_58.out -fa39c5bfe6c13eb5324fba201e9ab7e1 emissiontrue_res_59.out -d8bf15fbc7c518d763b2efa9d3d28ef2 emissiontrue_res_60.out -7a160fb9f07317b53c13ea6d63cb978e emissiontrue_res_61.out -048a5e3161bcd03dd782d8027e6925f4 emissiontrue_res_62.out -ff67b5dc757380bffc4f87d90a6898c6 emissiontrue_res_63.out -2881f44b20a65d31dff4a5414f6f2362 emissiontrue_res_64.out -3b31536580cb9cffd316a4e3caba08dd emissiontrue_res_65.out -273428d42380f08e9429d0109d06ae40 emissiontrue_res_66.out -e1792d1e140582983099dcd9f786492f emissiontrue_res_67.out -9fbf864fa61116e9f28b8b63411882f7 emissiontrue_res_68.out -671120c57fbee246a946adc22b8c2ba3 emissiontrue_res_69.out -f4270005c328a93fbe4dfa36d45a4b7d emissiontrue_res_70.out -61a345a7a515d7d18e1cc80dce1fd43c emissiontrue_res_71.out -a7be8c91f0cc5bea9a611debf14cbacf emissiontrue_res_72.out -be432fa37bacf3dcac8c062b5a32bf6d emissiontrue_res_73.out -c998e8db6da25720422497ec9004728e emissiontrue_res_74.out -dd0379f8cee49aed12a0cb16c375acdb emissiontrue_res_75.out -a730184bfb9f4f49fc0a85f6ff6c7b80 emissiontrue_res_76.out -041bf247a36a676297c6e572dd6076e8 emissiontrue_res_77.out -1f622bac25f4ede015e41c2cfab26f91 emissiontrue_res_78.out -03880bf9a5ccbb153e9b9cb7252507de emissiontrue_res_79.out -d6b91a8a879c41db91d6d8a1fd2e1cfa emissiontrue_res_80.out -afbb435db75bcac21f7097bb5b44c265 emissiontrue_res_81.out -8a3d1024a8546ed2d0bcad762baac39a emissiontrue_res_82.out -66cebcafcfa171672b95c695cd9f821b emissiontrue_res_83.out -ee722f27d5f6b82c4a8bc0772e6681f8 emissiontrue_res_84.out -e945a94c3c76e40fcc9a7f8b9bfa31e4 emissiontrue_res_85.out -b8929a4b94a29d50b986e6019caee4ea emissiontrue_res_86.out -bc4c78dfeb2b70b4e03e22ae4aad0306 emissiontrue_res_87.out -6b5252ea88bc79daf1df62c5a5f61fe7 emissiontrue_res_88.out -d340b8404b5f993c487de0f9e5be0464 emissiontrue_res_89.out -195d32c0039f58ac7203c549453f8ec1 emissiontrue_res_90.out -5c8d8902822e7925e83d64bf4d67bc90 emissiontrue_res_91.out -b18f8730f9de6d8f56f34b948489ec8d emissiontrue_res_92.out -aa9f9d8317db0f97019be1bf05c36a32 emissiontrue_res_93.out -df1484f3b24e5173a31a2e496c04166e emissiontrue_res_94.out -0cbdc62ffce5688bd58805c873be9f89 emissiontrue_res_95.out -cfbedb1f6be28a5205686538e0a0e102 emissiontrue_res_96.out -ee7b117bcc203fa9da9c1f530859725e emissiontrue_res_97.out -17ae8f115a621c762b01fbb522b590cc emissiontrue_res_98.out -f488ecba4cbe41a57e365c4b04b7c861 emissiontrue_res_99.out +7b0086fe577d37ce260278374178dc0d deposition.out +7be4c9d9385e11c98506c09824606499 emission.out +db5bddf812e29b83030c4551767d5716 emission_res_00.out +d24aa15a2bb9db9e34eaca885760875a emission_res_01.out +630a3028f7ecb54e82a6e841562a39d5 emission_res_02.out +63780f98380d9b4aecfeab7a137d49f4 emission_res_03.out +f37c784e4b5f65f4d2b64f4606b66401 emission_res_04.out +b9a7ec16052597e919ad39242d4e0d90 emission_res_05.out +51e7b44b1d246d13c17e8b792bc8464e emission_res_06.out +3c25109b93e948873d42e92233d7e1e3 emission_res_07.out +c716f4f56565838e245c8434181b04ba emission_res_08.out +05552a1adb795a7da45a0188129ac1b7 emission_res_09.out +82cdf963380479bed6bdb50603730977 emission_res_10.out +cc65d922e43283f2fc46216c977228de emission_res_11.out +eeaad85aedc1312f6b11cfc06d41dc2b emission_res_12.out +664c0c2eded7056551a6998aad7538eb emission_res_13.out +ffd57940f1b2b465096a7c34dfe02865 emission_res_14.out +6cda4db563a0d3ad351418b02fa7514a emission_res_15.out +f6fac7e3d9e6390c8787158bb738700d emission_res_16.out +56fa68e8fa00032a637b42e4e943ecca emission_res_17.out +83e1675ed88fd491cdc2b4366f4a02ed emission_res_18.out +d4fc1367bfa28128a191f35b442f33fc emission_res_19.out +5131b9e14f3943656d8f07ffb1c67a08 emission_res_20.out +611dc6df1bb93fa2aafbca48d29b0b01 emission_res_21.out +590fd010ad5aa1a7da1c8ddac8ff4c6b emission_res_22.out +cda483da23f533f734d47ae422b7620b emission_res_23.out +27faad1a9a247f230df243af2f3160df emission_res_24.out +8d09cedd7ea2b87773af4eddbc381afd emission_res_25.out +84ed1d1a84111f7a95b32d9d7338576d emission_res_26.out +adfed2cb8ecc802dbb030b99a256637b emission_res_27.out +de817f3f79846b6a58c6366e65ffe7b4 emission_res_28.out +e232a6482bd44983f069fc696f71d304 emission_res_29.out +3ba4c5267f9d6f7cd7382e31c14ba1e3 emission_res_30.out +a8488cae91fddcc23cf54ee8c65b5d1d emission_res_31.out +796daf2d0d42f9a77115baa23f60f3da emission_res_32.out +7978797e62c858069a1fbb5fef09420e emission_res_33.out +27603f2b2ce2809951748fb20fe2073b emission_res_34.out +42a15aa6022851e8851090e8f9458397 emission_res_35.out +e8070b7e6138852f9c1240e265c4b48d emission_res_36.out +bcc9b710c1818a673a3bfb2dae05a0a5 emission_res_37.out +dc4669af5158d9c1dde1f064d981c09b emission_res_38.out +802728be1de600154a69e66cacc5c7d0 emission_res_39.out +7b5c9a234ad7d244f9932951211ebed7 emission_res_40.out +5a146b86bf1d81e12434513d78597297 emission_res_41.out +62bbde01a96e49b386cd35735fe65787 emission_res_42.out +adcd058fa412861b6fa5181007dbebe3 emission_res_43.out +40e3f49b240b80697e4ed2fe343c359b emission_res_44.out +2a0203d84c45ef681ff5ff8c12359e2e emission_res_45.out +773c02275aa9c05c8e68862ef343c8e3 emission_res_46.out +05a3c8ef670577716447c68bbcd6efb1 emission_res_47.out +cb479557cbe9377a4fe8b834c17c54ab emission_res_48.out +72e25147422d1f6450e5c5852e08064c emission_res_49.out +54acc4b3c22ef4e09428b6afacb0ef0e emission_res_50.out +68380c2e58373d0d8a5d1d4a5cf2b748 emission_res_51.out +d4a3c844fc95bb8177ff3ba7e765c08d emission_res_52.out +cafcfffcc54be0f38780ca5827199ef6 emission_res_53.out +c17fcc5de93c9ff5fa12c663040676d7 emission_res_54.out +e8f8ec2302137c31a598456abd9b3a8b emission_res_55.out +d3ca08ec1280f7d4e5d4304e0197adb2 emission_res_56.out +94a1eb74c5e8243a564a759e650423bc emission_res_57.out +7e2509aeb2e286fdafb11ca6c2cbc62f emission_res_58.out +b4e7f9409aaa64fab4b457ac9741bd46 emission_res_59.out +b762b78fc0842998629c2769c196d5cb emission_res_60.out +080d1763c94ed7bb8e3d9b8599f3bdf1 emission_res_61.out +37a20ea78a2c22f60d76bbd205924d3e emission_res_62.out +b4b81d6596923fdf47cbd19911ad389e emission_res_63.out +142a94abe84e10e328c69230e47b8a85 emission_res_64.out +f42e27dc400605615a0b7b3fb906aa37 emission_res_65.out +18b7f8b1057187e43a747ecb568f4023 emission_res_66.out +bcb00e1f5b9db68e1365e0ec7a7fa38c emission_res_67.out +ed318a8e15a1c896a0c02eed056be3fc emission_res_68.out +260bca6c64680197b31d45550e701129 emission_res_69.out +61b5c12507f582c4081a6d9646a3126a emission_res_70.out +f44164367db048647ac4414914fd061f emission_res_71.out +f61ed8e979bf54dfb02d3cd675da7ce6 emission_res_72.out +b09b628fcca9315999f291f712f22784 emission_res_73.out +9fdb166a05e1552aec84443f4179a148 emission_res_74.out +d1a3f269d9ef59eb30b7922f1e490f02 emission_res_75.out +3f76a493716dc8c24d7a455b09ff848c emission_res_76.out +811861b1c47432ba2a986b8b976e4ff9 emission_res_77.out +0df9bc1c06c195eb9cf8b366702dee26 emission_res_78.out +4274870ef45b5a4db768cf7726170e4f emission_res_79.out +6eacdede053a62233e0dc5870f238184 emission_res_80.out +7b798165b157bc2bc8b0cbedeabf0c1b emission_res_81.out +8812796aa99c1ae99ad42021ea41cb33 emission_res_82.out +0024867a5abcc59e641012b91d195acd emission_res_83.out +c5f8d3ecf55773f1320ba32cf2afe60b emission_res_84.out +fd477908191f20d1a1e73b6b9a7fd973 emission_res_85.out +bb1243401a67a3f8805996709b574baf emission_res_86.out +aef8a3877023eadda6e698add2b07d20 emission_res_87.out +96f1a013ec9a2631af7640d93bccc4bc emission_res_88.out +1add9eaf51b8a88eea8f740669ac70ed emission_res_89.out +3383d92019e24cdfe2c4497c9284c110 emission_res_90.out +45a076f2b71d496ca1cff5e5392c9455 emission_res_91.out +eee9d03f0c08e8a177da9525568c439b emission_res_92.out +17763c806a6b30a64bf2d8e8ee3c97bd emission_res_93.out +6aedc9152c440204864eda1f1a7c0cc1 emission_res_94.out +54a52ebf69011c19219b598c6aa398f3 emission_res_95.out +614116ed0cef52337a366d07075d2870 emission_res_96.out +4eba97bb8dee093b08900a73ef75abe5 emission_res_97.out +5e5f92faf808e60687b3b3d472f0d468 emission_res_98.out +f84fc5e996ec6df2081fed2c14a77ffd emission_res_99.out +3191102b8ad77efa933f962737f9485d emissiontrue.out +765b4bcb392a16e241f8df55b1d3cbc3 emissiontrue_res_00.out +e9edac6f89e566aa417330d36cb26cdf emissiontrue_res_01.out +be46ef5ca6b3d45871b45bfb1a8bc534 emissiontrue_res_02.out +4114082d6a57c918cded07374b53709c emissiontrue_res_03.out +97d0ec7d9fa86b384953099e01ead55e emissiontrue_res_04.out +82c373d771438ed440dafed57a290ebd emissiontrue_res_05.out +abc80eea97b1144861107d4e63545707 emissiontrue_res_06.out +6ef64a39b5b5778341f4f4ceb16b877e emissiontrue_res_07.out +90829d40c7099fbd0c8708ad28c3b5ca emissiontrue_res_08.out +061fe3dca5b243bd620fb86d647da8a8 emissiontrue_res_09.out +d2e0a4e627eae7b4eef10ba4998454d2 emissiontrue_res_10.out +9155cd8579c5fbbbdf03aea7e2e02008 emissiontrue_res_11.out +4181b0084059424940f6f423a7d750e2 emissiontrue_res_12.out +edf4411c2c28583ef1be966d8b68ed66 emissiontrue_res_13.out +7261e9930c07007dbe81a7c282f16fe5 emissiontrue_res_14.out +4dc15d6cf250379bbfa35b1fad009d2d emissiontrue_res_15.out +e2de56faff009e1ad2ce36f1d4f14623 emissiontrue_res_16.out +5f43d1a6a0c8e10906134f196ff29cb5 emissiontrue_res_17.out +9383067dda350bbe4388ac2f251d19e8 emissiontrue_res_18.out +f1fc693a19016331afdaf112d10e4f1f emissiontrue_res_19.out +2ffc5da0b9dd49931429cbbb3626fbd9 emissiontrue_res_20.out +316870cd1d71ef3c74771e95468e86a3 emissiontrue_res_21.out +9fa415e7a960d4ea43ebe2276006ec45 emissiontrue_res_22.out +35e0cfe5f7e5940ef0e8e71efe633be1 emissiontrue_res_23.out +682e3734f5eec2f9bfc844ff03b8a331 emissiontrue_res_24.out +49bd5e1796907f5a34ca40f33ce1aae6 emissiontrue_res_25.out +3b88c87fc1a08597a5a1aba202fd0e5e emissiontrue_res_26.out +3accce5bfd82b8309b77c1e1beac3b00 emissiontrue_res_27.out +6977ae55211d1a2aa441688e510e5008 emissiontrue_res_28.out +f99e571fc7df671489940fac125db2db emissiontrue_res_29.out +546a7ac1f72d050d3fe6a86bf54580b2 emissiontrue_res_30.out +f319068abfcc2eb58aaad6034e9b2cd8 emissiontrue_res_31.out +d878a0a4a4c172a23dd0e9dd2c72e30d emissiontrue_res_32.out +fc3b9a7404c5ef309990bba2f3972d3c emissiontrue_res_33.out +05eff2bcd22c2dce31075f8ed769f530 emissiontrue_res_34.out +254878534bb42f9f1c82516d96607a5b emissiontrue_res_35.out +9d8f24950e18d296164fda533dc0120a emissiontrue_res_36.out +bebbb86b9734a32ba6c5946a9b07fc79 emissiontrue_res_37.out +0e4e3412c7b7a2edaebe4b027afc657a emissiontrue_res_38.out +26a04d836835af549ee4afeefe2bd3a2 emissiontrue_res_39.out +e92559803f9e6120eef406bfb26ad20d emissiontrue_res_40.out +9be0e567efc2457643982875768fe07a emissiontrue_res_41.out +530497e07b6b75002ccfce680dbdfd18 emissiontrue_res_42.out +06453dbbcda764abd4ceecbcb0f6536a emissiontrue_res_43.out +d59e9a7d3478fbbcf600c8974d71bf35 emissiontrue_res_44.out +d46807d8ab14c9f468ffcc2e96fe099f emissiontrue_res_45.out +a4c1703d46fbc1f481999741e732313a emissiontrue_res_46.out +66adaa3a5806973a4d84bf8e7d4f07bf emissiontrue_res_47.out +13185d3396a74804da43f67cbbf7758f emissiontrue_res_48.out +41381a5288f1a14b68c5b2aa7fdbb8c2 emissiontrue_res_49.out +2fb181bfa45adef22eaa777052f785d8 emissiontrue_res_50.out +780ba87d355a79794331c01d2161f067 emissiontrue_res_51.out +e3ad5e85b383f9b10c31124516fdf80d emissiontrue_res_52.out +625b182b08acfc21b83d4e5616577cf6 emissiontrue_res_53.out +0ae5147bf32506029cb4dbeba71b5ee7 emissiontrue_res_54.out +3a0267040aed4544bbb6c8e53775ec7f emissiontrue_res_55.out +ccd14eeca3780deb6bc6c19255856895 emissiontrue_res_56.out +4e94ad5f27b6cffb974f145a732cc143 emissiontrue_res_57.out +b56846b75cc9f652bbfb28f35135cc71 emissiontrue_res_58.out +1a1ceaab5ebb3676b0e353f01ae466ca emissiontrue_res_59.out +a1aabcdfff90a2722f5be82cceb05d66 emissiontrue_res_60.out +0a4aab1329a6684de8e379731cdc1b3e emissiontrue_res_61.out +4980c2b839202e8bc30145bb05766ac7 emissiontrue_res_62.out +d73964b0d7161d45dee97bcd07643695 emissiontrue_res_63.out +82c7eb76c69947a27ddaeb19a8c26657 emissiontrue_res_64.out +cb5fbc1d7405a8070effdfa30c01c884 emissiontrue_res_65.out +734641d6d18ca8f1cef34b96bf0cc42c emissiontrue_res_66.out +e9d0fd5f82ea58a1afd769fd46b4e4bf emissiontrue_res_67.out +f82d52d28edf1a7ff2926c828ab06f11 emissiontrue_res_68.out +dbd52d7dff5ec40397166831c802bba7 emissiontrue_res_69.out +2926c7cdf2a9b3c8c0fee38f7281a927 emissiontrue_res_70.out +5dbe48a687f7584227e5dad0186fdb70 emissiontrue_res_71.out +daec33afbed1c5326240624c62e65452 emissiontrue_res_72.out +5bedcdbebf3c6a6ad408784e97553193 emissiontrue_res_73.out +caded959db96f5872cc8e3ec5cea0041 emissiontrue_res_74.out +0c847ceedb65a25bfd77e2282457c2e4 emissiontrue_res_75.out +5de836eb70ce31909b7c60d24cb72c5c emissiontrue_res_76.out +e9ebe3cfd80a3e55829dea2411455718 emissiontrue_res_77.out +e7a0fdaeaa9da7954f3736c6bc5d8163 emissiontrue_res_78.out +ac11bb0481ad3bfa505df210a0c9ea3e emissiontrue_res_79.out +49c0394503efcbd3c82dac17fe2d4698 emissiontrue_res_80.out +5178b823e5665cde48997f5079304aba emissiontrue_res_81.out +5deb66bc2277ca113135cdf45ba4c146 emissiontrue_res_82.out +8363eaa7ae8603da885d9943ac2c49c6 emissiontrue_res_83.out +556317ec387a9ffba0640ff4de475b3b emissiontrue_res_84.out +9cb1ead72da84ec61ed65dcc51157d59 emissiontrue_res_85.out +35c1510cb727c64847bad82592137b99 emissiontrue_res_86.out +76780ba9d2374d49e78933c176ebbc96 emissiontrue_res_87.out +6b3acfd3ed16c2e8c5005b2780438ffe emissiontrue_res_88.out +cc623376ceec1632e2b9926b758eb561 emissiontrue_res_89.out +3a796510dd7b528ba6aa8951ae8fc785 emissiontrue_res_90.out +722bc3fc8c70798b2fb67a78ad64a72f emissiontrue_res_91.out +5987be430524b2925ff6aaa59d4ba4c4 emissiontrue_res_92.out +fdee7bf98a65a428869cac1d84521e5b emissiontrue_res_93.out +31e38ea1b74a5492fcb2f03200cd01a5 emissiontrue_res_94.out +7ed9575a9763199db999d603822fc513 emissiontrue_res_95.out +8308379aef0dd1459056708079305a4a emissiontrue_res_96.out +a5c8b28aa3e2cc5de54713edc9fe939f emissiontrue_res_97.out +49f78280aaa7ce89d3fd02a41838b25d emissiontrue_res_98.out +8edd2bc778ba8422a30a8c379213ce6e emissiontrue_res_99.out 7d6e090f3e7cda4461a3965dc38a211e gamma_light_curve.out 484c6a1384f4bf203f31ce715419c6b1 gamma_spec.out -2b769145664780d4f90b07f963588536 gammalinelist.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -b1e9d6e1b0460ddb425ebe296ef0eaee light_curve.out -c4376a7fa8ea4fc8a0345dc0c3231889 light_curve_res.out +1f1e1b30d778c9ba21fb3880064881e8 light_curve.out +7f7bcd2002112a0e4711c73bccd780df light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -1338bf7d672024f42b380d8d0f080038 packets00_0000.out -0c819dfd660bd1129ec869f14b8935dd packets00_0001.out -d197dc03276447c2ce703bbb3cd6e5ff packets00_0002.out -d1c0b59a25497a262c3668b515c42369 packets00_0003.out -2013eb78c14b8ab574b3e7d045ee9f7f spec.out -f7aae73b1abecba91128abc65b17f4be spec_res.out +ccc8f2d29a0e29222d8da9217be3ac98 packets00_0000.out +863dd34e716754c90f820be0f6d8b188 packets00_0001.out +c333f3acb4cdb64c85c3516722469b4c packets00_0002.out +5b6305a7c3be05e9bfad24b4b92036ab packets00_0003.out +6126d7089d6cf1f1346b1a0ecdd5a175 spec.out +89d99d6b9c84cbda046215ba6334c2d9 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -09651e32e7dfb0398c957d377c0e9656 job1/estimators_0000.out -ac9ea61ba5c871f25071c13e5ad1d328 job1/estimators_0001.out -eac3fde83813a6ff3757b509b1561e99 job1/estimators_0002.out -394fbcae7cb9c701a2bda334f1cf7fc6 job1/estimators_0003.out +60d37ec5f93761cf5573c90dbd57541a job1/estimators_0000.out +9c1f185eb551dab9c7c248c50e0d2595 job1/estimators_0001.out +4e33c611311ac54137c06a654aa61197 job1/estimators_0002.out +bd65a154335cd4db369056d1df1135a1 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt index 7748a2486..fe0bdb336 100644 --- a/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_barnesthermalisation_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ 897316929176464ebc9ad085f31e7284 bflist.out -e9aae3a7ab36a1a44e40ea57355e1ba0 deposition.out -afe66f023087001ce7a9fff264f87b2b gamma_light_curve.out -2b769145664780d4f90b07f963588536 gammalinelist.out +a843c6d61851df012b9a3a998b5d62ac deposition.out +b4ddb779d8801db1150a1d1bb3848ae7 gamma_light_curve.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -c167f0a32585932e22e6265b0c9ebbbb light_curve.out +783a09335ccdf90537ba4d2f857c65d4 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -90053e981acde88f38e4a7614acd2cca packets00_0000.out -7f3cb2ff61dcf6693258fb12a8d4a2de packets00_0001.out -e3d4d90c60c5ffd0d7beae8dddd8cacf packets00_0002.out -04e3c8228a973338ecde2f6b90bc40bf packets00_0003.out -88a0e6320da73f235aec8739d4a123a3 spec.out +ac322ba6843f80b711d6037468cf352e packets00_0000.out +ffaae74e2da7b60425c5dc24230db837 packets00_0001.out +3dac388fb3ececee6e8e5d1d92b1be58 packets00_0002.out +7341ed51db875e40fa4ddb165053026b packets00_0003.out +942961c19ab4343ab654be82c0fc679c spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -9978501c2017ce329a24e54daffab148 job0/estimators_0000.out -93677b669e99a50f2e2af2814ac45d38 job0/estimators_0001.out -86a9ed26919747b91ef687add9752d7a job0/estimators_0002.out -209d5a8c2f888d5cefecbe77c1156e46 job0/estimators_0003.out +b9048eeea90abd87e5e8b93be14386e6 job0/estimators_0000.out +c105894720472e91b79788fd3b7ba01d job0/estimators_0001.out +ecf45ec6d7c057e10c0b94fabe5a92a6 job0/estimators_0002.out +e6b6ebda22ea263a3c48f1360c563a84 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt index 5bedf5372..23e8b33eb 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_final.txt @@ -100,108 +100,108 @@ b65007ef75f1eaf1a242c7b3119086c7 absorption_res_97.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_98.out b65007ef75f1eaf1a242c7b3119086c7 absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -36c53a971b39cd7d798471b5f1674ab2 deposition.out -ee60e743859c3ea2e0b13bb96718262e emission.out -5b5cbbc33f5a005f5fc164e755e4874c emission_res_00.out -f1b90bc2c43c1773ec470d3cd85dde59 emission_res_01.out -ce42a6571cadaceb68f47e32a7e0f3d2 emission_res_02.out -09c0577107e4ffdab46a012985c5e076 emission_res_03.out -79ad0829ab52f76f930bc498e4bc9e11 emission_res_04.out -f51ef4d304b7a8b9e28e122d56d84723 emission_res_05.out -4ca7e3e4a1c0dd9a2b598898394c2c03 emission_res_06.out -b463088c9a1a4a6a4df729b450d7dd67 emission_res_07.out -885b89009d73e4991d9e304b72670998 emission_res_08.out -1b595f4b1d19b05e667d255b2deba7b2 emission_res_09.out -fbbd709c745fb3528fd68b2a14df027f emission_res_10.out -6603ac2a3a5c1bc53fab11f992fc584e emission_res_11.out -ae81a8d1028a80481b962298770b5401 emission_res_12.out -f64b5d10f58bd56b124c07e890165ae2 emission_res_13.out -89cc30412e63e73ab84c6681d9fcd82e emission_res_14.out -f03d8a4101d1a1c2fd5da29a1eaab647 emission_res_15.out -e75f6ca6ef8922aaccba8237261df955 emission_res_16.out -1f8faf7732e0a0c32a77f0b04661c413 emission_res_17.out -d54eb08f80892a4118582b79189dfbb3 emission_res_18.out -0a56cebc1621df36c65b7ef6cdee7e05 emission_res_19.out -04d1a37fac98a832656e978094a43d6c emission_res_20.out -b19ad48cd03070148eb172bedf38fbb7 emission_res_21.out -0d655ac26da66fa25507695e4db1e817 emission_res_22.out -d1fea175ce452323dbf863357eeae15a emission_res_23.out -1841ce883463f39995332f8bbda2423b emission_res_24.out -c11fd5516e2307750d669df7039a7b20 emission_res_25.out -5b86b9df53b217f0afc4186cdc0a1293 emission_res_26.out -5e8acab45cbbb3dd8f697d8b285a2c9e emission_res_27.out -218ff185e70fb9017f1833282518e9e1 emission_res_28.out -a5ab48ed6db48645381ee1dca8de4cbf emission_res_29.out -9be7251c2722bd724a6987a75f1646a6 emission_res_30.out -a6fe7b9deddaf2eaaa65dd42e9bcbec1 emission_res_31.out -fa6b62976b9ba68e343a77c3d55ccb0e emission_res_32.out -3474f57d358c1a0f50db823ab8068290 emission_res_33.out -dfe037cdbfe02a84f5a0c9f1fb8b4fd6 emission_res_34.out -c96f9ce937680500a6cd04e8e15b2340 emission_res_35.out -bdac8dbcbcb7af99e91a22307ea6f814 emission_res_36.out -b9f335427b3e7fe0c2f6408f7afb238f emission_res_37.out -9a50103fce25e78d66692406a4c677d9 emission_res_38.out -48df2456573aba03d40145ab44edb42c emission_res_39.out -619470f037d33ee0756693b5ebc74b70 emission_res_40.out -aac3b42b0029a50fc65b196a58040ddf emission_res_41.out -0e2548c62162546a4459883fe2a59131 emission_res_42.out -f9b29ab230953449c4974d0080001afa emission_res_43.out -62fd3cdac988bfa7d237c1c3516fd428 emission_res_44.out -82216336acf3e904b9d1acfe7185594c emission_res_45.out -cc908279d19f0aaeb6aa323ccd72b2a3 emission_res_46.out -98a5b8c23cb0249c611e96ac6741ed58 emission_res_47.out -c68ed20f690597b6e969d476d7b7a69f emission_res_48.out -4ca22d7456bb4dd911c19ee66a9e1975 emission_res_49.out -2cc0b057bcf374b0959c868c02844bad emission_res_50.out -a4b992e1b8d48f4e948174e343663cf3 emission_res_51.out -d9e10632958f78e795c82277fb0a9425 emission_res_52.out -b4de3bad8762827a4757d23f501df846 emission_res_53.out -cb39071ecce707de6292d1fc3b402f67 emission_res_54.out -51d1dc630a99964d1cddb76b6c42e283 emission_res_55.out -d7ccf1583d57b1c8b52050687f1f4a42 emission_res_56.out -97af6c50c70c29d338c1674e8955ef65 emission_res_57.out -6436b855b32c5bb4864ae34ac479b8a6 emission_res_58.out -7dd8484239c18c3103ef61a65e293087 emission_res_59.out -27b80edcae0cb20c30bd40116e2c7370 emission_res_60.out -48781df2b675b45668a5e18fbb633bdf emission_res_61.out -61ab45b747c346298718c64fd5111b1f emission_res_62.out -8ad5e3a2e192bf7ad28fe018d6ed0a9a emission_res_63.out -d3d668c3f7d8e2231b8ab3da61960113 emission_res_64.out -e7b20a7c6a11c4b9a183728e57d71683 emission_res_65.out -f29028c1a600b52c9d2e8498cf953a14 emission_res_66.out -b6334c1158ff20a78b9ae2fd5af22a34 emission_res_67.out -fd02fb39331cc8ddc2ed50b77ec0324c emission_res_68.out -a2d03de2ef12752b0f15e297dc9c9340 emission_res_69.out -46c1009c127b71d4d6a8307ae82d8a00 emission_res_70.out -ade0d992a0febbc4ac7615722705a29f emission_res_71.out -c447df9343c5bbab867a643736635e55 emission_res_72.out -428b187e6a0bdda290527c311aa08113 emission_res_73.out -9ffb130cedb9a5823c7c79dd93b1cf5f emission_res_74.out -9c13ec9547badf606ad4f6d17c985007 emission_res_75.out -a6d66b10e0492e481db6612930fd074e emission_res_76.out -56ccdc3b383d96566e99c3e7eb8d7c2b emission_res_77.out -05d665e36617d1b37125874810c749aa emission_res_78.out -7f7fe112da08441d01497d3a724d0517 emission_res_79.out -5034f7fd2175d1b645741cd76fc84974 emission_res_80.out -d7df21e6450e763d9946231278bdf448 emission_res_81.out -31e3821a26c17525408cb6069d2b1633 emission_res_82.out -0d4d8f768a80b43be12607543159ab37 emission_res_83.out -5d454e2eee752935c8722ba9c79f87ec emission_res_84.out -06e5d9e2c8a55e524774d41f34ea3403 emission_res_85.out -acdeb126c274e61f69ab1ab9d9a89c7e emission_res_86.out -5098ac4a1f606c827b650563007e4cec emission_res_87.out -dcf89316163295f8cf705333cb7ca252 emission_res_88.out -a3ea2e2e94619a961a9d86d63a66e8d3 emission_res_89.out -c1a4662ff3ff24217bd23519be689d8d emission_res_90.out -43c31ba86a80fa91ef2dd6b0089e5a5d emission_res_91.out -e94f9ae65bca4f26f4c385a605251824 emission_res_92.out -beb656d366ea9e2f9fa7f5ced670384a emission_res_93.out -62b4ac7bb86680b8e0dd58b929b7d325 emission_res_94.out -874954196113d726af9db55259424708 emission_res_95.out -08a15ec6fbb99000f058b0ec8a143196 emission_res_96.out -13ce660057c530391b30848960d4c996 emission_res_97.out -be39e38cf053544e0e0a8e99292e4852 emission_res_98.out -02b06e2ed9a05ca2c075dcbd373f65b3 emission_res_99.out +2aae73c05f1ad09576d4bce3bfb05962 deposition.out +9d0298fbc6ad549b896efd32cc201631 emission.out +6dca37fc27dd8c1450b6bb9f8c106804 emission_res_00.out +da461958d5af515278853ac27b7a2a75 emission_res_01.out +4be88bcc8110481ce32a5517b22b31ae emission_res_02.out +765d28415728b6d87e7c30e5c4ec418c emission_res_03.out +120a0374e248a55031d61c0e60736312 emission_res_04.out +e90dbf10f05a42f4d6a98835fa624987 emission_res_05.out +1a077dc6906784913320c30da959827c emission_res_06.out +8e7ea2c8401a772a811224e558a56417 emission_res_07.out +72c62347b570de76a7b3654e24fc421a emission_res_08.out +6296340045d831efe0e03e51a22789cd emission_res_09.out +953621ff47e58444a712447e675babfa emission_res_10.out +4eac776f4e78964df654ff1053ef8aae emission_res_11.out +7ff75df985efb209a916404d5551513b emission_res_12.out +faa9eba97c6bf8f9b4d980e630b176b7 emission_res_13.out +2bc9b916c46b008ffef6f40414e14613 emission_res_14.out +89f46b7a50f329522a1a8bc071d115e3 emission_res_15.out +58b36230e8e6c54a0b2017621117dfac emission_res_16.out +49cab0f00d4e914bf557dc7fb55d0d3f emission_res_17.out +acbcd3c680ff332061e11fad67426bab emission_res_18.out +2acdc4db28179f9844304748c79323e5 emission_res_19.out +908720903f73ff0d85147f3adccedc80 emission_res_20.out +31c35c41408fe45b9307b0907acdccdc emission_res_21.out +6d2129c82184365f1ebef1668996d3ef emission_res_22.out +691fe23437f322f531091c8234e90550 emission_res_23.out +f69a88e1f251607915df0e48e61c48ed emission_res_24.out +a66bfe66477c4e78901e40054d2fc19b emission_res_25.out +37be2931607928336bc7b76c68232dcc emission_res_26.out +a2e10157ed7d6f56e712697ad17a016e emission_res_27.out +bef3a4301a6f1649212cbec70498ef12 emission_res_28.out +c0f1b724510fb3ad1313708c47ce29d4 emission_res_29.out +5012bb9ed8b35a65260e70ee14a114fc emission_res_30.out +5c7cb72a908bdef197ee4963bcc490bc emission_res_31.out +acb827f55dabbfe1924c2223be083b81 emission_res_32.out +b3a5182c233e4fad1d9f9d7344f1cccd emission_res_33.out +f125f6aff029030142a84da6657afcc8 emission_res_34.out +33c2391d804c3fdf0464b4a8a8db5597 emission_res_35.out +04ca7e4bc9c79f994753f1ddcd1c5d68 emission_res_36.out +61cf7e3c88684b7eb2558237e232b8f3 emission_res_37.out +6b879ed4d7ef052a66f10cca6ca28ebd emission_res_38.out +8c6dfa85b0e88e4d081d7324f902e64a emission_res_39.out +a8ff0602bc76532bdfe7d3c0065a3459 emission_res_40.out +9dedcb5ca5016b0499e64e123bd75b12 emission_res_41.out +96a546d6272859ea69e96dbd4fafe758 emission_res_42.out +7145a32ecdb0ddbb24d5387bfbc74e84 emission_res_43.out +61a1cc474e4a42d148dd7d2b301dd7ae emission_res_44.out +02c69ad37d2e645b9b9ffd97ec6282c0 emission_res_45.out +8a9165d8ba1728fd40532afc055fe664 emission_res_46.out +507eccc7f9c18273307a6f9f2cb9afec emission_res_47.out +3dd0a46b362cafba82a4bcf72eecb638 emission_res_48.out +232a7af47803c93b9a824105c33eb9d0 emission_res_49.out +0ea3c746c888e2ac44b727d4ba3bba0a emission_res_50.out +db9698001923539d3ce5f4a6c100cc14 emission_res_51.out +1c5374e16941c19d2d475b30be2681d5 emission_res_52.out +5460d83ed870970bc2f0a99c42a97b3c emission_res_53.out +7eb33c81651e826f1877abc1e9f04c27 emission_res_54.out +9a08cde6b78cbc9265d7b3c47312ecf6 emission_res_55.out +f63172b4345ed64d90e01d71f6cae8aa emission_res_56.out +7f81dc791cb807d28d244b0f8f55569a emission_res_57.out +0912731fe70a79af20c443ad8aa5f142 emission_res_58.out +16e5d979611934f4f794bfbfba9fda37 emission_res_59.out +95496bad307333c3415bc2d375f6a1d0 emission_res_60.out +90d12a6f695b9d9bb5a8fa28540046e0 emission_res_61.out +3988a446e80cc8267e6e8e313b397c9c emission_res_62.out +f8bc38b5a87c957a9d2355dc3dd35c6d emission_res_63.out +d4515d45f27d98a1f5b12649a2c9a24c emission_res_64.out +f2bcd8ce79ea56fa0890a8fc2974571d emission_res_65.out +2098c5f71542b2006c3c82b756a98613 emission_res_66.out +790f86e2f7dd9bb4d65f33d733b20b26 emission_res_67.out +7f56fd139f62e1f3807a9c6e6df0ff8b emission_res_68.out +ced4e4a273a255e61558e2442c8d6f35 emission_res_69.out +1223e911f78366889227b75bfbdb085e emission_res_70.out +d98db4ef1e73f520650f41f9d28d4d72 emission_res_71.out +6e1c747d665884dd1c81bea678009809 emission_res_72.out +adc4ea4c9ca085b6fce909638e897ce3 emission_res_73.out +319b8a8a0bff247e2bbb6885118bd0ae emission_res_74.out +f874d91344c412e4875a4687426ea005 emission_res_75.out +c62cb79e16f1c6e773f04655270559d4 emission_res_76.out +7c2686e76073476b709fe886db0bcff9 emission_res_77.out +16f1b9686ef8db078e00e7877bc3ef32 emission_res_78.out +2fe0c7cbec55a138c033ae969904762d emission_res_79.out +c0b0313ca5d24a691ed17165e3fd967f emission_res_80.out +58c6fb4585405640995605a158084c92 emission_res_81.out +4918b6a1360b7030dd2f8c29600b4317 emission_res_82.out +a253bd73e8060c5412e8ab1454115249 emission_res_83.out +5caaa0b9453721a4f968043776e44cbf emission_res_84.out +a1099b34736061fc702d1015c9b291e2 emission_res_85.out +fdab035606a5bbd7e4d37c664e488d0c emission_res_86.out +8b8e3a6ccffbd852064b99a01a58c05f emission_res_87.out +cada5b9c671948eeff40664f9e4e8525 emission_res_88.out +d1b7f8de7b359c805dd8cbd30f890a26 emission_res_89.out +b650d75af19c9478f1838e3c285df3e2 emission_res_90.out +e3727c9f612b15ddb372eb9b42358103 emission_res_91.out +1524a850e617da333208569d45a2255b emission_res_92.out +e9811ce3216ee7657979ed11facf9e08 emission_res_93.out +a8687bfa7b9edb59682591ace667224c emission_res_94.out +42c57bb83025a5e966e4eeca4083e7b6 emission_res_95.out +f3904d7d0ec7a95d049a8e4b9df1e9ca emission_res_96.out +4bde1b2e484bd45c2683f0f082348067 emission_res_97.out +dbccf9ac0f9e708ccde6c007ad0bf50a emission_res_98.out +516dd19bb296f93916c523ee48d2e69e emission_res_99.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_00.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_01.out @@ -303,22 +303,22 @@ be39e38cf053544e0e0a8e99292e4852 emission_res_98.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_97.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_98.out 321ece2a7759b37a7da621cd7a4eee90 emissiontrue_res_99.out -c42d80619ddea36d7f7fd7bc9ab257c2 gamma_light_curve.out -ee190b2ade0bbeb40a257d10ab7f1a34 gamma_spec.out -2b769145664780d4f90b07f963588536 gammalinelist.out +b892a6a806326450a45e243eaa9aa855 gamma_light_curve.out +88fa732a431441e28f41d05ebaae4ea3 gamma_spec.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -7e3aacd8ee3f3e1a3bd36ff94f4d85fe light_curve.out -789a5fa6f1c64c8b08062c61854f4b47 light_curve_res.out +70a19d16f42ec1963c92427ac7772aea light_curve.out +f51cb73825add4e3e63a793e307b3ec0 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -0d5fb0c7428d958910c037a7658af3b4 packets00_0000.out -b07e99459b2eaae02f5b45a719019248 packets00_0001.out -52c38efc594cb6fd7f96b2722df4197b packets00_0002.out -245600dfb88eeebea106755dcc4b07ad packets00_0003.out -174d35c403e43ae90380d786e591c078 spec.out -a35e02bc19e8aed065425582283e9d52 spec_res.out +5b090e97415e506f9b3b578ef21b2a5d packets00_0000.out +33ee3ef3a12cb7332c87723b1c1622c8 packets00_0001.out +97c322ecf3680bac5e593964f977d55e packets00_0002.out +009e1a7b6dd1ae7aefc78fb1144c842c packets00_0003.out +9eb81a817086a37fcb575ee3d6851bc6 spec.out +41605ded1144ef4802cd6c5915188be5 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -894b712119acaf3ce3ae3a9a7b67c333 job1/estimators_0000.out -3fe5acbfaf7a8d0042f85ec30f98bb32 job1/estimators_0001.out -ee5d305bb32b95e5e93adecca6abe78f job1/estimators_0002.out -c688e2fb47e2f4daee8af193fe26b9a7 job1/estimators_0003.out +1bf0adbdd716356ed24722115e9cac57 job1/estimators_0000.out +195852799a975a65872078097d31af60 job1/estimators_0001.out +7294438b4e29a75ffc68fb307e130d14 job1/estimators_0002.out +d5354f6b7b06fdfd49c8f387bacba760 job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt index 596f4e1e6..ec11ba10f 100644 --- a/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_expansionopac_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ b92a62c73f9262be2a6f6db5294d762d absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -fd6294b0c141377354770cb65fba1ed1 deposition.out -e1430aaaacf6c0c150cf57d0cbe764d8 emission.out +ea9c3d0c813157357e279a24ca5b6db1 deposition.out +e8110f66435450171d8bebb7f8731d69 emission.out f5902ae8e529c0e852df6b3614fd1597 emissiontrue.out -f3658f06dcf3f3cb59f2af794051dd09 gamma_light_curve.out -2b769145664780d4f90b07f963588536 gammalinelist.out +062e559bfaac6f8466027e63f63b4472 gamma_light_curve.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -79ada276fd59c2e1321109afd258fb59 light_curve.out +129f7ea5e0a1f64ab52dc649f1e92b51 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -5fa7e1c5ff3a497bded048dba65ea86b packets00_0000.out -83a9c67696d72ebd6eed3da323030e10 packets00_0001.out -61fa8c163469dade9ced584a19edb6ca packets00_0002.out -36075e4eb01b10e9213f54a6594b01eb packets00_0003.out -ff5a909e77a5ae78b0ff39c51813013d spec.out +768d54f3909c389d6ef1929e2cb7def8 packets00_0000.out +dcee73e9e660d612cdb8fd6778b9e684 packets00_0001.out +76664a1c70dc9b955ee7568ebe385375 packets00_0002.out +9ba62cb2bbabfc05a24f85ea93a5dd22 packets00_0003.out +ea27c88a63bc5ba2234920ea9a9995ee spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -0b45d96ce750f8d1d1f14b6fc47bebee job0/estimators_0000.out -c4cd5a51c5e2e4d3bb802cd9ab1ea77e job0/estimators_0001.out -2826b779993334c54235dea711d48428 job0/estimators_0002.out -9f8cf88d1a42ac2d5bbfdf7c327ba9d0 job0/estimators_0003.out +280a171c04dcfa7944bd6eda876cf299 job0/estimators_0000.out +77e4deac806a9316b8a43646841c9740 job0/estimators_0001.out +b5ad09035b0a9ddf18cccb7707d9f161 job0/estimators_0002.out +1d9f8cb356d0c093ae0ac922083ff965 job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt index 23b277cbf..4cdd0990e 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -6c32a87ac9d257a8b329a5f075efad3a absorption.out -70b683ad818216ec48d48696cbbbd075 absorption_res_00.out -0bbed7a5136fce5dc0489daa1f91bd1a absorption_res_01.out -7caee2243f96868528914ae280f946a0 absorption_res_02.out -50109d004978a600f4c7505cbc95728c absorption_res_03.out -a07108be239e1e2a7fb9d195ff9195f2 absorption_res_04.out -9c2dd19e20a5b65572c52ae70018087f absorption_res_05.out -f56fce649ac88ab5e590120959cba723 absorption_res_06.out -3f3edeefa2c49efc01ab9b858905c432 absorption_res_07.out -950caba1eb18e78c6b13e7559e5db2cf absorption_res_08.out -ae8bebae564422b200e2cf11d870b8ca absorption_res_09.out -a5e3cd330445d0cfa9ac0e4a463c55e1 absorption_res_10.out -6c8e26649544072f926d65a572ecec61 absorption_res_11.out -b99dbe8ccd589e4852e82ce9c074b08d absorption_res_12.out -f613cd0746f614759873f1fd6a525e1b absorption_res_13.out -41c6e8a8803cfa36866269dce65124bd absorption_res_14.out -f438d5343a18339268554c07d6fda55e absorption_res_15.out -ffc910e25fd0f72bf995e79237304851 absorption_res_16.out -9ae441d71d8854f37dbc94412ae76c97 absorption_res_17.out -e13654e23ef8e03fd735eaebebee9b28 absorption_res_18.out -874af4d9534de2321a1e28502489f1bb absorption_res_19.out -dda6dbd01f34ce94771d910a579ebc27 absorption_res_20.out -da4e61e4185fb54fac359d857e16fab0 absorption_res_21.out -bd868d631a29cf16758e20e9954cdd39 absorption_res_22.out -060b2deeb08274cb388bb710da0cb2ef absorption_res_23.out -0e11cae2199adf2358da2898f50770fb absorption_res_24.out -690a61bdc5807288ee186c12cae13850 absorption_res_25.out -689ae04979de85cee481ab64bb458e02 absorption_res_26.out -df02992609bce7b3bb1399065e3224a2 absorption_res_27.out -625e4dd1cf6becb28608e0b915db92a1 absorption_res_28.out -5464adb15639f49ba5599ef86e0b8578 absorption_res_29.out -473523c121ba4ffe9a4ee28c8a55977f absorption_res_30.out -1aca6c2e78404daa0848f699951bd77f absorption_res_31.out -365a42dc47224ff1641d890027d1cc3e absorption_res_32.out -fad44e570ed630367b2383e08c9e5b17 absorption_res_33.out -f627156ef5c56add4adc6041cb03903f absorption_res_34.out -79b50be9acff24b3ff7ec311eff953af absorption_res_35.out -b10e49910831962855e51f8efef8e0d1 absorption_res_36.out -33254fb8934eb66467fc89a27d128869 absorption_res_37.out -99bc60454b97ca3bee46b990d1e4d8c2 absorption_res_38.out -20329d703527026ec4a216d94f42f4be absorption_res_39.out -4b59cc44752138ce0b4be0b86ba37e2e absorption_res_40.out -ea6890f6076cfb17483f041b72776854 absorption_res_41.out -d25343c6d570a30df5070a40f3b56aab absorption_res_42.out -3a9d4209a067f2425b7e0c5e4780ae94 absorption_res_43.out -d31fdfb783127fc80eef3b751782a7f9 absorption_res_44.out -452b4f858430a96a3d84c49ea75bb9c2 absorption_res_45.out -a8f3ba15a7343663cb26d8a9132451f1 absorption_res_46.out -21be5c92e235e0755cf0fb36a0e68e16 absorption_res_47.out -77c6fd1b25694079d8b2fb91e4740709 absorption_res_48.out -a1986dd3cc131f88c289c832a0e729de absorption_res_49.out -766d614a8c44141a989f321c63596bd0 absorption_res_50.out -ca96a5c31bdf88a1a08ed84f13af2141 absorption_res_51.out -3216945730f187e9c83a964d04432241 absorption_res_52.out -008574e3a4a33362c6d709cc77a910d5 absorption_res_53.out -ea6221fe62552038e7dfd65a65aa69bc absorption_res_54.out -af56a6bcabdd0e7d31fd66a2c9c98c15 absorption_res_55.out -7845196ee00bdbe63ff85ff5bef65546 absorption_res_56.out -5e35255688ead8c4a81df1ac8110b61e absorption_res_57.out -e37de73840be356252a5c99f80b86a6b absorption_res_58.out -db827bd1935a7b48df4b727990ea90bd absorption_res_59.out -dc03931c924ef2ad3b7cc3128fdbc7da absorption_res_60.out -0d678bf1bd55213cd1d7d83de1b7f7c6 absorption_res_61.out -f758d34b14c36133801dd1f7fb6ac20e absorption_res_62.out -86ab5b5261a6519bb818a2716235631f absorption_res_63.out -3de1ed7603432fe860fbbd6898bbf74e absorption_res_64.out -2c74f885495a3a92ccafc748deaf01a0 absorption_res_65.out -38e4d59607605ea9afa5918d8297b87f absorption_res_66.out -08ac010423013a93d20ba13ef9f29360 absorption_res_67.out -e8e2ea73801314156514e3a855fa80fb absorption_res_68.out -2a99c37d1c0ceeb2383a96124fe48f01 absorption_res_69.out -06bbbe03922f984f8d726b6a8d80a354 absorption_res_70.out -2d0bc37970502b772811d289e6d03c5f absorption_res_71.out -05b3daac4f00bc84bfd4df025439e946 absorption_res_72.out -f70ad21e26267431b3a356107b14b0c9 absorption_res_73.out -49a57176915cc8ef99a9ddd7d554042c absorption_res_74.out -9e6fe2a725e05334641449df849fe57e absorption_res_75.out -83f11011a91434ddfc9ef42a57dc69b1 absorption_res_76.out -4be96d566e2a75932ac58d7cb8c2300a absorption_res_77.out -b6f2b1fb11b7d58c9943174c9d5de65b absorption_res_78.out -d9fb5ef6729689337d97613a6c7be9c5 absorption_res_79.out -129d7a3f336612a2cb72a117cb7fef69 absorption_res_80.out -314081e8a30fc87ea63e47b7188baff3 absorption_res_81.out -fd77abf1d1ae86df84f0efd29e18fd9f absorption_res_82.out -29b47e6926c73fa2e446d34fdfd36ceb absorption_res_83.out -7a450de8223cb82b3e6885d824cc7cc5 absorption_res_84.out -c7a8e65a818c852cc33b5986992f7491 absorption_res_85.out -d2069c00a3aa1250e24bfee5f3b04db2 absorption_res_86.out -498e5593f4ee5a9755c51b8004721435 absorption_res_87.out -9fb0bc71aac8756d463f1af7277b522c absorption_res_88.out -4bc3c1eb412c6977c728b03b315e06c8 absorption_res_89.out -64e5bc9131ee622e34434adbcec7f94e absorption_res_90.out -c3ab5f6299f06f94c23b91cd8cf60396 absorption_res_91.out -0f4c8858f821464b088ad2df750a8ea6 absorption_res_92.out -e8b48739bb8e87827646aef599bfbfa4 absorption_res_93.out -7c8ac6877eb808e1dbe1bebba2e32211 absorption_res_94.out -37da395cda8c34c9c7742d508f56e026 absorption_res_95.out -da57e71ad7436b36d30ff741e41a87fa absorption_res_96.out -d17be52ec55a01fd542f0d2275afcc3b absorption_res_97.out -6f6402a01ca879f11e76ba9574630dec absorption_res_98.out -1330bb475a0964fd04a664ba765e56d6 absorption_res_99.out +770cd81a98187cb8203f0e4b8851661a absorption.out +949ca5247707c08dce31be82c53dcde6 absorption_res_00.out +ea5f1fc5be108736bbf7ec754252f81b absorption_res_01.out +dfef8f7121bdb5e948cfcaf270ee14f7 absorption_res_02.out +29d753f7abda3879c7a61415e1b50e7b absorption_res_03.out +c716bfdcc23266d021f9226419845e44 absorption_res_04.out +684b28553a7d691b6d7d87065a123ab3 absorption_res_05.out +6eb05e39d5ab9ee9082e04f986545926 absorption_res_06.out +9208d1a3024ea8b7791b44037267e235 absorption_res_07.out +f6342862188c6e40c5cb62a48887e3e2 absorption_res_08.out +bc75654d3ef8ed627a4a166ca85a6f46 absorption_res_09.out +c6d215fcb726508be8a0d22e29bcf6be absorption_res_10.out +790f2b489219196c7d0e7b4eb6d08702 absorption_res_11.out +b094dd31af1b2acde7d2af40e61974db absorption_res_12.out +4a39640a3ce85a7b236f8f0d3b16f446 absorption_res_13.out +b6150844b3bca8049f94bdc9fe6d5c54 absorption_res_14.out +595806f27faf8b5c7aba82833e3b244c absorption_res_15.out +0ed106bb7a29899588594e80f117a8b6 absorption_res_16.out +b4761b18cd5678b1237ba3be38a7c9a0 absorption_res_17.out +2a543162ec3c1f3a37da639e4834de57 absorption_res_18.out +b28551ae4cd5f861013c0155e98ed415 absorption_res_19.out +973730340c83c3332b89ae95c586ac7c absorption_res_20.out +9f6a3da35057ef8ba59c54a27110f9d0 absorption_res_21.out +ebb507eb4fac604ab3162d065fab3243 absorption_res_22.out +d9c9e41dbffd921357104989e34a8df8 absorption_res_23.out +3ba1899e6184a87d4076a78d42bbcd8b absorption_res_24.out +61384d756fd61fce733e1c0198fedb37 absorption_res_25.out +16f469ae13fc2a3bd1cf169c3fe6f7eb absorption_res_26.out +0524ef5dd7d73310dea7d3e7d28ca488 absorption_res_27.out +552fd02ff2d45cda81b2838b6fbae126 absorption_res_28.out +4a7b18edb8c549d798b1d48182400f7b absorption_res_29.out +f859cd7624c8154337e9cec2c0443eb2 absorption_res_30.out +33c50865534515a70ded00c946656bdf absorption_res_31.out +fe3cd452db94d0413ae1db8a96094709 absorption_res_32.out +f3da947a87e1e16e4cfb2af49271f4ab absorption_res_33.out +59c9372ba2845dd012353682c0c30aaa absorption_res_34.out +fcd680d29d3039efdc23015f9ba4185a absorption_res_35.out +f5361d30bca6647a51f72fcc222e79da absorption_res_36.out +f1bcc5729dd9a4321859a9dd39fafa56 absorption_res_37.out +02f81eb69c9253b325f84f03f3ac9ff5 absorption_res_38.out +551fa43a2967f08a4404f78a21235243 absorption_res_39.out +3c18a061ce6e7d52f67ae7c3d961e4cd absorption_res_40.out +888487f498a34cbeb8991e1edd7b691f absorption_res_41.out +77a4c90d37b7977bfe345c8759d5467b absorption_res_42.out +9c8d7e84d85eef857d99d7c5c089c3a7 absorption_res_43.out +fea7bde996c3949111e342b559c239bd absorption_res_44.out +f781c2a8c04d97e4b70aaa6879c804a5 absorption_res_45.out +b159d7f638bae31d6e9803e143105225 absorption_res_46.out +3f1076669e516a4a422fe4652e0256af absorption_res_47.out +0bc8671f576d78c721b88897843fab05 absorption_res_48.out +111ba65b532b7687a48bebd25ead116a absorption_res_49.out +03c1b36b16386e7b117e5db05c7f5d52 absorption_res_50.out +fd97cd56144daccbd1d5710d5a057452 absorption_res_51.out +3b5fafb6f9806918075f7406bf327f55 absorption_res_52.out +d3f5546bf808ee3fca9b7e2eb900a2ca absorption_res_53.out +ff9224bf31632f11aefcd12dd4c2457d absorption_res_54.out +102700a4d7d3ed2e166f0eae6a3e3a53 absorption_res_55.out +5174b98a26c14345eced794b0a7a560e absorption_res_56.out +44806994f419af5402a44999295b99fb absorption_res_57.out +9f510c3f9ac16b0f2b5714a90fa92b5c absorption_res_58.out +1f08c98c1bcf9779812b3b67569b7922 absorption_res_59.out +dc9fdf860f33dddf38487052c0a22b26 absorption_res_60.out +4122bf1ff81d2e541a851624bedad4b7 absorption_res_61.out +93183b367e340f3a2e0cf35d99264c55 absorption_res_62.out +41f4f848a526578fb0f29b65b7f2ddc0 absorption_res_63.out +a5395f89858f592d8469f6c49c4e13bf absorption_res_64.out +39f85fc8f12ff6be48e4996d3df76154 absorption_res_65.out +d1a6fc159126f186ffa3cf577799a9b7 absorption_res_66.out +1b7e8d7a07d899d96c09862811cc1229 absorption_res_67.out +772ab73caa4266480a8cda5f0118ae65 absorption_res_68.out +8dc2f62093e749df1ef1ee5baeafa239 absorption_res_69.out +919ac8de8df8de3265faee39ff258211 absorption_res_70.out +7a77821553458c3e6d3f71a66389a997 absorption_res_71.out +847b20ec5c1d222e24584c4f4a060ef9 absorption_res_72.out +d826800b674848066b3b3f604629e707 absorption_res_73.out +9b63ac2332cefa1972d36d00785d954e absorption_res_74.out +770597e3330f81985d692531d9446fc3 absorption_res_75.out +754bc6800b54fa3fec3607fd847f6c03 absorption_res_76.out +5d779a1d2e0945dd77e5fa0aa918dac5 absorption_res_77.out +62a8850b9ade78f3a0e5abacec1994cc absorption_res_78.out +b9db5bdc90ebb90fe17e877d6469323f absorption_res_79.out +478b58028766ac5e6216269cb04bb852 absorption_res_80.out +912430eb73f242f8833f18febb1a8c8a absorption_res_81.out +3c00fdfab238f2c890da63c962b1729d absorption_res_82.out +ccb7a99f8de14515895bfd0b1837a6c7 absorption_res_83.out +775d5b615486cb2ebd76f8dc2c86941a absorption_res_84.out +37e5797bc572685add133ec3c19f40c9 absorption_res_85.out +6fef45ca444a5f735e610b2c25e0a4fd absorption_res_86.out +5f14f7f842ade6d32e625e96bcb8f164 absorption_res_87.out +02035b7948d2fc9058f08a0af155460f absorption_res_88.out +7c3ed6fbab2685cbd84f18d34e861d3e absorption_res_89.out +3a4f984d1dfe751188f756f0945ae8a9 absorption_res_90.out +3cfcba1f01a15576ce6bbee3ab8584d3 absorption_res_91.out +3bbe777a5122ca65f6f3366f5f50d9a9 absorption_res_92.out +926fd78a44f571d50861be8d85115573 absorption_res_93.out +f72536d49ea9870e9fcfcb34e5697ac9 absorption_res_94.out +c6c458bae3b5d66ad4bef639ae09204d absorption_res_95.out +b80ddc483845fd6b5fa00519fb3f7f57 absorption_res_96.out +fa89be05d23cfbf17032dad233b421ad absorption_res_97.out +76a536b4afa82e632fc50f495f6da09c absorption_res_98.out +5dc483748c236e2a40846e998546a37e absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -6097e7d015c08926d1a094899b644c90 deposition.out -a7334ce70ab45ad1bdc10afafe1c1ae4 emission.out -b9b02e1e727a758a78fd67b0f698de51 emission_res_00.out -7ca10b168860e2e62458a4177a7b5eb3 emission_res_01.out -958025f44e161528c21572783ceac794 emission_res_02.out -f0921f8ceddd36f249d87735c6ef4c2f emission_res_03.out -05156666fd7165d611021d33e260faf0 emission_res_04.out -e432511d73886977441b9b8df3d04d1a emission_res_05.out -2a827092eb3a7dc9dbba9dab9c7401bc emission_res_06.out -1e2ef4064a4442eace002e4a3d0d6be4 emission_res_07.out -4fef435891fe1738ab869e1321850460 emission_res_08.out -373fb583794afedfb1c8409f33f95a7f emission_res_09.out -e880d6db3604fd69f9abd94a730e1c81 emission_res_10.out -177ec9f87b5847f6bd49aa55fb4b2246 emission_res_11.out -f4cc2b3f7fe58aaf8aca17c120085649 emission_res_12.out -ccadd22de9453a677ae0b52ef0d22691 emission_res_13.out -a1f5d1e1ca790fcb459f37351ff03dcc emission_res_14.out -a1ba68e7307fe9aa0f18e016da6be34c emission_res_15.out -332aad97aa731d4baa663071f680dfd0 emission_res_16.out -0d515b16994281e03651c188b4f0eb08 emission_res_17.out -526596aaa44380bcea40a02db26debec emission_res_18.out -cbabe1d7d6c6377ce98b571e9072b993 emission_res_19.out -492b504a96cb744bd69c15187bb14591 emission_res_20.out -c09d00a717116fb3bacdf173acc8b45e emission_res_21.out -9faa6574412589e811e38dcd55e30aa2 emission_res_22.out -6fa3b29026b9a2da4731cd9a7c79c52e emission_res_23.out -2dcd588a98b971c44a146fe1285568f1 emission_res_24.out -27838ad43072b17ceea83a536e841109 emission_res_25.out -a359f64f9c7c858a25b78b6647660165 emission_res_26.out -cae2974849997afb1c8b3da1295c5933 emission_res_27.out -50a50d51249f89977a6859fd330ce63f emission_res_28.out -d10c49499a5b3ca538213cbba111b6c0 emission_res_29.out -5d24681b03786f070f5b5bf13b37103c emission_res_30.out -01d6e0ce7ca1c3850a30d1492d51c206 emission_res_31.out -df0ca8681525f259c45e5f612ff0fc61 emission_res_32.out -ff2dec034b91013add5495c0711384e3 emission_res_33.out -d5dd0c3239a8ad28ac204f17735f23f2 emission_res_34.out -6277465bc6681ddcfd25e8d820e808a2 emission_res_35.out -2f7fa54e96c6163acbb0c9fbbb0957c9 emission_res_36.out -4f6c595aab8288b66fb422543cb5fdef emission_res_37.out -0d3d0f4398ec4fa0841dc856d9cb4ad6 emission_res_38.out -0573da428731c5b2a8dfbbc9c8d65e2a emission_res_39.out -6c619321befa1cf21ffec40b3a75aff2 emission_res_40.out -5f7f79b3735f95484e3dd7a9283d26c5 emission_res_41.out -e5c2d49e4575a2dbdc8a09613482aa62 emission_res_42.out -55101df593e9d0bbd37c6a3ba27c24fc emission_res_43.out -9e298f07ab1ab38b61178755781b83a7 emission_res_44.out -cc682727ea89bfe8158166456f4180ed emission_res_45.out -988d205ad93ee21af868d1c566e53ce0 emission_res_46.out -533c041322b68cb3293bdf9e5637a28e emission_res_47.out -d33a8356fe7ac01b466987bbb9400bfb emission_res_48.out -305422fa22f65b0c3c95cb757c0948fe emission_res_49.out -b07467009410025e80f60f7f27599a58 emission_res_50.out -90b5dfe73aeea7c9ec0c5f63ecbd7cf1 emission_res_51.out -dabf2e2ad08c2c0f390bafde45f79060 emission_res_52.out -fa99dd84a4706b7bf0dee5838a2caa97 emission_res_53.out -1c104a1594f2a2a894645c27ec69030a emission_res_54.out -de2f3212b42b5b5b5a2962d71a02067e emission_res_55.out -b5e8c536f39ea33788d448e5bcaa72cf emission_res_56.out -53e37a611fd26c63764bddf2bd86edce emission_res_57.out -412d7069a8f7841a755f4bc68995d4b4 emission_res_58.out -788e05d7574fee2f581f344cfa9a89d3 emission_res_59.out -5848e952637bd425d06c5acc95cc41d9 emission_res_60.out -b903bd4c55e24f21a482357e4568b76a emission_res_61.out -735b7197fa398f8f31c52a42085baf6c emission_res_62.out -d60f52e1f718ac5e61e0a8385d51345c emission_res_63.out -31f8b577b2c6253c09edf51e556f2bfe emission_res_64.out -b38f5c9990f0de883a0dd93f9292ccc8 emission_res_65.out -bb15c3737a782c790c24074f1fa17f5d emission_res_66.out -0517e104a27fac11944dda2e381f2344 emission_res_67.out -6580631e160014a439c0b967efaed13e emission_res_68.out -9bc0f838a9c7153b5b3722ff0c655cea emission_res_69.out -9706c539e1e23c9315e898963e508e4d emission_res_70.out -6f0528171582b5765745d3860099a6c5 emission_res_71.out -14787890122c2b825bf85d638ac66c7c emission_res_72.out -34b46bd5f179f055b244e80d87b8ec47 emission_res_73.out -97432a8f498751c5c2df82c3cc1d5f1c emission_res_74.out -81ad122e4c40c517bbdff33d47523d00 emission_res_75.out -9ef1218de8eae4ae3ea54d8a00a06342 emission_res_76.out -c839c24c6e0c6d89c7dd6cae71ca6e85 emission_res_77.out -f7df1d3481c0f99ef315a9a75a728b9a emission_res_78.out -581f1a649dbb1ddc92f9023ffaf61457 emission_res_79.out -f8f1c4113ed1b3417351376787b4938c emission_res_80.out -e38cd23a2f215d6ce842a10b17d4f9f1 emission_res_81.out -3f4aa6ab21aed68f01f2a088e89c3fa8 emission_res_82.out -ed317345b0017feb761c9f30f232b781 emission_res_83.out -b999c8ad353d301508c6b814896f30de emission_res_84.out -16f5e166be4ee039365911bcea1c71d3 emission_res_85.out -60b7c8216710106c5e1773c364a58b2b emission_res_86.out -99ff241b7ff0875237c368b542be13d7 emission_res_87.out -da19a00b82858e67dd6da7a79e4ab667 emission_res_88.out -f2307cc270950eac3c0c6a51a6dd3c27 emission_res_89.out -248c40a52401451051facc8c1ad10d7b emission_res_90.out -91622fe8062a1c997e22ad599dee3c56 emission_res_91.out -d1d58dfec337d9512eb60925e1ea0cc4 emission_res_92.out -9342a1e16d17192307cbc99f50815a18 emission_res_93.out -4d0b5748af5a6517bc6d4c44d2d6e627 emission_res_94.out -136f2ca09e42a34722cb53750fb404f7 emission_res_95.out -f1775e028e2ce397b9e989b04419cd84 emission_res_96.out -aca84ede94af461133c95e4058117296 emission_res_97.out -b5165b7c3ae55222bd3b66cbdc0e2d66 emission_res_98.out -02793f101e8193b24e43e39a72586caf emission_res_99.out -2a5c21fd64fbf9a673d6dda04f1d5927 emissiontrue.out -55fdc2957d0fcc9060193ff05bef8c27 emissiontrue_res_00.out -0b6ac0b22afc10031d6882acb1002bda emissiontrue_res_01.out -a5af04b9eab7d6471e100a86de9f1141 emissiontrue_res_02.out -449374c739d7b4d654e01f3bab667cd7 emissiontrue_res_03.out -6b2769a0530b8d0a953159a817bc910d emissiontrue_res_04.out -ea8dd99a30e3f65b027b898a53ce4c96 emissiontrue_res_05.out -ccf73cda4fdd91cb2dfea38ff7f3917b emissiontrue_res_06.out -9f4d9179de3732b1660eda2542396ea8 emissiontrue_res_07.out -d5a0f2dadf91646e4f48a2876b9a488e emissiontrue_res_08.out -fcfbad2c7c877d29616e534592f0676a emissiontrue_res_09.out -9711c5b9a53a16e55ab8bcb4409d3ae6 emissiontrue_res_10.out -c3b09695a6ec66d62e038e0700a82154 emissiontrue_res_11.out -d3f9c3aece038556fda1568e867c30b5 emissiontrue_res_12.out -ccc0c551b3a294951fa0ad6c4968a1c1 emissiontrue_res_13.out -2a8c6fc70e760faf542a8076292de3c6 emissiontrue_res_14.out -10e7cdf789718dc102b1da488a6b13ea emissiontrue_res_15.out -c456ebb1ad6592fdbe0a59c397b1d616 emissiontrue_res_16.out -91dde63ef5b8297ca7f24a2c6625f257 emissiontrue_res_17.out -92fac447e6d1ff1627ba6d7c38cdd1c8 emissiontrue_res_18.out -97565384210340a388c2ea32756a3cc6 emissiontrue_res_19.out -ad12f8f4a541013f9a7efccbf694a263 emissiontrue_res_20.out -a2fc25b8bfa0598de3d6436dda7814e2 emissiontrue_res_21.out -8510b93cd6bd50637cf2c856011b54f8 emissiontrue_res_22.out -24e38d6dd36271227d8e54cc8c1fc9f9 emissiontrue_res_23.out -ec479601245af63cd65a6efdea7c28b0 emissiontrue_res_24.out -b59ac0b069a624c9ae09f7f402e6c1cc emissiontrue_res_25.out -335f286db0c5c6cfcae05578c6d39908 emissiontrue_res_26.out -e7bb5698d43a9eb6d75ba4ccf2848894 emissiontrue_res_27.out -c58acdacf25881b82bd8348e5fe20d78 emissiontrue_res_28.out -24ee98f3ed46b872a270cd207e836168 emissiontrue_res_29.out -fcaa3e6495a173ee1d702b525072bb60 emissiontrue_res_30.out -8f5cde52d67c3bcf040862336a1c379f emissiontrue_res_31.out -6e9bf7ebd7b7435c09d7e62d4699ed0e emissiontrue_res_32.out -fdb0a9117a4ba7af42460edf34fe862b emissiontrue_res_33.out -f02497f21b353430fabdeafe2d698d95 emissiontrue_res_34.out -4bfc17fba878708d345647366914c324 emissiontrue_res_35.out -974947a3c03065d37f8fc35a4d7c287d emissiontrue_res_36.out -3659f9a17d104adb9046a9bcdd900cce emissiontrue_res_37.out -729b5ad290d8815775f17c9fbf90298d emissiontrue_res_38.out -2a5dec3fceb8457b009efbf2dabba2bc emissiontrue_res_39.out -fc076f1bdbd19c6aa7ec38a2abcac2cb emissiontrue_res_40.out -581b9ace4930541f55257766b38cd6a0 emissiontrue_res_41.out -8adf7019579d73b94e95cd017ff36a7a emissiontrue_res_42.out -63e5f37d7b0ed90584b5e2110339d4c6 emissiontrue_res_43.out -54d8e565e2b323e604756caff3f5d924 emissiontrue_res_44.out -1c5a83055f70d350497d73d7d64baf93 emissiontrue_res_45.out -cb1daa5da4f593ab648d0f6359bbe18e emissiontrue_res_46.out -7f263da3579ad7f3cdc17a6115f343e0 emissiontrue_res_47.out -30787f966f78be5d48f08739acd9ac26 emissiontrue_res_48.out -36296b1061a47ba95835aca94fd068df emissiontrue_res_49.out -455a0eb4d77993ac7582ec907b4fa63f emissiontrue_res_50.out -337aa247804a2c9bf157a57e56bcda22 emissiontrue_res_51.out -af69b920454520d7d547c9325d84a929 emissiontrue_res_52.out -22a958110f2b05d9d8ce646f62d5e189 emissiontrue_res_53.out -62cb84ac4162beba12bc6e7b36e1542d emissiontrue_res_54.out -4c9ee1054f487df0f52f486eae767b13 emissiontrue_res_55.out -4d7bb6e51f337351a35f3724dcd224c3 emissiontrue_res_56.out -4fb48f823148552ff7b2523018a36c4a emissiontrue_res_57.out -45e16aac53c604c27ce376581b8ca77a emissiontrue_res_58.out -666f211e9203d4e4d79f367ac6197f12 emissiontrue_res_59.out -6612e5f8758a985940d3a533937d526f emissiontrue_res_60.out -e8c444c9de9101b22f3d2f630bb967bc emissiontrue_res_61.out -7e4f857047d54abce9e6354aa612cc36 emissiontrue_res_62.out -e00c5ccf8bbf375b1cdd14f95722ab8a emissiontrue_res_63.out -837e2480b5d343c6741279b39b2e7eee emissiontrue_res_64.out -f6c6b2fd6cfe5903a84e5bef318d2d1a emissiontrue_res_65.out -1a001e0369629a1566e3f5389d674565 emissiontrue_res_66.out -16dd8f0efe0871c7ba2323018f47fd0f emissiontrue_res_67.out -e7a52b1e0a8dd0950f616e1c0160de38 emissiontrue_res_68.out -ef7d9f37d999f06f5f9fec1b1eaf175f emissiontrue_res_69.out -50a464d8ebe40956b0ddd2573d28dd0e emissiontrue_res_70.out -3972cd9256c1d59b1eb853331c8f59d2 emissiontrue_res_71.out -fc3eccab798ea4df14f18dbda1a9b466 emissiontrue_res_72.out -21865746b4d76628f9260e250b4a4056 emissiontrue_res_73.out -58690a95e505189b77c3cef366458475 emissiontrue_res_74.out -b564cdb95ad2b2b57897891e94b54d51 emissiontrue_res_75.out -0599468a2f168e4439f13bfe85820b55 emissiontrue_res_76.out -922ff67fe134432e6be19ca391d95a7f emissiontrue_res_77.out -b899dbf7321093d50870ab6e2d29661c emissiontrue_res_78.out -23cd8280a24394f7523f0da2bb2299aa emissiontrue_res_79.out -574f833e9888172dcd2d13d9b27c22d9 emissiontrue_res_80.out -b776945cd632ca451b10271bcfb25f4e emissiontrue_res_81.out -4959130b18d6dbd591cbe9ecf297865f emissiontrue_res_82.out -fddd2d5aa52c816f6d4c86bfe91c6980 emissiontrue_res_83.out -1987eb5161fae664d9f9c4623aec6d52 emissiontrue_res_84.out -acc84a710dcfdfecb65768af6719e59f emissiontrue_res_85.out -80fc2385fa329233f2ce88aadb823529 emissiontrue_res_86.out -29954468cf512e7e4726d6997f8e0edb emissiontrue_res_87.out -22bd9008c989dec1b3fbbaeb5585df2d emissiontrue_res_88.out -9ac2ce7848b261465e67ad67ad9db108 emissiontrue_res_89.out -9ec011415cbbf0f912a91379903bd683 emissiontrue_res_90.out -af668a24d5b573a8ddea1224f5f042e4 emissiontrue_res_91.out -a68798b17fcfb7ddbcfe838b0adf8944 emissiontrue_res_92.out -5ab69bf64dbfe323be4cace58642182c emissiontrue_res_93.out -d0f439c6a296804d0a3dc1fecca7f0dc emissiontrue_res_94.out -687493730698aefa27b36721c2c13cac emissiontrue_res_95.out -add3f2b9e1897092dfa6a9cc2ae60e13 emissiontrue_res_96.out -6ad55ad7c6b8c10aa171bbdcfbe557c0 emissiontrue_res_97.out -c5469fb7ebe9a487003478f39d9e4f7d emissiontrue_res_98.out -da76c4a991cdef77d7a8fe291cae633b emissiontrue_res_99.out -19ff935ead37f47f4637d09c4bbdf94a gamma_light_curve.out -0ec8518b09891bdd5ae92701250e926f gamma_spec.out -2b769145664780d4f90b07f963588536 gammalinelist.out +089947ab1cad24b287b41370dba9110b deposition.out +ef71f088e5d39c0a109cc5d759880026 emission.out +586e13c8a0cfc2483808bd59a3198cb8 emission_res_00.out +5e9ee51d6c52b16a642987e571d43ef5 emission_res_01.out +d82a75fca1d4029e424d2464feda0c92 emission_res_02.out +40a93b522b2bab2572a453493a835a1c emission_res_03.out +e34652987bfd37f6207d0209dfd4c31d emission_res_04.out +0f23dc3c86f34e1a2c520ba7d8a36a57 emission_res_05.out +0f11dac3669627a959f55ed5dfdda851 emission_res_06.out +7557e9738eaa448553ae108792c17443 emission_res_07.out +f4bef0b483f699806d0c2f1bd584ac81 emission_res_08.out +ba56be2ad8135b798a1e3e62372ece12 emission_res_09.out +4430ae2f54fb3d718f98c2f394d30775 emission_res_10.out +a0cba58dcac852552587f0add95c7f7a emission_res_11.out +e7f8815d7c08ec0722bb59bba37e7b71 emission_res_12.out +dd95daa37e5f8c6d8ecf76a8fa9a5a49 emission_res_13.out +54a7a0cc48387ceddfa392a902285990 emission_res_14.out +11a0d8987ccccfa6d5830d0b28d5cd62 emission_res_15.out +8b558a4507e3d234122edca48c0e5a34 emission_res_16.out +821b62f4fd7c86e74b0ca92e4f85d634 emission_res_17.out +fa9369f1879e39ff103a4bbf0858fb8a emission_res_18.out +6cb32755780eae2e41c6cfaf57643476 emission_res_19.out +e4b7fd3d4d19a8af9fd7da401e4ea60c emission_res_20.out +4d2c082629a5df0b166fb35bb09893c7 emission_res_21.out +824031ec3d910589e7f7e0c51ce3dbcf emission_res_22.out +9a227f13a316ce80e11a43f9a99aadb4 emission_res_23.out +c0eaeb00492e2fa83512119e832259e1 emission_res_24.out +bab84b55b2634d9abe1bd46ca8d28958 emission_res_25.out +75e089fe4cb3418f7910196f9a448296 emission_res_26.out +707602a3f32de4a5607e375801fffded emission_res_27.out +67a9fb2a421d4213d572f858398b4432 emission_res_28.out +00a0f6a7ae2642af1f524545b3b7d3e1 emission_res_29.out +c78e6b2dc0dde9942569f54c9a19f762 emission_res_30.out +d3e99f472820ae9c8f0e52a824f52c85 emission_res_31.out +e02076fa82c93cbfe0da400e15bb9302 emission_res_32.out +8ace3610f4c85ec1c1ff3528b71785cc emission_res_33.out +08a6f6debc2db7fdad514077736cfaaf emission_res_34.out +e72cbb6c15109fd40865e04f3636357f emission_res_35.out +fecd7fb8f9ea7baf0a97ddfba16e7ca8 emission_res_36.out +b0c79fb85c98ca113bb60013cba194fd emission_res_37.out +89f36f61b3f49d385501d8450b99dae4 emission_res_38.out +1e8fad6d63e6f2b85ea018f39c334b8f emission_res_39.out +b38b08a041236dacd1708170380436e6 emission_res_40.out +3cfe94270b2c683215692f3abb320f7e emission_res_41.out +468df0e91b4466d355c83d3fe7638aa0 emission_res_42.out +db51a7ee308b7ff5d6b8a6abbf8627d1 emission_res_43.out +c0176ca05c8310e96f37e0e90849197a emission_res_44.out +b309dc07d3d3f9b03f2e0993d0885b42 emission_res_45.out +73dc9f974b66b142230a8f3b73ca5d4c emission_res_46.out +ad1ea2552e4ec394a0925b6374d4ecca emission_res_47.out +cba9d7f8518b9a80ec2ebd639fe24ec3 emission_res_48.out +6e5e34757710deb3aa18738863b1af13 emission_res_49.out +0b4616da8b29e7fb0c1c5fa80d137c44 emission_res_50.out +8d4c9bb69986b167c11d11d336a7bdca emission_res_51.out +92fc58c24f2543f45a0a83f902e21dbe emission_res_52.out +b9f6684692f6c0d631b88c5892a88e7e emission_res_53.out +2daf8bcdf7c03c08c00dfee8da543993 emission_res_54.out +b090b7186345c1e6347eb7469d4fafdb emission_res_55.out +537f205aac7fc4ff03cd8b31b323db14 emission_res_56.out +38703c7e70361281d527e6aab096bb31 emission_res_57.out +437a0927e89736c5ae8421633af03c7f emission_res_58.out +e266d9e15064912562f2b0d347d91cc3 emission_res_59.out +e505f0af152b2e2cdf318b98f977a49c emission_res_60.out +a72b5155ad1347a5cc9b822a9fa8f2d0 emission_res_61.out +b95846ea7a540223b0cec90479c7fc34 emission_res_62.out +6929efbd67b80db080327b045c6e11fc emission_res_63.out +b5a5c85d8389a8efb61d4113b24ade84 emission_res_64.out +c9c486aabd8b9d440df3428536df7c31 emission_res_65.out +0095f403d14bacc946a9ca0c83137e8e emission_res_66.out +321047b198dafbc2e5307a754a9e635a emission_res_67.out +cfc1de8bdf7e7a7c827240d2942e8d6a emission_res_68.out +e5f89b307dfcc9ebfca61b7b1eead3b3 emission_res_69.out +500b76fd1a89fb3681cd401b9c51d576 emission_res_70.out +c9f5afa099c4349935a3da0ad9578968 emission_res_71.out +a2b35abb4214e894a6ea000cda4307f5 emission_res_72.out +c39f4c5368ae337cba45c58b34afab46 emission_res_73.out +e509862b6c5d2b8f292ac5d7c1bdcf4f emission_res_74.out +5defb95b560a4954c34d7f644fc9770c emission_res_75.out +061d69ea80bdc5f30e23acfe8dfa6487 emission_res_76.out +664a7ff7ce2f9c89e0bf81d6ed356778 emission_res_77.out +b80c79144fd24b88e6037a79c8b97856 emission_res_78.out +d744c311368d1c4c9225d299be5fcb2c emission_res_79.out +cebc3c8d3e9b6c1510976cd710635fdd emission_res_80.out +c81bc1e22ae98433db8df876b958441e emission_res_81.out +703727201ff3763125be2f8937fddb4e emission_res_82.out +545418f2ea8b83be0d1152840c88992c emission_res_83.out +0b1ce17e4f20f87ba750f3c4d7852287 emission_res_84.out +4c218bc1e57c570aa74b0d725bb875dc emission_res_85.out +73a86ec75bb4741f2c80cd12d7c7ece2 emission_res_86.out +c0454cb0b0bfe2e0b82505545526dc81 emission_res_87.out +12d72a65cdaafa365ce538d4da3eff8f emission_res_88.out +7cd044a63092ea4f6032c6f9b0013dde emission_res_89.out +73de5f706889fce2ae3f554694ca3958 emission_res_90.out +0d88ffd50bd3785790d3285f45281943 emission_res_91.out +c0b173c9ab5d1f348d82c3cbf7bb113b emission_res_92.out +656b312851de5802933f4329bbc18180 emission_res_93.out +32d8334fc206d6ed7dbf26a869eb4700 emission_res_94.out +c6cc7c96f95bf24eacf896c4fd263e4a emission_res_95.out +2526c83be672635422075d8bdc292b43 emission_res_96.out +57e2db086dd3def2ed0bdc848429e71b emission_res_97.out +6161fffb8260f94fe3c7831344bb59d1 emission_res_98.out +3a0a614dc35d97cfe943427e2522600f emission_res_99.out +14fabcbaf6b130194f90aca714e712c9 emissiontrue.out +c1a82f445db2ad262b87100653e43396 emissiontrue_res_00.out +3fb5e94731437247e1fd43164b90fa9c emissiontrue_res_01.out +041545e70931b46bdd358c1cb5d23b65 emissiontrue_res_02.out +a3abe61e714f0252f93a487ddab9758c emissiontrue_res_03.out +7d9fb7514677bc3262ea7173c7f8c6af emissiontrue_res_04.out +f947d49052aa20e0dcde875f9cc540fc emissiontrue_res_05.out +6b5095feb7997969d96043afb26181dd emissiontrue_res_06.out +02a45c5d50a24f2b88d3d8549d026e0d emissiontrue_res_07.out +7547b7318562aa8dc9a90591ed9c0d64 emissiontrue_res_08.out +a4e343a05708ca0406001083885433f5 emissiontrue_res_09.out +cf5228b2da69a06e75ede5f8fb40244b emissiontrue_res_10.out +38a17cf91d8044a890e84e8850341407 emissiontrue_res_11.out +70b00b9db91a0c14faeab4980ffe3e3c emissiontrue_res_12.out +d77b3abde72c6a86dbebe662d228d846 emissiontrue_res_13.out +529daa4c249e1e9d629a1cd00e62c4fe emissiontrue_res_14.out +dd190fc63c4e24cb0d5d0bc38bf3a8b6 emissiontrue_res_15.out +f2b6d4baaee16a22a616bb8d6405a564 emissiontrue_res_16.out +ae6d449ab80bc642c4918c633a0086f2 emissiontrue_res_17.out +c508822a961b8e484cc55f1b2c621361 emissiontrue_res_18.out +799c4715e515c8c317b788491e5889a9 emissiontrue_res_19.out +e1e1f693d01a21330382bc424f9319c2 emissiontrue_res_20.out +bf553130830be01085b640723c0b21dc emissiontrue_res_21.out +3417723578b33cc9d10da41ea4f6fe31 emissiontrue_res_22.out +da9d7ccc326a3eb097f0ffbb94ceb455 emissiontrue_res_23.out +3a81ea60d526e26474c68ad1e9c1c4ec emissiontrue_res_24.out +812531e293c78559f0c70503dee227a9 emissiontrue_res_25.out +ef9f6eeb49dc6f505c9f75264b71c1b0 emissiontrue_res_26.out +3e4b82ba901f079e7e8cd2acc5542ed0 emissiontrue_res_27.out +79f733f7cd9b449be58c8e84d8acf576 emissiontrue_res_28.out +65afa666c306d6f4575014767e231bae emissiontrue_res_29.out +886e740c584df4ef7a07a24f42a1afab emissiontrue_res_30.out +f432eaaa73cb9d43c10cf8579ca06a03 emissiontrue_res_31.out +52d9644ea035de4028c1240bdafa1333 emissiontrue_res_32.out +6aa88d4003b2e222fdb3334924c7c52a emissiontrue_res_33.out +c3b2ce12b8e796786c9f8d7a367f3b73 emissiontrue_res_34.out +bf7d953889df9ae8f53c58a121ddc9f6 emissiontrue_res_35.out +b6fd2bfcb72bb8f29328cd0ad226efb2 emissiontrue_res_36.out +aecec1f9166512c379a15e825fb36ca7 emissiontrue_res_37.out +e9690571ef5ff448dbd5f766d33297a5 emissiontrue_res_38.out +0be7fe156149d6896501dfdc9a573d8c emissiontrue_res_39.out +9cccfc3f8a2bbd632dbd58752304a873 emissiontrue_res_40.out +70a1246238e6ce182b22617ecfe4e31f emissiontrue_res_41.out +601e1fb6c023242ae639ce24e831bc5c emissiontrue_res_42.out +5e3ba3670b0dbdac16d26ca8ac4c9a2f emissiontrue_res_43.out +6d304610afbe67967bbec9e433b43ba5 emissiontrue_res_44.out +8fcfb2edc5623849c2dae5b1a8143afe emissiontrue_res_45.out +955fd9df482d87e5a54218d52f87eb40 emissiontrue_res_46.out +eb9dc3ff19197b8650642a0d22ce0dea emissiontrue_res_47.out +4cd45abcfb3a2aab2bc87596c9438915 emissiontrue_res_48.out +f34174705092ece4768754c325536cf6 emissiontrue_res_49.out +24edc56006f5b857dbb4e2eff5374b1f emissiontrue_res_50.out +8a244d67da4a4212cc8cc25871c89788 emissiontrue_res_51.out +f994ddacf2a7f30a626cc00314192414 emissiontrue_res_52.out +cd45f7cd56711eeedfa0df63436c49c7 emissiontrue_res_53.out +d08739b27dc69cbf80118485fdc9296f emissiontrue_res_54.out +5a2c930b61b4d79f190f96ff4b8c3149 emissiontrue_res_55.out +98dc06dde3f98712722fbece65197c72 emissiontrue_res_56.out +28c80a25ed8e384878d8b4881de9fa1b emissiontrue_res_57.out +fc4625e116679367a7a77d9f7db060b0 emissiontrue_res_58.out +4f7b7cad254a01471355120f4c8c350d emissiontrue_res_59.out +e5cd534481fa7d5f1976a7f4a9ba10a2 emissiontrue_res_60.out +4b6e8c1f3352bce03d535e1e7ca9815a emissiontrue_res_61.out +cc78de8bcd6388ceba5b240e52603be0 emissiontrue_res_62.out +628994e0ef7313a79fe83595fd64e40d emissiontrue_res_63.out +e174546c2bc05fff9777fc343bdfac7a emissiontrue_res_64.out +4fb49c25dd6089f94a1399fd916badb0 emissiontrue_res_65.out +3b782d0849aaefb653a93ed45fd84ccd emissiontrue_res_66.out +b8aad60552eafccd1c3a7662e06da82f emissiontrue_res_67.out +be980a3d8b5d2cd48a26760786f3c7ec emissiontrue_res_68.out +41982d62c4c32866abc29f882b0012df emissiontrue_res_69.out +7ca9fd3bab48775100840d5931de87d8 emissiontrue_res_70.out +574a23ccef930f336b350a1db082916d emissiontrue_res_71.out +4e1e77a82a625bc54a1ee8e15eb85dcf emissiontrue_res_72.out +c480c7f2a3402618f81d4723a3b4686b emissiontrue_res_73.out +d8ab2e2efcac9ff6f30147dd1eec466b emissiontrue_res_74.out +eb7068190bb2c08167a534d2f26e4101 emissiontrue_res_75.out +5d50b5d97f141f734d873e48de75abf0 emissiontrue_res_76.out +71bb19a1c3c8fbf1a971d4379dfb6ab3 emissiontrue_res_77.out +4df83d0517260eb00885a1f07c270fba emissiontrue_res_78.out +6936f4159783d801c173e27dbffe6ade emissiontrue_res_79.out +164ce21681f0c13f82bf101157fa815a emissiontrue_res_80.out +f576228ae4959d49a41e858ce0883548 emissiontrue_res_81.out +afa0c57c1d85f93f9fbc36525273097e emissiontrue_res_82.out +24af789e7f815498214d3810771e498e emissiontrue_res_83.out +25b2ba0ec7d18c3d4cd5a3746d16bcf1 emissiontrue_res_84.out +131fba7c5421b445619e38818a45fd7a emissiontrue_res_85.out +eb9e842d97b8ab9ae07627b82a5d0317 emissiontrue_res_86.out +50ae0eceafcf8cd0e910f500a065c63f emissiontrue_res_87.out +b4edeae79047253615532c6c4f349c86 emissiontrue_res_88.out +697bc7d161b771b9646a811ee6e32e1c emissiontrue_res_89.out +a290598903a17e309cf7238a145adce6 emissiontrue_res_90.out +33a1f7161f77ea575ede1be16406bc86 emissiontrue_res_91.out +8616403d3d82ed185eca3f4cf5ffb458 emissiontrue_res_92.out +2d03e2c74e2216714961a4f729d58b0c emissiontrue_res_93.out +9ce49fa1a773b635e374e0275b1245c4 emissiontrue_res_94.out +80b6ea0ac24a73b15b1fd223b147e2ea emissiontrue_res_95.out +e7d9e1fe26231b845722cf05b2649f51 emissiontrue_res_96.out +f5091fd9b395a020b0c8970a210091f6 emissiontrue_res_97.out +95dce1e6df0d417e0ab6a815bdc4d923 emissiontrue_res_98.out +1febd49609f65308996c8befe9811cff emissiontrue_res_99.out +48dda4ebcc59ff66671d8f1e08b25669 gamma_light_curve.out +880ff36fa1f2bd4ceb4d4cb8eca19dbf gamma_spec.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -c418bd488a88758b8998799fb0e85f56 light_curve.out -dc87afe89962c6cc982654d6b51fe6d4 light_curve_res.out +1bb45c3f866deed342ef8bd8049d40d3 light_curve.out +4ec8cbbb9553df20610badda47c64cdd light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d874fa90ab0cd656db374027c4d84263 packets00_0000.out -c42b25777b701b4bafbbe678ab9cb553 packets00_0001.out -4189f86a3de001dc02082a24da06459f packets00_0002.out -5f80eab7dae548e5b2033d039c81806f packets00_0003.out -75a19500dc039b998f89bdaa549d4840 spec.out -fc09caca8a29c0090c5747885cb037aa spec_res.out +075961b82282cc1e797ff03eb74319be packets00_0000.out +0068c62a0da3c5998b760517398b17ed packets00_0001.out +2c2071e8d5c721d1754e7d1dfb36b841 packets00_0002.out +7948d1611f47816b4709fcc550e3b3f3 packets00_0003.out +979929d71d468011f0c347981b8ecc3a spec.out +7f7c4746ae394bd67985077f93860c0c spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -75c948225d2fb276096ede730fee51ee job1/estimators_0000.out -85461f2da040db701a7a2a6f53b84ec2 job1/estimators_0001.out -10927255bf1fa8f5974b96dd08e6d2be job1/estimators_0002.out -ccaf7f79f0cf53bc9ee30ae26a672426 job1/estimators_0003.out +8ec2c87f3caf844a3586ab0efed84149 job1/estimators_0000.out +f7e7ab8f3dc7e4829088a8420413f0ed job1/estimators_0001.out +7d03054f8a27a94888a85cc72e7ddb44 job1/estimators_0002.out +1b2b0c7b5eb27fa180e020384693de5a job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt index 383d9c49c..5bc8585bc 100644 --- a/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -ab3d72c064c34a388f7b61274f4cfe7a deposition.out -dcde6c7de036fea5e230d1d09e8bf708 gamma_light_curve.out -2b769145664780d4f90b07f963588536 gammalinelist.out +18971bf7c803cdb5c6c7493a5cb26d29 deposition.out +e7d466d389c333f75ca3daf89c4f7d9c gamma_light_curve.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -f0c53ee7bd627cdffa79a78172ae55b0 light_curve.out +bd40f9d7fbbb3bef2258786416249837 light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -66841da450aa382ffb1bc89f4a2a5ab3 packets00_0000.out -0ed4bdd8a029f59a5274448a1afab0e5 packets00_0001.out -332651698a9ce00b998de24435e3f424 packets00_0002.out -273f83e24133d8984219f4afe187c397 packets00_0003.out -b653a3329cd63cfa1f429ff83c33693b spec.out +280355233a3e158633a61e93f253fa92 packets00_0000.out +5bed57e24186fc4a4ac59809c13babba packets00_0001.out +278b5befed7627a0c2e6aa0af09871e6 packets00_0002.out +944a6650bae17c2a740514098c19c7a3 packets00_0003.out +464b6cdd37f001e61e5b0de2a06fa8c5 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -3a92706d94b2a4dfb4eb12b375c09bea job0/estimators_0000.out -a4bcb8cf8684bfd118fea9ebbcdc6021 job0/estimators_0001.out -1243ebd40d52270f3c272a87f1c2344a job0/estimators_0002.out -43676cd3885a88ed6cd81ade39494090 job0/estimators_0003.out +bd223ed2edb4bbeab6a1fff1b4f908ef job0/estimators_0000.out +b7dd0ec2a3d4dedbba2d7372ad9ecab2 job0/estimators_0001.out +dd47fd9ab2b51d6eb408e799aba5e235 job0/estimators_0002.out +0dec07f56e90d85586e0b641fa27b23e job0/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt index f37031da7..15a92fad3 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -2e7b663f164bdd72fe716b7d135750ef absorption.out -6ecf11a47a87cad40b429e9338b734bd absorption_res_00.out -6407a4a3b29ab902bebd654a7b7c3c68 absorption_res_01.out -bb5ed8764e5e2eed5ebd6071b9375f42 absorption_res_02.out -22a8dd64be413bd1664b7eded2386c8d absorption_res_03.out -116fdd38a2e04fcff3935a05aed76a4f absorption_res_04.out -67e4c15ccd610ddf68e464c636b6cad2 absorption_res_05.out -e9875f312fdce351e061fc174176390c absorption_res_06.out -88a0ed55f55e89791e7762a857e018a5 absorption_res_07.out -43eb1eca351d728939fb69ff495b4117 absorption_res_08.out -07fe46786a77629f4dd2db0c3fa640eb absorption_res_09.out -53d09b154b5a73bf5c98dca3fdc85983 absorption_res_10.out -40662db2a132755d8364a7fbc0cdd9fa absorption_res_11.out -d6d650b29413712984316bd91a33e6be absorption_res_12.out -8f9c1f752cbf7ca70c6bbecfd8017915 absorption_res_13.out -5e360d40e941279f1437e1eda46b8ea1 absorption_res_14.out -7f745061478c02fc1a5a8379f47306ce absorption_res_15.out -568faae2e909c096c890c112a7aa40d2 absorption_res_16.out -f7ae8820520f4b742111071957058b39 absorption_res_17.out -e085e3cc6fe466427026168727c933b9 absorption_res_18.out -10b1e73f5cfaeddafa84ae606c7aa8cd absorption_res_19.out -938e38d23771034e6e09d0130daaabe6 absorption_res_20.out -1faff481aca7b77a38b67de3ddc627c0 absorption_res_21.out -c21d82c2ebd6b760168b43167324c231 absorption_res_22.out -91040148a57801904d696f1adfba6f3d absorption_res_23.out -1af98527fecd5422b2963167c9bc4da0 absorption_res_24.out -2d7a408af3d3278764d2a62eb961ede7 absorption_res_25.out -790d6f70af8287223d67e4b81c0b7e60 absorption_res_26.out -ea785cb54e989aa9a8d66fc8fae6de9c absorption_res_27.out -6c7e1434d3d82059b9c99d2dcdb03458 absorption_res_28.out -01749ddb5eec5e2e880990cddce44cd2 absorption_res_29.out -05810c3ad79fc0cfebf5f2e91e441811 absorption_res_30.out -b5b61e79f1e08db8b532fc03bc1adad6 absorption_res_31.out -8f88b3d35c682e706982acfe2df41168 absorption_res_32.out -28f7bf92f6d4c9bd7753febeebb08478 absorption_res_33.out -860979413f2ef4a30705e283046f7b06 absorption_res_34.out -c44951d480a759207cf11d7de48bf1ec absorption_res_35.out -07d960e109e8f9716c41e1e25699b50e absorption_res_36.out -9c62d1b053f08ac57552e726e9d4741e absorption_res_37.out -96eca3daa261eda6ca3e5a0ee849b3a5 absorption_res_38.out -1cf4f88396dbeb183425e4b6d6361c5c absorption_res_39.out -46cb681361080900802d742706a2275e absorption_res_40.out -07e02c06d0a417ee0a5cff195e85bb59 absorption_res_41.out -07c5f65abf0eed12c47a356addaab54c absorption_res_42.out -42ebe5b9861cae4c9a1b576db4522659 absorption_res_43.out -0f96a678990a026c2fe90fc00cd20789 absorption_res_44.out -8b321c3f8fd79b76174caf6c3828eeaf absorption_res_45.out -f763d23d48ed0e81d9bdd3704894994f absorption_res_46.out -bc52d9d599fcbb19a720c0946d1436ef absorption_res_47.out -001db24cc0e6c404ad00ae45d412e59c absorption_res_48.out -c37dd834cff3259a5be3549bdfee9a25 absorption_res_49.out -44456faf931e883398319edb172652f3 absorption_res_50.out -7056ac2e8d893cd1ad030a4bb49362e3 absorption_res_51.out -2da4499b204de7b2211779243c6b6775 absorption_res_52.out -795c43851b2a6d42a803de2fd7851ce1 absorption_res_53.out -d24bbb846487a1464a2861a6ff8b8016 absorption_res_54.out -28aacc2c2e23c2acdde412d52942a8b5 absorption_res_55.out -fe409acc060f0d87073cd51ab4b6c5d3 absorption_res_56.out -1fbba6029ccd64bf2c80fd9131056c90 absorption_res_57.out -352a79d31035ee042eccb8e6181d9150 absorption_res_58.out -f6c9751ed3b232b7aa2983dacdf19aec absorption_res_59.out -8feab73450c286589bd18b967fc26437 absorption_res_60.out -e617a6576a411f7a93287f4402514f18 absorption_res_61.out -20f3ebe500b107629adcaaedf9250301 absorption_res_62.out -798c0fb74f4e4a6f3ffa3820ff9e4c17 absorption_res_63.out -78d566eb62fdba1dbd86c9fb97ef0c30 absorption_res_64.out -df84b07365eec4dcbcdf4254abc7d624 absorption_res_65.out -c8264148eb0ae635559777c3bc4bb81c absorption_res_66.out -4c7d55792fe893a86db91bd29757010a absorption_res_67.out -95ab118d3ada53147e28412925197c6f absorption_res_68.out -20889c4c79dd5061ff9b3f699fbd4df0 absorption_res_69.out -223f27852af47a1245c2e7ac8d32e749 absorption_res_70.out -f030adeab0506e171e6db328099a3cac absorption_res_71.out -eb338409d285fcb174c125151da034d1 absorption_res_72.out -dc8cafe880e06b74907470f54e5c8788 absorption_res_73.out -a2a8746d9724131275c21acad44b1afc absorption_res_74.out -a3ae5b4e45a2ff30024b8e6f53693547 absorption_res_75.out -3c73cff3ac03f77e1e0a5c5bf87e503e absorption_res_76.out -7ff77a451d11fd16553a2c7af73926ba absorption_res_77.out -fa20bea5cc6016e2d691fa28344e0d74 absorption_res_78.out -bea0552e1dfe5b36946d4bcf956af2bb absorption_res_79.out -d6430e1b0f6fd6233abe4560f7707263 absorption_res_80.out -78071b5cc87534d33f3f6f50632acf72 absorption_res_81.out -cc03d6d2470438b117352adbe08758a1 absorption_res_82.out -8ba76eb04ee787ba2da486e29b7e362a absorption_res_83.out -18cee9a228d1cd540af45d0647166943 absorption_res_84.out -63584942292285c061fc2d23070390b0 absorption_res_85.out -e5283e4fdd7178073415acc86215f0f6 absorption_res_86.out -04e3c2643735bc19c821a584c1e5d8d1 absorption_res_87.out -8dfaf6eab14e20d07aedcf6127343ab6 absorption_res_88.out -516b771f2034e088efa3a07ad9ea30a0 absorption_res_89.out -4ce0fea7d880ae5866c42d5354c74ee1 absorption_res_90.out -f04020b3354c482b666e1e353a0ade12 absorption_res_91.out -69ff1797e1f695e047e764286d5c3de9 absorption_res_92.out -47068749b5f58ce5c95d2c84073baea9 absorption_res_93.out -4732e4145032fd628d51c96f0bdc373c absorption_res_94.out -3fd4955f3a8f20b06cefe05846f2decf absorption_res_95.out -6e1166394c267d7387429e5079fa4bef absorption_res_96.out -9ec2e5dbee3fb47d1f82ae4a326f3afa absorption_res_97.out -b75385a68294590db24314feb36f21c5 absorption_res_98.out -150efdd908168411b9a358899ea73ed9 absorption_res_99.out +e1a0b2c4f649f4e73288d511ab8d9cf8 absorption.out +b7fd051e6404d4a57199fa9716243aef absorption_res_00.out +6f520a2c2ea961d0308a65e769b1854f absorption_res_01.out +71e2b66662165ee048471e971945c215 absorption_res_02.out +71e98689da82b33e9e091d7aaa5612c7 absorption_res_03.out +8cecf514c7deb427898ae4e8946c9658 absorption_res_04.out +20ae325defd91add775011bbe56c969b absorption_res_05.out +25b29e406d2c7d9b9d5f5683e50e2c04 absorption_res_06.out +611003759b48838342546598b03cb497 absorption_res_07.out +be1b42fa38bcbd0a2ac3d421dc44ca54 absorption_res_08.out +0fccec08a08daa2d7eae86a429f94ed9 absorption_res_09.out +ead1c2a3f06cdad8ccf47ed2d3341025 absorption_res_10.out +72e76d45a7c0b9f1d60d0200e2081478 absorption_res_11.out +f00eb9e3de6433faa38b22269f082f8e absorption_res_12.out +e1a355e4533bd7cbfa923b3e85386682 absorption_res_13.out +714d52e32ca7f854e92f1989712dedc8 absorption_res_14.out +7969dba17b36b8f113776e3ebba2ec95 absorption_res_15.out +a58fa910f9b46ce8fd80188f9e01eced absorption_res_16.out +095d6b9cf4bc6267cde55018d4fbc7ff absorption_res_17.out +03a685a6a5abbbbcbe3f539abbdb56ce absorption_res_18.out +42ac937b3725ff19af9d7e20ac016746 absorption_res_19.out +3f589a9bd0c391ac1502fb175da106f0 absorption_res_20.out +741c87db5e4f8d78ffd2bf270c2cf5e9 absorption_res_21.out +2f9a6cca529e62004902374b388beabb absorption_res_22.out +1b6fd2cb43ee6675471cca33b3a67fbc absorption_res_23.out +4935e6f8779ba242cf562cc206caaeb1 absorption_res_24.out +5ea4f401c1a02e4179441b4e111d37a0 absorption_res_25.out +bd8f257ba85a3e1149bcbd31fbb19ab5 absorption_res_26.out +00045b6e9888c6acb5c2c91e59ea7f10 absorption_res_27.out +04b1004ac6117937749f2317498a91e7 absorption_res_28.out +bddd7ce6a572a6c2320d87458ecbc178 absorption_res_29.out +e2c9a1660f635f84075f00d131b31fba absorption_res_30.out +4a710e50370dc991606d4b68a2e928f0 absorption_res_31.out +c1c17ff8e18014d77018cb56c2494b7a absorption_res_32.out +19b3a9c3ee9201cbdd7cdbd9c617eea4 absorption_res_33.out +077c2af3ac6594bcb0bb173ec904cf72 absorption_res_34.out +9a95011b004b16ff738a19f748325f8e absorption_res_35.out +b7a0c5597782f0427ce8db5f865f18c0 absorption_res_36.out +07ebf60414f9defbbe75cd94903f1015 absorption_res_37.out +9094c7cc2b53ce7230d5e3b6c83b5c24 absorption_res_38.out +25c8df3e6ed7e1c9315829fe4cbc0f10 absorption_res_39.out +a075169d83d4c52530292234e78c720f absorption_res_40.out +e1146eb22a09639a47d7b6e511042be7 absorption_res_41.out +1fe6f6f5225c4b0e8c9aceeb15a4217e absorption_res_42.out +fd7448d1594b78fc9776be0a49ed7320 absorption_res_43.out +9b3a6cfd76c2ae4df2a17023b942ef76 absorption_res_44.out +de1fe800e2d61bb78f14027e6d238a3c absorption_res_45.out +c296f049c9fc6e5c719f378bd9b91a06 absorption_res_46.out +4c16f8412f2cb0f69ac654d471b7dab8 absorption_res_47.out +19accfe0f73436254b1c5e4c02e87b5b absorption_res_48.out +cbcab8221071d881553f35bc3b941174 absorption_res_49.out +344d4eaf70cd4ef58fa510036027961b absorption_res_50.out +8a3194bde02e439e55712f077b330d25 absorption_res_51.out +8cf79d1e3288e51fc382b64321c0aed9 absorption_res_52.out +5e416b0dba3d4e153220b7998d09bb0e absorption_res_53.out +9beae96af3f994daa0f6a26be34ce361 absorption_res_54.out +b9193f53a032fd51e1d6e27945df04a6 absorption_res_55.out +992e5820d12a022dbbf28b8e338ca1e4 absorption_res_56.out +63b5e95e94e3de872942ae3182ebd239 absorption_res_57.out +ecc80e3741eb55513b5e612019adbe71 absorption_res_58.out +e7503608529159bc88e7f1c534bd97ef absorption_res_59.out +ac34e5edbf02346c3ab038c8435a77fb absorption_res_60.out +02af7a1452edce233b75bc65d5d021b5 absorption_res_61.out +b52e39d90030992efaf958323c30c1d7 absorption_res_62.out +c60f06fba404ff20769a1100bfbd4eb6 absorption_res_63.out +56cb3263370fca9b6af40fe3ff0a1f16 absorption_res_64.out +138f6056dfd5df1be332c688d859e9e2 absorption_res_65.out +4cb967224096bc8a11771c549b4b2f8c absorption_res_66.out +5142e5ed1e15de8ff6df237fd07f695a absorption_res_67.out +7d4cbad9c1f5d75cc6201e64a39b8ede absorption_res_68.out +633df30ac296fd39c4d047b05178958f absorption_res_69.out +f57d33c9c0bf8f17e3101a5adabb57f1 absorption_res_70.out +0104d4dba7847e7240b0dcbfba7af078 absorption_res_71.out +f14551e62f14f1167630e28813667e1c absorption_res_72.out +e9621a3e3acac9ae70866eba54b4e7df absorption_res_73.out +24bef4ddac906a7717227300ccb6aef4 absorption_res_74.out +7a73080fe083c5febf4aff4ff9275654 absorption_res_75.out +aeb367df18cdcf2d9e275bdad69c58b7 absorption_res_76.out +de65d56079ec560c6881faffce3e8f38 absorption_res_77.out +5709def360557a64da67c99a63a57bd7 absorption_res_78.out +19df2f964c76e8380c536e4631945c59 absorption_res_79.out +c28ee5e67c7c032437d8c3fc5b18b23f absorption_res_80.out +00fcfe7112c53319e71bd3f8a4f5bead absorption_res_81.out +931b43201bd738bd51e3614eee57fb37 absorption_res_82.out +083bd4a2be7dca0df60aebdecfccf5da absorption_res_83.out +067832f2edee35f44daf135d8c9dc1d0 absorption_res_84.out +a15625f64dfe95c01baeecb806a581e0 absorption_res_85.out +cab6ef5fc4d11b81370f40ca52a3f78c absorption_res_86.out +e595babc87b90ccdaab07b22b68b9477 absorption_res_87.out +35f193927382d8e3b0954d916389dd6e absorption_res_88.out +ed6b55b36368be592ee374d2a51d2fe6 absorption_res_89.out +5be7a3f9cb819e146ba47ede7adc6260 absorption_res_90.out +3bb0af2f05c649cc236a312de38fdd1c absorption_res_91.out +2060e6a7bf78735e75bfb706cef5a035 absorption_res_92.out +f7dc110816b71139f6fd83544bad711b absorption_res_93.out +7603204255680af803117e605e3fc4cf absorption_res_94.out +67ac740439cb667558e64b12916e9bd5 absorption_res_95.out +6cd1fc8f2d270a5af35c47accf76f057 absorption_res_96.out +ca3ea246aad475656688e3e1817f59c1 absorption_res_97.out +46908172dc349b5aa0c679f3971e1003 absorption_res_98.out +a3c424b084e66721f244f254958fb2fe absorption_res_99.out 897316929176464ebc9ad085f31e7284 bflist.out -e2a3add7bf9902def7761af58204df16 deposition.out -df2411bf53d9e8a65897b9176011aaf2 emission.out -01350f3129565d1472dc8705cc30fe54 emission_res_00.out -a48a26db68581485e30b75773bec9bb9 emission_res_01.out -724578ad36aaad4fd238f8042b85f2e8 emission_res_02.out -8e759f96584bb8debdc7c1f83629bc50 emission_res_03.out -79277a8eac3d3c6a5961f9b76ba96d10 emission_res_04.out -9e9466be83f7eed6d1271412ce916979 emission_res_05.out -0aaa29aad041ae1865f44fb752951526 emission_res_06.out -60b3168fa24555d595e5f2e1efde7c8f emission_res_07.out -deabae82e894941c822b6fdd078b224a emission_res_08.out -945be6245196152b08ff06dcad9de2db emission_res_09.out -295c062bf01df7706113652487cde520 emission_res_10.out -71ee2c539c12d5fca8dc20b3d21bcbf4 emission_res_11.out -2a54aef7a8ae040b9980e064427f1421 emission_res_12.out -0c98ca415a90724dcf87273e6eb26111 emission_res_13.out -2985961691ed7b57a8fc3ee303dae87b emission_res_14.out -2d67bdf1cd9cd7e6e140f3b7428cc62a emission_res_15.out -a70ad565b692d7f30c5892164163fc0b emission_res_16.out -f25e0df40069ab8f8827f3075e4c8bac emission_res_17.out -85f54006eaf0fdce59b376acab655c27 emission_res_18.out -f46f3e9ba8f53d4b638492d1f99431e0 emission_res_19.out -e10dd39e3f8189e48345b58472bf9b8e emission_res_20.out -e3c64840b1b8ed87e985a66f596ccdc1 emission_res_21.out -abf97707c78048b99853bdc0339fa779 emission_res_22.out -958552fb091897733fdfc93561bed0ea emission_res_23.out -4b866591450232dd718f40470dca2897 emission_res_24.out -38f49a2b49f5bbba5cfb6bf5a321bee8 emission_res_25.out -e988aed28e287f9b69192f817b15a488 emission_res_26.out -440a9a423c90b9bc812f3073354965ef emission_res_27.out -a1fd901ea10d0e4603dc6cad63a12b20 emission_res_28.out -4ad66e267376d4498eed495d64d76a6e emission_res_29.out -61ab17da0175872af239676e43482b26 emission_res_30.out -6b60d9b399f2e282fcad023cb8632829 emission_res_31.out -30dcec8a52f61748d1edd2781da0e5d3 emission_res_32.out -7ddb90954353841186358361abb68dfb emission_res_33.out -6653ccf8a8e14559e215ea40a36c010b emission_res_34.out -d7c593e8fb0f824c911f8cb536c2f7a5 emission_res_35.out -f3426c8d52cd679b5702ae46c2acad2c emission_res_36.out -943774d7f68e3adbea2ffc8d9f5a7d5d emission_res_37.out -9502ea22491234192cd167d5ca8fb1af emission_res_38.out -6086e867686df38fd936d7132d76979e emission_res_39.out -94ede1526c0caa99af4003e9c2b64403 emission_res_40.out -9ec4aba491e50c31d14cd2d21117ea69 emission_res_41.out -5d15934f27dff46bbb7aa07282734f7c emission_res_42.out -3b6aa93f40a91ca301cbee53321691e2 emission_res_43.out -b948908006ec407b1b2eeb79779d4c74 emission_res_44.out -065d1917e8c3a45e44337f4f5f9db27c emission_res_45.out -7990f5c5f5929e43c0c627d47459cd4d emission_res_46.out -82104e216ac7dc875880cb6d239c1f67 emission_res_47.out -06da0b2ca79ec79fb83b10cacbd2334c emission_res_48.out -0718719ca98be1a02901ad8c0c449c69 emission_res_49.out -c6c06becd04625247906e9577f90e998 emission_res_50.out -e0fb2119f99c3bbd88f073c4c5f930d3 emission_res_51.out -63753e84b3460505ca0525c711cb2646 emission_res_52.out -27af4e1d69abb46db89a2b5d2ec420b2 emission_res_53.out -2204414b178a31f8feeef3e683944815 emission_res_54.out -212b14f6d30191be02bb6ee96a1be5f3 emission_res_55.out -f03473a4256262154b395f5f08b603dd emission_res_56.out -ff476d1c73e1c9348e9c5887162a3ead emission_res_57.out -8ef5a65dfe635940c25d2230624b1f65 emission_res_58.out -5f81ce79f11befeac373c60b59e4e070 emission_res_59.out -b258268d94879a0868abc244da6ae45a emission_res_60.out -6b3b3697b4540ace5088f39056ba03bf emission_res_61.out -367d9151365662f8b2b591bb6553d79e emission_res_62.out -e52ca5fe46620aa3a2db85be0f03d9f0 emission_res_63.out -0186d08c4cde468f90c72bf82a7830fd emission_res_64.out -84fad345fabca98140fcf106f5da755b emission_res_65.out -8839287e54b06f85ad92334a80fe5473 emission_res_66.out -447d33a80233cb41b6fa5c7c8df814c5 emission_res_67.out -a2363156955a2b1e94289c4a37be0130 emission_res_68.out -43955369157d30af813b2a4d43ece4d9 emission_res_69.out -90789ebf70db9c3beaaf39bb9c49c609 emission_res_70.out -429c80bc04bbfb1752c3a0275102d397 emission_res_71.out -9f51ecfe04c4aa82c4560308089c0459 emission_res_72.out -4b07fe32035dd071e2bfee5069c4a711 emission_res_73.out -5670012a476d356170b1a2def25b2b07 emission_res_74.out -2adfc7dfaaf8b85c22ab23ad830fb773 emission_res_75.out -14c9be6a82d39cb0ab62f779b2801302 emission_res_76.out -c771314fc05f66db1dfcab73c345b449 emission_res_77.out -43625dc5aeb13349ccf4f622e27942e2 emission_res_78.out -63e411d7ce30b0686917f96802c753d1 emission_res_79.out -0555634b1055f134e18a75956e4c123b emission_res_80.out -c6b9df9921b3de02e8fbc6b050590d12 emission_res_81.out -3a21b21061d064b42e81621996ca3445 emission_res_82.out -68b2c942bd014353568e607c68893c7d emission_res_83.out -4a9ffda7dc7c2557ddc9281bb33f2287 emission_res_84.out -fc44d709571377cff3972152e1d3861a emission_res_85.out -e572786cfabab03f69a135441eb6a60a emission_res_86.out -39048b2bb718d96bd20dc501515a5024 emission_res_87.out -35821d991547227f9b08dfbfdb08bbf8 emission_res_88.out -ddccb05c6cd5341b5e86562da26c447f emission_res_89.out -c56efd1a4a628512240239982da477e0 emission_res_90.out -a6a268dabd04912cc259f265b5291984 emission_res_91.out -1f6e229e859889c534f82b78bea882d0 emission_res_92.out -c12d41bbf3ce6c4161a513f306757966 emission_res_93.out -83cd9792b1fb8da0894cc45f35806135 emission_res_94.out -7486ace72c54890a96b163f25059dc02 emission_res_95.out -3f92049c4a266a313f31e6c4bd32c7b6 emission_res_96.out -b8c3d1563e890ad5e2e5849ba470b4f2 emission_res_97.out -87d07a3744dcefb5d91c65b67e9648be emission_res_98.out -f64642cebbe63806d3172a97a9fa4f48 emission_res_99.out -540a7bf037980e462f8d3711712c0606 emissiontrue.out -dd2f166b12726e264876f8f29c07cbf6 emissiontrue_res_00.out -eeb418bafc872f498f4b52e8f805e0e4 emissiontrue_res_01.out -053286aae7bea4820959cdb5794184a0 emissiontrue_res_02.out -8dac36a1f78dc85e4a6917e4b72d49a5 emissiontrue_res_03.out -720dfc0cfa99aa2e8870ac5e99c49650 emissiontrue_res_04.out -54570cbeb15009957833cda024981975 emissiontrue_res_05.out -794e5fb1d4d4d044a86d984c0ff1c194 emissiontrue_res_06.out -2264dfd2960e837234e0f5d7725fd2a7 emissiontrue_res_07.out -7fb37fd41ccbf08a63ced7f5fc1fa917 emissiontrue_res_08.out -d31f927d2e98c5524d4a41fc369dca03 emissiontrue_res_09.out -85ef25dc6190246cc6db1701d7feee13 emissiontrue_res_10.out -4ab4d8fb3d5f9c33e7614a99e15be51d emissiontrue_res_11.out -4bc17d5bb946ec1f9adebb9161a5153e emissiontrue_res_12.out -13e2ab8f2266b02cdb57846b237faef8 emissiontrue_res_13.out -1c0072a7c3c6807956ae431ac3c5a2e9 emissiontrue_res_14.out -4246b93a2b6112cdb9eda3add6be172b emissiontrue_res_15.out -bb5a57ac115688a130d6f292afac3493 emissiontrue_res_16.out -9e2468ecf0e8dd7ccb4251877dde4f78 emissiontrue_res_17.out -0775bb802633f59bce72d4ad4b99f707 emissiontrue_res_18.out -808fbc0cd01bc4665089fb105c6b9365 emissiontrue_res_19.out -25f223f9b52b4de21aa2b9d293c4ec7c emissiontrue_res_20.out -666b7bcc699efbb169d2a1b9c4c04b1d emissiontrue_res_21.out -d0c8d1ae7d196a73168a6c3a78b21026 emissiontrue_res_22.out -58291bf08665e2c10644573a6fea446b emissiontrue_res_23.out -3dbef62cbc57f6f7cea4b18f6d28ddd6 emissiontrue_res_24.out -df00e04269f7c24f1a75af748bdf0e4a emissiontrue_res_25.out -e22595c9ddf56eb6ec656d0b917e3096 emissiontrue_res_26.out -4a9ad6bc539fe26af73dbdaa8bf7850e emissiontrue_res_27.out -c5f4f31a269ec4f9a08053ebfdb3031a emissiontrue_res_28.out -12ad315bdb7ea4022c506364fcca3e73 emissiontrue_res_29.out -2fda140d5b095085f17cf73e97343997 emissiontrue_res_30.out -372dd2b477d715847a024eb1d23c2472 emissiontrue_res_31.out -740e3fdaffcfb5d0b877966e97e9af2c emissiontrue_res_32.out -0d45c4ad72fd1d2af1cee91edae97127 emissiontrue_res_33.out -78f801801ed410044a10378c8ad9c7ad emissiontrue_res_34.out -0904c8eb5133eee2faeebee6ef7d9ba1 emissiontrue_res_35.out -0f6b452a99ef1d14c84c625cdf93dd11 emissiontrue_res_36.out -bc48ca1b1b1929a6d425a671bf05d757 emissiontrue_res_37.out -d314c6af0126184130f86ac4978e1f99 emissiontrue_res_38.out -bb5f178f281aefa4e6a93cfb760ca2b4 emissiontrue_res_39.out -6b2c86d13f484f62a77f662013850f30 emissiontrue_res_40.out -195ea97aeb26b7fdb98b517dcb636603 emissiontrue_res_41.out -ec3d1e60b1d4ab6b9e3b3dda81c613cb emissiontrue_res_42.out -e564c5f938ea729bad79820edd2beb6d emissiontrue_res_43.out -e04ea3d1c00f355db49d5682cb66c534 emissiontrue_res_44.out -65ef30974aa46f7b36982218e4a36488 emissiontrue_res_45.out -5c7a6ae80ad998c8b70d30b95a1808ab emissiontrue_res_46.out -536b29f5dc30df8d899183f93a35dc76 emissiontrue_res_47.out -0521d32f609c16dc8b779133f1a2ba07 emissiontrue_res_48.out -2fc1ac8e9e74267a5997ed3d6134618a emissiontrue_res_49.out -776cbef30cc2db594e1b5d64da48d903 emissiontrue_res_50.out -ab3526171b5743f50e06628284679535 emissiontrue_res_51.out -69d0d747f69baca53f395a15fd30591c emissiontrue_res_52.out -b006c620d8a874a8a57c44432b7c7bb3 emissiontrue_res_53.out -863d9dc2c491b0e85de290556415c0cb emissiontrue_res_54.out -bc2cd9e3e47a2efcf061849167f9e62e emissiontrue_res_55.out -0d980ac6b592b178233a54ad62cfcd04 emissiontrue_res_56.out -bd079fe68daa7d482ffa2383b4675285 emissiontrue_res_57.out -b2c299c80a0e5cd094da5c8969294892 emissiontrue_res_58.out -2aa62481a9278334cd6222a162adfb57 emissiontrue_res_59.out -65cdf14d3f14e1751bc340f7670cd6d2 emissiontrue_res_60.out -ee5fa7a9703c429e9a8ab55006f9593c emissiontrue_res_61.out -6f6a0a849aa564a42cb8575f628e9ae4 emissiontrue_res_62.out -bc812faec076deae43b9ddf073d043ed emissiontrue_res_63.out -d6b179b165d4d0d9d88bdc868b8a7660 emissiontrue_res_64.out -b3762653c9cc2936e81efb945104be9b emissiontrue_res_65.out -f420a017ce7bc0182e6860f8ddb1e93c emissiontrue_res_66.out -ef0a4e2b758ce718292a6ed41586ec3d emissiontrue_res_67.out -d78039d02e4cbf99be8bba1df8927e7b emissiontrue_res_68.out -7788710bee7289714acbf3eb70f110bc emissiontrue_res_69.out -bb6611cc8427c1415ed66b73cf7722c7 emissiontrue_res_70.out -aa2b1532839d7a5ab07f1dd95f9856e1 emissiontrue_res_71.out -4340b45a21d728bc4f33aaaad1ef133c emissiontrue_res_72.out -4018a659fef94947d1699b9ac5e7ec57 emissiontrue_res_73.out -e3098c2db8ac98c0492b4ab3ec8093fa emissiontrue_res_74.out -16e4fc326470d3d8efd4cfb9ab62ba92 emissiontrue_res_75.out -2ec330979739777b625650005b219186 emissiontrue_res_76.out -d3d64acddf367de39723b9dab1ad537f emissiontrue_res_77.out -06bac0c3246059482229af9630b3b11b emissiontrue_res_78.out -04abfcf860ef9be8eb1b93832ac79434 emissiontrue_res_79.out -c2ee36a45d0106502179c5dd001e7b4d emissiontrue_res_80.out -8fe00b92c1210ac615a9c057c2dc5eda emissiontrue_res_81.out -e7cd2477c5eab1b517cfcf4443d3a19b emissiontrue_res_82.out -0e7f17de4779ac70bab0a00a6b16299c emissiontrue_res_83.out -7482fe56667250179d9c0a7afaaf0082 emissiontrue_res_84.out -4e184b1077db35b92fb39791c56d3da2 emissiontrue_res_85.out -1aa26c01090d5d4dda9d6c7da081e68e emissiontrue_res_86.out -67d9b2b664dbdcc48385d84f6244b921 emissiontrue_res_87.out -e6635781905d77d3495017a32f7506ab emissiontrue_res_88.out -304a727f6caa2a1f71595915e43534ae emissiontrue_res_89.out -d758ed01696467c8f9e2d69e963802b6 emissiontrue_res_90.out -1e4d458465e3be8e994dc407aa9349b7 emissiontrue_res_91.out -3d5c1497e3f073b5b6aa2d677a481fe9 emissiontrue_res_92.out -78a9fa4f2d7fc4bc6a673b2513c3f492 emissiontrue_res_93.out -2cf49123f8d03f89a700024343834d71 emissiontrue_res_94.out -b94c76380b1b62c8382e89131d5e8480 emissiontrue_res_95.out -df3ff20df7fcb220169b36198147f1fc emissiontrue_res_96.out -c7d59db7e83a3c394a2e3fc9479eba6d emissiontrue_res_97.out -957d2d25952450b47a817f128444ae51 emissiontrue_res_98.out -3c34789461da4884157b5c4f6160d9fc emissiontrue_res_99.out -811d9e2b2a8752f84e78b5d39ca7ca29 gamma_light_curve.out -7089f1479b4fd210d618b87c561eed68 gamma_spec.out -2b769145664780d4f90b07f963588536 gammalinelist.out +5e39a05c917e3d20c76abf170d96bee1 deposition.out +8abaeba3a25a1150f9c075a69680f8c8 emission.out +b49768c9680052483abaf3a9aa7b6b90 emission_res_00.out +60f5f9e7825935ff8341ee4921877d3a emission_res_01.out +d295b510d2ef0a6c348047f612bef389 emission_res_02.out +4783db0bf6c16881b21e3608e2ae58a1 emission_res_03.out +fcf4d18b0db2bbbc4d6c42af00af6869 emission_res_04.out +3bb4f9cc8e12de6f1fb47d0bfaa00d79 emission_res_05.out +1638cbe1afddf15788314286e82e2961 emission_res_06.out +a293ac84585dad150e65e6a45ec92e62 emission_res_07.out +5d00895082cee12698e29270c16a291f emission_res_08.out +9dd40edd2ab526028c46161457d25dcc emission_res_09.out +e6c06123e17e03e028b5205c56e9d7a0 emission_res_10.out +2b428875aa649e9e694ca9bdedcc9f34 emission_res_11.out +3924a0af92338fc4ff3dda4d420c29c2 emission_res_12.out +9783d099e6d446b9d022bb802e27e455 emission_res_13.out +7a8af42f43dc297d94eb45b9288f2a62 emission_res_14.out +0e1d45f55921f710c27fceeb28dbf4b3 emission_res_15.out +897eb02bede788c1cb56748aef11be5c emission_res_16.out +e9c8b6ebe0d1a130c3cb98ed64f9474d emission_res_17.out +3f5c9bed3870f66bc7fc8fc97ecb422b emission_res_18.out +8162f398fd17ed373745c1089bc2e68b emission_res_19.out +1e276a902cad6745340102c2aa19ef0c emission_res_20.out +ca5557368ac592b8e3693538462a9f56 emission_res_21.out +2cd094e38e89b723d2ce537aeeaf46a5 emission_res_22.out +2c7f174138b50e9eda83f3e661f0aacb emission_res_23.out +fb5cebd9a650581feed4b9c0cab3dcd1 emission_res_24.out +1d5057c93d4a26bfca34766b8cb43c0d emission_res_25.out +681ccbc40f9c4898c7c582b908225959 emission_res_26.out +6de58a3dec6c6ba79e60842db0a3a615 emission_res_27.out +edbdc0d4e486230ea8cbf6aa32a0068f emission_res_28.out +198a2778fa797f7aed66c6b2f7d5d022 emission_res_29.out +f2d1492fd9552d88bcefdbfe38bd9aae emission_res_30.out +379c7aa0eb5d2e9697f106fe5a043d44 emission_res_31.out +5eddbfbfc669c5f36e74d74c8c5981e0 emission_res_32.out +5f3e794eeef623c724fc2a051ad87734 emission_res_33.out +91aad1c4d09d79911ee2127c7981b35c emission_res_34.out +0479181b5f986ff5ce46be6d29da8063 emission_res_35.out +e3eb5b50c0f03bf3defcd8d5bed45bfa emission_res_36.out +641a44dd944027985e3a0bc31b48a4ea emission_res_37.out +8ef3abcbd667fedb860b092548d9cd68 emission_res_38.out +a86be6b208169aeff921a763c4143909 emission_res_39.out +2fa6ae39918a2d500547e07a85adf4ce emission_res_40.out +c264607619e938364ed2f1491a710fb1 emission_res_41.out +c0b20e7c0f53f4f285c20bafa43c5cf7 emission_res_42.out +d0ad58be16c1c94f50fb389d60a8c606 emission_res_43.out +0898ae6c768701fdaec3e8553dd8e41c emission_res_44.out +368d4b20ae23846d25fb3b65d419cfe8 emission_res_45.out +3ff579f1d10e6b15c51d79b0d7237af2 emission_res_46.out +9efa63ba236cbf829cd8202757cf60b4 emission_res_47.out +687f953a34b5d2264f6bdc16ff089362 emission_res_48.out +e272ec56be1d5434912156da71ac5fb3 emission_res_49.out +ef93d2626caaf8efeac02f9a3c51b981 emission_res_50.out +7dbf2ec2ac901bb52e30b2c882f232e9 emission_res_51.out +2de153563ca6ee0b08d223e79d1b59b9 emission_res_52.out +1077dfe1009d055200a6d6a7bf6a92bf emission_res_53.out +4bda1fdd058d61ac626a4829af1ac2df emission_res_54.out +199ea58d7637a311cf1215d9b09db3f5 emission_res_55.out +88fc9604a99d88a2448e8b96b7aa2163 emission_res_56.out +6a49ae302229cfaea18f508d6415ec57 emission_res_57.out +1d2a1aeaf8bdbeef98d9184aabb67744 emission_res_58.out +2354cbee92e2aefa0acd174b88d2397a emission_res_59.out +6bcabfda098c76eddff55de1607f6eed emission_res_60.out +5ac9800df0e1693fbaaf51fb0999dcdd emission_res_61.out +c547c1354eb9723c39a83619511e6d8a emission_res_62.out +aa747536d5bf4729cb1fe524e04fd2c9 emission_res_63.out +ea12da93f35b03dbff062876a888eb48 emission_res_64.out +54b5f5fc39eb2ea01983211559b524cc emission_res_65.out +079a68d85dad9e7320454fd3b2502a87 emission_res_66.out +34e04f3e3183271e994ed20f5d1d3483 emission_res_67.out +80195a0d200e1931b342d8f78467a784 emission_res_68.out +c98fb9d7a1606606b4967db07618f0d8 emission_res_69.out +fb6901bf9e0ba0d14562b390f7935bcd emission_res_70.out +1cf7c021ac9a4d7e598948c0b65bb58a emission_res_71.out +5f47b9680162669c51c6516bf4ad152a emission_res_72.out +4048016916fee957894995fd9ecddc2e emission_res_73.out +36cf9fdcb24504a80ff39d45f6e19dfd emission_res_74.out +280af401c41aa0952d452dff4bf10cef emission_res_75.out +74822adb97c431d770d1ea8b7363d075 emission_res_76.out +db4f7afd5233226542f37cf0a36dfce7 emission_res_77.out +47fdaeb88e00eb5096a99d0d167bb13f emission_res_78.out +576017a6f6b4b60b771b4dae5d93f554 emission_res_79.out +e72c72b74c83dfc23ed171b45b38cb53 emission_res_80.out +64c2690727de5548008be31d1d4464a3 emission_res_81.out +d75575929bb734faf78e0579afdae8d7 emission_res_82.out +ecbf7787a36f4c2e3fa24f6d2f6bacde emission_res_83.out +fcafd9911fcd16adb782187c19f7bfb2 emission_res_84.out +483c1ace6adb1832246f36d36aac6e8d emission_res_85.out +40710b76735551bc9a4fd95d0bcc9f94 emission_res_86.out +6e0ecb17d64ec480a91c8e7790d898f0 emission_res_87.out +2f40bfaaa86cefb942753f9b0c7d684c emission_res_88.out +0888c1599037fcf6d0e21d0fa5bd5add emission_res_89.out +baf1a84b72719db23d8eb6bedec6a8ce emission_res_90.out +d3b914fb278e098d0789d4ea0030bfcc emission_res_91.out +2d397110baf2d92697842b37a3d7170f emission_res_92.out +084daf08062f5d0bda1b7e63a381fcab emission_res_93.out +96b13b8b8cafe2859a560cefae2a915b emission_res_94.out +cdc316db0012d223e737ed755d172da7 emission_res_95.out +b0d97b84dc8b827f3fc44ad58db34d97 emission_res_96.out +69464f0682be53b8d4264ad087b9c270 emission_res_97.out +e63e522480d31a30fe79a41bd7bc2134 emission_res_98.out +c76f65aa4c9a4d0bb8097060f5c3870a emission_res_99.out +68c9a0374fe4e1a254519b8f833c82f2 emissiontrue.out +5c2bcc4e70c45f4c3dba385964300b1a emissiontrue_res_00.out +b4b990f549e1ea6917dc4bfc6badf758 emissiontrue_res_01.out +21f8ab893be0b532c2b1422135a7c071 emissiontrue_res_02.out +5f4f8bc675487628f8039a68450fbf52 emissiontrue_res_03.out +043b0deaabfc7d895a0af8950c6e2e2b emissiontrue_res_04.out +9b440979b9ca82fa7070c7b1f27b5535 emissiontrue_res_05.out +d07f1f731ac2b2fb5d88636487bf3159 emissiontrue_res_06.out +673f3114a090e8c870386c4ccaa58670 emissiontrue_res_07.out +ca5455e0615ce87442f108aecade8184 emissiontrue_res_08.out +5ae48d0f11b3aa2d40ba1bed011f8b69 emissiontrue_res_09.out +7c66cc04453c72a541a4c41aceb1e99d emissiontrue_res_10.out +eabdb9b7da85ec0b448efdb1423faeba emissiontrue_res_11.out +f9a1403b96db72684a7d7b92100ab4b6 emissiontrue_res_12.out +23a59b7ca0e4de8bb6cba8ed721a8c58 emissiontrue_res_13.out +dd7ee140b67f0a955de677478734ef6d emissiontrue_res_14.out +27e2da5d0f35c6fbf7b5abb1c0bae7c6 emissiontrue_res_15.out +58eb22630756ea7d38c329c3293d6370 emissiontrue_res_16.out +648e9e490885daa8f2e7508a55071c95 emissiontrue_res_17.out +925576693253d48f6e6f58e3c4418bd1 emissiontrue_res_18.out +96efc8548edb5c9841362dd962eb989b emissiontrue_res_19.out +2f227afa08f4a69baf06d48ea0c988f2 emissiontrue_res_20.out +654e082e89438dde57b0c5235e956b35 emissiontrue_res_21.out +5c2fcdea4550a31e30494ec07b3ffc66 emissiontrue_res_22.out +1b3db815d03d9b04501af5b494fdf418 emissiontrue_res_23.out +e97c85c0ac6733a052a142ab8abd8aca emissiontrue_res_24.out +32a520ede0805ee203f0150f407c32c4 emissiontrue_res_25.out +575755b79be1b751b6ee1c8dace8fab8 emissiontrue_res_26.out +571fb8b9a81839c066c8d72856147e50 emissiontrue_res_27.out +6728ec6ca2a3066c5fa623177656c8ae emissiontrue_res_28.out +8db80faa9b9875ffbb7e3a4fa01020b4 emissiontrue_res_29.out +58dbe56880c24cc78307fdd1c8a55ccb emissiontrue_res_30.out +14ac5805ab04b2a9c393f9ca2950b057 emissiontrue_res_31.out +89b7b7b9ec2ed58bf562fa22fa226b24 emissiontrue_res_32.out +812f72d125ab03872072e4fc26dbea46 emissiontrue_res_33.out +ac6f10ac31723249295024d9bbbbb60f emissiontrue_res_34.out +4c93bd961af40cce65e965ff50050989 emissiontrue_res_35.out +86fd5e120cd616cc84beb949f350d650 emissiontrue_res_36.out +43e99e1ed566574590c31ad38a8af831 emissiontrue_res_37.out +f2316c2b2c4e05f08579bdd78d4f7b5b emissiontrue_res_38.out +a406ce2fbc4413fae82b41a22b70b07d emissiontrue_res_39.out +4a59935130506837fabee92061ec079f emissiontrue_res_40.out +83ff4353733c22454bb89bea9d2e1deb emissiontrue_res_41.out +7fe20cfabbee34ffd88c7da55e79b5b9 emissiontrue_res_42.out +0d79bdf1ade4f77498cfaf810374b96c emissiontrue_res_43.out +45252b532e2ed63e26f7379d058aef6d emissiontrue_res_44.out +b9461cd2890660aaff30b00f233ff418 emissiontrue_res_45.out +d2c6fe2274d94c8959f8006b574107dd emissiontrue_res_46.out +5eb66e3f430159039b2707e359c296e8 emissiontrue_res_47.out +d9216bbf46ff6b96e15fbc73d3e135d4 emissiontrue_res_48.out +23423a46cfda202d3d694e811cc4b856 emissiontrue_res_49.out +da61a6e58bc10253b858c36f94577b2d emissiontrue_res_50.out +d598f14efa3b839d22d6eb1c1b2e76f8 emissiontrue_res_51.out +100f1b4e8845f757330ccbb459fdde85 emissiontrue_res_52.out +5da734e0eb7dfb9f5119c99fa32bb916 emissiontrue_res_53.out +aa7d564a862ba27fa3e337d45c31736b emissiontrue_res_54.out +135243b92c9cb9bea0ddaa8101c29779 emissiontrue_res_55.out +d4751a4040f4edf6b39ec68677ba03b8 emissiontrue_res_56.out +3b06041b6c4c25f0104e54e9cc6603fa emissiontrue_res_57.out +d3fa0bdbca62c5723efccbc9547cf95b emissiontrue_res_58.out +b4a3a8e224d6613302831fb8afdd1324 emissiontrue_res_59.out +548aa5fcc03e8b48304a3f6b1a7ebe4e emissiontrue_res_60.out +6845fe4264d4a5fc312f98b59bce195f emissiontrue_res_61.out +9a89826c9428ce7542a6327e88eb5f05 emissiontrue_res_62.out +b52f7f84e12919295e365bbbf38d3ba2 emissiontrue_res_63.out +592f35fecab02ec4fd3e8d714ff68a5c emissiontrue_res_64.out +74db2a19584eb24f93e19a9d6f722011 emissiontrue_res_65.out +8bf2c6feb8945f3d65ca02dce595ee03 emissiontrue_res_66.out +f72c6aed2a96c39cc77b095188c6304b emissiontrue_res_67.out +8f8c10a2eea0d48577a4931954b35ac5 emissiontrue_res_68.out +b5e4a6a48940d622dc0b8f779984a3e7 emissiontrue_res_69.out +20d19a49fc0cc30d9bb5c310b491538a emissiontrue_res_70.out +b59e67844707421e22bc5c95c49a8232 emissiontrue_res_71.out +b33a17276c14ed72f6cf2c0606b0a572 emissiontrue_res_72.out +d6f0ed29a617cd58bfba3dce25b7385a emissiontrue_res_73.out +3df21e8727d8c3d9e77d19c6da123c98 emissiontrue_res_74.out +8caead6d03c23347fa29050112c8de9d emissiontrue_res_75.out +7b150b4ce4e7740bafc247c42af5dc58 emissiontrue_res_76.out +8e22a28a0ab68bedaa2514ba63e0ef22 emissiontrue_res_77.out +e9b370bd0943317aa03eeaac6d3d2a4a emissiontrue_res_78.out +5c5fda3d4acebc91a2a378b0b96843f2 emissiontrue_res_79.out +19287106c7522f24be3905a370b9f482 emissiontrue_res_80.out +ba05c071aefca66a86a33f7fb137a0d3 emissiontrue_res_81.out +f7c00c099a6fa453e75803589452e271 emissiontrue_res_82.out +c2053bcc119aa72dc5e2ee9b4c7a6217 emissiontrue_res_83.out +229aa692e64c57f939c9987b2719468d emissiontrue_res_84.out +3143e7888d41c65271d6f8b951c8f86a emissiontrue_res_85.out +6778a6bd72fd4da2c58bbdd0afe103d7 emissiontrue_res_86.out +54e6f51a71ffd7625f733d37f5738c5c emissiontrue_res_87.out +70fa3966f870d35357cdd9cec999de64 emissiontrue_res_88.out +3da0f5dc565dd9162cc502a319f4eab0 emissiontrue_res_89.out +1392e8bc22b15f9b488ddba0e8cc2797 emissiontrue_res_90.out +7549f96eb4c851e939445f6dfcf75d11 emissiontrue_res_91.out +d9db29877c28ec97b096bcc98ae4146f emissiontrue_res_92.out +ac23052815c09e9df452e822757cbb8c emissiontrue_res_93.out +f348d60cef0bd76caa65547dcd27653e emissiontrue_res_94.out +6525e0275b32c768ae093e02c3d64164 emissiontrue_res_95.out +27a8135ad55fe2d45f30cfc0c8adf069 emissiontrue_res_96.out +d209a20ccce09db376e216a4faab5b4e emissiontrue_res_97.out +cf22787c1df81526ab7a791c67d59130 emissiontrue_res_98.out +172f62814c541e36527b6cfaa35a4a94 emissiontrue_res_99.out +427f4ef57c2b89cc51e98967d7bb1146 gamma_light_curve.out +896f475a679a4cda4925616bf9dcbe45 gamma_spec.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -921bee473309a3ce383491ae0e960973 light_curve.out -45367bb87fbb87d83a989dd396432059 light_curve_res.out +a6a6464f48117ab5e832e0cf40a69537 light_curve.out +aeace87889f502b80eed411a12b1cc69 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -40f77198c2de368bdc98ef21639b1ecf packets00_0000.out -63f250cb7df583bc3ecb9393b550834b packets00_0001.out -1981cc7eb1a690d599e7927af9f34201 packets00_0002.out -2d7648f5c9a62b28ecbfd764fd148702 packets00_0003.out -bb247a6213ff848ca038d6c7368d9762 spec.out -f51cbb087c29f30368ed94046f8080e1 spec_res.out +7c9047bf83e16ab9cd90405a52d4ae5c packets00_0000.out +250cd2232b02b45d00b0f8d1537e84bb packets00_0001.out +a0b79bd4db24fc84eeeb5ce0d4db407b packets00_0002.out +2651bbb8863beedbb656010599fdedb3 packets00_0003.out +6aab1c1cac59a43cb2061f35f67a59c8 spec.out +a41d52678d1ee00fdf93cb04a961df44 spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -74da084e4d53ed6309a45a460870e39a job1/estimators_0000.out -aac96d617e8d1f4d38dfe8c8d3747358 job1/estimators_0001.out -17a1c6bcc9b4d66864fd278db2601a60 job1/estimators_0002.out -56468257da13a15505bb30f26c25c4be job1/estimators_0003.out +c7c1b38069253416fceabc75df32fb24 job1/estimators_0000.out +4a5ae634c6d659d9820f8f55578805be job1/estimators_0001.out +b5dded938b02ee865dbb01a0eb270e82 job1/estimators_0002.out +cf23efe6c288e101b5f85c87fab4261c job1/estimators_0003.out diff --git a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt index b35aea5a4..c28555fda 100644 --- a/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_2dgrid_xcomgammaphotoion_inputfiles/results_md5_job0.txt @@ -1,21 +1,21 @@ -ecb663d454dac15eb2ff74b4ca4c581d absorption.out +b9bd7c8e420130aa192f03ed6b8ba274 absorption.out 897316929176464ebc9ad085f31e7284 bflist.out -4390433658071b1024615d76491f7e4d deposition.out -22eaa6841bd5831a2087097c379f5c4e emission.out -2da765a27454802fe49aafb0b7978540 emissiontrue.out -8a96d831cb9626b727029d980ad1bb4d gamma_light_curve.out -2b769145664780d4f90b07f963588536 gammalinelist.out +55075156f9dc8dda218132cb72ae33a9 deposition.out +18368591effeddd3fa55a1c6f9e21993 emission.out +bca5e8879f1877502d7760c11a34cd1c emissiontrue.out +903350f9fb1a35a9c815ce773ef73484 gamma_light_curve.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out 29ac1cb06f3139df7cbca0bbdb426e1c grid.out -5e36aef9929f8ab61fa35cba5969663b light_curve.out +fcca5a673a45aec021f3ec01b1c54bdb light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -d7c33a4fc48a35472da38bd58bd7a66e packets00_0000.out -4e3fcb685c790aac6ba82d4ac4fb42e7 packets00_0001.out -58ebb999b4e2e9d4dfa0763f06ce88cf packets00_0002.out -71f446d85027c652e0a0ae80327b1e0f packets00_0003.out -bb3e8856c519696a8af781915be05c81 spec.out +1862c00c7ad6aaf770db4d53867fada2 packets00_0000.out +752233e91a4c331d99bfb7ac50bb5134 packets00_0001.out +d941f9103d61ace31db4b444388c1c26 packets00_0002.out +16e22719005e6657174f7b3596fa2a67 packets00_0003.out +35584535184d3d2f25868baba6c50eac spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -0a029585f75d28b146493a4ad8e072c9 job0/estimators_0000.out -8c285d9ee87777ac585a1afd2e1ea568 job0/estimators_0001.out -f2fccf596e474acc5e0ab17aee2e3b12 job0/estimators_0002.out -ead312ccff0e5916f5004e32beae8559 job0/estimators_0003.out +21e9a8637a411f17d8c18822f6645162 job0/estimators_0000.out +52c7f5f4f4775ee5be7071ca5922a41e job0/estimators_0001.out +b6f98a0633cbfc8993bc64c730993867 job0/estimators_0002.out +ed196efc59077c8f48ffc1c31f6bfb41 job0/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt index fb6833053..340853ed0 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_final.txt @@ -1,324 +1,324 @@ -931c97ffb5d4d9c9fd10cf1284387208 absorption.out -45fc92e39e41c375ae20d69e160572c9 absorption_res_00.out -158afae1f979b7b51a5711971c84c821 absorption_res_01.out -ca26598a8e991b08f2cc5ba1f37bd5ff absorption_res_02.out -3ece848c3c0e8c245276069672e4c479 absorption_res_03.out -5bca6c45b209ef1657dc89486aa23eab absorption_res_04.out -baf8d2827c63a2f84a635778e86b9b93 absorption_res_05.out -1b76fb486d17b76f148aad380eff6eed absorption_res_06.out -efe596a3c21db4b55607969cedc6e5ec absorption_res_07.out -bdd26207e0bf7f7fcb7593e980bda525 absorption_res_08.out -543ab9837681a6d2c0c4d6dd71a06d99 absorption_res_09.out -756ddfe504e396577a298050f4ec8e82 absorption_res_10.out -51976c1d4238b80b7d5f965afddd744d absorption_res_11.out -4fa3601d333b1171edbd9be2c28f19e8 absorption_res_12.out -7a0e77895411ebefda43c30734998a3c absorption_res_13.out -b936f574fdc2afb713d6d11c373d2d22 absorption_res_14.out -0b3183706d3507a85bb7545eca8042bf absorption_res_15.out -0835933cb9b8266e273eb9177ddc9466 absorption_res_16.out -972ecccfbe135137c1faf24fe02dc722 absorption_res_17.out -354c324a72d2148e03e90397b506c98a absorption_res_18.out -4e9ec25f7c87d5ecd66399ec4de70370 absorption_res_19.out -c4a3022dccf3f75162719f4dc055d4bc absorption_res_20.out -79bc69757d8a70ab5f8df7b5c7af9877 absorption_res_21.out -f73d9622514bd8a06eeafe39e2086d23 absorption_res_22.out -3410ef187f67fd3e7367057da7fbff05 absorption_res_23.out -3d6ec91bf43cbab49db4cb8f160ac414 absorption_res_24.out -e76b39f8eda9843ca94cc38313b9a05c absorption_res_25.out -d39a1024a883ddf281cf76f216ef3213 absorption_res_26.out -cf83afb6df1d75fa24215c17f7b5304e absorption_res_27.out -85cf48df266846bf8a40f9cd862647ba absorption_res_28.out -562beb760d8cb4f3c8f3d695f6392c86 absorption_res_29.out -f642de7b7c6733faafee267b4d9d3767 absorption_res_30.out -66b949dc8333823fcdd22f880db8ba99 absorption_res_31.out -fc98760a9f5cf3e86a26763b4a7ef6c1 absorption_res_32.out -cdb693ddb09a3fae645f17c83879f05a absorption_res_33.out -f7c0229ba7247a9e43e9ac2d35fa09c6 absorption_res_34.out -25599ba375ecec58b6ad25ec098acee9 absorption_res_35.out -4233503db76611ce865f25655f41c975 absorption_res_36.out -6bd67f7c4e4935e63ac585e6f15a2d9c absorption_res_37.out -da66d1158f211d1e9969b8db32999422 absorption_res_38.out -53bfecaf6887d2d3dcc3b0c9e218a15c absorption_res_39.out -fd5b9de30acfc77d6ecd4c2d35705fd9 absorption_res_40.out -95c28cbe1f4615c9b697d002d6058c68 absorption_res_41.out -1f68e28cda1eaad1420aada83a4974a7 absorption_res_42.out -25f4dedc15b0adb3b5c087a252197d27 absorption_res_43.out -350d405aabce54a59058300953ce74a4 absorption_res_44.out -4980f419b481860d4482191e8860b97e absorption_res_45.out -875662a4ece981353504708350c7fc2f absorption_res_46.out -0525bee34bb539407f3da46165ccf83c absorption_res_47.out -8c7bb374867c9b6602a4bc6512dbd968 absorption_res_48.out -e17b1b0d4ee8cff8fdae911d888e787f absorption_res_49.out -8af9e1db924c294821ee5242bc604609 absorption_res_50.out -5c8ac1e6b3db541009b78bb9a49ee090 absorption_res_51.out -8b21d319f4d5917cdff0ea54eb0d05f9 absorption_res_52.out -85e294aceffeb502d12a08585cc5c7fa absorption_res_53.out -9ce79225ae7678af0a3e8cdf583f86f2 absorption_res_54.out -91f3aaa50a065a05da424f14a9feb863 absorption_res_55.out -06705d8b1496eb85fe124e2c499fa39b absorption_res_56.out -8cd8977f01f190ac40bb7a69cf297355 absorption_res_57.out -e50250c7db5bab88f07c33ea40afd303 absorption_res_58.out -745153d716bbf36ee2c06993ee7ab609 absorption_res_59.out -becc501f78574398cf6a6153913af27e absorption_res_60.out -859340e7dc554e9ca62b6d3fc63c9528 absorption_res_61.out -862d77d746d5c1cdd3f1b327ad44cca7 absorption_res_62.out -d3f8c8696f2246cdef0c7d40c731d854 absorption_res_63.out -623e3e0a3a1e5210c1def3a007ef7bba absorption_res_64.out -bbbb9c213b0be6b3778a0f08039dcd68 absorption_res_65.out -aaeaa16e2d5448bdea04d54dccd5fd03 absorption_res_66.out -efec4fdd6c829b84f5f69c6a0b88392e absorption_res_67.out -8a04358a043d2542d9dacbcbcceae569 absorption_res_68.out -7fae37dc0355c76241856b387014c868 absorption_res_69.out -322c294a1a3655a2b5ddc10f38e813e1 absorption_res_70.out -4b3846f784e73144cb66c12513fa2484 absorption_res_71.out -8aac92bd56053c9c25c95888114f2d2f absorption_res_72.out -d3dc47009a90fbb60b742933ae198d90 absorption_res_73.out -816193467de45a82006ed18c6a9b1d31 absorption_res_74.out -84830e58bff187fc381a35d0128b7a99 absorption_res_75.out -d3dccea5e7478d18bdb32e71de66ab42 absorption_res_76.out -1fa0829e43b21e2890999ed9f0c52410 absorption_res_77.out -8fc9374480ac761c4e64ce2c013a7fe2 absorption_res_78.out -2af9d7c906aab8a53dd14386a81db8c8 absorption_res_79.out -5fb1a4fcee24abd1c2ad95fe99a01141 absorption_res_80.out -dc3d6fa13b48338d1d87e643e918ccf1 absorption_res_81.out -eb0428709342297aa5785dd6b3e53f4d absorption_res_82.out -20546f0d95299c712e8839c64e8ea3b7 absorption_res_83.out -d1030d11adc82a7b615187366af963f2 absorption_res_84.out -206951cd7e22e54f1d217313bad2d50a absorption_res_85.out -dff02f6d8a232e588449d5f4590bc03f absorption_res_86.out -309a8fe28c71aa426e35eaa3cfed1100 absorption_res_87.out -762b3d2ae1a0e8d4581e78655b3c2537 absorption_res_88.out -cae86777a7f7783a2265bf049db25998 absorption_res_89.out -f380f94e9e14263b10431187520faa4f absorption_res_90.out -d63d436d019d0111f372e41cc37f1a82 absorption_res_91.out -4db08a469f1e3035d70bb8c1c14c4b9f absorption_res_92.out -1f0898a6bbd27f5d1e6d2fc522128c86 absorption_res_93.out -e9a6edb0f9f9c0f0ca5e9b269172ea4c absorption_res_94.out -feb823b4debbc9c584a38fca3dfecab4 absorption_res_95.out -e5ceee3b7262cb62fb78cdca0ea59fa9 absorption_res_96.out -4c3c0b3b673d92b79f01e9a9f5d5f7d6 absorption_res_97.out -177d2331a3ff15e7d4e34f6d4574e0f7 absorption_res_98.out -f7b68c0636c7ca9bf007c942ad1d812f absorption_res_99.out +8b9b75805604f987b1b6f0828cb42db3 absorption.out +0551d308120d87afb4ae7bb26448669d absorption_res_00.out +d4614cfb1738a0043c442cb6d1d31b2e absorption_res_01.out +c9745095f39f0eadba084527ef947296 absorption_res_02.out +cce5e3efeb0ce0000f4ecb314eef4b6f absorption_res_03.out +e17a3d5e2adf9639ec994ba01caa9783 absorption_res_04.out +e1c834398786e283f9046a6c4e98584e absorption_res_05.out +5aba73c9bd48049a3b64f78a66f05900 absorption_res_06.out +6cfb529b94ac5c42aceb7d335889c1b3 absorption_res_07.out +2da5111c54d2448770b4f5ed0ec8cd46 absorption_res_08.out +a23252ab90c03c9807451dbd0efdbbc2 absorption_res_09.out +211241a31dd8981ddc970e4bb88fe7d3 absorption_res_10.out +c17a768d9eeb89536f21497f82cb6a0d absorption_res_11.out +c57922a16ed11bf4e277f509be43286f absorption_res_12.out +f881a18cc77970f2b4039c3f59187cd4 absorption_res_13.out +bc3b7c3a52308677de2c7ea3122fb4c9 absorption_res_14.out +c1a23cb79d39f336952044788f6fbb3c absorption_res_15.out +5f03830409c46f27a058d18bdb91d0fc absorption_res_16.out +f2446d93d2574ad69b1488adc3fd0fea absorption_res_17.out +897fa67124f134b88b780420e2061a78 absorption_res_18.out +2ad6461f163b705c292c2bd329cca3eb absorption_res_19.out +49e856b7d219ca928990cd99be2f462a absorption_res_20.out +76a0729e9ab96b6cba9a50bb000f6cad absorption_res_21.out +624dec0f4a3e3b0201a7c0ccdcf3ea67 absorption_res_22.out +6896a566f74d312c7c3cdccfc3614962 absorption_res_23.out +d2935d60651ca01a0a799460f23bf28f absorption_res_24.out +ed83b02f7a5b3cd1a8a7edcf57160e0b absorption_res_25.out +0975b60bcb856c80c22fa3edba68f48e absorption_res_26.out +b02f495b4e7f0e482a082d3515b459a8 absorption_res_27.out +808d297712afe998b0c13c8949d9dde7 absorption_res_28.out +df28db01e9bb6f0853500d2b5d62f8b6 absorption_res_29.out +dfe79e241d6f92f9455615adddbf298f absorption_res_30.out +7943b9d65e35836c73462c2901b77e13 absorption_res_31.out +06e59897305588d8df925774941c7a9d absorption_res_32.out +e70d8df69e45d26c9868684d8fdf20f4 absorption_res_33.out +7cdedb27f438b23a21af70aefd9e9d34 absorption_res_34.out +6b40a4d7256bca5d74711320fc6b8710 absorption_res_35.out +a617b98792820cd68d0e4ad4a6975cbd absorption_res_36.out +929f95591a7523ba46305002ed4f458e absorption_res_37.out +2b289ce261209e2a3144002cf064fdeb absorption_res_38.out +097fb6edc4e65fa328b09e2f863759f2 absorption_res_39.out +e8cc6a8aae67c130a52d0b3db53b12d3 absorption_res_40.out +0dd2ae93396ccd2d842d7572e73f98a2 absorption_res_41.out +531a81395ae22afb85cf087c36fb8423 absorption_res_42.out +67498246dc7bf81a48247b0be5f85836 absorption_res_43.out +0a3b2a6507b8606ea033fd834be19347 absorption_res_44.out +ef016c7c88a874a46f037801a785d08f absorption_res_45.out +0b5820e489ab4db618754cc002d6c92f absorption_res_46.out +060119b89514e06cd674a0ad834a5729 absorption_res_47.out +700afdba5372820582707e0f21bb7546 absorption_res_48.out +f8bc34345c4b8b1a672c40890590c887 absorption_res_49.out +0b38d20d0d636b165e9d0f34a6995d96 absorption_res_50.out +5100077a19c0e841147297565a2f1fab absorption_res_51.out +2e36bda515aef1289765143e66ddeebd absorption_res_52.out +d60cecbc01f14e359ecde93dd2e557a1 absorption_res_53.out +9170c0f069d1d19dab73ca097173d70a absorption_res_54.out +8439c5569078031926a13e98601941e4 absorption_res_55.out +31bbadf3c358ed5e8beaa2edfc8e06ec absorption_res_56.out +a40c5f842e9970278b8d11b9db2f179f absorption_res_57.out +7180b230bf242906ad22d7970eb5db5f absorption_res_58.out +3a10d28aaf56c8d5f665a5cdee1d3f35 absorption_res_59.out +d590a5e4bc21d3f48936b20eafd6aca7 absorption_res_60.out +5131b22f16df86fe67eb9dbbffac075b absorption_res_61.out +b28cf22d5bbff6efda089ec31f8ce06b absorption_res_62.out +cba500370895f2a704332ca5854cbda5 absorption_res_63.out +57751522bf57049499c029cf3d5f42c0 absorption_res_64.out +5930a61e295d3821ab634b3ed51b525f absorption_res_65.out +c18de766201199cad275e3ff98bee413 absorption_res_66.out +550f79e2668dde041d3ed1459069cccc absorption_res_67.out +d3e98214cc182a192afe867bac06b40e absorption_res_68.out +1421128310c2fd67fb24da5c873d0ff2 absorption_res_69.out +e4babe3083668c0630a002daabb9eff4 absorption_res_70.out +db6842b1a09d4cf2cf6449ef3d80820c absorption_res_71.out +6f92130f20f9e5291368efff6ec53db1 absorption_res_72.out +76b381586201fa12de17fff07c1e99b9 absorption_res_73.out +d29b6167fd1f22c26d91d6d0183b8fc7 absorption_res_74.out +f5c35b1711b466c9d05f59cfd3a19b84 absorption_res_75.out +b13c8d685f9cd11f909164d26f8806a2 absorption_res_76.out +de690e387cda986bd15186896fc1b3dd absorption_res_77.out +65f7209f0c5b11e78ca63b8f0a75dd93 absorption_res_78.out +6b2a1c709bb58790ebf1aa7f105eab57 absorption_res_79.out +8ad868e67883cf804ab7366f2c1f8719 absorption_res_80.out +20d989d87b6c7f06c36bc46523ea7f6b absorption_res_81.out +510d2937831222842531b34ffaa5298f absorption_res_82.out +b236cb2c45ffbaa93cbd48a821fe7faa absorption_res_83.out +97426be533e7e664f2a69b717a7a247a absorption_res_84.out +5744983c969ed16f20534b7376b4cd09 absorption_res_85.out +a24c8c2a57f2b1c7dc7af6b9f536958a absorption_res_86.out +206aff8e814da13666ed844bf67e6041 absorption_res_87.out +b106307b3aa5f08aa6368016b1688d3d absorption_res_88.out +79126439ea344bef1586bf4434ecf9ed absorption_res_89.out +77e05430c7cbd9eddfea152e2011c407 absorption_res_90.out +c04d23e12bd22d83e45bd6ec17e6db62 absorption_res_91.out +a4ced6ac3d845e3222ac704df9048858 absorption_res_92.out +9879b8ee7c6bba6ebda50bd51f9afdb0 absorption_res_93.out +d72374724f1e45758df903e98fe8322d absorption_res_94.out +1ca2186aa538bcc3102a475e741a6ed7 absorption_res_95.out +fecdca88f0e6ddac0b219a48dae20e1f absorption_res_96.out +c4bbd02f7c50e152861baaeb7f62a3fc absorption_res_97.out +58ea695525e4fab0c87814c03030c6c5 absorption_res_98.out +1fcfcad4b7dacf0777d47317f1f922b0 absorption_res_99.out f9bb214eb7f1ac22791a13c8025c4887 bflist.out -8b1a781723d7e9bcb2b03cac75dccdd4 deposition.out -3ca46c8cb5ca3f148548262e536aa502 emission.out -efb2a97f998b06b7a3ff16a5475405c5 emission_res_00.out -a42dabde264a364f813a89253d2b6799 emission_res_01.out -84167f306d8675235373c338a37e5024 emission_res_02.out -fa857d721e3a34d3e1a334a2a929cc8f emission_res_03.out -51782eaa0705606547e064c2526f9445 emission_res_04.out -2e14b027dbeb690482ea09750a9c67e0 emission_res_05.out -09f0210bec04a76457f377ac3462d8bf emission_res_06.out -fd61a7aba1d9eb9b6899651d241ba298 emission_res_07.out -04026ce955041f5d75d9cd391886df19 emission_res_08.out -eabcca1f3d5d584d5f8c35fe82d2caf9 emission_res_09.out -0d059a759689989fdd824bb791391da9 emission_res_10.out -25481b8e52aee29f5c85812602c79354 emission_res_11.out -c48574184e78d9ccb9ffae553e30f384 emission_res_12.out -51f24905da355a12e3ff05f6d7f5f512 emission_res_13.out -c3e3ec0c38e30504ec9ccc4e3e18ae4d emission_res_14.out -cb1f0d5fa32d63f65414337384e77393 emission_res_15.out -8d75c51213dbf4c99eea3b1e1258909f emission_res_16.out -d235e6113d6b52296ad453961bd20bd1 emission_res_17.out -5ca3083f45154a896a9a63c4b210a0bf emission_res_18.out -b5304475b5305a83705d95aac217b624 emission_res_19.out -07dffa4005e7eaca2abfacfeff9c38ac emission_res_20.out -640b0741add1dfb4ffea23e78175b7fa emission_res_21.out -ab8fcb310d470aec8bfa1c2cb692cf3a emission_res_22.out -3f63a6ccaee7203266e3e884837571b4 emission_res_23.out -631db0929de7dcda980ceaa28b205702 emission_res_24.out -43c98724f8bbe3c0abd0c181690873d8 emission_res_25.out -812a5ce219ea03ee1e4a87b157deb124 emission_res_26.out -8dbdec471531273000dcace8a14aa758 emission_res_27.out -9631d29fc0e9c81ee1d6bdc0a54b06c5 emission_res_28.out -1ccde2142e85ee944af651d62997b206 emission_res_29.out -e51cb80d790e9753fd45576be521b620 emission_res_30.out -0ac3b4058a71cf83e087995ab7638594 emission_res_31.out -98252c8b2479a8cd9dfb29243f74436c emission_res_32.out -3c37d6bb2ff7cee3c25b9062eb74a9f1 emission_res_33.out -4ee0abc14bce47ef04de014ce11638f4 emission_res_34.out -835811e35b298f41549bc92071400da4 emission_res_35.out -5c9fe9cc1d7fe59d75288ea24bd79b36 emission_res_36.out -53221fd3c2a2dffe03d3b69d553871c2 emission_res_37.out -190ef003c342968c064536e8342fea79 emission_res_38.out -6baa1cc1098fe5761da9148b02d07fca emission_res_39.out -5a74c088c4447ef8084e4baf4a55c143 emission_res_40.out -6f94628732892df9176f993c6bc2c6f3 emission_res_41.out -861582bcf4aa45f5ed71419b23939f4d emission_res_42.out -64a4f1a0e386e0458b5b644b6d3569de emission_res_43.out -28087c1e4014faaf9f637ea130ba73e3 emission_res_44.out -3874d4b6fe32b7a023cecff720130cb2 emission_res_45.out -8ad86da8eacf53e38355de574c2c227c emission_res_46.out -f31a39b4fa8e391134811cbf6b90dda6 emission_res_47.out -6c7ad623e88658314eb69fa685aab5d6 emission_res_48.out -32ab3cd0b2fb155ca57424df13803ba3 emission_res_49.out -714e6f74808bf4fc4167bd464a325456 emission_res_50.out -799b820709008d77b263b1ecc2633260 emission_res_51.out -008a75660dbb8ee8926e708f18680d00 emission_res_52.out -6fd7ba30e4e4bb38991ffba8f506c3d1 emission_res_53.out -8fe0c12b36bebf572e5beba70a8d9b40 emission_res_54.out -cb556ed989910b0681c03f8ce658c134 emission_res_55.out -75d8e66cc6bfc9976fd5e8371f5bc8de emission_res_56.out -d6fcff00cd33bf0a770266a61a701bda emission_res_57.out -1f7352a9e05b4c76412dc497bab215da emission_res_58.out -6364c1460bf27f6f552aee3ff0604a4a emission_res_59.out -443971b047db3b8a6a47672d70a78263 emission_res_60.out -254e2941d94d1611dc9c77a7bb1ef836 emission_res_61.out -7424c8ce30b08fcff6299695af7dde79 emission_res_62.out -78a3ee2a6710f9c5ebd93ab7a8657be8 emission_res_63.out -2a0642ce1914923a9d306e61be8dad4f emission_res_64.out -fe92a431f55a94c0cbfed14e14621833 emission_res_65.out -264e90b5ddf1b707c3cfa9b70024be9f emission_res_66.out -bc6bb0e72fb993f69950059a69941f06 emission_res_67.out -2f4fc837d59a59dda1715d96093a1ea6 emission_res_68.out -536a6bb78fa845eb5e65a5cb8de1db9e emission_res_69.out -945686d9ed8abfd7031f695cd8a5dd83 emission_res_70.out -798506de309f1878f94502b879497d4a emission_res_71.out -1265fb80e89ee15389da8dfce7b24a1c emission_res_72.out -03efa70ee26b750ec3470e1e280bf90f emission_res_73.out -4df2361ba3097710c6323947e15c0b24 emission_res_74.out -cbeb12b5858ace20b5f40d008b2ec9aa emission_res_75.out -eb7d4ad950d1cf86b645cc683c10bd6b emission_res_76.out -5c0ba65e3c2e74a9ef768f8d1b7ada50 emission_res_77.out -65665c6c9e4e011724bace6c0bbc4b9c emission_res_78.out -a5890a8a62f48d3d55bf09743b603d52 emission_res_79.out -20217cb15b379a51dd590fd03a3f0d28 emission_res_80.out -f44a34e336c7cc1b95e3ea2c3e12adb4 emission_res_81.out -5cf5dfa93d2deee8ff6bc9c6db2541b2 emission_res_82.out -9908642f26515576b9db5485134b6963 emission_res_83.out -b9b1239557508f025de7178882f8be22 emission_res_84.out -42d791ea9c7207b7e2e6668e64aff955 emission_res_85.out -60bde2e2dc48b57aabd70030e6e23c5a emission_res_86.out -965da381c5a3a2fec11ed72a6bae7346 emission_res_87.out -2cf6a1b6faa99e00dd805912659e0e1b emission_res_88.out -5c3b8e26184cac764d7129f529f2f5ef emission_res_89.out -e2551e1ddb39ab1cab6805837dbcefb3 emission_res_90.out -745de626b661c48712a2a25c5fc0c2a1 emission_res_91.out -087f89cbf65a727741bceac4eea78a2f emission_res_92.out -1f1b09dace020e65f7f1745505e8f672 emission_res_93.out -6798465db15a07927b58f0bac6bf4009 emission_res_94.out -5c28a2a329e5d5a125e27ea899d344cb emission_res_95.out -31b4846a82e8f1e96a05a006d9f6fbcb emission_res_96.out -9dce3bdab79270ebdc7e2dadbdb00d09 emission_res_97.out -cf5dd72a7476a489593cf09466f0fddc emission_res_98.out -c6333d10cab0ea07fcd2fd07c70034c3 emission_res_99.out -3f3294daf992f147d8ba87d0659eb026 emissiontrue.out -c98a0e115ff2bedc71ad5d06bc46cbdd emissiontrue_res_00.out -919980d48d9531e0e20489305fe0d589 emissiontrue_res_01.out -e3bd87a53c44b78dac244fc06774f74b emissiontrue_res_02.out -caafec683f8c23e9ef15298a21cae04b emissiontrue_res_03.out -b7b13cb06b213339f278033501a5c191 emissiontrue_res_04.out -9a29d54c35d6b7313f902c0b1bb7599d emissiontrue_res_05.out -af7960ee378bb3124c1ab6b99112e542 emissiontrue_res_06.out -9c6e5ae4c1d6d066e1484582c8619d74 emissiontrue_res_07.out -9b1032295003fc634de687165e6e9523 emissiontrue_res_08.out -234d4929bf4c1a4995afe41d76bb2684 emissiontrue_res_09.out -b53d480e51148fb0ed9d88219da3c5a7 emissiontrue_res_10.out -ec3739f05813a62d3c465c3641e321b8 emissiontrue_res_11.out -3b511944d1a92e2ddb296a17ae19bcbe emissiontrue_res_12.out -63988843a3d5374d313dd4ce5851777f emissiontrue_res_13.out -624b604d787e115400af1f5e91b44966 emissiontrue_res_14.out -88243dc5380ba936f0d167ec747924d4 emissiontrue_res_15.out -61fd8766ea2d51ffd3ce619f889fc341 emissiontrue_res_16.out -bf33621e63f720bd51bdcb39b9a41c57 emissiontrue_res_17.out -31070c2dc3784d4b4a13835b2ac179be emissiontrue_res_18.out -94a8e37157294185ed3d3717a63db709 emissiontrue_res_19.out -f46a303297c7f3e532518d3f710aebf7 emissiontrue_res_20.out -17515c627adec802ac58b8e5dcc6da5f emissiontrue_res_21.out -03871e2c3fd09ab9775212406c91e853 emissiontrue_res_22.out -fc0540cf5147f126fa258ad2136e716c emissiontrue_res_23.out -befdec2593fae1d4a72bb292b752f3d9 emissiontrue_res_24.out -e4c30cbc725e0f8c84fff1443c07c5ea emissiontrue_res_25.out -3eddded35fcaa06fdb0060da2cfc4697 emissiontrue_res_26.out -c58a4c9e446f49b73ee8e00d9740c32f emissiontrue_res_27.out -2e5ee93842799f852007f59efe6fa468 emissiontrue_res_28.out -5404de96ebf2632514809d2a627d0286 emissiontrue_res_29.out -c89ce7a0a2337b3c95d3067cbc7b313b emissiontrue_res_30.out -06175bb372384aa50d414479bc83da45 emissiontrue_res_31.out -f6a11f75bf997c7114086e73a1ed1275 emissiontrue_res_32.out -c3794d45a6d4515ccd180e3fc0bf3cf2 emissiontrue_res_33.out -b664347f4abf082718072a523df33ecd emissiontrue_res_34.out -72b434706d74faf90ddc6d1914c88c96 emissiontrue_res_35.out -6c69bf37e8362d2b499465db8804a5f7 emissiontrue_res_36.out -fb98e59aa0d7e98f6dcd9591781d7f9c emissiontrue_res_37.out -acc9b971f7c2b9b44933a46dd68ebcd0 emissiontrue_res_38.out -84866cb4b84925339c4ad052ddde01fb emissiontrue_res_39.out -5835326f44b75d54b472d968b381a4d5 emissiontrue_res_40.out -3804242eebe6e368996132c19a7c3e57 emissiontrue_res_41.out -47ed580bb2513aac5d82a0196d993299 emissiontrue_res_42.out -7d424c9b1ae15fb84f86df9dbc9ce73e emissiontrue_res_43.out -50864642b8e70949234375cfb9e48586 emissiontrue_res_44.out -2687f46746ea59871599adba8224767a emissiontrue_res_45.out -4e4feb446d944669f6a26997bd8876bd emissiontrue_res_46.out -6cf1970b4b46133a06bd0300ad55b320 emissiontrue_res_47.out -47d138a8e735fd40979c8d78936126b8 emissiontrue_res_48.out -595e0d0829f3b376162dcde00f8b0eff emissiontrue_res_49.out -c3c644b0bc99c6888b621da34db89868 emissiontrue_res_50.out -cc2f48d2af9ab2a631534e9fdd2f5877 emissiontrue_res_51.out -c1a82d76c64074f6ab510411def9238f emissiontrue_res_52.out -51c06170b630f3fded7db77131a89f1a emissiontrue_res_53.out -dc200d7bb90a3a5f03c8b021fa8a6480 emissiontrue_res_54.out -0ef6577077bf41bfbed269f2d4f2d525 emissiontrue_res_55.out -9bd253e45e94b52d1e5c9cede313a75d emissiontrue_res_56.out -5b131b9c46f11100e53a4ff46be6bfe9 emissiontrue_res_57.out -0934346f117b1291081b7a0a754df2c8 emissiontrue_res_58.out -c836a2c3155c1977e8832692d5d00ca6 emissiontrue_res_59.out -17be98f743fc2d96968fb41848de5680 emissiontrue_res_60.out -5740cace63535a3406ddf90941c3de10 emissiontrue_res_61.out -5a74bf3c318d4c15c4e201ea300ca358 emissiontrue_res_62.out -6cda2c7eb62e6d289632adf761c4dbab emissiontrue_res_63.out -a405c78d833b7bd37cc1b545304654fb emissiontrue_res_64.out -b7e6c1cfa8b61a5c9b6300df5635b522 emissiontrue_res_65.out -ba297d0e2780439288cc26837b6f55a9 emissiontrue_res_66.out -3d6e46cadc2fb50de64f2e8ba36c96e4 emissiontrue_res_67.out -f7bd48e9ad58f44fbe5519fefcc60174 emissiontrue_res_68.out -4d8e9c610776fc15b9ee0cfca9886e40 emissiontrue_res_69.out -22c7168316cfd353733f430e40ee33bc emissiontrue_res_70.out -7664328d845c0964bb4f62f25e2eb53f emissiontrue_res_71.out -15c5df41bc2bea7c55d12a8afa745be5 emissiontrue_res_72.out -2ca910467b8274e3b72f744daf5067f1 emissiontrue_res_73.out -7cbb4d5d43a9ece02b3d4c05b9f608cb emissiontrue_res_74.out -88c4afc2a954c48532d930bb5a5a1a5a emissiontrue_res_75.out -65fe497b52f19c9fd068dbcb4d8690e2 emissiontrue_res_76.out -3bc18b08834bcdaad251361d750d6341 emissiontrue_res_77.out -47d8f081b33c3e90aab80cda9ace5cc7 emissiontrue_res_78.out -e3789e5b54c3724f332ee38ca6657aa2 emissiontrue_res_79.out -e3504ef9a6abcc2ef00d68b435a862cf emissiontrue_res_80.out -d6b95930b9f4e2183ad797a168170114 emissiontrue_res_81.out -ca395553dfcc2a9f8461f46ae8505a52 emissiontrue_res_82.out -c8648b1db2f63eee19098a7d8b6bb78d emissiontrue_res_83.out -7e06d4e41af77f410bc8092389fa1bb3 emissiontrue_res_84.out -9b196a474cdaa9e1cc38d1cb635de7cb emissiontrue_res_85.out -5b55c6ae5fabd22aac576c590a0577f4 emissiontrue_res_86.out -ade09e7cfb4ffd8273057ff215b0a1a7 emissiontrue_res_87.out -191e742e7ee8c8135d43bc7916e3fc62 emissiontrue_res_88.out -925886a6ecbba522e0dcd8a5f7cf5e82 emissiontrue_res_89.out -20372b9bd4089b4134866cdc18af7408 emissiontrue_res_90.out -5775a7cac3e6fc0aba609811e1e81aeb emissiontrue_res_91.out -a19b09db4371baf6bb740dda2beae51a emissiontrue_res_92.out -c271b4ad987e592da9b037b41cb42781 emissiontrue_res_93.out -d8c570fc7b74510a75ea9f53de0da1ef emissiontrue_res_94.out -2e2384e2faa540b678c1970ecda87bd3 emissiontrue_res_95.out -a2aca5f8ea42526d6fb26f225059f724 emissiontrue_res_96.out -cf9f298b68301c0658d4c99feaa7ad13 emissiontrue_res_97.out -ec84019316219d6da3b5e775df634823 emissiontrue_res_98.out -32c54228f21daef517842c0312ebad67 emissiontrue_res_99.out -d5ce5bdb06e91519b27416a22f7100ff gamma_light_curve.out -980745142eda1cf04f5c89f10c3fc96b gamma_spec.out -2b769145664780d4f90b07f963588536 gammalinelist.out +a30e76659cec4f90e950a4439c5a60a9 deposition.out +72b4b475f9e62d723b6000d93aadb3d2 emission.out +009d9e3c4afd782eaad054e7dc28659e emission_res_00.out +9a3c8ea160a86ae4f494a26c80b7cf0f emission_res_01.out +7b81d452eecb942ff1979d016778d18b emission_res_02.out +88f6abf9ce3796b75e3249b5869d0b9c emission_res_03.out +a5bc9eef0b0852689d58c5650d1e56e5 emission_res_04.out +62c63e89f13e633462b6c22db616a92f emission_res_05.out +9a870b9e1e6b67a559f5b998b368bec5 emission_res_06.out +39ffdeddfd33f29d5374fd504af19adf emission_res_07.out +b5fa64d9aa58fb48dbb30610492e6e7d emission_res_08.out +77977adf28e2718d91b659f43b2b32f1 emission_res_09.out +6958e6bd2bef91bccebe15ab860b3f23 emission_res_10.out +13691d4816f580616ee4db397c54571c emission_res_11.out +5a9afd149b1b52c90ab975b90fcc097e emission_res_12.out +b54f0d7301e5310e312d21c61e2543b8 emission_res_13.out +a17d33178f5a89f76dde36054b02a9b4 emission_res_14.out +d124c1a87f0d18b3f7be3a0fab54b7fd emission_res_15.out +cadc9d7cd8eceb9620702d90af211d41 emission_res_16.out +3821b17b121db8f6195d3feefec1bdf3 emission_res_17.out +0e22c2f4b67c52cb4b46d7f3a58de2cc emission_res_18.out +164678ddf49b403c3175a9a2e3da5551 emission_res_19.out +b717a92038829e55840dc3d65e0bb7b5 emission_res_20.out +727e6002f8d575bc6fc814c75435efa9 emission_res_21.out +fdb63c2473a1ac8fdf54084e8a480e78 emission_res_22.out +f375baa4223488bf31f6af5aaa92274a emission_res_23.out +2b750d6a1fb351aa8c16ece23ddf49f7 emission_res_24.out +d007fe6faea05b813171f72d6906d1d0 emission_res_25.out +130fdb5d27f0fb155316b79f45f5822b emission_res_26.out +725e7e73ecce1970f5c82c3de0fa4dc1 emission_res_27.out +19830afbc3ed07c1f11d2caf95a299be emission_res_28.out +17afb0c235e1a64ab69a9db593206294 emission_res_29.out +15890383471f2ede4f46b3759430802a emission_res_30.out +88ab6e63cbc2718115b41a5cfa074772 emission_res_31.out +417826ebcf07c6d766d46c2e99146d31 emission_res_32.out +194a62b026ce457dc65d87c4db70a453 emission_res_33.out +b5d19ee965bb54aff17fbb7de3c861a0 emission_res_34.out +6031b50cfc9e0b5d6f1156a375bff56d emission_res_35.out +9c0b368459c4fc8b4a858dd858a39eca emission_res_36.out +878354ef4e3370d57db534df498037cc emission_res_37.out +dad9b998b1039097fdfc53d75f3fca7b emission_res_38.out +3ee46353e984d8b440b65723fbee320a emission_res_39.out +b16cf20f139bc13a7f8bcace24036dae emission_res_40.out +7ba660b5887bdf28577f9cec18fcc523 emission_res_41.out +ac3850e2ca7c36615992708d37b6b9ef emission_res_42.out +ff88827c8d4632496dbf1c7a4d92dcf2 emission_res_43.out +b55db503bf552672b68ca89a680d40c6 emission_res_44.out +d53e5376cceb6c5e04f1d8475b309c9e emission_res_45.out +f59af7a95f0a797fc42347415fcaaae7 emission_res_46.out +ce0ff677829340320077adf4e1a01cc3 emission_res_47.out +f896d158318acc54b70fd8c43b9bf104 emission_res_48.out +11c52429172f0fcdee5925843d43cb07 emission_res_49.out +6e406be2456a8ee0af8e2589113190fc emission_res_50.out +0149100c13ae05da720aa4c82615f9af emission_res_51.out +e4e2b61a9ae318aa9dd312389e2ddcad emission_res_52.out +f34feb0de9828c2360f3af4ea12a4190 emission_res_53.out +1a8f45902fd489cbcf1f3d1b4d30c05b emission_res_54.out +7dc3904e54e8f50e48d55e18a6ebbf72 emission_res_55.out +f472f1a505462a17f0d2b1ebd271db3b emission_res_56.out +cecd0a4fa74ffb3727931ae18d6063c6 emission_res_57.out +f43d393c383b77dc339e695fc76831c2 emission_res_58.out +09665a8fde5ad2d7ff9ed4092299c68a emission_res_59.out +92dbefa116c5f4876c77928b84a487bb emission_res_60.out +d7da5e601327e14c9e8e7433d56122fa emission_res_61.out +2f531f419580c3f719e30ecc8b727e46 emission_res_62.out +c7e7883f9d399e2b3e72a2961701809e emission_res_63.out +6803ae41aa008c721c2e99447be33d28 emission_res_64.out +bb2e608a75d11078b606f55eabbe3ab9 emission_res_65.out +82c3bf2c6217fa2709fe841f4af3ca5b emission_res_66.out +52e65ef938a38edc237b345c5245f37a emission_res_67.out +b79f740bd9415e247471c2f7bdc6ea3b emission_res_68.out +6bdb86c26b7714d66320198133f140a7 emission_res_69.out +5f7742012fc51766c0e89829cd919d49 emission_res_70.out +849d9097690feb58d08500f08a138b36 emission_res_71.out +d351f2c4a061133b676f9876b5c7ea9e emission_res_72.out +05f335d1292033ab3182654e75a76ef4 emission_res_73.out +2522843969b76b7a4312cdb992bbace8 emission_res_74.out +24e3ee9d1dceb1e7eb5a820b3e367174 emission_res_75.out +69357ce4b870bb5cdc92c20c2e3abec4 emission_res_76.out +88af99c954218b1af7be344357bb0947 emission_res_77.out +5489890871859e941feef0c6061a7a6f emission_res_78.out +a2ce74eb8d76450b62fbac9856d936e1 emission_res_79.out +284c46d7ec41cea0c0e01cd240efe455 emission_res_80.out +99b2b4b936364a295c1c11477b1dbab4 emission_res_81.out +0261b9ab09590f78efcdc2ba44767cdc emission_res_82.out +fd59a3e3addc2027f8206458fe2d216f emission_res_83.out +ddf40799d222c97b1c666d0745872e30 emission_res_84.out +645043fdc6c749a73e47eb9ed4f2f280 emission_res_85.out +ebee8ed0ff2a78074eb2c71980a89e0e emission_res_86.out +f210ee9ac6322ac7cc882b2e98926b7e emission_res_87.out +9bdac7a2978415f9ba9728e65a0d96c1 emission_res_88.out +6f931c884cb8905d50f92c2fac8b2a53 emission_res_89.out +e2ba6debe28389ab94c833a5d205ee0f emission_res_90.out +ad24a1de76284cbc776cedffb8af9b6f emission_res_91.out +584456dde74b74bcd0e89c14e9ec1732 emission_res_92.out +277ca64a1ca57745d99780993423f070 emission_res_93.out +5e195947c62cb304e021404013334e52 emission_res_94.out +a0e529485eda05ba386cd8902580697d emission_res_95.out +609bb1c64f29255783d457a44f130ac2 emission_res_96.out +8bf591b098d644a447832031d623f88b emission_res_97.out +c783b86cd41054e51d7f9700fe21fcb0 emission_res_98.out +2b74023913609ebeb58d45cc2981ae87 emission_res_99.out +7901b41731ff57dacf2a43f6a85fb954 emissiontrue.out +99a8c1bfb76cdb8efaa21b43bc011c9c emissiontrue_res_00.out +f7df1e45778324b1dcd83e332ba8ca4d emissiontrue_res_01.out +1b4b1ee33cb939432c53f5e5b4734369 emissiontrue_res_02.out +e94bbdba0d8fc6ed242bdcf12320a072 emissiontrue_res_03.out +a6fdd942e3eb73beb502303588491c02 emissiontrue_res_04.out +4be714add02b6cef837dfab9e2d4e10a emissiontrue_res_05.out +637cfc76c26eb7aab498c2ce61c24f38 emissiontrue_res_06.out +a6893940dbcdbed7eb9b1bae64532441 emissiontrue_res_07.out +900ffdde85f54b049e3adb6a044c7ce9 emissiontrue_res_08.out +3c2a251c85f4fc8745a1dee3cd7dcf0d emissiontrue_res_09.out +e9775553301330bc1ea2bd20f1ae6ed4 emissiontrue_res_10.out +98ccc036e97efab76fb0422f962020d6 emissiontrue_res_11.out +1012344e3d2eb73ab37227c72eb7e4c6 emissiontrue_res_12.out +2258769b4f9ffa70e5d8e622a18765e1 emissiontrue_res_13.out +1d2d457c0d87f17909ec8d0f0d26dbf6 emissiontrue_res_14.out +3411804ed0f7862f0399f8856155634f emissiontrue_res_15.out +6dc55360796b6bf5644f25b07841dc24 emissiontrue_res_16.out +aed1eb8176e4cb23f7eaec15870d5f40 emissiontrue_res_17.out +d63bd1084b8f5f4257141903e91b0964 emissiontrue_res_18.out +756cb9f34c9a9eddd865437b724d069e emissiontrue_res_19.out +1399028e68bc847daf407ad8b99c13af emissiontrue_res_20.out +90111501b2a873f2380e53ee1edf5b54 emissiontrue_res_21.out +6f48d433acdf92207d686b1186b7b560 emissiontrue_res_22.out +13b31e8d59d7091127f7eb026964bf7e emissiontrue_res_23.out +149e217bc3f87172e30effac0ece3bc2 emissiontrue_res_24.out +82317a6b3a8baef98f52a101e7e341f4 emissiontrue_res_25.out +3a35e360e562c0336400b2966f12d8e7 emissiontrue_res_26.out +6c912e4af865a54a51f80789f536343b emissiontrue_res_27.out +5b53fb685461505701532100ce01f8cd emissiontrue_res_28.out +e1f2de9c15200ce82970906832950e38 emissiontrue_res_29.out +0d63bdd13eb31d291a5238278671f4cb emissiontrue_res_30.out +3775535f8271d6895ce5e73ee79136d3 emissiontrue_res_31.out +77ed9b185aa6939eb247ca0b2d8d9ea6 emissiontrue_res_32.out +6520d08607dc503091ad9080a0aab8f1 emissiontrue_res_33.out +b70482d169b6421f701eb8c6a1e43c32 emissiontrue_res_34.out +4e7fecf280a26d54f36e6417101650b7 emissiontrue_res_35.out +224a4dc4a1903af3804ae0aceecae94a emissiontrue_res_36.out +01593a366993ce7d3c1d4ebc5cb951a3 emissiontrue_res_37.out +5a813d431106c488b358447f8e15935c emissiontrue_res_38.out +541776bef9099e464562a20ecd66b82d emissiontrue_res_39.out +99c151d09479c6d69a8c6c0ff428d984 emissiontrue_res_40.out +366010e639a618d1478b0f142fcbf9a3 emissiontrue_res_41.out +b7a09073b1d491aaa59c69c333fcfe0b emissiontrue_res_42.out +dc97c0808f2a90b890e84d29337cfb6e emissiontrue_res_43.out +04579165d72b9d2f385b9e3c72569442 emissiontrue_res_44.out +8fa9fdf2fe2c530306796fcc1c447835 emissiontrue_res_45.out +809e15ffa15e1a850953d67dfe655479 emissiontrue_res_46.out +aca1a71bc93b9cf117a6dca7cb1418be emissiontrue_res_47.out +3e779cff13d7eb6f032953fc68a53c3b emissiontrue_res_48.out +bd5c013d1e7f4d2a12c1d0c0009a1412 emissiontrue_res_49.out +96c8154eb6e0b09068796adfac90f811 emissiontrue_res_50.out +e96b4626dd9ba1491ae8ffe22be94eeb emissiontrue_res_51.out +ddb69de4e68a6eb61173f1c19335531b emissiontrue_res_52.out +118cb5dd3a1b90ba63ff190f762bac2e emissiontrue_res_53.out +a95fafbe80dee0c572f033c48c8ff8e1 emissiontrue_res_54.out +09f8973842e75d04ad96efefafd46ec5 emissiontrue_res_55.out +254f7c547ea0576a876d51a69a2ce927 emissiontrue_res_56.out +8380c66162f45e7afdd51d0a545a308a emissiontrue_res_57.out +f247bfddac8bc59ba1c1168d64ffc198 emissiontrue_res_58.out +b96fac3728fd28b10b4b97554ff171b2 emissiontrue_res_59.out +6b2abdd66e2e074a2ada67f7f8d9fc44 emissiontrue_res_60.out +9bf5778d156361fb40d0d6b1b4c2d2c2 emissiontrue_res_61.out +fce2b17184161d1c401d9d65bc5cb7ee emissiontrue_res_62.out +d6c5bade61096f6af740d392f4c18e58 emissiontrue_res_63.out +be4b519ee946788f3399bb65c0d389b1 emissiontrue_res_64.out +138959428d444fd63e291623080f3e47 emissiontrue_res_65.out +278af585b80e8057fc40564be99e3b8d emissiontrue_res_66.out +5e579e4c17497158182f04827f7ec0d9 emissiontrue_res_67.out +9f315c665f4e588862725c7df0871ecc emissiontrue_res_68.out +559c1caad6dff0e288a3e8d1c286656e emissiontrue_res_69.out +07c4ad426d1e8ff83cc9e173827f4081 emissiontrue_res_70.out +52dd50bc9ac6a5a4861eed0fc91ce411 emissiontrue_res_71.out +bcaa7352e6fc78b32c22fcb143c97664 emissiontrue_res_72.out +c02189045f227b31173f29f3234d1ab4 emissiontrue_res_73.out +c0d0352255df14bed530b0fcbdfff6c7 emissiontrue_res_74.out +d49e482ad99e90282c6528dddaad19a0 emissiontrue_res_75.out +833f8523bffa01b014033481ec23c601 emissiontrue_res_76.out +4f5cf7e4e2a08d1aa122319149daeee0 emissiontrue_res_77.out +9906c0d321f3b602c09d7d2f9a82388e emissiontrue_res_78.out +1ecb96423e45c467415015b1e8f9f590 emissiontrue_res_79.out +ed2b4ac6e34056c35b5a900c1a86e1d2 emissiontrue_res_80.out +53d964ff1c35d21eb1f5ecd634276e4a emissiontrue_res_81.out +607e926a4a12fb4575c6352939f25539 emissiontrue_res_82.out +bd7e40019b41ed3b0183526365a8de26 emissiontrue_res_83.out +bc1296075d86cbf04c104b6ce0b4165f emissiontrue_res_84.out +5dd88bebfcb9758ea8571b3287f47801 emissiontrue_res_85.out +51b304e4d759f63f6ca34885388f0ccb emissiontrue_res_86.out +38525aa4e05379ea6430fd0cf307a461 emissiontrue_res_87.out +4b47c8bc5193a3d385c5b13978f88857 emissiontrue_res_88.out +146d50c91f64be3481ae49efba1c0041 emissiontrue_res_89.out +cf1795ddd8174def5f05971014b8ce64 emissiontrue_res_90.out +8876d97488157998777ed47bcb9e303e emissiontrue_res_91.out +e4e2319aaa3cb1a2be86be51cc76a142 emissiontrue_res_92.out +e652fd662e8adfde1d8466ad50f7de4f emissiontrue_res_93.out +70d3eedee2e461cc9400740e95c3c570 emissiontrue_res_94.out +caa81b0ebd448c8f05b9c96f47bc8240 emissiontrue_res_95.out +266cbe1762d8ee65caf46c7151660a40 emissiontrue_res_96.out +cffd09b89712aa2de6496daeb68bf4fc emissiontrue_res_97.out +621ab521fe9dcf5be05fa15c67b3f9df emissiontrue_res_98.out +b7487d4c7cc2e74821bfdfc832e8c010 emissiontrue_res_99.out +7a91154fe2bbae3499196ba1dbc7842b gamma_light_curve.out +9f20343023e66b309e4fd7d850700ae2 gamma_spec.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -96ea3e3328e70b4491ffe0d55e853b29 light_curve.out -7e4a49bf389bf336c0745b602e21468f light_curve_res.out +8c9487755e6433e190e01304936cb1c7 light_curve.out +e7377cfeaf6152a11236f11d1b7368e7 light_curve_res.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -9ac2e742736a386964564a7a03f426db packets00_0000.out -5ff366aa042aca37c22e262e97876ef1 packets00_0001.out -6ae2565142cbf1ae6c652342468d3d67 packets00_0002.out -7d9cbc99445626402d07bd66f0556aeb packets00_0003.out -a1d482542b13466b0b7976654de18bee spec.out -9f902c07f4dd9d8ca3664cab3dea060a spec_res.out +afadb21a9122004dc5a49ca2d9683575 packets00_0000.out +b5f195c27bf5674e707ce9bda8f64847 packets00_0001.out +2aefbe08c8db35a049c0cc9fbf019519 packets00_0002.out +229bf6430bf5d343bc565cf005d3349a packets00_0003.out +726c278b2d9720d0cec3cbfe59215420 spec.out +6bdc94f2b5e4fc97ae6279912ac645dc spec_res.out a351f1711fecd60c023d0ba7332092db timesteps.out -6c6c02e417fd289811b9a3f1071d974d job1/estimators_0000.out -b9fe9ebe83ed5cea006834f825349bfe job1/estimators_0001.out -b933e40d7f87bf73b8c56bbbdc035037 job1/estimators_0002.out -a494bfcfce9d35ca15cb9633e7b3d7cf job1/estimators_0003.out +d0daa40f06d0df3fd0e35a71aea4a6dd job1/estimators_0000.out +f7b8fd32c7cfcbfd9b355f1c1599c137 job1/estimators_0001.out +b160125cc2e19c4b54d3a94f260e290c job1/estimators_0002.out +533b4323db702788bf2058c07a490ad4 job1/estimators_0003.out diff --git a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt index 81be18378..e28c817a9 100644 --- a/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt +++ b/tests/kilonova_2d_3dgrid_inputfiles/results_md5_job0.txt @@ -1,18 +1,18 @@ f9bb214eb7f1ac22791a13c8025c4887 bflist.out -7909ca40a46c503427a3668ec9512c2f deposition.out -c657b77e4d00bad2650f40ed0f2ca494 gamma_light_curve.out -2b769145664780d4f90b07f963588536 gammalinelist.out +091644c279a655fb21bb5e512ea00265 deposition.out +2ea6f21e9602c465e5ff9cc012889fa7 gamma_light_curve.out +39151bd4001a12fb66ba18af93d71d39 gammalinelist.out b72b67aae10074c2b0915aaad7d9ccbc grid.out -2c912821e702307536768d4a714fd680 light_curve.out +dd3e893742897aca1b7b6ca0d668606f light_curve.out 3d4b61fa5c0c8987526ebd71787cb8ea linestat.out d80043ce6bedca56511b9fd3f7c0a49f modelgridrankassignments.out -4f87a99a2945c219881086c9ef1e0304 packets00_0000.out -cf6d2847ed627f6018794964232f3e60 packets00_0001.out -2d6fe04c6e5b997d2b1ae1f28833a7fb packets00_0002.out -f8a58f999a95e3dd96ef3797c04a8f1a packets00_0003.out -efeeac5b0345ab0e40d5eab91e7c8b13 spec.out +c96a93a4aa4b26b4b4400816313a9ca4 packets00_0000.out +24139c21b1efbca8a9ad7e517c2e326f packets00_0001.out +ff4b1a613b906a408811460740b01b7c packets00_0002.out +49584a89e33482c567ab45a20387964a packets00_0003.out +55154814d694ee0d1e6ddbacf3e550f7 spec.out a351f1711fecd60c023d0ba7332092db timesteps.out -62783f048fc6a50fd8eec41d80a98cca job0/estimators_0000.out -2be2d54a38f9d5c0136a0c74bf023983 job0/estimators_0001.out -1a223ba1b090edeb6c14d4450878a1d1 job0/estimators_0002.out -55044a8a50537fa2fbac942f95112038 job0/estimators_0003.out +99af9f7157153f1875cdb7d4a1b0adb7 job0/estimators_0000.out +3aac0d2d33b46cd6c187ebaacaa6005d job0/estimators_0001.out +bd5f6a2e8610b3a2c730c5ae233622fb job0/estimators_0002.out +bbcd601c18c2e6ec48f08bed79d6c3a0 job0/estimators_0003.out From 79fca84bae8d0f71c0919d22745a86b1faf0051f Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 9 Dec 2024 11:26:50 +0100 Subject: [PATCH 112/117] Fix exspec bash script file detection (avoid wildcard) --- .gitattributes | 1 + scripts/exspec-after.sh | 2 +- scripts/exspec-before.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index d1c51d251..1b4132b1c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,4 +14,5 @@ Makefile text eol=lf *.jpg binary *.gz binary *.xz binary +*.zst binary *.zstd binary diff --git a/scripts/exspec-after.sh b/scripts/exspec-after.sh index f15144aa5..8411f5377 100755 --- a/scripts/exspec-after.sh +++ b/scripts/exspec-after.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # only compress the files if we successfully ran exspec -if [ -f emission.out* ]; then +if [[ -f emission.out || -f emission.out.zstd ]]; then # zstd does decent compression at high speeds cmdcompress="zstd -T0 -16 -v --rm -f" diff --git a/scripts/exspec-before.sh b/scripts/exspec-before.sh index fcf266cbf..a0480d3ed 100755 --- a/scripts/exspec-before.sh +++ b/scripts/exspec-before.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # packet output files outside the artis folder, so move them back to run exspec -if [[ ! -f packets00_0000.out* && -f packets/packets00_0000.out* ]]; then +if [[ ! -f packets00_0000.out && ! -f packets00_0000.out.zst && -f packets/packets00_0000.out.zst ]]; then mv packets/packets*.out* . fi From 2af98310c00d25271522add3dc3ccdbf656b5882 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 9 Dec 2024 11:26:50 +0100 Subject: [PATCH 113/117] Fix exspec bash script file detection (avoid wildcard) --- scripts/exspec-before.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/exspec-before.sh b/scripts/exspec-before.sh index a0480d3ed..3c458453b 100755 --- a/scripts/exspec-before.sh +++ b/scripts/exspec-before.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # packet output files outside the artis folder, so move them back to run exspec -if [[ ! -f packets00_0000.out && ! -f packets00_0000.out.zst && -f packets/packets00_0000.out.zst ]]; then +if [[ ! -f packets00_0000.out && ! -f packets00_0000.out.zst && (-f packets/packets00_0000.out || -f packets/packets00_0000.out.zst) ]]; then mv packets/packets*.out* . fi From b91d60f0233c566f102a8b0c6cf6dacf21d160cf Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Mon, 9 Dec 2024 15:19:27 +0100 Subject: [PATCH 114/117] De-duplicate alphadecays.txt --- data/alphadecays.txt | 74 -------------------------------------------- 1 file changed, 74 deletions(-) diff --git a/data/alphadecays.txt b/data/alphadecays.txt index 05c6bc596..a858f6b54 100644 --- a/data/alphadecays.txt +++ b/data/alphadecays.txt @@ -24,115 +24,41 @@ 213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 -209 83 0 0 0 0 0 0 0 0 214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 -210 82 0 0 0 0 0 0 0 0 215 82 0 1 36 0 2.9 0.0000000000000000 0.96699999999999997 0.0000000000000000 215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 -207 82 0 0 0 0 0 0 0 0 216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.55950000000000000 -208 82 0 0 0 0 0 0 0 0 217 83 0 1 98.5 0 2.92 0.0000000000000000 0.97333329999999996 0.0000000000000000 217 84 1 0 1.53 6.66022 0 6.66022 0.0 0.0 -213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 -209 83 0 0 0 0 0 0 0 0 218 83 0 1 33 0 4.819 0.0000000000000000 1.2965430000000000 1.3470000000000000 218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 -214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 -214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 -214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 -210 82 0 0 0 0 0 0 0 0 219 84 0 1 3e-07 0 2.405 0.0000000000000000 0.80166669999999995 0.0000000000000000 219 85 0.97 0.03 56 6.324 1.566 6.0220000000000002 0.0000000000000000 1.6410000000000001E-002 219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 -215 83 0 1 462 0 2.189 0.0000000000000000 0.10956380000000000 0.76190000000000002 -215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 -207 82 0 0 0 0 0 0 0 0 220 84 0 1 3e-07 0 1.113 0.0000000000000000 0.37100000000000000 0.0000000000000000 220 85 0.08 0.92 222.6 6.05 3.74 0.47539999999999999 0.37246040000000002 1.1679999999999999 220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 -216 83 0 1 135 0 4.0901 0.0000000000000000 1.3633679999999999 0.0000000000000000 -216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 -208 82 0 0 0 0 0 0 0 0 221 85 0 1 138 0 2.341 0.0000000000000000 0.78033330000000001 0.0000000000000000 221 86 0.22 0.78 1542 6.148 1.194 1.1980000000000000 0.11954239999999999 0.25009999999999999 221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 217 85 1 0 3.230000e-2 7.201300 0 7.0629999999999997 0.0 0.0 -217 84 1 0 1.53 6.66022 0 6.66022 0.0 0.0 -213 82 0 1 612 0 2.04634 0.0000000000000000 0.68211199999999994 0.0000000000000000 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.1974000000000000 -209 83 0 0 0 0 0 0 0 0 222 85 0 1 54 0 4.427 0.0000000000000000 1.4756669999999998 0.0000000000000000 222 86 1 0 330350 5.5903 0 5.4889999999999999 3.8892149999999998E-004 0.0000000000000000 -218 84 0.9998 0.0002 185.88 6.11468 0.26 6.0010000000000003 9.1147460000000002E-006 1.4340000000000000E-005 -214 82 0 1 1608 0 1.019 0.0000000000000000 0.23927909999999999 0.22469999999999998 -214 83 0.00021 0.99979 1194 5.6168 3.27 1.1470000000000000E-003 1.4756929999999999 0.64000000000000001 -214 84 1 0 0.0001643 7.83346 0 7.6870000000000003 8.3017219999999997E-005 0.0000000000000000 -210 81 0 1 78 0 5.482 0.0000000000000000 2.5009739999999998 1.2160000000000000 -210 82 0 0 0 0 0 0 0 0 223 85 0 1 50 0 3.167 0.0000000000000000 1.0556669999999999 0.0000000000000000 223 86 0 1 1458 0 2.012 0.0000000000000000 0.30934079999999997 0.52660000000000007 223 87 6e-05 0.99994 1320 5.562 1.1492 3.2770000000000000E-004 4.8698349999999994E-002 0.34560000000000002 223 88 1 0 987552 5.9793 0 5.6650000000000000 0.13356070000000000 0.0000000000000000 -219 86 1 0 3.96 6.9461 0 6.7549999999999999 5.8128189999999996E-002 0.0000000000000000 -215 84 0.999998 2.3e-06 0.001781 7.5263 0.715 7.3879999999999999 3.0021600000000001E-004 0.0000000000000000 -211 82 0 1 2166 0 1.367 0.0000000000000000 6.3723440000000006E-002 0.44550000000000001 -211 83 0.99724 0.00276 128.4 6.7503 0.574 6.5490000000000004 4.7661610000000000E-002 4.7720000000000000E-004 -211 84 1 0 5.160000e-1 7.594500 0 7.4420000000000002 8.0287729999999995E-003 0.0000000000000000 -207 81 0 1 286.2 0 1.418 0.0000000000000000 2.3805810000000001E-003 0.49160000000000004 -207 82 0 0 0 0 0 0 0 0 224 86 0 1 6420 0 0.783 0.0000000000000000 0.26100000000000001 0.0000000000000000 224 87 0 1 199.8 0 2.83 0.0000000000000000 0.53339530000000002 0.83460000000000001 224 88 1 0 316224 5.78887 0 5.6730000000000000 1.0388479999999999E-002 0.000000000000000 -220 86 1 0 55.6 6.40467 0 6.2869999999999999 6.2838309999999997E-004 0.0000000000000000 -216 84 1 0 0.145 6.9063 0 6.7780000000000005 1.5305070000000002E-005 0.0000000000000000 -212 82 0 1 38304 0 0.5699 0.0000000000000000 0.14333779999999999 0.10020000000000001 -212 83 0.3594 0.6406 3633 6.20726 2.2521 2.1750000000000003 0.10401439999999999 0.49390000000000001 -212 84 1 0 2.99e-07 8.95412 0 8.7850000000000001 0.0000000000000000 0.0000000000000000 -208 81 0 1 183.18000000000001 0 4.999 0.0000000000000000 3.3806279999999997 0.5595000000000000 -208 82 0 0 0 0 0 0 0 0 225 86 0 1 279.6 0 2.74 0.0000000000000000 0.57196979999999997 0.75570000000000004 225 87 0 1 237 0 1.82 0.0000000000000000 0.60666669999999989 0.0000000000000000 225 88 0 1 1.28736e+06 0 0.357 0.0000000000000000 1.3983770000000000E-002 9.2390000000000000E-002 225 89 1 0 864000 5.9351 0 5.7759999999999998 1.5370379999999998E-002 0.0000000000000000 -221 87 1 0 294 6.4576 0 6.3559999999999999 2.8574259999999997E-002 0.0000000000000000 -217 85 1 0 3.230000e-2 7.201300 0 7.0629999999999997 2.1010950000000000E-004 1.6039999999999999E-005 -213 83 0.022 0.978 2735.4 5.982 1.423 0.12220000000000000 0.12653610000000001 0.42399999999999999 -213 84 1 0 4.2e-06 8.537 0 8.3759999999999994 3.7382399999999996E-005 0.0000000000000000 -209 81 0 1 132 0 3.977 0.0000000000000000 2.1421209999999999 0.65539999999999998 -209 82 0 1 11710.8 0 0.644 0.0000000000000000 0.0000000000000000 0.19740000000000002 -209 83 0 0 0 0 0 0 0 0 226 86 0 1 444 0 1.401 0.0000000000000000 0.46699999999999997 0.0000000000000000 226 87 0 1 49 0 3.671 0.0000000000000000 0.43404640000000000 1.1910000000000001 226 88 0 0 0 0 0 0 0 0 From 90facb5f1c18f757f5d7f82880b9ce64079fc3b7 Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 11 Dec 2024 11:48:09 +0100 Subject: [PATCH 115/117] Compile with march=native on GSI Virgo --- Makefile | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 7f5c4d68a..a3b26e445 100644 --- a/Makefile +++ b/Makefile @@ -148,30 +148,17 @@ ifeq ($(shell uname -s),Darwin) # CXXFLAGS += -Rpass-missed=loop-vectorize # CXXFLAGS += -Rpass-analysis=loop-vectorize - # add -lprofiler for gperftools - # LDFLAGS += $(LIB) - # LDFLAGS += -lprofiler - else - # sometimes the login nodes have slightly different CPUs - # to the job nodes. Try to find the lowest common denominator here - # to enable vector extensions - # CXXFLAGS += -march=cascadelake - # CXXFLAGS += -march=skylake-avx512 - # CXXFLAGS += -march=icelake-server + # sometimes the login nodes have different CPUs + # to the job nodes. march=native assumes that they are the same + # (or that the job CPUs support all features of the login CPUs) # to get the current CPU architecture, run this: # g++ -march=native -Q --help=target | grep -- '-march= ' | cut -f3 - ifneq (,$(shell hostname -A | grep gsi.de)) - # virgo has some AMD nodes and some Intel. - # As of 6th July 2024, the login nodes are cascadelake, and we select zen3 nodes to run on. - CXXFLAGS += -march=x86-64-v3 -mtune=znver3 - else - # for GitHub actions, checksums must match with different assigned CPUs, so avoid -march=native (use lowest common denominator) - # update: all zenver3 now? - CXXFLAGS += -march=native - endif + CXXFLAGS += -march=native + + # CXXFLAGS += -march=icelake-server endif From 1182745007557ff4e5691499107e7428220aff7c Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Wed, 11 Dec 2024 11:49:34 +0100 Subject: [PATCH 116/117] Add new virgo partition to jobscript --- scripts/artis-virgo-submit.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/artis-virgo-submit.sh b/scripts/artis-virgo-submit.sh index e66f20186..968859cb5 100755 --- a/scripts/artis-virgo-submit.sh +++ b/scripts/artis-virgo-submit.sh @@ -2,3 +2,6 @@ export APPTAINER_SHARENS=true export APPTAINER_CONFIGDIR=/tmp/$USER sbatch -J $(basename $(exec pwd)) --ntasks=1920 --ntasks-per-node=128 --mem-per-cpu=2000MB --partition=long --time=24:00:00 --constraint=amd,epyc,7713 --mail-type=ALL --mail-user=${USER}@gsi.de --no-requeue -- artis/scripts/artis-virgo-slurmjob.sh + +# AMD EPYC 9654 with 192 real cores per node and 4 GB/core. march=znver4 +#sbatch -J $(basename $(exec pwd)) --ntasks=960 --ntasks-per-node=192 --mem-per-cpu=2000MB --partition=new --time=24:00:00 --mail-type=ALL --mail-user=${USER}@gsi.de --no-requeue -- artis/scripts/artis-virgo-slurmjob.sh From f28074818c8b4c6a32777124b03ab1c5714f111c Mon Sep 17 00:00:00 2001 From: Luke Shingles Date: Tue, 17 Dec 2024 10:12:19 +0000 Subject: [PATCH 117/117] Rename 'CI Slow' to 'CI Extensive Test Mode' --- .github/workflows/cislowtestmode.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cislowtestmode.yml b/.github/workflows/cislowtestmode.yml index 055297cdb..97fff5a75 100644 --- a/.github/workflows/cislowtestmode.yml +++ b/.github/workflows/cislowtestmode.yml @@ -1,5 +1,5 @@ --- -name: CI Slow +name: CI Extensive Test Mode on: push: