From 0627182425213bab4dafe3f758179cb8ae59a06b Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Thu, 19 Mar 2026 11:06:43 -0500 Subject: [PATCH 01/33] Split plasma_dummy and macro_dummy into sub-structs for future shared/private MPI memory model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is Phase 1 of a plan to reduce memory usage when running Sirocco with many MPI ranks on a single node. Currently every rank holds a complete copy of plasmamain and macromain (~700 MB per rank for a 10K cell macro-atom model). The goal is to enable MPI-3 shared memory windows so that ranks on the same node share one read-only copy of plasma state, while each rank maintains its own private copy of the estimator arrays that are accumulated during photon transport. The key difficulty is that during photon transport, all ranks write estimator fields (j, heat_tot, heat_lines, etc.) to any cell a photon passes through, so the plasma struct cannot be naively placed in shared memory. The solution is to separate fields by their MPI communication pattern, so that in a future phase the read-only and accumulated portions can be allocated in different memory regions. STRUCT REORGANIZATION (source/sirocco.h): The monolithic plasma_dummy struct (~100 fields) has been split into three nested sub-structures, categorized by how each field is used during the MPI-parallel photon transport phase: plasma_state (read-only during transport): Fields that are set during initialization or wind updates and only read during photon transport. Includes ne, rho, vol, xgamma, t_r, t_e, w, density[], partition[], levden[], recomb_simple[], kbf_use[], spectral model parameters (pl_alpha, exp_temp, spec_mod_type, etc.), and kappa_ff_factor. In a future shared-memory phase, this sub-struct will be placed in an MPI shared window visible to all ranks on a node. plasma_estimators (accumulated during transport, reduced across ranks): Fields that every rank increments via += as photons traverse cells. After transport, these are summed across ranks by reduce_simple_estimators() using MPI_Allreduce. Includes j, j_direct, j_scatt, ave_freq, ip, heat_tot, heat_lines, heat_ff, heat_comp, heat_photo, cool_tot, kpkt_abs, xj[], xave_freq[], rad_force_es[], F_vis[], F_UV[], cell_spec_flux[], ioniz[], heat_ion[], and photon passage counters (ntot, nioniz, etc.). In a future phase, each rank will hold a private copy of this sub-struct. plasma_derived (computed during wind updates, broadcast to ranks): Fields computed from the estimators during the wind update phase, then broadcast to all ranks. Includes cooling rates (cool_lines, cool_comp, cool_di, cool_dr, etc.), luminosities (lum_lines, lum_ff, lum_rr, lum_tot, etc.), ionization-band quantities, convergence diagnostics (converge_t_r, converge_t_e, gain, etc.), scatter counters, persistent radiation force averages, and per-ion derived arrays (scatters[], cool_rr_ion[], lum_rr_ion[], recomb[], etc.). The top-level struct becomes: typedef struct plasma { int nwind, nplasma; struct plasma_state state; struct plasma_estimators est; struct plasma_derived derived; } plasma_dummy; The same treatment was applied to macro_dummy, split into: macro_state - jbar_old, gamma_old, gamma_e_old, alpha_st_old, alpha_st_e_old, store_matom_matrix, matom_transition_mode macro_estimators - jbar, gamma, gamma_e, alpha_st, alpha_st_e, recomb_sp, recomb_sp_e, matom_abs, cooling_bf, cooling_bf_col, cooling_bb, and cooling totals macro_derived - matom_emiss, kpkt_rates_known, matom_matrix, matrix_rates_known, cooling_bb_simple_tot Several #define constants and enum spec_mod_type_enum were moved from inside the plasma_dummy struct body to file scope, as required for the sub-struct definitions. MECHANICAL REFACTORING (55 source files): All field accesses across the codebase were updated: xplasma->ne -> xplasma->state.ne xplasma->j -> xplasma->est.j xplasma->lum_tot -> xplasma->derived.lum_tot plasmamain[n].density -> plasmamain[n].state.density macromain[n].jbar -> macromain[n].est.jbar (and so on for all fields) Eight field names conflicted with fields in other structs (WindPtr, PhotPtr, ions, etc.): w, vol, f1, f2, ip, xi, nbands, xgamma. For these, only accesses through known PlasmaPtr variable names (xplasma, plasmamain[...]) were modified, to avoid false positives. MPI COMMUNICATION (communicate_plasma.c, communicate_macro.c): The MPI_Pack/MPI_Unpack sequences in broadcast_plasma_grid(), reduce_simple_estimators(), broadcast_updated_plasma_properties(), broadcast_wind_luminosity(), broadcast_wind_cooling(), and the macro equivalents were all updated to use the new field paths. The pack/unpack order and buffer size constants (N_BASIC_DOUBLES=73, N_BASIC_INTS=22) are unchanged — this is a purely structural refactoring with no change to the communication protocol. DYNAMIC MEMORY (source/gridwind.c): calloc_dyn_plasma() and calloc_estimators() updated to allocate arrays within the appropriate sub-structs (e.g., plasmamain[n]. state.density, macromain[n].est.jbar). WIND SAVE I/O (source/windsave.c): fwrite/fread calls for dynamic arrays updated to new field paths. Note: the binary wind save format changes because sizeof(plasma_dummy) and sizeof(macro_dummy) changed due to sub-struct padding. Old wind save files are incompatible with this version. VERSION BUMP (source/Makefile): VERSION changed from 1.2 to 2.0 to reflect the struct layout change and wind save incompatibility. BUG FIXES: source/signal.c - Fix race condition in xsignal_rm(): Replaced fopen() existence check followed by system("rm ...") with a single remove() call that ignores ENOENT. The old code had a TOCTOU race when multiple processes called xsignal_rm concurrently. py_progs/run_check.py - Fix xwindsave2table() version fallback: Fixed three bugs that prevented the fallback from working: (1) Header check now accepts 'Sirocco' in addition to 'Python'. (2) Binary name now includes hyphen: windsave2table-VERSION. (3) Fixed syntax error in print statement on line 158. py_progs/regression_check.py - Fall back to .spec for model discovery: When .out.pf files are missing, the comparison now discovers models from .spec files instead of failing with zero models. py_progs/regression_plot.py - Same .spec fallback for plot generation: Applied the identical fallback so comparison plots are generated even when .out.pf files are absent. Co-Authored-By: Claude Opus 4.6 --- py_progs/regression_check.py | 19 +- py_progs/regression_plot.py | 8 +- py_progs/run_check.py | 15 +- source/Makefile | 2 +- source/bands_spec.c | 29 +- source/charge_exchange.c | 13 +- source/communicate_macro.c | 165 ++-- source/communicate_plasma.c | 1475 +++++++++++++++++--------------- source/compton.c | 24 +- source/cooling.c | 80 +- source/define_wind.c | 75 +- source/density.c | 2 +- source/dielectronic.c | 4 +- source/direct_ion.c | 3 +- source/emission.c | 89 +- source/estimators_macro.c | 200 ++--- source/estimators_simple.c | 296 +++---- source/gridwind.c | 72 +- source/hydro_import.c | 82 +- source/inspect_wind.c | 18 +- source/ionization.c | 287 ++++--- source/janitor.c | 74 +- source/levels.c | 18 +- source/lines.c | 44 +- source/macro_accelerate.c | 133 +-- source/macro_gen_f.c | 64 +- source/macro_gov.c | 46 +- source/matom.c | 90 +- source/matom_diag.c | 8 +- source/matrix_ion.c | 40 +- source/modify_wind.c | 30 +- source/partition.c | 18 +- source/photon2d.c | 8 +- source/photon_gen_matom.c | 16 +- source/pi_rates.c | 30 +- source/rad_hydro_files.c | 128 +-- source/radiation.c | 104 +-- source/recomb.c | 59 +- source/resonate.c | 46 +- source/run.c | 4 +- source/saha.c | 48 +- source/setup_line_transfer.c | 8 +- source/signal.c | 20 +- source/sirocco.h | 505 ++++++----- source/sirocco_optd_trans.c | 6 +- source/spectral_estimators.c | 105 +-- source/swind_ion.c | 44 +- source/swind_macro.c | 107 +-- source/swind_sub.c | 294 ++++--- source/test_cooling.c | 40 +- source/tests/unit_test_model.c | 74 +- source/trans_phot.c | 2 +- source/unit_test.c | 20 +- source/wind2d.c | 8 +- source/wind_sum.c | 12 +- source/wind_updates2d.c | 414 ++++----- source/windsave.c | 120 +-- source/windsave2fits.c | 16 +- source/windsave2table_sub.c | 158 ++-- 59 files changed, 3030 insertions(+), 2889 deletions(-) diff --git a/py_progs/regression_check.py b/py_progs/regression_check.py index 66419e95b..5ec741c30 100755 --- a/py_progs/regression_check.py +++ b/py_progs/regression_check.py @@ -195,26 +195,33 @@ def doit(run1='py_180809',run2='',outputfile='check.txt'): pf1=glob('%s/*.out.pf' % run1) pf2=glob('%s/*.out.pf' % run2) - # print(pf1) - # print(pf2) + # Fall back to .spec files if .out.pf files are missing + if len(pf1)==0: + pf1=glob('%s/*.spec' % run1) + ext1='.spec' + else: + ext1='.out.pf' + if len(pf2)==0: + pf2=glob('%s/*.spec' % run2) + ext2='.spec' + else: + ext2='.out.pf' name1=[] root1=[] for one in pf1: - x=one.replace('.out.pf','') + x=one.replace(ext1,'') root1.append(x) x=x.split('/') name1.append(x[1]) - # print(name1) name2=[] root2=[] for one in pf2: - x=one.replace('.out.pf','') + x=one.replace(ext2,'') root2.append(x) x=x.split('/') name2.append(x[1]) - # print(name2) table1=Table([name1,root1],names=['name','root1']) diff --git a/py_progs/regression_plot.py b/py_progs/regression_plot.py index dc3ae8b09..b6eae04f2 100755 --- a/py_progs/regression_plot.py +++ b/py_progs/regression_plot.py @@ -592,11 +592,15 @@ def do_all(run1='py82i_181127',run2='py82i_181126',outdir=''): fig_num=1 files=glob('%s/*.out.pf' % run1) - # print(files) + if len(files)==0: + files=glob('%s/*.spec' % run1) + ext='.spec' + else: + ext='.out.pf' for one in files: word=one.split('/') - model=word[1].replace('.out.pf','') + model=word[1].replace(ext,'') doit_two(run1,run2,model,outdir) # print(fig_num) diff --git a/py_progs/run_check.py b/py_progs/run_check.py index 63fcbeccb..84f1f8b49 100644 --- a/py_progs/run_check.py +++ b/py_progs/run_check.py @@ -138,12 +138,15 @@ def xwindsave2table(root): if len(sfiles): foo=open(sfiles[0]) line=foo.readline() + foo.close() words=line.split() - if words[1]=='Python': + if words[1] in ('Python', 'Sirocco'): xver=words[3] - command='windsave2table%s %s' % (xver,root) + command='windsave2table-%s %s' % (xver,root) else: - return FALSE + return True + else: + return True print('We will try this command instead :', command) @@ -152,12 +155,12 @@ def xwindsave2table(root): proc=subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) stdout,stderr=proc.communicate() if proc.returncode: - print('Error: also failed trying to run %s ' % xver,proc.returncode) + print('Error: also failed trying to run %s ' % command,proc.returncode) return True elif len(stderr): - print('Error: also failed with ' %s) + print('Error: also failed with %s' % command) print(stderr.decode()) - return True + return True else: return False diff --git a/source/Makefile b/source/Makefile index 819d6efa1..3cc5d5fc4 100644 --- a/source/Makefile +++ b/source/Makefile @@ -147,7 +147,7 @@ LDFLAGS+= -L$(LIB) -lm -lgsl -lgslcblas $(CUDA_LIBS) #Note that version should be a single string without spaces. -VERSION = 1.2 +VERSION = 2.0 diff --git a/source/bands_spec.c b/source/bands_spec.c index 52721f537..3e17480eb 100644 --- a/source/bands_spec.c +++ b/source/bands_spec.c @@ -56,19 +56,22 @@ xband; **********************************************************/ void -band_copy() +band_copy () { - int n,nband; - for (n=0;ndensity[n]; + nh1 = xplasma->state.density[n]; } if (ion[n].z == 1 && ion[n].istate == 2) { - nh2 = xplasma->density[n]; + nh2 = xplasma->state.density[n]; } } @@ -162,11 +162,13 @@ ch_ex_heat (one, t_e) { if (ion[n].n_ch_ex < 0) //We dont have a proper rate, so use the approximation { - x += xplasma->vol * charge_exchange_recomb_rates[n] * nh1 * xplasma->density[n] * 2.86 * (ion[n].istate - 1) * EV2ERGS; + x += xplasma->state.vol * charge_exchange_recomb_rates[n] * nh1 * xplasma->state.density[n] * 2.86 * (ion[n].istate - 1) * EV2ERGS; } else { - x += xplasma->vol * charge_exchange_recomb_rates[n] * nh1 * xplasma->density[n] * charge_exchange[ion[n].n_ch_ex].energy_defect; + x += + xplasma->state.vol * charge_exchange_recomb_rates[n] * nh1 * xplasma->state.density[n] * + charge_exchange[ion[n].n_ch_ex].energy_defect; } } } @@ -177,7 +179,8 @@ ch_ex_heat (one, t_e) if (ion[charge_exchange[n].nion2].z == 1) //A hydrogen recomb - metal ionization rate { x += - xplasma->vol * charge_exchange_ioniz_rates[n] * nh2 * xplasma->density[charge_exchange[n].nion1] * charge_exchange[n].energy_defect; + xplasma->state.vol * charge_exchange_ioniz_rates[n] * nh2 * xplasma->state.density[charge_exchange[n].nion1] * + charge_exchange[n].energy_defect; } return (x); } diff --git a/source/communicate_macro.c b/source/communicate_macro.c index 573404861..23d2b0045 100644 --- a/source/communicate_macro.c +++ b/source/communicate_macro.c @@ -65,8 +65,9 @@ broadcast_macro_atom_emissivities (const int n_start, const int n_stop, const in for (n_plasma = n_start; n_plasma < n_stop; ++n_plasma) { MPI_Pack (&n_plasma, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].matom_emiss, nlevels_macro, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].derived.matom_emiss, nlevels_macro, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); } } @@ -80,8 +81,9 @@ broadcast_macro_atom_emissivities (const int n_start, const int n_stop, const in for (i = 0; i < num_comm; i++) { MPI_Unpack (comm_buffer, comm_buffer_size, &position, &n_plasma, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n_plasma].kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].matom_emiss, nlevels_macro, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n_plasma].derived.kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].derived.matom_emiss, nlevels_macro, MPI_DOUBLE, + MPI_COMM_WORLD); } } } @@ -143,14 +145,17 @@ broadcast_macro_atom_recomb (const int n_start, const int n_stop, const int n_ce MPI_Pack (&n_plasma, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); // which cell we're working on if (nlevels_macro > 0) { - MPI_Pack (macromain[n_plasma].recomb_sp, size_alpha_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].recomb_sp_e, size_alpha_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.recomb_sp, size_alpha_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.recomb_sp_e, size_alpha_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); } if (nphot_total > 0) { - MPI_Pack (plasmamain[n_plasma].recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, - &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); } } } @@ -168,15 +173,16 @@ broadcast_macro_atom_recomb (const int n_start, const int n_stop, const int n_ce if (nlevels_macro > 0) { - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].recomb_sp, size_alpha_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].recomb_sp_e, - size_alpha_est, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.recomb_sp, size_alpha_est, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.recomb_sp_e, size_alpha_est, MPI_DOUBLE, + MPI_COMM_WORLD); } if (nphot_total > 0) { - MPI_Unpack (comm_buffer, comm_buffer_size, &position, plasmamain[n_plasma].recomb_simple, + MPI_Unpack (comm_buffer, comm_buffer_size, &position, plasmamain[n_plasma].state.recomb_simple, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, plasmamain[n_plasma].recomb_simple_upweight, + MPI_Unpack (comm_buffer, comm_buffer_size, &position, plasmamain[n_plasma].state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); } } @@ -238,16 +244,19 @@ broadcast_updated_macro_atom_properties (const int n_start, const int n_stop, co for (n_plasma = n_start; n_plasma < n_stop; ++n_plasma) { MPI_Pack (&n_plasma, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].jbar, size_Jbar_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].jbar_old, size_Jbar_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].gamma, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].gamma_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].gamma_e, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].gamma_e_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].alpha_st, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (macromain[n_plasma].alpha_st_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (¯omain[n_plasma].kpkt_rates_known, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (¯omain[n_plasma].matrix_rates_known, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.jbar, size_Jbar_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].state.jbar_old, size_Jbar_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.gamma, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].state.gamma_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.gamma_e, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].state.gamma_e_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].est.alpha_st, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (macromain[n_plasma].state.alpha_st_old, size_gamma_est, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (¯omain[n_plasma].derived.kpkt_rates_known, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (¯omain[n_plasma].derived.matrix_rates_known, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); } } @@ -261,16 +270,20 @@ broadcast_updated_macro_atom_properties (const int n_start, const int n_stop, co for (i = 0; i < num_comm; ++i) { MPI_Unpack (comm_buffer, comm_buffer_size, &position, &n_plasma, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].jbar, size_Jbar_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].jbar_old, size_Jbar_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].gamma, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].gamma_old, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].gamma_e, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].gamma_e_old, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].alpha_st, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].alpha_st_old, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, ¯omain[n_plasma].kpkt_rates_known, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, ¯omain[n_plasma].matrix_rates_known, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.jbar, size_Jbar_est, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].state.jbar_old, size_Jbar_est, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.gamma, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].state.gamma_old, size_gamma_est, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.gamma_e, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].state.gamma_e_old, size_gamma_est, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].est.alpha_st, size_gamma_est, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n_plasma].state.alpha_st_old, size_gamma_est, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, ¯omain[n_plasma].derived.kpkt_rates_known, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, ¯omain[n_plasma].derived.matrix_rates_known, 1, MPI_INT, MPI_COMM_WORLD); } } } @@ -331,9 +344,9 @@ broadcast_macro_atom_state_matrix (int n_start, int n_stop, int n_cells_rank) MPI_Pack (&n, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); /* we only communicate the matrix if it is being stored in this cell */ - if (macromain[n].store_matom_matrix == TRUE) + if (macromain[n].state.store_matom_matrix == TRUE) { - MPI_Pack (macromain[n].matom_matrix[0], matrix_size * matrix_size, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_Pack (macromain[n].derived.matom_matrix[0], matrix_size * matrix_size, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); } } @@ -351,9 +364,9 @@ broadcast_macro_atom_state_matrix (int n_start, int n_stop, int n_cells_rank) MPI_Unpack (comm_buffer, comm_buffer_size, &position, &n, 1, MPI_INT, MPI_COMM_WORLD); /* we only communicate the matrix if it is being stored in this cell */ - if (macromain[n].store_matom_matrix == TRUE) + if (macromain[n].state.store_matom_matrix == TRUE) { - MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n].matom_matrix[0], matrix_size * matrix_size, MPI_DOUBLE, + MPI_Unpack (comm_buffer, comm_buffer_size, &position, macromain[n].derived.matom_matrix[0], matrix_size * matrix_size, MPI_DOUBLE, MPI_COMM_WORLD); } } @@ -426,52 +439,52 @@ reduce_macro_atom_estimators (void) for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { /* one kpkt_abs quantity per cell */ - cell_helper[mpi_i] = plasmamain[mpi_i].kpkt_abs / np_mpi_global; + cell_helper[mpi_i] = plasmamain[mpi_i].est.kpkt_abs / np_mpi_global; /* each of the cooling sums and normalisations also have one quantity per cell */ - cell_helper[mpi_i + NPLASMA] = macromain[mpi_i].cooling_normalisation / np_mpi_global; - cell_helper[mpi_i + 2 * NPLASMA] = macromain[mpi_i].cooling_bftot / np_mpi_global; - cell_helper[mpi_i + 3 * NPLASMA] = macromain[mpi_i].cooling_bf_coltot / np_mpi_global; - cell_helper[mpi_i + 4 * NPLASMA] = macromain[mpi_i].cooling_bbtot / np_mpi_global; - cell_helper[mpi_i + 5 * NPLASMA] = macromain[mpi_i].cooling_ff / np_mpi_global; - cell_helper[mpi_i + 6 * NPLASMA] = macromain[mpi_i].cooling_ff_lofreq / np_mpi_global; - cell_helper[mpi_i + 7 * NPLASMA] = macromain[mpi_i].cooling_adiabatic / np_mpi_global; + cell_helper[mpi_i + NPLASMA] = macromain[mpi_i].est.cooling_normalisation / np_mpi_global; + cell_helper[mpi_i + 2 * NPLASMA] = macromain[mpi_i].est.cooling_bftot / np_mpi_global; + cell_helper[mpi_i + 3 * NPLASMA] = macromain[mpi_i].est.cooling_bf_coltot / np_mpi_global; + cell_helper[mpi_i + 4 * NPLASMA] = macromain[mpi_i].est.cooling_bbtot / np_mpi_global; + cell_helper[mpi_i + 5 * NPLASMA] = macromain[mpi_i].est.cooling_ff / np_mpi_global; + cell_helper[mpi_i + 6 * NPLASMA] = macromain[mpi_i].est.cooling_ff_lofreq / np_mpi_global; + cell_helper[mpi_i + 7 * NPLASMA] = macromain[mpi_i].est.cooling_adiabatic / np_mpi_global; for (n = 0; n < nlevels_macro; n++) { - level_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].matom_abs[n] / np_mpi_global; + level_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.matom_abs[n] / np_mpi_global; } for (n = 0; n < size_Jbar_est; n++) { - jbar_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].jbar[n] / np_mpi_global; + jbar_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.jbar[n] / np_mpi_global; } for (n = 0; n < size_gamma_est; n++) { - gamma_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].alpha_st[n] / np_mpi_global; - gamma_helper[mpi_i + ((n + size_gamma_est) * NPLASMA)] = macromain[mpi_i].alpha_st_e[n] / np_mpi_global; - gamma_helper[mpi_i + ((n + 2 * size_gamma_est) * NPLASMA)] = macromain[mpi_i].gamma[n] / np_mpi_global; - gamma_helper[mpi_i + ((n + 3 * size_gamma_est) * NPLASMA)] = macromain[mpi_i].gamma_e[n] / np_mpi_global; + gamma_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.alpha_st[n] / np_mpi_global; + gamma_helper[mpi_i + ((n + size_gamma_est) * NPLASMA)] = macromain[mpi_i].est.alpha_st_e[n] / np_mpi_global; + gamma_helper[mpi_i + ((n + 2 * size_gamma_est) * NPLASMA)] = macromain[mpi_i].est.gamma[n] / np_mpi_global; + gamma_helper[mpi_i + ((n + 3 * size_gamma_est) * NPLASMA)] = macromain[mpi_i].est.gamma_e[n] / np_mpi_global; } for (n = 0; n < size_alpha_est; n++) { - alpha_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].recomb_sp[n] / np_mpi_global; - alpha_helper[mpi_i + ((n + size_alpha_est) * NPLASMA)] = macromain[mpi_i].recomb_sp_e[n] / np_mpi_global; + alpha_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.recomb_sp[n] / np_mpi_global; + alpha_helper[mpi_i + ((n + size_alpha_est) * NPLASMA)] = macromain[mpi_i].est.recomb_sp_e[n] / np_mpi_global; } for (n = 0; n < nphot_total; n++) { - cooling_bf_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].cooling_bf[n] / np_mpi_global; - cooling_bf_helper[mpi_i + ((n + nphot_total) * NPLASMA)] = macromain[mpi_i].cooling_bf_col[n] / np_mpi_global; + cooling_bf_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.cooling_bf[n] / np_mpi_global; + cooling_bf_helper[mpi_i + ((n + nphot_total) * NPLASMA)] = macromain[mpi_i].est.cooling_bf_col[n] / np_mpi_global; } for (n = 0; n < nlines; n++) { - cooling_bb_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].cooling_bb[n] / np_mpi_global; + cooling_bb_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.cooling_bb[n] / np_mpi_global; } } @@ -491,51 +504,51 @@ reduce_macro_atom_estimators (void) for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { /* one kpkt_abs quantity per cell */ - plasmamain[mpi_i].kpkt_abs = cell_helper2[mpi_i]; + plasmamain[mpi_i].est.kpkt_abs = cell_helper2[mpi_i]; /* each of the cooling sums and normalisations also have one quantity per cell */ - macromain[mpi_i].cooling_normalisation = cell_helper2[mpi_i + NPLASMA]; - macromain[mpi_i].cooling_bftot = cell_helper2[mpi_i + 2 * NPLASMA]; - macromain[mpi_i].cooling_bf_coltot = cell_helper2[mpi_i + 3 * NPLASMA]; - macromain[mpi_i].cooling_bbtot = cell_helper2[mpi_i + 4 * NPLASMA]; - macromain[mpi_i].cooling_ff = cell_helper2[mpi_i + 5 * NPLASMA]; - macromain[mpi_i].cooling_ff_lofreq = cell_helper2[mpi_i + 6 * NPLASMA]; - macromain[mpi_i].cooling_adiabatic = cell_helper2[mpi_i + 7 * NPLASMA]; + macromain[mpi_i].est.cooling_normalisation = cell_helper2[mpi_i + NPLASMA]; + macromain[mpi_i].est.cooling_bftot = cell_helper2[mpi_i + 2 * NPLASMA]; + macromain[mpi_i].est.cooling_bf_coltot = cell_helper2[mpi_i + 3 * NPLASMA]; + macromain[mpi_i].est.cooling_bbtot = cell_helper2[mpi_i + 4 * NPLASMA]; + macromain[mpi_i].est.cooling_ff = cell_helper2[mpi_i + 5 * NPLASMA]; + macromain[mpi_i].est.cooling_ff_lofreq = cell_helper2[mpi_i + 6 * NPLASMA]; + macromain[mpi_i].est.cooling_adiabatic = cell_helper2[mpi_i + 7 * NPLASMA]; for (n = 0; n < nlevels_macro; n++) { - macromain[mpi_i].matom_abs[n] = level_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.matom_abs[n] = level_helper2[mpi_i + (n * NPLASMA)]; } for (n = 0; n < size_Jbar_est; n++) { - macromain[mpi_i].jbar[n] = jbar_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.jbar[n] = jbar_helper2[mpi_i + (n * NPLASMA)]; } for (n = 0; n < size_gamma_est; n++) { - macromain[mpi_i].alpha_st[n] = gamma_helper2[mpi_i + (n * NPLASMA)]; - macromain[mpi_i].alpha_st_e[n] = gamma_helper2[mpi_i + ((n + size_gamma_est) * NPLASMA)] / np_mpi_global; - macromain[mpi_i].gamma[n] = gamma_helper2[mpi_i + ((n + 2 * size_gamma_est) * NPLASMA)]; - macromain[mpi_i].gamma_e[n] = gamma_helper2[mpi_i + ((n + 3 * size_gamma_est) * NPLASMA)]; + macromain[mpi_i].est.alpha_st[n] = gamma_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.alpha_st_e[n] = gamma_helper2[mpi_i + ((n + size_gamma_est) * NPLASMA)] / np_mpi_global; + macromain[mpi_i].est.gamma[n] = gamma_helper2[mpi_i + ((n + 2 * size_gamma_est) * NPLASMA)]; + macromain[mpi_i].est.gamma_e[n] = gamma_helper2[mpi_i + ((n + 3 * size_gamma_est) * NPLASMA)]; } for (n = 0; n < size_alpha_est; n++) { - macromain[mpi_i].recomb_sp[n] = alpha_helper2[mpi_i + (n * NPLASMA)]; - macromain[mpi_i].recomb_sp_e[n] = alpha_helper2[mpi_i + ((n + size_alpha_est) * NPLASMA)]; + macromain[mpi_i].est.recomb_sp[n] = alpha_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.recomb_sp_e[n] = alpha_helper2[mpi_i + ((n + size_alpha_est) * NPLASMA)]; } for (n = 0; n < nphot_total; n++) { - macromain[mpi_i].cooling_bf[n] = cooling_bf_helper2[mpi_i + (n * NPLASMA)]; - macromain[mpi_i].cooling_bf_col[n] = cooling_bf_helper2[mpi_i + ((n + nphot_total) * NPLASMA)]; + macromain[mpi_i].est.cooling_bf[n] = cooling_bf_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.cooling_bf_col[n] = cooling_bf_helper2[mpi_i + ((n + nphot_total) * NPLASMA)]; } for (n = 0; n < nlines; n++) { - macromain[mpi_i].cooling_bb[n] = cooling_bb_helper2[mpi_i + (n * NPLASMA)]; + macromain[mpi_i].est.cooling_bb[n] = cooling_bb_helper2[mpi_i + (n * NPLASMA)]; } } diff --git a/source/communicate_plasma.c b/source/communicate_plasma.c index a23a4f5ba..6ad940c1f 100644 --- a/source/communicate_plasma.c +++ b/source/communicate_plasma.c @@ -84,150 +84,153 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra cell = &plasmamain[n_plasma]; MPI_Pack (&cell->nwind, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (&cell->nplasma, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ne, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->rho, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->vol, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->xgamma, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->density, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->partition, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->levden, nlte_levels, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->kappa_ff_factor, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->kpkt_abs, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->kbf_use, nphot_total, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->kbf_nuse, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->t_r, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->t_r_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->t_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->t_e_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->dt_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->dt_e_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_tot_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->abs_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_ind_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_lines_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_photo_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_lines_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_bf_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_photo, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_z, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_auger, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_ch_ex, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->abs_photo, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->abs_auger, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->w, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot_star, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot_bl, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot_disk, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot_wind, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ntot_agn, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nscat_es, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nscat_res, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nscat_bf, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nscat_ff, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->mean_ds, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->n_ds, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nrad, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->nioniz, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->ioniz, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->recomb, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->inner_ioniz, n_inner_tot, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->inner_recomb, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->scatters, nions, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->xscatters, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->heat_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->heat_inner_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->cool_rr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->lum_rr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->cool_dr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->j, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ave_freq, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->xj, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->xave_freq, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->fmin, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->fmax, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->fmin_mod, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->fmax_mod, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->xsd_freq, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->nxtot, NXBANDS, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->spec_mod_type, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->pl_alpha, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->j_direct, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->j_scatt, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ip_direct, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ip_scatt, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->max_freq, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_rr_metals, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_di, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_dr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_rr_metals, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_tot_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_lines_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_ff_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_adiabatic_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_comp_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_di_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_dr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->cool_rr_metals_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->lum_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->heat_shock, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->bf_simple_ionpool_in, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->comp_nujnu, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->gain, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->converge_t_r, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->converge_t_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->converge_hc, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->trcheck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->techeck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->hccheck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->converge_whole, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->converging, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->ip, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->xi, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.ne, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.rho, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.vol, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.xgamma, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.density, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.partition, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.levden, nlte_levels, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.kappa_ff_factor, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.kpkt_abs, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.kbf_use, nphot_total, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.kbf_nuse, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.t_r, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.t_r_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.t_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.t_e_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.dt_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.dt_e_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.heat_tot_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.abs_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_ind_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_lines_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_photo_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_lines_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_bf_macro, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_photo, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_z, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_auger, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.heat_ch_ex, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.abs_photo, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.abs_auger, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.w, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot_star, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot_bl, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot_disk, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot_wind, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ntot_agn, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.nscat_es, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.nscat_res, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.nscat_bf, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.nscat_ff, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.mean_ds, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.n_ds, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.nrad, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.nioniz, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.ioniz, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.recomb, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.inner_ioniz, n_inner_tot, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.inner_recomb, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.scatters, nions, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.xscatters, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.heat_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.heat_inner_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.cool_rr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.lum_rr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.cool_dr_ion, nions, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.j, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ave_freq, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.xj, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.xave_freq, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.fmin, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.fmax, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.fmin_mod, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.fmax_mod, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.xsd_freq, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.nxtot, NXBANDS, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->state.spec_mod_type, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.pl_alpha, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.j_direct, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.j_scatt, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ip_direct, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ip_scatt, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.max_freq, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.cool_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_rr_metals, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_di, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_dr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_rr_metals, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_tot_old, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_lines_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_ff_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_adiabatic_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_comp_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_di_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_dr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.cool_rr_metals_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.lum_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.heat_shock, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.comp_nujnu, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (cell->derived.rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (cell->derived.rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, + MPI_COMM_WORLD); + MPI_Pack (&cell->derived.gain, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.converge_t_r, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.converge_t_e, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.converge_hc, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.trcheck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.techeck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.hccheck, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.converge_whole, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.converging, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->est.ip, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&cell->derived.xi, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); } } @@ -243,150 +246,156 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra cell = &plasmamain[n_plasma]; MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nwind, 1, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nplasma, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ne, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->rho, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->vol, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->xgamma, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->density, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->partition, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->levden, nlte_levels, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->kappa_ff_factor, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->recomb_simple, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->recomb_simple_upweight, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->kpkt_abs, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->kbf_use, nphot_total, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->kbf_nuse, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->t_r_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->t_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->dt_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->dt_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->abs_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_ind_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_photo_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_bf_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_z, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_ch_ex, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->abs_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->abs_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->w, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot_star, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot_bl, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot_disk, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot_wind, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ntot_agn, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nscat_es, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nscat_res, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nscat_bf, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nscat_ff, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->mean_ds, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->n_ds, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nrad, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->nioniz, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->ioniz, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->inner_ioniz, n_inner_tot, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->inner_recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->scatters, nions, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->xscatters, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->heat_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->heat_inner_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->cool_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->lum_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->cool_dr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->j, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ave_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->xj, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->xave_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->fmin, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->fmax, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->fmin_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->fmax_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->xsd_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->nxtot, NXBANDS, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->spec_mod_type, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->pl_alpha, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->j_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->j_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ip_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ip_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->max_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_lines_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_ff_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_adiabatic_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_comp_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_di_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_dr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->cool_rr_metals_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->lum_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->bf_simple_ionpool_in, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->bf_simple_ionpool_out, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->n_bf_in, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->n_bf_out, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->gain, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->converge_t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->converge_t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->converge_hc, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->trcheck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->techeck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->hccheck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->converge_whole, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->converging, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->ip, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->xi, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.ne, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.rho, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.vol, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.xgamma, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.density, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.partition, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.levden, nlte_levels, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.kappa_ff_factor, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.recomb_simple, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.kpkt_abs, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.kbf_use, nphot_total, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.kbf_nuse, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.t_r_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.t_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.dt_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.dt_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.heat_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.abs_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_ind_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_photo_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_bf_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_z, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.heat_ch_ex, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.abs_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.abs_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.w, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot_star, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot_bl, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot_disk, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot_wind, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ntot_agn, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.nscat_es, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.nscat_res, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.nscat_bf, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.nscat_ff, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.mean_ds, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.n_ds, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.nrad, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.nioniz, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.ioniz, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.inner_ioniz, n_inner_tot, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.inner_recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.scatters, nions, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.xscatters, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.heat_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.heat_inner_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.cool_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.lum_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.cool_dr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.j, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ave_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.xj, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.xave_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.fmin, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.fmax, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.fmin_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.fmax_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.xsd_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.nxtot, NXBANDS, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.spec_mod_type, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.pl_alpha, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.j_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.j_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ip_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ip_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.max_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_lines_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_ff_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_adiabatic_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_comp_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_di_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_dr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.cool_rr_metals_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.lum_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_in, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_out, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.gain, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.converge_t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.converge_t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.converge_hc, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.trcheck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.techeck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.hccheck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.converge_whole, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.converging, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->est.ip, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.xi, 1, MPI_DOUBLE, MPI_COMM_WORLD); } } } @@ -452,10 +461,10 @@ broadcast_wind_luminosity (const int n_start, const int n_stop, const int n_cell for (n_plasma = n_start; n_plasma < n_stop; ++n_plasma) { MPI_Pack (&n_plasma, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); } } @@ -470,10 +479,10 @@ broadcast_wind_luminosity (const int n_start, const int n_stop, const int n_cell { int cell; MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].derived.lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].derived.lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].derived.lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[cell].derived.lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); } } @@ -540,15 +549,15 @@ broadcast_wind_cooling (const int n_start, const int n_stop, const int n_cells_r for (i = n_start; i < n_stop; ++i) { MPI_Pack (&i, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_di, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_dr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[i].heat_shock, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].est.cool_tot, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.lum_ff, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.lum_lines, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.cool_rr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.cool_comp, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.cool_di, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.cool_dr, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[i].derived.heat_shock, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); } } @@ -563,15 +572,15 @@ broadcast_wind_cooling (const int n_start, const int n_stop, const int n_cells_r { int n; MPI_Unpack (comm_buffer, comm_buffer_size, &position, &n, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].est.cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, &plasmamain[n].derived.heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); } } } @@ -615,8 +624,8 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra //OLD const int num_ints = 1 + n_cells_max * (20 + nphot_total + 2 * NXBANDS + 2 * N_PHOT_PROC + nions); const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + 2 * NXBANDS + 2 * N_PHOT_PROC + nions); const int num_doubles = - n_cells_max * (N_BASIC_DOUBLES + 1 * 3 + 9 * 4 + 6 * NFLUX_ANGLES + 3 * NFORCE_DIRECTIONS + 9 * nions + 1 * nlte_levels + 3 * nphot_total + - 1 * n_inner_tot + 9 * NXBANDS + 1 * NBINS_IN_CELL_SPEC); + n_cells_max * (N_BASIC_DOUBLES + 1 * 3 + 9 * 4 + 6 * NFLUX_ANGLES + 3 * NFORCE_DIRECTIONS + 9 * nions + 1 * nlte_levels + + 3 * nphot_total + 1 * n_inner_tot + 9 * NXBANDS + 1 * NBINS_IN_CELL_SPEC); const int size_of_comm_buffer = calculate_comm_buffer_size (num_ints, num_doubles); char *const comm_buffer = malloc (size_of_comm_buffer); @@ -639,161 +648,176 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_Pack (&n_plasma, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (&plasmamain[n_plasma].nwind, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (&plasmamain[n_plasma].nplasma, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ne, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].rho, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].vol, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].xgamma, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].density, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].partition, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].levden, nlte_levels, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].kappa_ff_factor, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].state.ne, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.rho, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.vol, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.xgamma, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.density, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.partition, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.levden, nlte_levels, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.kappa_ff_factor, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.recomb_simple, nphot_total, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.kpkt_abs, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.kbf_use, nphot_total, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.kbf_nuse, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.t_r, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.t_r_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.t_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.t_e_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.dt_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.dt_e_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.heat_tot_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.abs_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_lines, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_ff, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_ind_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_lines_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_photo_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_lines_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_bf_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_photo, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_z, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_auger, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.heat_ch_ex, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.abs_photo, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.abs_auger, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].state.w, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot_star, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot_bl, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot_disk, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot_wind, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ntot_agn, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.nscat_es, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.nscat_bf, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.nscat_ff, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.mean_ds, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.n_ds, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.nrad, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.nioniz, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.ioniz, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.recomb, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.inner_ioniz, n_inner_tot, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.scatters, nions, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.xscatters, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.heat_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.heat_inner_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.cool_rr_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.lum_rr_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.j, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ave_freq, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.xj, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.xave_freq, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.fmin_mod, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.fmax_mod, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.xsd_freq, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.nxtot, NXBANDS, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.spec_mod_type, NXBANDS, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.pl_alpha, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].state.exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, + &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].est.F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].kpkt_emiss, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].kpkt_abs, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].kbf_use, nphot_total, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].kbf_nuse, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].t_r, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].t_r_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].t_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].t_e_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].dt_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].dt_e_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_tot_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].abs_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_lines, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_ff, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_ind_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_lines_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_photo_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_lines_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_bf_macro, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_photo, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_z, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_auger, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_ch_ex, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].abs_photo, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].abs_auger, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].w, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot_star, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot_bl, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot_disk, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot_wind, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ntot_agn, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].nscat_es, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].nscat_bf, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].nscat_ff, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].mean_ds, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].n_ds, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].nrad, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].nioniz, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].ioniz, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].recomb, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].inner_ioniz, n_inner_tot, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].scatters, nions, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].xscatters, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].heat_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].heat_inner_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].cool_rr_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].lum_rr_ion, nions, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].j, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ave_freq, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].xj, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].xave_freq, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].fmin_mod, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].fmax_mod, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].xsd_freq, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].nxtot, NXBANDS, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].spec_mod_type, NXBANDS, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].pl_alpha, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].derived.F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, + &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].derived.F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].est.j_direct, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.j_scatt, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ip_direct, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ip_scatt, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.max_freq, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.cool_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_lines, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_ff, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_rr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_rr_metals, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_di, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_dr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_rr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_rr_metals, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_tot_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.lum_lines_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.lum_ff_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_adiabatic_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.lum_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_comp_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.cool_di_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_dr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.cool_rr_metals_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].j_direct, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].j_scatt, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ip_direct, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ip_scatt, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].max_freq, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_lines, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_ff, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_adiabatic, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_rr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_rr_metals, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_comp, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_di, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_dr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_rr, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_rr_metals, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_tot, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_tot_old, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_lines_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_ff_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_adiabatic_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_comp_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_di_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_dr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_rr_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].cool_rr_metals_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].lum_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].heat_shock, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].bf_simple_ionpool_in, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].comp_nujnu, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.lum_tot_ioniz, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.heat_shock, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (&plasmamain[n_plasma].derived.comp_nujnu, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].gain, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].converge_t_r, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].converge_t_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].converge_hc, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].trcheck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].techeck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].hccheck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].converge_whole, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].converging, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].ip, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].xi, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, + &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, + &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, + &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.gain, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.converge_t_r, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.converge_t_e, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.converge_hc, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.trcheck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.techeck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.hccheck, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.converge_whole, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.converging, 1, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].est.ip, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n_plasma].derived.xi, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); } } @@ -810,165 +834,192 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &n_plasma, 1, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nwind, 1, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nplasma, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ne, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].rho, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].vol, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].xgamma, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].density, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].partition, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].levden, nlte_levels, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].kappa_ff_factor, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].recomb_simple, nphot_total, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.ne, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.rho, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.vol, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.xgamma, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.density, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.partition, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.levden, nlte_levels, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.kappa_ff_factor, 1, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.recomb_simple, nphot_total, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.recomb_simple_upweight, nphot_total, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.kpkt_abs, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.kbf_use, nphot_total, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.kbf_nuse, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.t_r_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.t_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.dt_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.dt_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.heat_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.abs_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_ind_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_photo_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_lines_macro, 1, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_bf_macro, 1, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_z, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.heat_ch_ex, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.abs_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.abs_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].state.w, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot_star, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot_bl, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot_disk, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot_wind, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ntot_agn, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.nscat_es, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.nscat_bf, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.nscat_ff, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.mean_ds, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.n_ds, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.nrad, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.nioniz, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.ioniz, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.inner_ioniz, n_inner_tot, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.scatters, nions, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.xscatters, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.heat_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.heat_inner_ion, nions, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.cool_rr_ion, nions, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.lum_rr_ion, nions, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.j, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ave_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.xj, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.xave_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.fmin_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.fmax_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.xsd_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.nxtot, NXBANDS, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.spec_mod_type, NXBANDS, MPI_INT, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.pl_alpha, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_vis_persistent, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_UV_persistent, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_Xray_persistent, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_UV_ang_theta_persist, NFLUX_ANGLES, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_UV_ang_phi_persist, NFLUX_ANGLES, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, + MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.j_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.j_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ip_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ip_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.max_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].recomb_simple_upweight, nphot_total, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].kpkt_emiss, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].kpkt_abs, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].kbf_use, nphot_total, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].kbf_nuse, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].t_r_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].t_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].dt_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].dt_e_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].abs_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_ind_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_photo_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_lines_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_bf_macro, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_z, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_ch_ex, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].abs_photo, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].abs_auger, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].w, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot_star, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot_bl, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot_disk, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot_wind, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ntot_agn, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nscat_es, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nscat_bf, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nscat_ff, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].mean_ds, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].n_ds, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nrad, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].nioniz, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].ioniz, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].recomb, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].inner_ioniz, n_inner_tot, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].scatters, nions, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].xscatters, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].heat_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].heat_inner_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].cool_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].lum_rr_ion, nions, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].j, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ave_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].xj, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].xave_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].fmin_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].fmax_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].xsd_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].nxtot, NXBANDS, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].spec_mod_type, NXBANDS, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].pl_alpha, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_vis_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_lines_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_ff_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_adiabatic_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_Xray_persistent, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_comp_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_theta, NFLUX_ANGLES, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_di_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_phi, NFLUX_ANGLES, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_dr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_r, NFLUX_ANGLES, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_theta_persist, NFLUX_ANGLES, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_phi_persist, NFLUX_ANGLES, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.cool_rr_metals_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].F_UV_ang_r_persist, NFLUX_ANGLES, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.lum_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].j_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].j_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ip_direct, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ip_scatt, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].max_freq, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_adiabatic, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_comp, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_di, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_dr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_rr_metals, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_tot, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_tot_old, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_lines_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_ff_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_adiabatic_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_comp_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_di_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_dr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_rr_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].cool_rr_metals_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].lum_tot_ioniz, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].bf_simple_ionpool_in, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].bf_simple_ionpool_out, 1, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].n_bf_in, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].n_bf_out, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.n_bf_in, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.n_bf_out, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_es_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_ff_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.rad_force_ff, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].rad_force_bf_persist, NFORCE_DIRECTIONS, MPI_DOUBLE, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.rad_force_bf, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].gain, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].converge_t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].converge_t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].converge_hc, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].trcheck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].techeck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].hccheck, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].converge_whole, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].converging, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].ip, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].xi, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.rad_force_es_persist, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.rad_force_ff_persist, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.rad_force_bf_persist, NFORCE_DIRECTIONS, + MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.gain, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.converge_t_r, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.converge_t_e, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.converge_hc, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.trcheck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.techeck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.hccheck, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.converge_whole, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.converging, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].est.ip, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.xi, 1, MPI_DOUBLE, MPI_COMM_WORLD); } } } @@ -1055,69 +1106,69 @@ reduce_simple_estimators (void) // the following blocks gather all the estimators to the zeroth (Master) thread for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { - maxfreqhelper[mpi_i] = plasmamain[mpi_i].max_freq; - redhelper[mpi_i] = plasmamain[mpi_i].j / np_mpi_global; - redhelper[mpi_i + NPLASMA] = plasmamain[mpi_i].ave_freq / np_mpi_global; - redhelper[mpi_i + 2 * NPLASMA] = plasmamain[mpi_i].cool_tot / np_mpi_global; - redhelper[mpi_i + 3 * NPLASMA] = plasmamain[mpi_i].heat_tot / np_mpi_global; - redhelper[mpi_i + 4 * NPLASMA] = plasmamain[mpi_i].heat_lines / np_mpi_global; - redhelper[mpi_i + 5 * NPLASMA] = plasmamain[mpi_i].heat_ff / np_mpi_global; - redhelper[mpi_i + 6 * NPLASMA] = plasmamain[mpi_i].heat_comp / np_mpi_global; - redhelper[mpi_i + 7 * NPLASMA] = plasmamain[mpi_i].heat_ind_comp / np_mpi_global; - redhelper[mpi_i + 8 * NPLASMA] = plasmamain[mpi_i].heat_photo / np_mpi_global; - redhelper[mpi_i + 9 * NPLASMA] = plasmamain[mpi_i].ip / np_mpi_global; - redhelper[mpi_i + 10 * NPLASMA] = plasmamain[mpi_i].j_direct / np_mpi_global; - redhelper[mpi_i + 11 * NPLASMA] = plasmamain[mpi_i].j_scatt / np_mpi_global; - redhelper[mpi_i + 12 * NPLASMA] = plasmamain[mpi_i].ip_direct / np_mpi_global; - redhelper[mpi_i + 13 * NPLASMA] = plasmamain[mpi_i].ip_scatt / np_mpi_global; - redhelper[mpi_i + 14 * NPLASMA] = plasmamain[mpi_i].heat_auger / np_mpi_global; - redhelper[mpi_i + 15 * NPLASMA] = plasmamain[mpi_i].rad_force_es[0] / np_mpi_global; - redhelper[mpi_i + 16 * NPLASMA] = plasmamain[mpi_i].rad_force_es[1] / np_mpi_global; - redhelper[mpi_i + 17 * NPLASMA] = plasmamain[mpi_i].rad_force_es[2] / np_mpi_global; - redhelper[mpi_i + 18 * NPLASMA] = plasmamain[mpi_i].rad_force_es[3] / np_mpi_global; - redhelper[mpi_i + 19 * NPLASMA] = plasmamain[mpi_i].F_vis[0] / np_mpi_global; - redhelper[mpi_i + 20 * NPLASMA] = plasmamain[mpi_i].F_vis[1] / np_mpi_global; - redhelper[mpi_i + 21 * NPLASMA] = plasmamain[mpi_i].F_vis[2] / np_mpi_global; - redhelper[mpi_i + 22 * NPLASMA] = plasmamain[mpi_i].F_vis[3] / np_mpi_global; - redhelper[mpi_i + 23 * NPLASMA] = plasmamain[mpi_i].F_UV[0] / np_mpi_global; - redhelper[mpi_i + 24 * NPLASMA] = plasmamain[mpi_i].F_UV[1] / np_mpi_global; - redhelper[mpi_i + 25 * NPLASMA] = plasmamain[mpi_i].F_UV[2] / np_mpi_global; - redhelper[mpi_i + 26 * NPLASMA] = plasmamain[mpi_i].F_UV[3] / np_mpi_global; - redhelper[mpi_i + 27 * NPLASMA] = plasmamain[mpi_i].F_Xray[0] / np_mpi_global; - redhelper[mpi_i + 28 * NPLASMA] = plasmamain[mpi_i].F_Xray[1] / np_mpi_global; - redhelper[mpi_i + 29 * NPLASMA] = plasmamain[mpi_i].F_Xray[2] / np_mpi_global; - redhelper[mpi_i + 30 * NPLASMA] = plasmamain[mpi_i].F_Xray[3] / np_mpi_global; - redhelper[mpi_i + 31 * NPLASMA] = plasmamain[mpi_i].rad_force_bf[0] / np_mpi_global; - redhelper[mpi_i + 32 * NPLASMA] = plasmamain[mpi_i].rad_force_bf[1] / np_mpi_global; - redhelper[mpi_i + 33 * NPLASMA] = plasmamain[mpi_i].rad_force_bf[2] / np_mpi_global; - redhelper[mpi_i + 34 * NPLASMA] = plasmamain[mpi_i].rad_force_bf[3] / np_mpi_global; - redhelper[mpi_i + 35 * NPLASMA] = plasmamain[mpi_i].rad_force_ff[0] / np_mpi_global; - redhelper[mpi_i + 36 * NPLASMA] = plasmamain[mpi_i].rad_force_ff[1] / np_mpi_global; - redhelper[mpi_i + 37 * NPLASMA] = plasmamain[mpi_i].rad_force_ff[2] / np_mpi_global; - redhelper[mpi_i + 38 * NPLASMA] = plasmamain[mpi_i].rad_force_ff[3] / np_mpi_global; + maxfreqhelper[mpi_i] = plasmamain[mpi_i].est.max_freq; + redhelper[mpi_i] = plasmamain[mpi_i].est.j / np_mpi_global; + redhelper[mpi_i + NPLASMA] = plasmamain[mpi_i].est.ave_freq / np_mpi_global; + redhelper[mpi_i + 2 * NPLASMA] = plasmamain[mpi_i].est.cool_tot / np_mpi_global; + redhelper[mpi_i + 3 * NPLASMA] = plasmamain[mpi_i].est.heat_tot / np_mpi_global; + redhelper[mpi_i + 4 * NPLASMA] = plasmamain[mpi_i].est.heat_lines / np_mpi_global; + redhelper[mpi_i + 5 * NPLASMA] = plasmamain[mpi_i].est.heat_ff / np_mpi_global; + redhelper[mpi_i + 6 * NPLASMA] = plasmamain[mpi_i].est.heat_comp / np_mpi_global; + redhelper[mpi_i + 7 * NPLASMA] = plasmamain[mpi_i].est.heat_ind_comp / np_mpi_global; + redhelper[mpi_i + 8 * NPLASMA] = plasmamain[mpi_i].est.heat_photo / np_mpi_global; + redhelper[mpi_i + 9 * NPLASMA] = plasmamain[mpi_i].est.ip / np_mpi_global; + redhelper[mpi_i + 10 * NPLASMA] = plasmamain[mpi_i].est.j_direct / np_mpi_global; + redhelper[mpi_i + 11 * NPLASMA] = plasmamain[mpi_i].est.j_scatt / np_mpi_global; + redhelper[mpi_i + 12 * NPLASMA] = plasmamain[mpi_i].est.ip_direct / np_mpi_global; + redhelper[mpi_i + 13 * NPLASMA] = plasmamain[mpi_i].est.ip_scatt / np_mpi_global; + redhelper[mpi_i + 14 * NPLASMA] = plasmamain[mpi_i].est.heat_auger / np_mpi_global; + redhelper[mpi_i + 15 * NPLASMA] = plasmamain[mpi_i].est.rad_force_es[0] / np_mpi_global; + redhelper[mpi_i + 16 * NPLASMA] = plasmamain[mpi_i].est.rad_force_es[1] / np_mpi_global; + redhelper[mpi_i + 17 * NPLASMA] = plasmamain[mpi_i].est.rad_force_es[2] / np_mpi_global; + redhelper[mpi_i + 18 * NPLASMA] = plasmamain[mpi_i].est.rad_force_es[3] / np_mpi_global; + redhelper[mpi_i + 19 * NPLASMA] = plasmamain[mpi_i].est.F_vis[0] / np_mpi_global; + redhelper[mpi_i + 20 * NPLASMA] = plasmamain[mpi_i].est.F_vis[1] / np_mpi_global; + redhelper[mpi_i + 21 * NPLASMA] = plasmamain[mpi_i].est.F_vis[2] / np_mpi_global; + redhelper[mpi_i + 22 * NPLASMA] = plasmamain[mpi_i].est.F_vis[3] / np_mpi_global; + redhelper[mpi_i + 23 * NPLASMA] = plasmamain[mpi_i].est.F_UV[0] / np_mpi_global; + redhelper[mpi_i + 24 * NPLASMA] = plasmamain[mpi_i].est.F_UV[1] / np_mpi_global; + redhelper[mpi_i + 25 * NPLASMA] = plasmamain[mpi_i].est.F_UV[2] / np_mpi_global; + redhelper[mpi_i + 26 * NPLASMA] = plasmamain[mpi_i].est.F_UV[3] / np_mpi_global; + redhelper[mpi_i + 27 * NPLASMA] = plasmamain[mpi_i].est.F_Xray[0] / np_mpi_global; + redhelper[mpi_i + 28 * NPLASMA] = plasmamain[mpi_i].est.F_Xray[1] / np_mpi_global; + redhelper[mpi_i + 29 * NPLASMA] = plasmamain[mpi_i].est.F_Xray[2] / np_mpi_global; + redhelper[mpi_i + 30 * NPLASMA] = plasmamain[mpi_i].est.F_Xray[3] / np_mpi_global; + redhelper[mpi_i + 31 * NPLASMA] = plasmamain[mpi_i].est.rad_force_bf[0] / np_mpi_global; + redhelper[mpi_i + 32 * NPLASMA] = plasmamain[mpi_i].est.rad_force_bf[1] / np_mpi_global; + redhelper[mpi_i + 33 * NPLASMA] = plasmamain[mpi_i].est.rad_force_bf[2] / np_mpi_global; + redhelper[mpi_i + 34 * NPLASMA] = plasmamain[mpi_i].est.rad_force_bf[3] / np_mpi_global; + redhelper[mpi_i + 35 * NPLASMA] = plasmamain[mpi_i].est.rad_force_ff[0] / np_mpi_global; + redhelper[mpi_i + 36 * NPLASMA] = plasmamain[mpi_i].est.rad_force_ff[1] / np_mpi_global; + redhelper[mpi_i + 37 * NPLASMA] = plasmamain[mpi_i].est.rad_force_ff[2] / np_mpi_global; + redhelper[mpi_i + 38 * NPLASMA] = plasmamain[mpi_i].est.rad_force_ff[3] / np_mpi_global; for (mpi_j = 0; mpi_j < NXBANDS; mpi_j++) { - redhelper[mpi_i + (39 + mpi_j) * NPLASMA] = plasmamain[mpi_i].xj[mpi_j] / np_mpi_global; - redhelper[mpi_i + (39 + NXBANDS + mpi_j) * NPLASMA] = plasmamain[mpi_i].xave_freq[mpi_j] / np_mpi_global; - redhelper[mpi_i + (39 + 2 * NXBANDS + mpi_j) * NPLASMA] = plasmamain[mpi_i].xsd_freq[mpi_j] / np_mpi_global; + redhelper[mpi_i + (39 + mpi_j) * NPLASMA] = plasmamain[mpi_i].est.xj[mpi_j] / np_mpi_global; + redhelper[mpi_i + (39 + NXBANDS + mpi_j) * NPLASMA] = plasmamain[mpi_i].est.xave_freq[mpi_j] / np_mpi_global; + redhelper[mpi_i + (39 + 2 * NXBANDS + mpi_j) * NPLASMA] = plasmamain[mpi_i].est.xsd_freq[mpi_j] / np_mpi_global; /* 131213 NSH populate the band limited min and max frequency arrays */ - maxbandfreqhelper[mpi_i * NXBANDS + mpi_j] = plasmamain[mpi_i].fmax[mpi_j]; - minbandfreqhelper[mpi_i * NXBANDS + mpi_j] = plasmamain[mpi_i].fmin[mpi_j]; + maxbandfreqhelper[mpi_i * NXBANDS + mpi_j] = plasmamain[mpi_i].est.fmax[mpi_j]; + minbandfreqhelper[mpi_i * NXBANDS + mpi_j] = plasmamain[mpi_i].est.fmin[mpi_j]; } for (mpi_j = 0; mpi_j < nions; mpi_j++) { - ion_helper[mpi_i * nions + mpi_j] = plasmamain[mpi_i].ioniz[mpi_j] / np_mpi_global; + ion_helper[mpi_i * nions + mpi_j] = plasmamain[mpi_i].est.ioniz[mpi_j] / np_mpi_global; } for (mpi_j = 0; mpi_j < n_inner_tot; mpi_j++) { - inner_ion_helper[mpi_i * n_inner_tot + mpi_j] = plasmamain[mpi_i].inner_ioniz[mpi_j] / np_mpi_global; + inner_ion_helper[mpi_i * n_inner_tot + mpi_j] = plasmamain[mpi_i].est.inner_ioniz[mpi_j] / np_mpi_global; } for (mpi_j = 0; mpi_j < NFLUX_ANGLES; mpi_j++) { - flux_helper[mpi_i * (3 * NFLUX_ANGLES) + mpi_j] = plasmamain[mpi_i].F_UV_ang_theta[mpi_j] / np_mpi_global; - flux_helper[mpi_i * (3 * NFLUX_ANGLES) + NFLUX_ANGLES + mpi_j] = plasmamain[mpi_i].F_UV_ang_phi[mpi_j] / np_mpi_global; - flux_helper[mpi_i * (3 * NFLUX_ANGLES) + 2 * NFLUX_ANGLES + mpi_j] = plasmamain[mpi_i].F_UV_ang_r[mpi_j] / np_mpi_global; + flux_helper[mpi_i * (3 * NFLUX_ANGLES) + mpi_j] = plasmamain[mpi_i].est.F_UV_ang_theta[mpi_j] / np_mpi_global; + flux_helper[mpi_i * (3 * NFLUX_ANGLES) + NFLUX_ANGLES + mpi_j] = plasmamain[mpi_i].est.F_UV_ang_phi[mpi_j] / np_mpi_global; + flux_helper[mpi_i * (3 * NFLUX_ANGLES) + 2 * NFLUX_ANGLES + mpi_j] = plasmamain[mpi_i].est.F_UV_ang_r[mpi_j] / np_mpi_global; } } @@ -1143,70 +1194,70 @@ reduce_simple_estimators (void) /* Unpacking stuff */ for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { - plasmamain[mpi_i].max_freq = maxfreqhelper2[mpi_i]; - plasmamain[mpi_i].j = redhelper2[mpi_i]; - plasmamain[mpi_i].ave_freq = redhelper2[mpi_i + NPLASMA]; - plasmamain[mpi_i].cool_tot = redhelper2[mpi_i + 2 * NPLASMA]; - plasmamain[mpi_i].heat_tot = redhelper2[mpi_i + 3 * NPLASMA]; - plasmamain[mpi_i].heat_lines = redhelper2[mpi_i + 4 * NPLASMA]; - plasmamain[mpi_i].heat_ff = redhelper2[mpi_i + 5 * NPLASMA]; - plasmamain[mpi_i].heat_comp = redhelper2[mpi_i + 6 * NPLASMA]; - plasmamain[mpi_i].heat_ind_comp = redhelper2[mpi_i + 7 * NPLASMA]; - plasmamain[mpi_i].heat_photo = redhelper2[mpi_i + 8 * NPLASMA]; - plasmamain[mpi_i].ip = redhelper2[mpi_i + 9 * NPLASMA]; - plasmamain[mpi_i].j_direct = redhelper2[mpi_i + 10 * NPLASMA]; - plasmamain[mpi_i].j_scatt = redhelper2[mpi_i + 11 * NPLASMA]; - plasmamain[mpi_i].ip_direct = redhelper2[mpi_i + 12 * NPLASMA]; - plasmamain[mpi_i].ip_scatt = redhelper2[mpi_i + 13 * NPLASMA]; - plasmamain[mpi_i].heat_auger = redhelper2[mpi_i + 14 * NPLASMA]; - plasmamain[mpi_i].rad_force_es[0] = redhelper2[mpi_i + 15 * NPLASMA]; - plasmamain[mpi_i].rad_force_es[1] = redhelper2[mpi_i + 16 * NPLASMA]; - plasmamain[mpi_i].rad_force_es[2] = redhelper2[mpi_i + 17 * NPLASMA]; - plasmamain[mpi_i].rad_force_es[3] = redhelper2[mpi_i + 18 * NPLASMA]; - plasmamain[mpi_i].F_vis[0] = redhelper2[mpi_i + 19 * NPLASMA]; - plasmamain[mpi_i].F_vis[1] = redhelper2[mpi_i + 20 * NPLASMA]; - plasmamain[mpi_i].F_vis[2] = redhelper2[mpi_i + 21 * NPLASMA]; - plasmamain[mpi_i].F_vis[3] = redhelper2[mpi_i + 22 * NPLASMA]; - plasmamain[mpi_i].F_UV[0] = redhelper2[mpi_i + 23 * NPLASMA]; - plasmamain[mpi_i].F_UV[1] = redhelper2[mpi_i + 24 * NPLASMA]; - plasmamain[mpi_i].F_UV[2] = redhelper2[mpi_i + 25 * NPLASMA]; - plasmamain[mpi_i].F_UV[3] = redhelper2[mpi_i + 26 * NPLASMA]; - plasmamain[mpi_i].F_Xray[0] = redhelper2[mpi_i + 27 * NPLASMA]; - plasmamain[mpi_i].F_Xray[1] = redhelper2[mpi_i + 28 * NPLASMA]; - plasmamain[mpi_i].F_Xray[2] = redhelper2[mpi_i + 29 * NPLASMA]; - plasmamain[mpi_i].F_Xray[3] = redhelper2[mpi_i + 30 * NPLASMA]; - plasmamain[mpi_i].rad_force_bf[0] = redhelper2[mpi_i + 31 * NPLASMA]; - plasmamain[mpi_i].rad_force_bf[1] = redhelper2[mpi_i + 32 * NPLASMA]; - plasmamain[mpi_i].rad_force_bf[2] = redhelper2[mpi_i + 33 * NPLASMA]; - plasmamain[mpi_i].rad_force_bf[3] = redhelper2[mpi_i + 34 * NPLASMA]; - plasmamain[mpi_i].rad_force_ff[0] = redhelper2[mpi_i + 35 * NPLASMA]; - plasmamain[mpi_i].rad_force_ff[1] = redhelper2[mpi_i + 36 * NPLASMA]; - plasmamain[mpi_i].rad_force_ff[2] = redhelper2[mpi_i + 37 * NPLASMA]; - plasmamain[mpi_i].rad_force_ff[3] = redhelper2[mpi_i + 38 * NPLASMA]; + plasmamain[mpi_i].est.max_freq = maxfreqhelper2[mpi_i]; + plasmamain[mpi_i].est.j = redhelper2[mpi_i]; + plasmamain[mpi_i].est.ave_freq = redhelper2[mpi_i + NPLASMA]; + plasmamain[mpi_i].est.cool_tot = redhelper2[mpi_i + 2 * NPLASMA]; + plasmamain[mpi_i].est.heat_tot = redhelper2[mpi_i + 3 * NPLASMA]; + plasmamain[mpi_i].est.heat_lines = redhelper2[mpi_i + 4 * NPLASMA]; + plasmamain[mpi_i].est.heat_ff = redhelper2[mpi_i + 5 * NPLASMA]; + plasmamain[mpi_i].est.heat_comp = redhelper2[mpi_i + 6 * NPLASMA]; + plasmamain[mpi_i].est.heat_ind_comp = redhelper2[mpi_i + 7 * NPLASMA]; + plasmamain[mpi_i].est.heat_photo = redhelper2[mpi_i + 8 * NPLASMA]; + plasmamain[mpi_i].est.ip = redhelper2[mpi_i + 9 * NPLASMA]; + plasmamain[mpi_i].est.j_direct = redhelper2[mpi_i + 10 * NPLASMA]; + plasmamain[mpi_i].est.j_scatt = redhelper2[mpi_i + 11 * NPLASMA]; + plasmamain[mpi_i].est.ip_direct = redhelper2[mpi_i + 12 * NPLASMA]; + plasmamain[mpi_i].est.ip_scatt = redhelper2[mpi_i + 13 * NPLASMA]; + plasmamain[mpi_i].est.heat_auger = redhelper2[mpi_i + 14 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_es[0] = redhelper2[mpi_i + 15 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_es[1] = redhelper2[mpi_i + 16 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_es[2] = redhelper2[mpi_i + 17 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_es[3] = redhelper2[mpi_i + 18 * NPLASMA]; + plasmamain[mpi_i].est.F_vis[0] = redhelper2[mpi_i + 19 * NPLASMA]; + plasmamain[mpi_i].est.F_vis[1] = redhelper2[mpi_i + 20 * NPLASMA]; + plasmamain[mpi_i].est.F_vis[2] = redhelper2[mpi_i + 21 * NPLASMA]; + plasmamain[mpi_i].est.F_vis[3] = redhelper2[mpi_i + 22 * NPLASMA]; + plasmamain[mpi_i].est.F_UV[0] = redhelper2[mpi_i + 23 * NPLASMA]; + plasmamain[mpi_i].est.F_UV[1] = redhelper2[mpi_i + 24 * NPLASMA]; + plasmamain[mpi_i].est.F_UV[2] = redhelper2[mpi_i + 25 * NPLASMA]; + plasmamain[mpi_i].est.F_UV[3] = redhelper2[mpi_i + 26 * NPLASMA]; + plasmamain[mpi_i].est.F_Xray[0] = redhelper2[mpi_i + 27 * NPLASMA]; + plasmamain[mpi_i].est.F_Xray[1] = redhelper2[mpi_i + 28 * NPLASMA]; + plasmamain[mpi_i].est.F_Xray[2] = redhelper2[mpi_i + 29 * NPLASMA]; + plasmamain[mpi_i].est.F_Xray[3] = redhelper2[mpi_i + 30 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_bf[0] = redhelper2[mpi_i + 31 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_bf[1] = redhelper2[mpi_i + 32 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_bf[2] = redhelper2[mpi_i + 33 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_bf[3] = redhelper2[mpi_i + 34 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_ff[0] = redhelper2[mpi_i + 35 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_ff[1] = redhelper2[mpi_i + 36 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_ff[2] = redhelper2[mpi_i + 37 * NPLASMA]; + plasmamain[mpi_i].est.rad_force_ff[3] = redhelper2[mpi_i + 38 * NPLASMA]; for (mpi_j = 0; mpi_j < NXBANDS; mpi_j++) { - plasmamain[mpi_i].xj[mpi_j] = redhelper2[mpi_i + (39 + mpi_j) * NPLASMA]; - plasmamain[mpi_i].xave_freq[mpi_j] = redhelper2[mpi_i + (39 + NXBANDS + mpi_j) * NPLASMA]; - plasmamain[mpi_i].xsd_freq[mpi_j] = redhelper2[mpi_i + (39 + NXBANDS * 2 + mpi_j) * NPLASMA]; + plasmamain[mpi_i].est.xj[mpi_j] = redhelper2[mpi_i + (39 + mpi_j) * NPLASMA]; + plasmamain[mpi_i].est.xave_freq[mpi_j] = redhelper2[mpi_i + (39 + NXBANDS + mpi_j) * NPLASMA]; + plasmamain[mpi_i].est.xsd_freq[mpi_j] = redhelper2[mpi_i + (39 + NXBANDS * 2 + mpi_j) * NPLASMA]; /* 131213 NSH And unpack the min and max banded frequencies to the plasma array */ - plasmamain[mpi_i].fmax[mpi_j] = maxbandfreqhelper2[mpi_i * NXBANDS + mpi_j]; - plasmamain[mpi_i].fmin[mpi_j] = minbandfreqhelper2[mpi_i * NXBANDS + mpi_j]; + plasmamain[mpi_i].est.fmax[mpi_j] = maxbandfreqhelper2[mpi_i * NXBANDS + mpi_j]; + plasmamain[mpi_i].est.fmin[mpi_j] = minbandfreqhelper2[mpi_i * NXBANDS + mpi_j]; } for (mpi_j = 0; mpi_j < nions; mpi_j++) { - plasmamain[mpi_i].ioniz[mpi_j] = ion_helper2[mpi_i * nions + mpi_j]; + plasmamain[mpi_i].est.ioniz[mpi_j] = ion_helper2[mpi_i * nions + mpi_j]; } for (mpi_j = 0; mpi_j < n_inner_tot; mpi_j++) { - plasmamain[mpi_i].inner_ioniz[mpi_j] = inner_ion_helper2[mpi_i * n_inner_tot + mpi_j]; + plasmamain[mpi_i].est.inner_ioniz[mpi_j] = inner_ion_helper2[mpi_i * n_inner_tot + mpi_j]; } for (mpi_j = 0; mpi_j < NFLUX_ANGLES; mpi_j++) { - plasmamain[mpi_i].F_UV_ang_theta[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + mpi_j]; - plasmamain[mpi_i].F_UV_ang_phi[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + NFLUX_ANGLES + mpi_j]; - plasmamain[mpi_i].F_UV_ang_r[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + 2 * NFLUX_ANGLES + mpi_j]; + plasmamain[mpi_i].est.F_UV_ang_theta[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + mpi_j]; + plasmamain[mpi_i].est.F_UV_ang_phi[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + NFLUX_ANGLES + mpi_j]; + plasmamain[mpi_i].est.F_UV_ang_r[mpi_j] = flux_helper2[mpi_i * (3 * NFLUX_ANGLES) + 2 * NFLUX_ANGLES + mpi_j]; } } @@ -1247,17 +1298,17 @@ reduce_simple_estimators (void) for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { - iredhelper[mpi_i] = plasmamain[mpi_i].ntot; - iredhelper[mpi_i + NPLASMA] = plasmamain[mpi_i].ntot_star; - iredhelper[mpi_i + 2 * NPLASMA] = plasmamain[mpi_i].ntot_bl; - iredhelper[mpi_i + 3 * NPLASMA] = plasmamain[mpi_i].ntot_disk; - iredhelper[mpi_i + 4 * NPLASMA] = plasmamain[mpi_i].ntot_wind; - iredhelper[mpi_i + 5 * NPLASMA] = plasmamain[mpi_i].ntot_agn; - iredhelper[mpi_i + 6 * NPLASMA] = plasmamain[mpi_i].nioniz; + iredhelper[mpi_i] = plasmamain[mpi_i].est.ntot; + iredhelper[mpi_i + NPLASMA] = plasmamain[mpi_i].est.ntot_star; + iredhelper[mpi_i + 2 * NPLASMA] = plasmamain[mpi_i].est.ntot_bl; + iredhelper[mpi_i + 3 * NPLASMA] = plasmamain[mpi_i].est.ntot_disk; + iredhelper[mpi_i + 4 * NPLASMA] = plasmamain[mpi_i].est.ntot_wind; + iredhelper[mpi_i + 5 * NPLASMA] = plasmamain[mpi_i].est.ntot_agn; + iredhelper[mpi_i + 6 * NPLASMA] = plasmamain[mpi_i].est.nioniz; for (mpi_j = 0; mpi_j < NXBANDS; mpi_j++) { - iredhelper[mpi_i + (7 + mpi_j) * NPLASMA] = plasmamain[mpi_i].nxtot[mpi_j]; + iredhelper[mpi_i + (7 + mpi_j) * NPLASMA] = plasmamain[mpi_i].est.nxtot[mpi_j]; } } @@ -1272,17 +1323,17 @@ reduce_simple_estimators (void) for (mpi_i = 0; mpi_i < NPLASMA; mpi_i++) { - plasmamain[mpi_i].ntot = iredhelper2[mpi_i]; - plasmamain[mpi_i].ntot_star = iredhelper2[mpi_i + NPLASMA]; - plasmamain[mpi_i].ntot_bl = iredhelper2[mpi_i + 2 * NPLASMA]; - plasmamain[mpi_i].ntot_disk = iredhelper2[mpi_i + 3 * NPLASMA]; - plasmamain[mpi_i].ntot_wind = iredhelper2[mpi_i + 4 * NPLASMA]; - plasmamain[mpi_i].ntot_agn = iredhelper2[mpi_i + 5 * NPLASMA]; - plasmamain[mpi_i].nioniz = iredhelper2[mpi_i + 6 * NPLASMA]; + plasmamain[mpi_i].est.ntot = iredhelper2[mpi_i]; + plasmamain[mpi_i].est.ntot_star = iredhelper2[mpi_i + NPLASMA]; + plasmamain[mpi_i].est.ntot_bl = iredhelper2[mpi_i + 2 * NPLASMA]; + plasmamain[mpi_i].est.ntot_disk = iredhelper2[mpi_i + 3 * NPLASMA]; + plasmamain[mpi_i].est.ntot_wind = iredhelper2[mpi_i + 4 * NPLASMA]; + plasmamain[mpi_i].est.ntot_agn = iredhelper2[mpi_i + 5 * NPLASMA]; + plasmamain[mpi_i].est.nioniz = iredhelper2[mpi_i + 6 * NPLASMA]; for (mpi_j = 0; mpi_j < NXBANDS; mpi_j++) { - plasmamain[mpi_i].nxtot[mpi_j] = iredhelper2[mpi_i + (7 + mpi_j) * NPLASMA]; + plasmamain[mpi_i].est.nxtot[mpi_j] = iredhelper2[mpi_i + (7 + mpi_j) * NPLASMA]; } } @@ -1313,7 +1364,7 @@ reduce_simple_estimators (void) { for (mpi_j = 0; mpi_j < NPLASMA; mpi_j++) { - redhelper[mpi_i * NPLASMA + mpi_j] = plasmamain[mpi_j].cell_spec_flux[mpi_i] / np_mpi_global; + redhelper[mpi_i * NPLASMA + mpi_j] = plasmamain[mpi_j].est.cell_spec_flux[mpi_i] / np_mpi_global; } } @@ -1324,7 +1375,7 @@ reduce_simple_estimators (void) { for (mpi_j = 0; mpi_j < NPLASMA; mpi_j++) { - plasmamain[mpi_j].cell_spec_flux[mpi_i] = redhelper2[mpi_i * NPLASMA + mpi_j]; + plasmamain[mpi_j].est.cell_spec_flux[mpi_i] = redhelper2[mpi_i * NPLASMA + mpi_j]; } } diff --git a/source/compton.c b/source/compton.c index 35548e8b4..db750c010 100644 --- a/source/compton.c +++ b/source/compton.c @@ -52,7 +52,7 @@ compton_scatter (p) - t_e = xplasma->t_e; + t_e = xplasma->state.t_e; compton_get_thermal_velocity (t_e, velocity_electron); @@ -170,7 +170,7 @@ kappa_comp (xplasma, freq) sigma = compton_alpha (freq) * THOMPSON; //the energy exchange cross section x = (sigma * PLANCK) / (MELEC * VLIGHT * VLIGHT); - x *= xplasma->ne * freq; + x *= xplasma->state.ne * freq; ndom = wmain[xplasma->nwind].ndom; x *= zdom[ndom].fill; // multiply by the filling factor- @@ -219,7 +219,7 @@ kappa_ind_comp (xplasma, freq) sigma = THOMPSON * compton_alpha (freq); //the energy exchange cross section - x = (xplasma->ne) / (MELEC); + x = (xplasma->state.ne) / (MELEC); x *= sigma * J; x *= 1 / (2 * freq * freq); @@ -291,36 +291,36 @@ total_comp (one, t_e) x = 0.0; //Since J_nu is constant for a given cycle - we only need to compute the integral once when searching for a thermal balance - if (xplasma->comp_nujnu < 0.0) + if (xplasma->derived.comp_nujnu < 0.0) { if (geo.spec_mod) //Check to see if we have generated a spectral model { for (j = 0; j < geo.nxfreq; j++) { - if (xplasma->spec_mod_type[j] != SPEC_MOD_FAIL) //Only bother doing the integrals if we have a model in this band + if (xplasma->state.spec_mod_type[j] != SPEC_MOD_FAIL) //Only bother doing the integrals if we have a model in this band { - f1 = xplasma->fmin_mod[j]; - f2 = xplasma->fmax_mod[j]; + f1 = xplasma->state.fmin_mod[j]; + f2 = xplasma->state.fmax_mod[j]; if (f1 > 1e18) x += num_int (comp_cool_integrand, f1, f2, 1e-6); else - x += THOMPSON * xplasma->xj[j]; //If in the Thompson limit, we just multiply the band limited frequency integrated mean intensity by the Thompson cross section + x += THOMPSON * xplasma->est.xj[j]; //If in the Thompson limit, we just multiply the band limited frequency integrated mean intensity by the Thompson cross section } } } else //If no spectral model - we do the best we can, and multply the mean intensity by the Thompson cross section. { - x = THOMPSON * xplasma->j; + x = THOMPSON * xplasma->est.j; } - xplasma->comp_nujnu = x; + xplasma->derived.comp_nujnu = x; } else - x = xplasma->comp_nujnu; + x = xplasma->derived.comp_nujnu; //Multply by the other terms - including temperature - this gives the temperature dependance of this cooling term. - x *= (16. * PI * BOLTZMANN * t_e * xplasma->ne) / (MELEC * VLIGHT * VLIGHT) * xplasma->vol; + x *= (16. * PI * BOLTZMANN * t_e * xplasma->state.ne) / (MELEC * VLIGHT * VLIGHT) * xplasma->state.vol; return (x); diff --git a/source/cooling.c b/source/cooling.c index b05797b6e..96751caaf 100644 --- a/source/cooling.c +++ b/source/cooling.c @@ -42,7 +42,7 @@ cooling (xplasma, t) double t; { - xplasma->t_e = t; + xplasma->state.t_e = t; if (geo.adiabatic) @@ -53,37 +53,37 @@ cooling (xplasma, t) so we use the 'test' temperature to compute it. If div_v is less than zero, we don't do anything here, and so the existing value of adiabatic cooling is used - this was computed in wind_updates2d before the call to ion_abundances. */ - xplasma->cool_adiabatic = adiabatic_cooling (&wmain[xplasma->nwind], t); + xplasma->derived.cool_adiabatic = adiabatic_cooling (&wmain[xplasma->nwind], t); } } else { - xplasma->cool_adiabatic = 0.0; + xplasma->derived.cool_adiabatic = 0.0; } /*81c - nsh - we now treat DR cooling as a recombinational process - still unsure as to how to treat emission, so at the moment it remains here */ - xplasma->cool_dr = total_fb (xplasma, t, 0, VERY_BIG, FB_REDUCED, INNER_SHELL); + xplasma->derived.cool_dr = total_fb (xplasma, t, 0, VERY_BIG, FB_REDUCED, INNER_SHELL); /* 78b - nsh adding this line in next to calculate direct ionization cooling without generating photons */ - xplasma->cool_di = total_di (&wmain[xplasma->nwind], t); + xplasma->derived.cool_di = total_di (&wmain[xplasma->nwind], t); /* 70g compton cooling calculated here to avoid generating photons */ - xplasma->cool_comp = total_comp (&wmain[xplasma->nwind], t); + xplasma->derived.cool_comp = total_comp (&wmain[xplasma->nwind], t); /* we now call xtotal emission which computes the cooling rates for processes which can, in principle, make photons. */ - xplasma->cool_tot = - xplasma->cool_adiabatic + xplasma->cool_dr + xplasma->cool_di + - xplasma->cool_comp + xtotal_emission (&wmain[xplasma->nwind], 0., VERY_BIG); + xplasma->est.cool_tot = + xplasma->derived.cool_adiabatic + xplasma->derived.cool_dr + xplasma->derived.cool_di + + xplasma->derived.cool_comp + xtotal_emission (&wmain[xplasma->nwind], 0., VERY_BIG); - return (xplasma->cool_tot); + return (xplasma->est.cool_tot); } @@ -136,18 +136,18 @@ xtotal_emission (one, f1, f2) nplasma = one->nplasma; xplasma = &plasmamain[nplasma]; - t_e = xplasma->t_e; // Change so calls to total emission are simpler + t_e = xplasma->state.t_e; // Change so calls to total emission are simpler if (f2 < f1) { - xplasma->cool_tot = xplasma->lum_lines = xplasma->lum_ff = xplasma->cool_rr = 0; //NSH 1108 Zero the new cool_comp variable NSH 1101 - removed + xplasma->est.cool_tot = xplasma->derived.lum_lines = xplasma->derived.lum_ff = xplasma->derived.cool_rr = 0; //NSH 1108 Zero the new cool_comp variable NSH 1101 - removed } else { if (geo.rt_mode == RT_MODE_MACRO) //Switch for macro atoms (SS) { - xplasma->cool_bf_macro = total_fb_matoms (xplasma, t_e, f1, f2); - xplasma->cool_rr = xplasma->cool_bf_macro + total_fb (xplasma, t_e, f1, f2, FB_REDUCED, OUTER_SHELL); //outer shellrecombinations + xplasma->derived.cool_bf_macro = total_fb_matoms (xplasma, t_e, f1, f2); + xplasma->derived.cool_rr = xplasma->derived.cool_bf_macro + total_fb (xplasma, t_e, f1, f2, FB_REDUCED, OUTER_SHELL); //outer shellrecombinations //The first term here is the fb cooling due to macro ions and the second gives //the fb cooling due to simple ions. //total_fb has been modified to exclude recombinations treated using macro atoms. @@ -155,25 +155,25 @@ xtotal_emission (one, f1, f2) //now in case they should be used in the future. But they could //also be removed. // (SS) - cooling = xplasma->cool_rr; - xplasma->lum_lines = total_bb_cooling (xplasma, t_e); - cooling += xplasma->lum_lines; + cooling = xplasma->derived.cool_rr; + xplasma->derived.lum_lines = total_bb_cooling (xplasma, t_e); + cooling += xplasma->derived.lum_lines; /* total_bb_cooling gives the total cooling rate due to bb transisions whether they are macro atoms or simple ions. */ - xplasma->lum_ff = total_free (xplasma, t_e, f1, f2); - cooling += xplasma->lum_ff; + xplasma->derived.lum_ff = total_free (xplasma, t_e, f1, f2); + cooling += xplasma->derived.lum_ff; } else //default (non-macro atoms) (SS) { /*The line cooling is equal to the line emission */ - cooling = xplasma->lum_lines = total_line_emission (xplasma, f1, f2); + cooling = xplasma->derived.lum_lines = total_line_emission (xplasma, f1, f2); /* The free free cooling is equal to the free free emission */ - cooling += xplasma->lum_ff = total_free (xplasma, t_e, f1, f2); + cooling += xplasma->derived.lum_ff = total_free (xplasma, t_e, f1, f2); /*The free bound cooling is equal to the recomb rate x the electron energy - the boinding energy - this is computed with the FB_REDUCED switch */ - cooling += xplasma->cool_rr = total_fb (xplasma, t_e, f1, f2, FB_REDUCED, OUTER_SHELL); //outer shell recombinations + cooling += xplasma->derived.cool_rr = total_fb (xplasma, t_e, f1, f2, FB_REDUCED, OUTER_SHELL); //outer shell recombinations } @@ -212,11 +212,11 @@ xtotal_emission (one, f1, f2) * from all particles. Adiabatic coolling due to the radiation * pressure is not considered. * - * The routine does not populate xplasma->cool_adiabatic. + * The routine does not populate xplasma->derived.cool_adiabatic. * * Note also that this function should only be called * if geo.adiabatic == 1, in which case it populates - * xplasma->cool_adiabatic. This is used in heating and cooling + * xplasma->derived.cool_adiabatic. This is used in heating and cooling * balance. We also use it as a potential destruction choice for * kpkts in which case the kpkt is thrown away by setting its istat * to P_ADIABATIC. @@ -243,15 +243,15 @@ adiabatic_cooling (one, t) nplasma = one->nplasma; xplasma = &plasmamain[nplasma]; - nparticles = xplasma->ne; + nparticles = xplasma->state.ne; /* loop over all ions as they all contribute to the pressure */ for (nion = 0; nion < nions; nion++) { - nparticles += xplasma->density[nion]; + nparticles += xplasma->state.density[nion]; } - cooling = nparticles * BOLTZMANN * t * xplasma->vol * one->div_v; + cooling = nparticles * BOLTZMANN * t * xplasma->state.vol * one->div_v; return (cooling); } @@ -317,7 +317,7 @@ shock_heating (one) x = geo.shock_factor / (r * r * r * r); - x *= xplasma->vol; + x *= xplasma->state.vol; return (x); } @@ -392,7 +392,7 @@ wind_cooling (void) /* We are going to do this bit in parallel, as cooling evaluates some expensive integrals */ for (n_plasma = n_start; n_plasma < n_stop; ++n_plasma) { - cool_tot_cell = cooling (&plasmamain[n_plasma], plasmamain[n_plasma].t_e); + cool_tot_cell = cooling (&plasmamain[n_plasma], plasmamain[n_plasma].state.t_e); if (cool_tot_cell < 0) { Error ("wind_cooling: xtotal emission %8.4e is < 0!\n", cool_tot_cell); @@ -406,26 +406,26 @@ wind_cooling (void) * up some numbers */ for (n_plasma = 0; n_plasma < NPLASMA; ++n_plasma) { - cool_tot += plasmamain[n_plasma].cool_tot; - cool_rr += plasmamain[n_plasma].cool_rr; - cool_comp += plasmamain[n_plasma].cool_comp; - cool_dr += plasmamain[n_plasma].cool_dr; - cool_di += plasmamain[n_plasma].cool_di; + cool_tot += plasmamain[n_plasma].est.cool_tot; + cool_rr += plasmamain[n_plasma].derived.cool_rr; + cool_comp += plasmamain[n_plasma].derived.cool_comp; + cool_dr += plasmamain[n_plasma].derived.cool_dr; + cool_di += plasmamain[n_plasma].derived.cool_di; - lum_lines += plasmamain[n_plasma].lum_lines; - lum_ff += plasmamain[n_plasma].lum_ff; + lum_lines += plasmamain[n_plasma].derived.lum_lines; + lum_ff += plasmamain[n_plasma].derived.lum_ff; // Calculate the total adiabatic heating/cooling separating these into two variables if (geo.adiabatic) { - if (plasmamain[n_plasma].cool_adiabatic >= 0.0) + if (plasmamain[n_plasma].derived.cool_adiabatic >= 0.0) { - cool_adiab += plasmamain[n_plasma].cool_adiabatic; + cool_adiab += plasmamain[n_plasma].derived.cool_adiabatic; } else { - heat_adiab += plasmamain[n_plasma].cool_adiabatic; + heat_adiab += plasmamain[n_plasma].derived.cool_adiabatic; } } else @@ -437,7 +437,7 @@ wind_cooling (void) /* Calculate the non-thermal heating (for FU Ori models with extra wind heating) */ if (geo.nonthermal) { - nonthermal += plasmamain[n_plasma].heat_shock; + nonthermal += plasmamain[n_plasma].derived.heat_shock; } } diff --git a/source/define_wind.c b/source/define_wind.c index 5b2e4dcdd..e420a0837 100644 --- a/source/define_wind.c +++ b/source/define_wind.c @@ -80,12 +80,12 @@ calculate_mdot_wind (void) if (w[nstart + i * mdim].inwind == W_ALL_INWIND) { nplasma = w[nstart + i * mdim].nplasma; - mdotbase += plasmamain[nplasma].rho * PI * rr * w[nstart + i * mdim].v[2]; + mdotbase += plasmamain[nplasma].state.rho * PI * rr * w[nstart + i * mdim].v[2]; } if (w[n].inwind == W_ALL_INWIND) { nplasma = w[n].nplasma; - mdotwind += plasmamain[nplasma].rho * PI * rr * w[n].v[2]; + mdotwind += plasmamain[nplasma].state.rho * PI * rr * w[n].v[2]; } } @@ -137,8 +137,8 @@ create_macro_grid (void) for (n_plasma = n_start; n_plasma < n_stop; ++n_plasma) { - macromain[n_plasma].store_matom_matrix = modes.store_matom_matrix; - macromain[n_plasma].matom_transition_mode = geo.matom_transition_mode; + macromain[n_plasma].state.store_matom_matrix = modes.store_matom_matrix; + macromain[n_plasma].state.matom_transition_mode = geo.matom_transition_mode; } calloc_matom_matrix (NPLASMA); @@ -159,19 +159,19 @@ set_spectral_models (PlasmaPtr cell) for (n_band = 0; n_band < NXBANDS; n_band++) { - cell->spec_mod_type[n_band] = SPEC_MOD_FAIL; /*NSH 120817 - setting this to + cell->state.spec_mod_type[n_band] = SPEC_MOD_FAIL; /*NSH 120817 - setting this to a negative number means that at the outset, we assume we do not have a suitable model for the cell */ - cell->exp_temp[n_band] = geo.tmax; /*NSH 120817 - as an initial guess, - set this number to the hottest part of the model - - this should define where any exponential dropoff becomes important */ - cell->exp_w[n_band] = 0.0; /* 120817 Who knows what this should be! */ - cell->pl_alpha[n_band] = geo.alpha_agn; /*Awind2d: For domains an initial guess we assume the whole wind is - optically thin and so the spectral index for a PL illumination will be the - same everywhere. */ - cell->pl_log_w[n_band] = -1e99; /*131114 - a tiny weight - just to fill the variable */ - cell->fmin_mod[n_band] = 1e99; /* Set the minium model frequency to the max frequency in the band - means it will never be used which is correct at this time - there is no model */ - cell->fmax_mod[n_band] = 1e-99; /* Set the maximum model frequency to the min frequency in the band */ + cell->state.exp_temp[n_band] = geo.tmax; /*NSH 120817 - as an initial guess, + set this number to the hottest part of the model - + this should define where any exponential dropoff becomes important */ + cell->state.exp_w[n_band] = 0.0; /* 120817 Who knows what this should be! */ + cell->state.pl_alpha[n_band] = geo.alpha_agn; /*Awind2d: For domains an initial guess we assume the whole wind is + optically thin and so the spectral index for a PL illumination will be the + same everywhere. */ + cell->state.pl_log_w[n_band] = -1e99; /*131114 - a tiny weight - just to fill the variable */ + cell->state.fmin_mod[n_band] = 1e99; /* Set the minium model frequency to the max frequency in the band - means it will never be used which is correct at this time - there is no model */ + cell->state.fmax_mod[n_band] = 1e-99; /* Set the maximum model frequency to the min frequency in the band */ } } @@ -196,21 +196,21 @@ set_plasma_temperature (PlasmaPtr cell, int ndom, double xcen[3]) if (dom->wind_type == HYDRO) { - cell->t_r = hydro_temp (xcen); + cell->state.t_r = hydro_temp (xcen); } else if (dom->wind_type == IMPORT) { - cell->t_r = import_temperature (ndom, xcen, FALSE); + cell->state.t_r = import_temperature (ndom, xcen, FALSE); } else /* Taken from parameter file */ { - cell->t_r = dom->twind; + cell->state.t_r = dom->twind; } /* Initialize variables having to do with convergence in initial stages */ - cell->gain = 0.5; - cell->dt_e_old = 0.0; - cell->dt_e = 0.0; + cell->derived.gain = 0.5; + cell->derived.dt_e_old = 0.0; + cell->derived.dt_e = 0.0; /* The next lines set the electron temperature to 0.9 times the radiation temperature (which is a bit odd since the input is the wind temperature, but is taken to be the radiation temperature). If we have @@ -218,19 +218,19 @@ set_plasma_temperature (PlasmaPtr cell, int ndom, double xcen[3]) user gets what they are expecting. For LTE_TE mode, t_e is set to t_r and remains fixed. */ if (dom->wind_type == IMPORT) { - cell->t_e = import_temperature (ndom, xcen, TRUE); + cell->state.t_e = import_temperature (ndom, xcen, TRUE); } else if (geo.ioniz_mode == IONMODE_LTE_TE) { - cell->t_e = cell->t_e_old = cell->t_r; // LTE_TE: t_e fixed at initial t_r + cell->state.t_e = cell->state.t_e_old = cell->state.t_r; // LTE_TE: t_e fixed at initial t_r } else if (modes.fixed_temp == FALSE && modes.zeus_connect == FALSE) { - cell->t_e = cell->t_e_old = 0.9 * cell->t_r; // Lucy guess + cell->state.t_e = cell->state.t_e_old = 0.9 * cell->state.t_r; // Lucy guess } else //If we want to fix the temperature, we set it to tr which has previously been set to twind { - cell->t_e = cell->t_e_old = cell->t_r; + cell->state.t_e = cell->state.t_e_old = cell->state.t_r; } } @@ -285,9 +285,9 @@ create_plasma_grid (void) ndom = wmain[nwind].ndom; stuff_v (w[nwind].xcen, xcen); - plasmamain[n_plasma].xgamma = wmain[nwind].xgamma_cen; - plasmamain[n_plasma].rho = model_rho (ndom, xcen) / (zdom[ndom].fill * plasmamain[n_plasma].xgamma); - plasmamain[n_plasma].vol = w[nwind].vol * zdom[ndom].fill; + plasmamain[n_plasma].state.xgamma = wmain[nwind].xgamma_cen; + plasmamain[n_plasma].state.rho = model_rho (ndom, xcen) / (zdom[ndom].fill * plasmamain[n_plasma].state.xgamma); + plasmamain[n_plasma].state.vol = w[nwind].vol * zdom[ndom].fill; /* This is where we initialise the spectral models for the wind. */ set_spectral_models (&plasmamain[n_plasma]); @@ -299,11 +299,11 @@ create_plasma_grid (void) rrstar = 1.0 - (geo.rstar * geo.rstar) / (xcen[0] * xcen[0] + xcen[1] * xcen[1] + xcen[2] * xcen[2]); if (rrstar > 0) { - plasmamain[n_plasma].w = 0.5 * (1 - sqrt (rrstar)); + plasmamain[n_plasma].state.w = 0.5 * (1 - sqrt (rrstar)); } else { /* Allow for possibility that grid point is inside star */ - plasmamain[n_plasma].w = 0.5; + plasmamain[n_plasma].state.w = 0.5; } /* Determine the initial ion abundances, using either LTE or fixed concentrations */ @@ -323,33 +323,34 @@ create_plasma_grid (void) { Error ("wind_define after ion_abundances: cell %d rho %8.2e t_r %8.2e t_e %8.2e w %8.2e\n", - n_plasma, plasmamain[n_plasma].rho, plasmamain[n_plasma].t_r, plasmamain[n_plasma].t_e, plasmamain[n_plasma].w); + n_plasma, plasmamain[n_plasma].state.rho, plasmamain[n_plasma].state.t_r, plasmamain[n_plasma].state.t_e, + plasmamain[n_plasma].state.w); } /* Initialize arrays for tracking number of scatters in the cell */ for (nion = 0; nion < nions; nion++) { - plasmamain[n_plasma].scatters[nion] = 0; - plasmamain[n_plasma].xscatters[nion] = 0; + plasmamain[n_plasma].derived.scatters[nion] = 0; + plasmamain[n_plasma].derived.xscatters[nion] = 0; } /* Calculate adiabatic and non-thermal heating contributions */ if (geo.adiabatic) { - plasmamain[n_plasma].cool_adiabatic = adiabatic_cooling (&w[nwind], plasmamain[n_plasma].t_e); + plasmamain[n_plasma].derived.cool_adiabatic = adiabatic_cooling (&w[nwind], plasmamain[n_plasma].state.t_e); } else { - plasmamain[n_plasma].cool_adiabatic = 0.0; + plasmamain[n_plasma].derived.cool_adiabatic = 0.0; } if (geo.nonthermal) { nwind = plasmamain[n_plasma].nwind; - plasmamain[n_plasma].heat_shock = shock_heating (&w[nwind]); + plasmamain[n_plasma].derived.heat_shock = shock_heating (&w[nwind]); } else { - plasmamain[n_plasma].heat_shock = 0.0; + plasmamain[n_plasma].derived.heat_shock = 0.0; } } diff --git a/source/density.c b/source/density.c index 4f7151da4..78fa477d0 100644 --- a/source/density.c +++ b/source/density.c @@ -66,7 +66,7 @@ in the plasma structure*/ for (nn = 0; nn < nelem; nn++) { nplasma = wmain[nnn[nn]].nplasma; - dd += plasmamain[nplasma].density[nion] * frac[nn]; + dd += plasmamain[nplasma].state.density[nion] * frac[nn]; } } else diff --git a/source/dielectronic.c b/source/dielectronic.c index 35b71ead9..8433196af 100644 --- a/source/dielectronic.c +++ b/source/dielectronic.c @@ -139,9 +139,9 @@ total_dr (one, t_e) /* One possibility is to use the mean k.e. of electrons this is based on the idea that an eleectron is absorbed, so a guess would be to just say its energy is re-radiated. This is clearly an over estimate since some of the enegy is lost to binding energy */ -// x += xplasma->vol * xplasma->ne * xplasma->density[n + 1] * dr_coeffs[n] * meanke; +// x += xplasma->state.vol * xplasma->state.ne * xplasma->state.density[n + 1] * dr_coeffs[n] * meanke; /* A different estimate is to use the ionization potential of the ion - this is order of magnitude at best */ -// x += xplasma->vol * xplasma->ne * xplasma->density[n + 1] * dr_coeffs[n] * ion[n].ip; +// x += xplasma->state.vol * xplasma->state.ne * xplasma->state.density[n + 1] * dr_coeffs[n] * ion[n].ip; x += 0.0; //At present, we just set it to zero - obviously an underestimate! } } diff --git a/source/direct_ion.c b/source/direct_ion.c index e1c4c52c1..8b0f6b563 100644 --- a/source/direct_ion.c +++ b/source/direct_ion.c @@ -204,7 +204,8 @@ total_di (one, t_e) { if (ion[n].dere_di_flag) { - cooling_rate += xplasma->vol * xplasma->ne * xplasma->density[n] * di_coeffs[n] * dere_di_rate[ion[n].nxderedi].xi * EV2ERGS; + cooling_rate += + xplasma->state.vol * xplasma->state.ne * xplasma->state.density[n] * di_coeffs[n] * dere_di_rate[ion[n].nxderedi].xi * EV2ERGS; } } return (cooling_rate); diff --git a/source/emission.c b/source/emission.c index 36a502510..ae6710131 100644 --- a/source/emission.c +++ b/source/emission.c @@ -115,16 +115,16 @@ wind_luminosity (double f1, double f2, int mode) if (mode == MODE_OBSERVER_FRAME_TIME) { - gamma_factor = 1.0 / plasmamain[n_plasma].xgamma; /* this is dt_cmf */ + gamma_factor = 1.0 / plasmamain[n_plasma].state.xgamma; /* this is dt_cmf */ } else { gamma_factor = 1.0; } - lum_lines += plasmamain[n_plasma].lum_lines * gamma_factor; - lum_rad_recomb += plasmamain[n_plasma].lum_rr * gamma_factor; - lum_free_free += plasmamain[n_plasma].lum_ff * gamma_factor; + lum_lines += plasmamain[n_plasma].derived.lum_lines * gamma_factor; + lum_rad_recomb += plasmamain[n_plasma].derived.lum_rr * gamma_factor; + lum_free_free += plasmamain[n_plasma].derived.lum_ff * gamma_factor; } total_lum = lum_lines + lum_rad_recomb + lum_free_free; @@ -178,51 +178,51 @@ total_emission (xplasma, f1, f2) { double t_e; - t_e = xplasma->t_e; + t_e = xplasma->state.t_e; if (f2 < f1) { - xplasma->lum_tot = xplasma->lum_lines = xplasma->lum_ff = xplasma->lum_rr = 0; + xplasma->derived.lum_tot = xplasma->derived.lum_lines = xplasma->derived.lum_ff = xplasma->derived.lum_rr = 0; } else { if (geo.rt_mode == RT_MODE_MACRO) { - xplasma->lum_rr = (total_fb_matoms (xplasma, t_e, f1, f2) + total_fb (xplasma, t_e, f1, f2, FB_FULL, OUTER_SHELL)); //outer shellrecombinations + xplasma->derived.lum_rr = (total_fb_matoms (xplasma, t_e, f1, f2) + total_fb (xplasma, t_e, f1, f2, FB_FULL, OUTER_SHELL)); //outer shellrecombinations /* *The first term here is the fb cooling due to macro ions and the second gives *the fb cooling due to simple ions. *total_fb has been modified to exclude recombinations treated using macro atoms. */ - xplasma->lum_tot = xplasma->cool_rr; + xplasma->derived.lum_tot = xplasma->derived.cool_rr; /* Note: This the fb_matom call makes no use of f1 or f2. They are passed for * now in case they should be used in the future. But they could * also be removed. * (SS) */ - xplasma->lum_lines = total_bb_cooling (xplasma, t_e); - xplasma->lum_tot += xplasma->lum_lines; + xplasma->derived.lum_lines = total_bb_cooling (xplasma, t_e); + xplasma->derived.lum_tot += xplasma->derived.lum_lines; /* total_bb_cooling gives the total cooling rate due to bb transisions whether they are macro atoms or simple ions. */ - xplasma->lum_ff = total_free (xplasma, t_e, f1, f2); - xplasma->lum_tot += xplasma->lum_ff; + xplasma->derived.lum_ff = total_free (xplasma, t_e, f1, f2); + xplasma->derived.lum_tot += xplasma->derived.lum_ff; } else //default (non-macro atoms) (SS) { - xplasma->lum_tot = xplasma->lum_lines = total_line_emission (xplasma, f1, f2); - xplasma->lum_tot += xplasma->lum_ff = total_free (xplasma, t_e, f1, f2); + xplasma->derived.lum_tot = xplasma->derived.lum_lines = total_line_emission (xplasma, f1, f2); + xplasma->derived.lum_tot += xplasma->derived.lum_ff = total_free (xplasma, t_e, f1, f2); /* We compute the radiative recombination luminosity - this is not the same as the rr cooling rate and so is stored in a separate variable */ - xplasma->lum_tot += xplasma->lum_rr = total_fb (xplasma, t_e, f1, f2, FB_FULL, OUTER_SHELL); //outer shell recombinations + xplasma->derived.lum_tot += xplasma->derived.lum_rr = total_fb (xplasma, t_e, f1, f2, FB_FULL, OUTER_SHELL); //outer shell recombinations } } - return (xplasma->lum_tot); + return (xplasma->derived.lum_tot); } @@ -316,8 +316,8 @@ photo_gen_wind (p, weight, freqmin, freqmax, photstart, nphot) while (xlumsum < xlum) { - dt_cmf = 1.0 / plasmamain[nplasma].xgamma; - xlumsum += plasmamain[nplasma].lum_tot * dt_cmf; + dt_cmf = 1.0 / plasmamain[nplasma].state.xgamma; + xlumsum += plasmamain[nplasma].derived.lum_tot * dt_cmf; nplasma++; } nplasma--; @@ -330,21 +330,21 @@ photo_gen_wind (p, weight, freqmin, freqmax, photstart, nphot) /* At this point we know the cell in which the photon will be generated */ - plasmamain[nplasma].nrad += 1; + plasmamain[nplasma].derived.nrad += 1; /*Determine the type of photon this photon will be and increment ptype, which stores the total number of * each photon type to be made in each cell. We don't need to account for time * dilation heere, because all processes are in the same cell*/ - lum = plasmamain[nplasma].lum_tot; + lum = plasmamain[nplasma].derived.lum_tot; xlum = lum * random_number (0.0, 1.0); xlumsum = 0; - if ((xlumsum += plasmamain[nplasma].lum_ff) > xlum) + if ((xlumsum += plasmamain[nplasma].derived.lum_ff) > xlum) { ptype[nplasma][FREE_FREE]++; } - else if ((xlumsum += plasmamain[nplasma].lum_rr) > xlum) + else if ((xlumsum += plasmamain[nplasma].derived.lum_rr) > xlum) { ptype[nplasma][FREE_BOUND]++; } @@ -378,7 +378,8 @@ photo_gen_wind (p, weight, freqmin, freqmax, photstart, nphot) if (p[np].freq <= 0.0) { Error_silent - ("photo_gen_wind: On return from one_ff: icell %d vol %g t_e %g\n", nplasma, plasmamain[nplasma].vol, plasmamain[nplasma].t_e); + ("photo_gen_wind: On return from one_ff: icell %d vol %g t_e %g\n", nplasma, plasmamain[nplasma].state.vol, + plasmamain[nplasma].state.t_e); p[np].freq = 0.0; } } @@ -492,7 +493,7 @@ one_line (xplasma, nres) double xlum, xlumsum; int m; /* Put in a bunch of checks */ - if (xplasma->lum_lines <= 0) + if (xplasma->derived.lum_lines <= 0) { Error ("one_line: requesting a line when line lum is 0\n"); return (0); @@ -504,7 +505,7 @@ one_line (xplasma, nres) } - xlum = xplasma->lum_lines * random_number (0.0, 1.0); + xlum = xplasma->derived.lum_lines * random_number (0.0, 1.0); xlumsum = 0; m = nline_min; @@ -569,14 +570,14 @@ total_free (xplasma, t_e, f1, f2) return (0.0); } - if (ALPHA_FF * xplasma->t_e / H_OVER_K < f1) + if (ALPHA_FF * xplasma->state.t_e / H_OVER_K < f1) { return (0.0); } - if (ALPHA_FF * xplasma->t_e / H_OVER_K < f2) + if (ALPHA_FF * xplasma->state.t_e / H_OVER_K < f2) { - f2 = ALPHA_FF * xplasma->t_e / H_OVER_K; + f2 = ALPHA_FF * xplasma->state.t_e / H_OVER_K; } if (t_e < TMIN) @@ -590,11 +591,11 @@ total_free (xplasma, t_e, f1, f2) g_ff_h = g_ff_he = 1.0; if (nelements > 1) { - x = BREMS_CONSTANT * xplasma->ne * (xplasma->density[1] * g_ff_h + 4. * xplasma->density[4] * g_ff_he) / H_OVER_K; + x = BREMS_CONSTANT * xplasma->state.ne * (xplasma->state.density[1] * g_ff_h + 4. * xplasma->state.density[4] * g_ff_he) / H_OVER_K; } else { - x = BREMS_CONSTANT * xplasma->ne * (xplasma->density[1] * g_ff_h) / H_OVER_K; + x = BREMS_CONSTANT * xplasma->state.ne * (xplasma->state.density[1] * g_ff_h) / H_OVER_K; } } else @@ -606,16 +607,16 @@ total_free (xplasma, t_e, f1, f2) { gsqrd = ((ion[nion].istate - 1) * (ion[nion].istate - 1) * RYD2ERGS) / (BOLTZMANN * t_e); gaunt = gaunt_ff (gsqrd); - sum += xplasma->density[nion] * (ion[nion].istate - 1) * (ion[nion].istate - 1) * gaunt; + sum += xplasma->state.density[nion] * (ion[nion].istate - 1) * (ion[nion].istate - 1) * gaunt; } } - x = BREMS_CONSTANT * xplasma->ne * (sum) / H_OVER_K; + x = BREMS_CONSTANT * xplasma->state.ne * (sum) / H_OVER_K; } /* JM 1604 -- The reason why this is proportional to t_e**1/2, rather than t_e**(-1/2) as in equation 40 of LK02 is because one gets an extra factor of (k*t_e/h) when one does the integral */ - x *= sqrt (t_e) * xplasma->vol; + x *= sqrt (t_e) * xplasma->state.vol; x *= (exp (-H_OVER_K * f1 / t_e) - exp (-H_OVER_K * f2 / t_e)); return (x); } @@ -674,11 +675,11 @@ ff (xplasma, t_e, freq) g_ff_h = g_ff_he = 1.0; if (nelements > 1) { - fnu = BREMS_CONSTANT * xplasma->ne * (xplasma->density[1] * g_ff_h + 4. * xplasma->density[4] * g_ff_he); + fnu = BREMS_CONSTANT * xplasma->state.ne * (xplasma->state.density[1] * g_ff_h + 4. * xplasma->state.density[4] * g_ff_he); } else { - fnu = BREMS_CONSTANT * xplasma->ne * (xplasma->density[1] * g_ff_h); + fnu = BREMS_CONSTANT * xplasma->state.ne * (xplasma->state.density[1] * g_ff_h); } } else @@ -690,17 +691,17 @@ ff (xplasma, t_e, freq) { gsqrd = ((ion[nion].istate - 1) * (ion[nion].istate - 1) * RYD2ERGS) / (BOLTZMANN * t_e); gaunt = gaunt_ff (gsqrd); - sum += xplasma->density[nion] * (ion[nion].istate - 1) * (ion[nion].istate - 1) * gaunt; + sum += xplasma->state.density[nion] * (ion[nion].istate - 1) * (ion[nion].istate - 1) * gaunt; } else { sum += 0.0; } } - fnu = BREMS_CONSTANT * xplasma->ne * (sum); + fnu = BREMS_CONSTANT * xplasma->state.ne * (sum); } - ff_constant = fnu * xplasma->vol; + ff_constant = fnu * xplasma->state.vol; } @@ -753,31 +754,31 @@ one_ff (xplasma, f1, f2) if (f2 < f1) { - Error ("one_ff: Bad inputs f2 %g < f1 %g returning 0.0 t_e %g\n", f2, f1, xplasma->t_e); + Error ("one_ff: Bad inputs f2 %g < f1 %g returning 0.0 t_e %g\n", f2, f1, xplasma->state.t_e); return (-1.0); } /* Check to see if we have already generated a pdf */ - if (xplasma->t_e != one_ff_te || f1 != one_ff_f1 || f2 != one_ff_f2) + if (xplasma->state.t_e != one_ff_te || f1 != one_ff_f1 || f2 != one_ff_f2) { /* Generate a new pdf */ dfreq = (f2 - f1) / (ARRAY_PDF - 1); for (n = 0; n < ARRAY_PDF - 1; n++) { ff_x[n] = f1 + dfreq * n; - ff_y[n] = ff (xplasma, xplasma->t_e, ff_x[n]); + ff_y[n] = ff (xplasma, xplasma->state.t_e, ff_x[n]); } ff_x[ARRAY_PDF - 1] = f2; - ff_y[ARRAY_PDF - 1] = ff (xplasma, xplasma->t_e, ff_x[ARRAY_PDF - 1]); + ff_y[ARRAY_PDF - 1] = ff (xplasma, xplasma->state.t_e, ff_x[ARRAY_PDF - 1]); if ((echeck = cdf_gen_from_array (&cdf_ff, ff_x, ff_y, ARRAY_PDF, f1, f2)) != 0) { Error ("one_ff: cdf_gen_from_array error %d : nplasma %d f1 %g f2 %g te %g ne %g nh %g vol %g\n", - echeck, xplasma->nplasma, f1, f2, xplasma->t_e, xplasma->ne, xplasma->density[1], xplasma->vol); + echeck, xplasma->nplasma, f1, f2, xplasma->state.t_e, xplasma->state.ne, xplasma->state.density[1], xplasma->state.vol); Exit (0); } - one_ff_te = xplasma->t_e; + one_ff_te = xplasma->state.t_e; one_ff_f1 = f1; one_ff_f2 = f2; } diff --git a/source/estimators_macro.c b/source/estimators_macro.c index 9a4554865..01cfced89 100644 --- a/source/estimators_macro.c +++ b/source/estimators_macro.c @@ -94,8 +94,8 @@ bf_estimators_increment (one, p, ds) freq_av = p->freq; - if (p->freq > xplasma->max_freq) - xplasma->max_freq = p->freq; + if (p->freq > xplasma->est.max_freq) + xplasma->est.max_freq = p->freq; if (modes.save_cell_stats && ncstat > 0) { @@ -108,16 +108,16 @@ bf_estimators_increment (one, p, ds) /* check that j and ave freq give sensible numbers */ - if (sane_check (xplasma->j) || sane_check (xplasma->ave_freq)) + if (sane_check (xplasma->est.j) || sane_check (xplasma->est.ave_freq)) { - Error ("bf_estimators_increment:sane_check Problem with j %g or ave_freq %g\n", xplasma->j, xplasma->ave_freq); + Error ("bf_estimators_increment:sane_check Problem with j %g or ave_freq %g\n", xplasma->est.j, xplasma->est.ave_freq); } - for (nn = 0; nn < xplasma->kbf_nuse; nn++) + for (nn = 0; nn < xplasma->state.kbf_nuse; nn++) { - n = xplasma->kbf_use[nn]; + n = xplasma->state.kbf_use[nn]; ft = phot_top[n].freq[0]; //This is the edge frequency (SS) if (ion[phot_top[n].nion].phot_info > 0) //topbase or hybrid @@ -127,7 +127,7 @@ bf_estimators_increment (one, p, ds) } else if (ion[phot_top[n].nion].phot_info == 0) //vfky { - density = xplasma->density[phot_top[n].nion]; + density = xplasma->state.density[phot_top[n].nion]; llvl = 0; // shouldn't ever be used } @@ -158,26 +158,26 @@ bf_estimators_increment (one, p, ds) weight_of_packet = p->w; y = weight_of_packet * x * ds; - exponential = y * exp (-(freq_av - ft) / BOLTZMANN / xplasma->t_e); + exponential = y * exp (-(freq_av - ft) / BOLTZMANN / xplasma->state.t_e); /* Increment the photoionization rate estimator */ - mplasma->gamma[xconfig[llvl].bfu_indx_first + m] += y / freq_av; + mplasma->est.gamma[xconfig[llvl].bfu_indx_first + m] += y / freq_av; - mplasma->alpha_st[xconfig[llvl].bfu_indx_first + m] += exponential / freq_av; + mplasma->est.alpha_st[xconfig[llvl].bfu_indx_first + m] += exponential / freq_av; - mplasma->gamma_e[xconfig[llvl].bfu_indx_first + m] += y / ft; + mplasma->est.gamma_e[xconfig[llvl].bfu_indx_first + m] += y / ft; - mplasma->alpha_st_e[xconfig[llvl].bfu_indx_first + m] += exponential / ft; + mplasma->est.alpha_st_e[xconfig[llvl].bfu_indx_first + m] += exponential / ft; /* Now record the contribution to the energy absorbed by macro atoms allowing for the filling factor. */ yy = y * den_config (xplasma, llvl) * zdom[ndom].fill; - mplasma->matom_abs[phot_top[n].uplev] += abs_cont = yy * ft / freq_av; + mplasma->est.matom_abs[phot_top[n].uplev] += abs_cont = yy * ft / freq_av; - xplasma->kpkt_abs += yy - abs_cont; + xplasma->est.kpkt_abs += yy - abs_cont; /* Check for packets that appear to travelling suspiciously large optical depth in the continuum */ @@ -203,12 +203,12 @@ bf_estimators_increment (one, p, ds) /* JM1411 -- added filling factor - density enhancement cancels with zdom[ndom].fill */ - xplasma->heat_photo += heat_contribution = y * density * (1.0 - (ft / freq_av)) * zdom[ndom].fill; + xplasma->est.heat_photo += heat_contribution = y * density * (1.0 - (ft / freq_av)) * zdom[ndom].fill; - xplasma->heat_tot += heat_contribution; + xplasma->est.heat_tot += heat_contribution; /* This heat contribution is also the contibution to making k-packets in this volume. So we record it. */ - xplasma->kpkt_abs += heat_contribution; + xplasma->est.kpkt_abs += heat_contribution; } } } @@ -229,12 +229,12 @@ bf_estimators_increment (one, p, ds) y = weight_of_packet * kappa_ff (xplasma, freq_av) * ds; - xplasma->heat_ff += heat_contribution = y; // record ff hea + xplasma->est.heat_ff += heat_contribution = y; // record ff hea /* This heat contribution is also the contibution to making k-packets in this volume. So we record it. */ /* JM 2402 note that previously we incorrectly included Compton processes in kpkt_abs, which could lead to large amounts of radiation coming out incorrectly in other k->r channels in spectral cycles */ - xplasma->kpkt_abs += heat_contribution; + xplasma->est.kpkt_abs += heat_contribution; @@ -242,7 +242,7 @@ bf_estimators_increment (one, p, ds) y = weight_of_packet * kappa_comp (xplasma, freq_av) * ds; - xplasma->heat_comp += y; // record the compton heating + xplasma->est.heat_comp += y; // record the compton heating heat_contribution += y; // add compton to the heat contribution @@ -250,12 +250,12 @@ bf_estimators_increment (one, p, ds) y = weight_of_packet * kappa_ind_comp (xplasma, freq_av) * ds; - xplasma->heat_ind_comp += y; // record the induced compton heating + xplasma->est.heat_ind_comp += y; // record the induced compton heating heat_contribution += y; // add induced compton to the heat contribution - xplasma->heat_tot += heat_contribution; // heat contribution is the contribution from compton, ind comp and ff processes + xplasma->est.heat_tot += heat_contribution; // heat contribution is the contribution from compton, ind comp and ff processes return (0); } @@ -348,7 +348,7 @@ bb_estimators_increment (one, p, tau_sobolev, dvds, nn) if (y >= 0) { - mplasma->jbar[xconfig[llvl].bbu_indx_first + n] += y; + mplasma->est.jbar[xconfig[llvl].bbu_indx_first + n] += y; } else { @@ -358,7 +358,7 @@ bb_estimators_increment (one, p, tau_sobolev, dvds, nn) /* Record contribution to energy absorbed by macro atoms. */ - mplasma->matom_abs[line_ptr->nconfigu] += weight_of_packet * (1. - exp (-tau_sobolev)); + mplasma->est.matom_abs[line_ptr->nconfigu] += weight_of_packet * (1. - exp (-tau_sobolev)); return (0); } @@ -434,19 +434,19 @@ normalise_macro_estimators (PlasmaPtr xplasma) the LTE population ratio. The multiplicative factor is given by: */ - stimfac = 0.5 * pow (PLANCK * PLANCK / 2. / PI / MELEC / BOLTZMANN / xplasma->t_e, 3. / 2.); + stimfac = 0.5 * pow (PLANCK * PLANCK / 2. / PI / MELEC / BOLTZMANN / xplasma->state.t_e, 3. / 2.); for (i = 0; i < nlte_levels; i++) { for (j = 0; j < xconfig[i].n_bfu_jump; j++) { - mplasma->gamma_old[xconfig[i].bfu_indx_first + j] = mplasma->gamma[xconfig[i].bfu_indx_first + j] / PLANCK / invariant_volume_time; // normalize by invariant_volume_time + mplasma->state.gamma_old[xconfig[i].bfu_indx_first + j] = mplasma->est.gamma[xconfig[i].bfu_indx_first + j] / PLANCK / invariant_volume_time; // normalize by invariant_volume_time - mplasma->gamma_e_old[xconfig[i].bfu_indx_first + j] = - mplasma->gamma_e[xconfig[i].bfu_indx_first + j] / PLANCK / invariant_volume_time; + mplasma->state.gamma_e_old[xconfig[i].bfu_indx_first + j] = + mplasma->est.gamma_e[xconfig[i].bfu_indx_first + j] / PLANCK / invariant_volume_time; - mplasma->gamma[xconfig[i].bfu_indx_first + j] = 0.0; //re-initialise for next iteration - mplasma->gamma_e[xconfig[i].bfu_indx_first + j] = 0.0; + mplasma->est.gamma[xconfig[i].bfu_indx_first + j] = 0.0; //re-initialise for next iteration + mplasma->est.gamma_e[xconfig[i].bfu_indx_first + j] = 0.0; /* For the stimulated recombination parts we need the the ratio of statistical weights too. For free electron statistical @@ -454,13 +454,13 @@ normalise_macro_estimators (PlasmaPtr xplasma) stat_weight_ratio = xconfig[phot_top[xconfig[i].bfu_jump[j]].uplev].g / xconfig[i].g; - mplasma->alpha_st_old[xconfig[i].bfu_indx_first + j] = - mplasma->alpha_st[xconfig[i].bfu_indx_first + j] * stimfac * stat_weight_ratio / PLANCK / invariant_volume_time; - mplasma->alpha_st[xconfig[i].bfu_indx_first + j] = 0.0; + mplasma->state.alpha_st_old[xconfig[i].bfu_indx_first + j] = + mplasma->est.alpha_st[xconfig[i].bfu_indx_first + j] * stimfac * stat_weight_ratio / PLANCK / invariant_volume_time; + mplasma->est.alpha_st[xconfig[i].bfu_indx_first + j] = 0.0; - mplasma->alpha_st_e_old[xconfig[i].bfu_indx_first + j] = - mplasma->alpha_st_e[xconfig[i].bfu_indx_first + j] * stimfac * stat_weight_ratio / PLANCK / invariant_volume_time; - mplasma->alpha_st_e[xconfig[i].bfu_indx_first + j] = 0.0; + mplasma->state.alpha_st_e_old[xconfig[i].bfu_indx_first + j] = + mplasma->est.alpha_st_e[xconfig[i].bfu_indx_first + j] * stimfac * stat_weight_ratio / PLANCK / invariant_volume_time; + mplasma->est.alpha_st_e[xconfig[i].bfu_indx_first + j] = 0.0; /* For continuua whose edges lie beyond freqmin assume that gamma is given by a black body. */ @@ -471,10 +471,10 @@ normalise_macro_estimators (PlasmaPtr xplasma) if (phot_top[xconfig[i].bfu_jump[j]].freq[0] < 7.5e12 || phot_top[xconfig[i].bfu_jump[j]].freq[0] > 5e18) { - mplasma->gamma_old[xconfig[i].bfu_indx_first + j] = get_gamma (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->gamma_e_old[xconfig[i].bfu_indx_first + j] = get_gamma_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->alpha_st_e_old[xconfig[i].bfu_indx_first + j] = get_alpha_st_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->alpha_st_old[xconfig[i].bfu_indx_first + j] = get_alpha_st (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.gamma_old[xconfig[i].bfu_indx_first + j] = get_gamma (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.gamma_e_old[xconfig[i].bfu_indx_first + j] = get_gamma_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.alpha_st_e_old[xconfig[i].bfu_indx_first + j] = get_alpha_st_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.alpha_st_old[xconfig[i].bfu_indx_first + j] = get_alpha_st (&phot_top[xconfig[i].bfu_jump[j]], xplasma); } } @@ -506,14 +506,14 @@ normalise_macro_estimators (PlasmaPtr xplasma) stimfac = 1. - stimfac; } else if (upper_density > DENSITY_PHOT_MIN && lower_density > DENSITY_PHOT_MIN - && xplasma->levden[xconfig[nlev_upper].nden] > DENSITY_MIN) + && xplasma->state.levden[xconfig[nlev_upper].nden] > DENSITY_MIN) { /* check for population inversions. We don't worry about this if the densities are extremely low or if the upper level has hit the density floor - the lower level is still allowed to hit this floor because it should never cause an inversion */ Error ("normalise_macro_estimators: bb stimulated correction factor is out of bounds, 0 <= stimfac < 1 but got %g\n", stimfac); - Error ("normalise_macro_estimators: upper_density %g lower_density %g xplasma->levden[config[nlev_upper].nden] %g\n", - upper_density, lower_density, xplasma->levden[xconfig[nlev_upper].nden]); + Error ("normalise_macro_estimators: upper_density %g lower_density %g xplasma->state.levden[config[nlev_upper].nden] %g\n", + upper_density, lower_density, xplasma->state.levden[xconfig[nlev_upper].nden]); stimfac = 0.0; } else @@ -524,9 +524,9 @@ normalise_macro_estimators (PlasmaPtr xplasma) /* normalise jbar. Note that this uses the cell volume rather than the filled volume */ line_freq = line[xconfig[i].bbu_jump[j]].freq; - mplasma->jbar_old[xconfig[i].bbu_indx_first + j] = - mplasma->jbar[xconfig[i].bbu_indx_first + j] * VLIGHT * stimfac / 4. / PI / invariant_volume_time / line_freq; - mplasma->jbar[xconfig[i].bbu_indx_first + j] = 0.0; + mplasma->state.jbar_old[xconfig[i].bbu_indx_first + j] = + mplasma->est.jbar[xconfig[i].bbu_indx_first + j] * VLIGHT * stimfac / 4. / PI / invariant_volume_time / line_freq; + mplasma->est.jbar[xconfig[i].bbu_indx_first + j] = 0.0; } } @@ -534,15 +534,15 @@ normalise_macro_estimators (PlasmaPtr xplasma) /* Get the heating contribution from macro atom bb transitions (the line heating). */ - xplasma->heat_lines += heat_contribution = macro_bb_heating (xplasma, xplasma->t_e); - xplasma->heat_lines_macro = heat_contribution; - xplasma->heat_tot += heat_contribution; + xplasma->est.heat_lines += heat_contribution = macro_bb_heating (xplasma, xplasma->state.t_e); + xplasma->est.heat_lines_macro = heat_contribution; + xplasma->est.heat_tot += heat_contribution; /* Get the bf heating contributions here too. (SS June 04) */ - xplasma->heat_photo += heat_contribution = macro_bf_heating (xplasma, xplasma->t_e); - xplasma->heat_photo_macro = heat_contribution; - xplasma->heat_tot += heat_contribution; + xplasma->est.heat_photo += heat_contribution = macro_bf_heating (xplasma, xplasma->state.t_e); + xplasma->est.heat_photo_macro = heat_contribution; + xplasma->est.heat_tot += heat_contribution; /* finally, check if we have any places where stimulated recombination wins over photoionization */ @@ -554,8 +554,8 @@ normalise_macro_estimators (PlasmaPtr xplasma) geo.macro_ioniz_mode = MACRO_IONIZ_MODE_ESTIMATORS; /* force recalculation of k-packet rates and matrices, if applicable */ - mplasma->kpkt_rates_known = FALSE; - mplasma->matrix_rates_known = FALSE; + mplasma->derived.kpkt_rates_known = FALSE; + mplasma->derived.matrix_rates_known = FALSE; return (0); } @@ -602,8 +602,8 @@ total_fb_matoms (xplasma, t_e, f1, f2) mplasma = ¯omain[xplasma->nplasma]; - t_e_store = xplasma->t_e; //store the temperature - will put it back at the end - xplasma->t_e = t_e; //for use in calls to alpha_sp below + t_e_store = xplasma->state.t_e; //store the temperature - will put it back at the end + xplasma->state.t_e = t_e; //for use in calls to alpha_sp below total = 0; @@ -625,22 +625,23 @@ total_fb_matoms (xplasma, t_e, f1, f2) This is essentially equation (33) of Lucy (2003) */ cool_contribution = - (mplasma->alpha_st_e_old[xconfig[i].bfu_indx_first + j] + + (mplasma->state.alpha_st_e_old[xconfig[i].bfu_indx_first + j] + alpha_sp (cont_ptr, xplasma, 1) - - mplasma->alpha_st_old[xconfig[i].bfu_indx_first + j] - - alpha_sp (cont_ptr, xplasma, 0)) * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * density * xplasma->ne * xplasma->vol; + - mplasma->state.alpha_st_old[xconfig[i].bfu_indx_first + j] + - alpha_sp (cont_ptr, xplasma, + 0)) * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * density * xplasma->state.ne * xplasma->state.vol; /* Now add the collisional ionization term. */ density = den_config (xplasma, cont_ptr->nlev); cool_contribution += - q_ioniz (cont_ptr, t_e) * density * xplasma->ne * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * xplasma->vol; + q_ioniz (cont_ptr, t_e) * density * xplasma->state.ne * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * xplasma->state.vol; /* That's the bf cooling contribution. */ total += cool_contribution; } } - xplasma->t_e = t_e_store; //restore the original value + xplasma->state.t_e = t_e_store; //restore the original value } @@ -678,7 +679,7 @@ total_bb_cooling (xplasma, t_e) double coll_rate, rad_rate; total = 0; // initialise - xplasma->cool_lines_macro = 0; + xplasma->derived.cool_lines_macro = 0; for (i = 0; i < nlines; i++) { line_ptr = &line[i]; @@ -686,8 +687,8 @@ total_bb_cooling (xplasma, t_e) { //This is a line from a macro atom for which we know //the upper and lower level populations lower_density = den_config (xplasma, line_ptr->nconfigl); - cool_contribution = (lower_density * q12 (line_ptr, t_e)) * xplasma->ne * xplasma->vol * line_ptr->freq * PLANCK; - xplasma->cool_lines_macro += cool_contribution; + cool_contribution = (lower_density * q12 (line_ptr, t_e)) * xplasma->state.ne * xplasma->state.vol * line_ptr->freq * PLANCK; + xplasma->derived.cool_lines_macro += cool_contribution; } else { //It's a simple line - don't know the level populations @@ -696,11 +697,11 @@ total_bb_cooling (xplasma, t_e) //The cooling rate is computed using the scattering probability formalism in KSL's notes on Sirocco. two_level_atom (line_ptr, xplasma, &lower_density, &upper_density); - coll_rate = q21 (line_ptr, t_e) * xplasma->ne * (1. - exp (-H_OVER_K * line_ptr->freq / t_e)); + coll_rate = q21 (line_ptr, t_e) * xplasma->state.ne * (1. - exp (-H_OVER_K * line_ptr->freq / t_e)); cool_contribution = (lower_density * line_ptr->gu / line_ptr->gl - - upper_density) * coll_rate / (exp (H_OVER_K * line_ptr->freq / t_e) - 1.) * xplasma->vol * line_ptr->freq * PLANCK; + upper_density) * coll_rate / (exp (H_OVER_K * line_ptr->freq / t_e) - 1.) * xplasma->state.vol * line_ptr->freq * PLANCK; rad_rate = a21 (line_ptr) * p_escape (line_ptr, xplasma); @@ -752,7 +753,7 @@ macro_bb_heating (xplasma, t_e) { //This is a line from a macro atom for which we know //the upper and lower level populations upper_density = den_config (xplasma, line_ptr->nconfigu); - heat_contribution = upper_density * q21 (line_ptr, t_e) * xplasma->ne * xplasma->vol * line_ptr->freq * PLANCK; + heat_contribution = upper_density * q21 (line_ptr, t_e) * xplasma->state.ne * xplasma->state.vol * line_ptr->freq * PLANCK; total += heat_contribution; } } @@ -800,15 +801,16 @@ macro_bf_heating (xplasma, t_e) /* Photoionization part. */ lower_density = den_config (xplasma, phot_top[xconfig[i].bfu_jump[j]].nlev); heat_contribution = - (mplasma->gamma_e_old[xconfig[i].bfu_indx_first + j] - - mplasma->gamma_old[xconfig[i].bfu_indx_first + - j]) * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * lower_density * xplasma->vol; + (mplasma->state.gamma_e_old[xconfig[i].bfu_indx_first + j] - + mplasma->state.gamma_old[xconfig[i].bfu_indx_first + + j]) * PLANCK * phot_top[xconfig[i].bfu_jump[j]].freq[0] * lower_density * xplasma->state.vol; /* Three body recombination part. */ upper_density = den_config (xplasma, phot_top[xconfig[i].bfu_jump[j]].uplev); heat_contribution += q_recomb (&phot_top[xconfig[i].bfu_jump[j]], - t_e) * xplasma->ne * xplasma->ne * PLANCK * upper_density * xplasma->vol * phot_top[xconfig[i].bfu_jump[j]].freq[0]; + t_e) * xplasma->state.ne * xplasma->state.ne * PLANCK * upper_density * xplasma->state.vol * + phot_top[xconfig[i].bfu_jump[j]].freq[0]; total += heat_contribution; @@ -861,21 +863,21 @@ bb_simple_heat (xplasma, p, tau_sobolev, nn) weight_of_packet = p->w; line_ptr = lin_ptr[nn]; - electron_temperature = xplasma->t_e; + electron_temperature = xplasma->state.t_e; rad_rate = a21 (line_ptr) * p_escape (line_ptr, xplasma); - coll_rate = q21 (line_ptr, electron_temperature) * xplasma->ne * (1. - exp (-H_OVER_K * line_ptr->freq / electron_temperature)); + coll_rate = q21 (line_ptr, electron_temperature) * xplasma->state.ne * (1. - exp (-H_OVER_K * line_ptr->freq / electron_temperature)); normalisation = rad_rate + coll_rate; /* Now add the heating contribution. */ - xplasma->heat_lines += heat_contribution = weight_of_packet * (coll_rate / normalisation) * (1. - exp (-1. * tau_sobolev)); + xplasma->est.heat_lines += heat_contribution = weight_of_packet * (coll_rate / normalisation) * (1. - exp (-1. * tau_sobolev)); - xplasma->heat_tot += heat_contribution; - xplasma->kpkt_abs += heat_contribution; + xplasma->est.heat_tot += heat_contribution; + xplasma->est.kpkt_abs += heat_contribution; return (0); @@ -914,10 +916,10 @@ check_stimulated_recomb (xplasma) for (j = 0; j < xconfig[i].n_bfu_jump; j++) { cont_ptr = &phot_top[xconfig[i].bfu_jump[j]]; - gamma = mplasma->gamma_old[xconfig[i].bfu_indx_first + j]; - st_recomb = mplasma->alpha_st_old[xconfig[i].bfu_indx_first + j]; - st_recomb *= xplasma->ne * den_config (xplasma, cont_ptr->uplev) / den_config (xplasma, cont_ptr->nlev); - coll_ioniz = q_ioniz (cont_ptr, xplasma->t_e) * xplasma->ne; + gamma = mplasma->state.gamma_old[xconfig[i].bfu_indx_first + j]; + st_recomb = mplasma->state.alpha_st_old[xconfig[i].bfu_indx_first + j]; + st_recomb *= xplasma->state.ne * den_config (xplasma, cont_ptr->uplev) / den_config (xplasma, cont_ptr->nlev); + coll_ioniz = q_ioniz (cont_ptr, xplasma->state.t_e) * xplasma->state.ne; if (st_recomb > (gamma + coll_ioniz)) st_recomb_err += 1; @@ -959,15 +961,15 @@ get_dilute_estimators (xplasma) { for (j = 0; j < xconfig[i].n_bfu_jump; j++) { - mplasma->gamma_old[xconfig[i].bfu_indx_first + j] = get_gamma (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->gamma_e_old[xconfig[i].bfu_indx_first + j] = get_gamma_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->alpha_st_e_old[xconfig[i].bfu_indx_first + j] = get_alpha_st_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); - mplasma->alpha_st_old[xconfig[i].bfu_indx_first + j] = get_alpha_st (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.gamma_old[xconfig[i].bfu_indx_first + j] = get_gamma (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.gamma_e_old[xconfig[i].bfu_indx_first + j] = get_gamma_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.alpha_st_e_old[xconfig[i].bfu_indx_first + j] = get_alpha_st_e (&phot_top[xconfig[i].bfu_jump[j]], xplasma); + mplasma->state.alpha_st_old[xconfig[i].bfu_indx_first + j] = get_alpha_st (&phot_top[xconfig[i].bfu_jump[j]], xplasma); } for (j = 0; j < xconfig[i].n_bbu_jump; j++) { line_ptr = &line[xconfig[i].bbu_jump[j]]; - mplasma->jbar_old[xconfig[i].bbu_indx_first + j] = mean_intensity (xplasma, line_ptr->freq, MEAN_INTENSITY_BB_MODEL); + mplasma->state.jbar_old[xconfig[i].bbu_indx_first + j] = mean_intensity (xplasma, line_ptr->freq, MEAN_INTENSITY_BB_MODEL); } } @@ -999,7 +1001,7 @@ get_gamma (cont_ptr, xplasma) double qromb (); double gamma_integrand (); - temp_ext2 = xplasma->t_r; //external temperature + temp_ext2 = xplasma->state.t_r; //external temperature cont_ext_ptr2 = cont_ptr; //external cont pointer fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -1013,7 +1015,7 @@ get_gamma (cont_ptr, xplasma) // gamma_value = qromb (gamma_integrand, fthresh, flast, 1e-4); gamma_value = num_int (gamma_integrand, fthresh, flast, 1e-4); - gamma_value *= 8 * PI / VLIGHT / VLIGHT * xplasma->w; + gamma_value *= 8 * PI / VLIGHT / VLIGHT * xplasma->state.w; return (gamma_value); @@ -1080,7 +1082,7 @@ get_gamma_e (cont_ptr, xplasma) double qromb (); double gamma_e_integrand (); - temp_ext2 = xplasma->t_r; //external temperature + temp_ext2 = xplasma->state.t_r; //external temperature cont_ext_ptr2 = cont_ptr; //external cont pointer fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -1094,7 +1096,7 @@ get_gamma_e (cont_ptr, xplasma) // gamma_e_value = qromb (gamma_e_integrand, fthresh, flast, 1e-4); gamma_e_value = num_int (gamma_e_integrand, fthresh, flast, 1e-4); - gamma_e_value *= 8 * PI / VLIGHT / VLIGHT * xplasma->w; + gamma_e_value *= 8 * PI / VLIGHT / VLIGHT * xplasma->state.w; return (gamma_e_value); @@ -1160,8 +1162,8 @@ get_alpha_st (cont_ptr, xplasma) double qromb (); double alpha_st_integrand (); - temp_ext2 = xplasma->t_e; //external for use in integrand - temp_ext_rad = xplasma->t_r; + temp_ext2 = xplasma->state.t_e; //external for use in integrand + temp_ext_rad = xplasma->state.t_r; cont_ext_ptr2 = cont_ptr; //" fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -1180,14 +1182,14 @@ get_alpha_st (cont_ptr, xplasma) through by the appropriate constant. */ if (cont_ptr->macro_info == 1 && geo.macro_simple == FALSE) { - alpha_st_value = alpha_st_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->t_e, -1.5); + alpha_st_value = alpha_st_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->state.t_e, -1.5); } else //case for simple element { - alpha_st_value = alpha_st_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->t_e, -1.5); //g for next ion up used + alpha_st_value = alpha_st_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->state.t_e, -1.5); //g for next ion up used } - alpha_st_value = alpha_st_value * ALPHA_SP_CONSTANT * xplasma->w; + alpha_st_value = alpha_st_value * ALPHA_SP_CONSTANT * xplasma->state.w; return (alpha_st_value); } @@ -1257,8 +1259,8 @@ get_alpha_st_e (cont_ptr, xplasma) double qromb (); double alpha_st_e_integrand (); - temp_ext2 = xplasma->t_e; //external for use in integrand - temp_ext_rad = xplasma->t_r; //" + temp_ext2 = xplasma->state.t_e; //external for use in integrand + temp_ext_rad = xplasma->state.t_r; //" cont_ext_ptr2 = cont_ptr; //" fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -1277,14 +1279,14 @@ get_alpha_st_e (cont_ptr, xplasma) through by the appropriate constant. */ if (cont_ptr->macro_info == TRUE && geo.macro_simple == FALSE) { - alpha_st_e_value = alpha_st_e_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->t_e, -1.5); + alpha_st_e_value = alpha_st_e_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->state.t_e, -1.5); } else //case for simple element { - alpha_st_e_value = alpha_st_e_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->t_e, -1.5); //g for next ion up used + alpha_st_e_value = alpha_st_e_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->state.t_e, -1.5); //g for next ion up used } - alpha_st_e_value = alpha_st_e_value * ALPHA_SP_CONSTANT * xplasma->w; + alpha_st_e_value = alpha_st_e_value * ALPHA_SP_CONSTANT * xplasma->state.w; return (alpha_st_e_value); } diff --git a/source/estimators_simple.c b/source/estimators_simple.c index d60a9f52c..697cdcb9d 100644 --- a/source/estimators_simple.c +++ b/source/estimators_simple.c @@ -99,23 +99,23 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) /*photon weight times distance in the shell is proportional to the mean intensity */ - xplasma->j += w_ave * ds; + xplasma->est.j += w_ave * ds; if (p->nscat == 0) { - xplasma->j_direct += w_ave * ds; + xplasma->est.j_direct += w_ave * ds; } else { - xplasma->j_scatt += w_ave * ds; + xplasma->est.j_scatt += w_ave * ds; } /* frequency weighted by the weights and distance in the shell . See eqn 2 ML93 */ - xplasma->mean_ds += ds; - xplasma->n_ds++; - xplasma->ave_freq += p->freq * w_ave * ds; + xplasma->est.mean_ds += ds; + xplasma->est.n_ds++; + xplasma->est.ave_freq += p->freq * w_ave * ds; /* The next loop updates the banded versions of j and ave_freq, analogously to routine inradiation nxfreq refers to how many frequencies we have defining the bands. So, if we have 5 bands, we have 6 frequencies, @@ -126,22 +126,22 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) as energy packets are indisivible in macro atom mode */ - for (i = 0; i < xplasma->nbands; i++) + for (i = 0; i < xplasma->state.nbands; i++) { - if (xplasma->f1[i] < p->freq && p->freq <= xplasma->f2[i]) + if (xplasma->state.f1[i] < p->freq && p->freq <= xplasma->state.f2[i]) { - xplasma->xave_freq[i] += p->freq * w_ave * ds; /* frequency weighted by weight and distance */ - xplasma->xsd_freq[i] += p->freq * p->freq * w_ave * ds; /* input to allow standard deviation to be calculated */ - xplasma->xj[i] += w_ave * ds; /* photon weight times distance travelled */ - xplasma->nxtot[i]++; /* increment the frequency banded photon counter */ + xplasma->est.xave_freq[i] += p->freq * w_ave * ds; /* frequency weighted by weight and distance */ + xplasma->est.xsd_freq[i] += p->freq * p->freq * w_ave * ds; /* input to allow standard deviation to be calculated */ + xplasma->est.xj[i] += w_ave * ds; /* photon weight times distance travelled */ + xplasma->est.nxtot[i]++; /* increment the frequency banded photon counter */ /* work out the range of frequencies within a band where photons have been seen */ - if (p->freq < xplasma->fmin[i]) + if (p->freq < xplasma->est.fmin[i]) { - xplasma->fmin[i] = p->freq; + xplasma->est.fmin[i] = p->freq; } - if (p->freq > xplasma->fmax[i]) + if (p->freq > xplasma->est.fmax[i]) { - xplasma->fmax[i] = p->freq; + xplasma->est.fmax[i] = p->freq; } } @@ -157,7 +157,7 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) { i = NBINS_IN_CELL_SPEC - 1; } - xplasma->cell_spec_flux[i] += w_ave * ds; + xplasma->est.cell_spec_flux[i] += w_ave * ds; @@ -167,18 +167,18 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) if (xplasma->nplasma != previous_nplasma || p->np != previous_np) { - xplasma->ntot++; + xplasma->est.ntot++; if (p->origin == PTYPE_STAR) - xplasma->ntot_star++; + xplasma->est.ntot_star++; else if (p->origin == PTYPE_BL) - xplasma->ntot_bl++; + xplasma->est.ntot_bl++; else if (p->origin == PTYPE_DISK) - xplasma->ntot_disk++; + xplasma->est.ntot_disk++; else if (p->origin == PTYPE_WIND) - xplasma->ntot_wind++; + xplasma->est.ntot_wind++; else if (p->origin == PTYPE_AGN) - xplasma->ntot_agn++; + xplasma->est.ntot_agn++; previous_nplasma = xplasma->nplasma; previous_np = p->np; } @@ -195,27 +195,27 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) if (xplasma->nplasma != previous_nioniz_nplasma || p->np != previous_nioniz_np) { - xplasma->nioniz++; + xplasma->est.nioniz++; previous_nioniz_nplasma = xplasma->nplasma; previous_nioniz_np = p->np; } /* IP needs to be radiation density in the cell. We sum contributions from each photon, then it is normalised in wind_update. */ - xplasma->ip += ((w_ave * ds) / (PLANCK * p->freq)); + xplasma->est.ip += ((w_ave * ds) / (PLANCK * p->freq)); if (HEV * p->freq < 13600) //Tartar et al integrate up to 1000Ryd to define the ionization parameter { - xplasma->xi += (w_ave * ds); + xplasma->derived.xi += (w_ave * ds); } if (p->nscat == 0) { - xplasma->ip_direct += ((w_ave * ds) / (PLANCK * p->freq)); + xplasma->est.ip_direct += ((w_ave * ds) / (PLANCK * p->freq)); } else { - xplasma->ip_scatt += ((w_ave * ds) / (PLANCK * p->freq)); + xplasma->est.ip_scatt += ((w_ave * ds) / (PLANCK * p->freq)); } } @@ -314,13 +314,13 @@ update_flux_estimators (xplasma, phot_mid, ds_obs, w_ave, ndom) iangle = (angle) / binw; //Turn the angle into an integer to pass into the flux array - //xplasma->F_UV_ang_theta[iangle] += flux[0]; - //xplasma->F_UV_ang_phi[iangle] += flux[1]; - //xplasma->F_UV_ang_r[iangle] += flux[2]; + //xplasma->est.F_UV_ang_theta[iangle] += flux[0]; + //xplasma->est.F_UV_ang_phi[iangle] += flux[1]; + //xplasma->est.F_UV_ang_r[iangle] += flux[2]; - xplasma->F_UV_ang_r[iangle] += flux[0] * sin (theta) + flux[2] * cos (theta); - xplasma->F_UV_ang_phi[iangle] += flux[1]; - xplasma->F_UV_ang_theta[iangle] += flux[0] * cos (theta) - flux[2] * sin (theta); + xplasma->est.F_UV_ang_r[iangle] += flux[0] * sin (theta) + flux[2] * cos (theta); + xplasma->est.F_UV_ang_phi[iangle] += flux[1]; + xplasma->est.F_UV_ang_theta[iangle] += flux[0] * cos (theta) - flux[2] * sin (theta); @@ -342,18 +342,18 @@ update_flux_estimators (xplasma, phot_mid, ds_obs, w_ave, ndom) if (phot_mid->freq < UV_low) { - vadd (xplasma->F_vis, flux, xplasma->F_vis); - xplasma->F_vis[3] += length (flux); + vadd (xplasma->est.F_vis, flux, xplasma->est.F_vis); + xplasma->est.F_vis[3] += length (flux); } else if (phot_mid->freq > UV_hi) { - vadd (xplasma->F_Xray, flux, xplasma->F_Xray); - xplasma->F_Xray[3] += length (flux); + vadd (xplasma->est.F_Xray, flux, xplasma->est.F_Xray); + xplasma->est.F_Xray[3] += length (flux); } else { - vadd (xplasma->F_UV, flux, xplasma->F_UV); - xplasma->F_UV[3] += length (flux); + vadd (xplasma->est.F_UV, flux, xplasma->est.F_UV); + xplasma->est.F_UV[3] += length (flux); } @@ -425,9 +425,9 @@ update_force_estimators (xplasma, p, phot_mid, ds, w_ave, ndom, z, frac_ff, frac } for (i = 0; i < 3; i++) { - xplasma->rad_force_ff[i] += dp_cyl[i]; + xplasma->est.rad_force_ff[i] += dp_cyl[i]; } - xplasma->rad_force_ff[3] += length (dp_cyl); + xplasma->est.rad_force_ff[3] += length (dp_cyl); stuff_v (p->lmn, p_out); renorm (p_out, (z * (frac_tot + frac_auger)) / VLIGHT); @@ -444,10 +444,10 @@ update_force_estimators (xplasma, p, phot_mid, ds, w_ave, ndom, z, frac_ff, frac } for (i = 0; i < 3; i++) { - xplasma->rad_force_bf[i] += dp_cyl[i]; + xplasma->est.rad_force_bf[i] += dp_cyl[i]; } - xplasma->rad_force_bf[3] += length (dp_cyl); + xplasma->est.rad_force_bf[3] += length (dp_cyl); stuff_v (p->lmn, p_out); renorm (p_out, w_ave * ds * klein_nishina (p->freq)); @@ -464,9 +464,9 @@ update_force_estimators (xplasma, p, phot_mid, ds, w_ave, ndom, z, frac_ff, frac } for (i = 0; i < 3; i++) { - xplasma->rad_force_es[i] += dp_cyl[i]; + xplasma->est.rad_force_es[i] += dp_cyl[i]; } - xplasma->rad_force_es[3] += length (dp_cyl); + xplasma->est.rad_force_es[3] += length (dp_cyl); return 0; } @@ -594,57 +594,58 @@ normalise_simple_estimators (xplasma) invariant_volume_time = wmain[nwind].vol / wmain[nwind].xgamma_cen; - if (xplasma->ntot > 0) + if (xplasma->est.ntot > 0) { - wtest = xplasma->ave_freq; - xplasma->ave_freq /= xplasma->j; /* Normalization to frequency moment */ - if (sane_check (xplasma->ave_freq)) + wtest = xplasma->est.ave_freq; + xplasma->est.ave_freq /= xplasma->est.j; /* Normalization to frequency moment */ + if (sane_check (xplasma->est.ave_freq)) { Error ("normalise_simple_estimators:sane_check nwind %d nplasma %d ave_freq %e j %e ntot %d\n", nwind, xplasma->nplasma, wtest, - xplasma->j, xplasma->ntot); + xplasma->est.j, xplasma->est.ntot); } - xplasma->j /= (4. * PI * invariant_volume_time); - xplasma->j_direct /= (4. * PI * invariant_volume_time); - xplasma->j_scatt /= (4. * PI * invariant_volume_time); + xplasma->est.j /= (4. * PI * invariant_volume_time); + xplasma->est.j_direct /= (4. * PI * invariant_volume_time); + xplasma->est.j_scatt /= (4. * PI * invariant_volume_time); - xplasma->t_r_old = xplasma->t_r; // Store the previous t_r in t_r_old immediately before recalculating + xplasma->state.t_r_old = xplasma->state.t_r; // Store the previous t_r in t_r_old immediately before recalculating /* the method of calculation of the band corrected radiation temperature depends on the flag BAND_CORRECTED_TRAD -- see issue #1097 */ if (BAND_CORRECTED_TRAD == FALSE) { - radiation_temperature = xplasma->t_r = PLANCK * xplasma->ave_freq / (BOLTZMANN * 3.832); + radiation_temperature = xplasma->state.t_r = PLANCK * xplasma->est.ave_freq / (BOLTZMANN * 3.832); } else { - radiation_temperature = xplasma->t_r = - estimate_temperature_from_mean_frequency (xplasma->ave_freq, xband.f1[0], xband.f2[xband.nbands - 1], radiation_temperature); + radiation_temperature = xplasma->state.t_r = + estimate_temperature_from_mean_frequency (xplasma->est.ave_freq, xband.f1[0], xband.f2[xband.nbands - 1], radiation_temperature); } - xplasma->w = - PI * xplasma->j / (STEFAN_BOLTZMANN * radiation_temperature * radiation_temperature * radiation_temperature * radiation_temperature); + xplasma->state.w = + PI * xplasma->est.j / (STEFAN_BOLTZMANN * radiation_temperature * radiation_temperature * radiation_temperature * + radiation_temperature); - if (xplasma->w > 1e10) + if (xplasma->state.w > 1e10) { - Error ("normalise_simple_estimators: Huge w %8.2e in cell %d trad %10.2e j %8.2e\n", xplasma->w, xplasma->nplasma, - radiation_temperature, xplasma->j); + Error ("normalise_simple_estimators: Huge w %8.2e in cell %d trad %10.2e j %8.2e\n", xplasma->state.w, xplasma->nplasma, + radiation_temperature, xplasma->est.j); } - if (sane_check (radiation_temperature) || sane_check (xplasma->w)) + if (sane_check (radiation_temperature) || sane_check (xplasma->state.w)) { - Error ("normalise_simple_estimators:sane_check %d trad %8.2e w %8.2g\n", xplasma->nplasma, radiation_temperature, xplasma->w); - Error ("normalise_simple_estimators: ave_freq %8.2e j %8.2e\n", xplasma->ave_freq, xplasma->j); + Error ("normalise_simple_estimators:sane_check %d trad %8.2e w %8.2g\n", xplasma->nplasma, radiation_temperature, xplasma->state.w); + Error ("normalise_simple_estimators: ave_freq %8.2e j %8.2e\n", xplasma->est.ave_freq, xplasma->est.j); Exit (0); } } else { - xplasma->j = xplasma->j_direct = xplasma->j_scatt = 0; + xplasma->est.j = xplasma->est.j_direct = xplasma->est.j_scatt = 0; if (modes.fixed_temp != 1) - xplasma->t_e *= 0.7; - if (xplasma->t_e < MIN_TEMP) - xplasma->t_e = MIN_TEMP; - xplasma->w = 0; + xplasma->state.t_e *= 0.7; + if (xplasma->state.t_e < MIN_TEMP) + xplasma->state.t_e = MIN_TEMP; + xplasma->state.w = 0; } /* Temporary location for constructing estimators from speectra */ @@ -654,32 +655,32 @@ normalise_simple_estimators (xplasma) { j = 0; - for (i = 0; i < xplasma->nbands; i++) + for (i = 0; i < xplasma->state.nbands; i++) { - xplasma->xave_freq[i] = 0; - xplasma->xsd_freq[i] = 0; - xplasma->xj[i] = 0; - xplasma->nxtot[i] = 0; - xplasma->fmin[i] = geo.cell_freq[NBINS_IN_CELL_SPEC]; - xplasma->fmax[i] = geo.cell_freq[0]; - - while (geo.cell_freq[j] < xplasma->f2[i] && j < NBINS_IN_CELL_SPEC) + xplasma->est.xave_freq[i] = 0; + xplasma->est.xsd_freq[i] = 0; + xplasma->est.xj[i] = 0; + xplasma->est.nxtot[i] = 0; + xplasma->est.fmin[i] = geo.cell_freq[NBINS_IN_CELL_SPEC]; + xplasma->est.fmax[i] = geo.cell_freq[0]; + + while (geo.cell_freq[j] < xplasma->state.f2[i] && j < NBINS_IN_CELL_SPEC) { double ave_freq; - if (xplasma->cell_spec_flux[j] > 0) + if (xplasma->est.cell_spec_flux[j] > 0) { ave_freq = 0.5 * (geo.cell_freq[j + 1] + geo.cell_freq[j]); - xplasma->xave_freq[i] += ave_freq * xplasma->cell_spec_flux[j]; - xplasma->xsd_freq[i] += ave_freq * ave_freq * xplasma->cell_spec_flux[j]; - xplasma->xj[i] += xplasma->cell_spec_flux[j]; - xplasma->nxtot[i]++; - if (ave_freq < xplasma->fmin[i]) + xplasma->est.xave_freq[i] += ave_freq * xplasma->est.cell_spec_flux[j]; + xplasma->est.xsd_freq[i] += ave_freq * ave_freq * xplasma->est.cell_spec_flux[j]; + xplasma->est.xj[i] += xplasma->est.cell_spec_flux[j]; + xplasma->est.nxtot[i]++; + if (ave_freq < xplasma->est.fmin[i]) { - xplasma->fmin[i] = ave_freq; + xplasma->est.fmin[i] = ave_freq; } - if (ave_freq > xplasma->fmax[i]) + if (ave_freq > xplasma->est.fmax[i]) { - xplasma->fmax[i] = ave_freq; + xplasma->est.fmax[i] = ave_freq; } } j++; @@ -697,20 +698,20 @@ normalise_simple_estimators (xplasma) /* Normalize and otherwise complete the information gathered about the coarse spectra used for generation of spectral models */ - for (i = 0; i < xplasma->nbands; i++) + for (i = 0; i < xplasma->state.nbands; i++) { - if (xplasma->nxtot[i] > 0) + if (xplasma->est.nxtot[i] > 0) { - xplasma->xave_freq[i] /= xplasma->xj[i]; - xplasma->xsd_freq[i] /= xplasma->xj[i]; - xplasma->xsd_freq[i] = sqrt (xplasma->xsd_freq[i] - (xplasma->xave_freq[i] * xplasma->xave_freq[i])); /*Compute standard deviation */ - xplasma->xj[i] /= (4 * PI * invariant_volume_time); /*Convert to radiation density */ + xplasma->est.xave_freq[i] /= xplasma->est.xj[i]; + xplasma->est.xsd_freq[i] /= xplasma->est.xj[i]; + xplasma->est.xsd_freq[i] = sqrt (xplasma->est.xsd_freq[i] - (xplasma->est.xave_freq[i] * xplasma->est.xave_freq[i])); /*Compute standard deviation */ + xplasma->est.xj[i] /= (4 * PI * invariant_volume_time); /*Convert to radiation density */ } else { - xplasma->xj[i] = 0; - xplasma->xave_freq[i] = 0; - xplasma->xsd_freq[i] = 0; + xplasma->est.xj[i] = 0; + xplasma->est.xave_freq[i] = 0; + xplasma->est.xsd_freq[i] = 0; } } @@ -723,7 +724,7 @@ normalise_simple_estimators (xplasma) freq_max = freq_min + geo.cell_delta_lfreq; dfreq = pow (10., freq_max) - pow (10., freq_min); - xplasma->cell_spec_flux[i] /= (4 * PI * invariant_volume_time * dfreq); + xplasma->est.cell_spec_flux[i] /= (4 * PI * invariant_volume_time * dfreq); } @@ -733,17 +734,17 @@ normalise_simple_estimators (xplasma) * and number density of hydrogen in the cell */ - nh = xplasma->rho * rho2nh; - xplasma->ip /= (VLIGHT * invariant_volume_time * nh); - xplasma->ip_direct /= (VLIGHT * invariant_volume_time * nh); - xplasma->ip_scatt /= (VLIGHT * invariant_volume_time * nh); + nh = xplasma->state.rho * rho2nh; + xplasma->est.ip /= (VLIGHT * invariant_volume_time * nh); + xplasma->est.ip_direct /= (VLIGHT * invariant_volume_time * nh); + xplasma->est.ip_scatt /= (VLIGHT * invariant_volume_time * nh); /* Normalise xi, which at this point should be the luminosity of * ionizing photons in a cell (just the sum of photon weights) */ - xplasma->xi *= 4. * PI; - xplasma->xi /= (invariant_volume_time * nh); + xplasma->derived.xi *= 4. * PI; + xplasma->derived.xi /= (invariant_volume_time * nh); /* * The radiation force and flux estimators are all observer frame @@ -752,22 +753,22 @@ normalise_simple_estimators (xplasma) */ /* there was an error here before, see #1030. The observer frame density is gamma times the CMF one */ - electron_density_obs = xplasma->ne * wmain[nwind].xgamma_cen; // Mihalas & Mihalas p146 + electron_density_obs = xplasma->state.ne * wmain[nwind].xgamma_cen; // Mihalas & Mihalas p146 volume_obs = wmain[nwind].vol / wmain[nwind].xgamma_cen; for (i = 0; i < NFORCE_DIRECTIONS; i++) { - xplasma->rad_force_es[i] *= (volume_obs * electron_density_obs) / (volume_obs * VLIGHT); - xplasma->F_vis[i] /= volume_obs; - xplasma->F_UV[i] /= volume_obs; - xplasma->F_Xray[i] /= volume_obs; + xplasma->est.rad_force_es[i] *= (volume_obs * electron_density_obs) / (volume_obs * VLIGHT); + xplasma->est.F_vis[i] /= volume_obs; + xplasma->est.F_UV[i] /= volume_obs; + xplasma->est.F_Xray[i] /= volume_obs; } for (i = 0; i < NFLUX_ANGLES; i++) { - xplasma->F_UV_ang_theta[i] /= volume_obs; - xplasma->F_UV_ang_phi[i] /= volume_obs; - xplasma->F_UV_ang_r[i] /= volume_obs; + xplasma->est.F_UV_ang_theta[i] /= volume_obs; + xplasma->est.F_UV_ang_phi[i] /= volume_obs; + xplasma->est.F_UV_ang_r[i] /= volume_obs; } return (0); @@ -791,52 +792,57 @@ update_persistent_directional_flux_estimators (int nplasma, double flux_persist_ if (geo.wcycle == 0) //If this is the first time through, then the persistent flux is empty. { - vadd (plasmamain[nplasma].F_vis_persistent, plasmamain[nplasma].F_vis, plasmamain[nplasma].F_vis_persistent); - vadd (plasmamain[nplasma].F_UV_persistent, plasmamain[nplasma].F_UV, plasmamain[nplasma].F_UV_persistent); - vadd (plasmamain[nplasma].F_Xray_persistent, plasmamain[nplasma].F_Xray, plasmamain[nplasma].F_Xray_persistent); - vadd (plasmamain[nplasma].rad_force_bf_persist, plasmamain[nplasma].rad_force_bf, plasmamain[nplasma].rad_force_bf_persist); + vadd (plasmamain[nplasma].derived.F_vis_persistent, plasmamain[nplasma].est.F_vis, plasmamain[nplasma].derived.F_vis_persistent); + vadd (plasmamain[nplasma].derived.F_UV_persistent, plasmamain[nplasma].est.F_UV, plasmamain[nplasma].derived.F_UV_persistent); + vadd (plasmamain[nplasma].derived.F_Xray_persistent, plasmamain[nplasma].est.F_Xray, plasmamain[nplasma].derived.F_Xray_persistent); + vadd (plasmamain[nplasma].derived.rad_force_bf_persist, plasmamain[nplasma].est.rad_force_bf, + plasmamain[nplasma].derived.rad_force_bf_persist); for (n = 0; n < NFLUX_ANGLES; n++) { - plasmamain[nplasma].F_UV_ang_theta_persist[n] = plasmamain[nplasma].F_UV_ang_theta_persist[n] + plasmamain[nplasma].F_UV_ang_theta[n]; - plasmamain[nplasma].F_UV_ang_phi_persist[n] = plasmamain[nplasma].F_UV_ang_phi_persist[n] + plasmamain[nplasma].F_UV_ang_phi[n]; - plasmamain[nplasma].F_UV_ang_r_persist[n] = plasmamain[nplasma].F_UV_ang_r_persist[n] + plasmamain[nplasma].F_UV_ang_r[n]; + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] + plasmamain[nplasma].est.F_UV_ang_theta[n]; + plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] + plasmamain[nplasma].est.F_UV_ang_phi[n]; + plasmamain[nplasma].derived.F_UV_ang_r_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_r_persist[n] + plasmamain[nplasma].est.F_UV_ang_r[n]; } } else { - rescale (plasmamain[nplasma].F_vis_persistent, (1 - flux_persist_scale), plasmamain[nplasma].F_vis_persistent); - rescale (plasmamain[nplasma].F_vis, flux_persist_scale, flux_helper); - vadd (plasmamain[nplasma].F_vis_persistent, flux_helper, plasmamain[nplasma].F_vis_persistent); + rescale (plasmamain[nplasma].derived.F_vis_persistent, (1 - flux_persist_scale), plasmamain[nplasma].derived.F_vis_persistent); + rescale (plasmamain[nplasma].est.F_vis, flux_persist_scale, flux_helper); + vadd (plasmamain[nplasma].derived.F_vis_persistent, flux_helper, plasmamain[nplasma].derived.F_vis_persistent); - rescale (plasmamain[nplasma].F_UV_persistent, (1 - flux_persist_scale), plasmamain[nplasma].F_UV_persistent); - rescale (plasmamain[nplasma].F_UV, flux_persist_scale, flux_helper); - vadd (plasmamain[nplasma].F_UV_persistent, flux_helper, plasmamain[nplasma].F_UV_persistent); + rescale (plasmamain[nplasma].derived.F_UV_persistent, (1 - flux_persist_scale), plasmamain[nplasma].derived.F_UV_persistent); + rescale (plasmamain[nplasma].est.F_UV, flux_persist_scale, flux_helper); + vadd (plasmamain[nplasma].derived.F_UV_persistent, flux_helper, plasmamain[nplasma].derived.F_UV_persistent); - rescale (plasmamain[nplasma].F_Xray_persistent, (1 - flux_persist_scale), plasmamain[nplasma].F_Xray_persistent); - rescale (plasmamain[nplasma].F_Xray, flux_persist_scale, flux_helper); - vadd (plasmamain[nplasma].F_Xray_persistent, flux_helper, plasmamain[nplasma].F_Xray_persistent); + rescale (plasmamain[nplasma].derived.F_Xray_persistent, (1 - flux_persist_scale), plasmamain[nplasma].derived.F_Xray_persistent); + rescale (plasmamain[nplasma].est.F_Xray, flux_persist_scale, flux_helper); + vadd (plasmamain[nplasma].derived.F_Xray_persistent, flux_helper, plasmamain[nplasma].derived.F_Xray_persistent); - rescale (plasmamain[nplasma].rad_force_bf_persist, (1 - flux_persist_scale), plasmamain[nplasma].rad_force_bf_persist); - rescale (plasmamain[nplasma].rad_force_bf, flux_persist_scale, flux_helper); - vadd (plasmamain[nplasma].rad_force_bf_persist, flux_helper, plasmamain[nplasma].rad_force_bf_persist); + rescale (plasmamain[nplasma].derived.rad_force_bf_persist, (1 - flux_persist_scale), plasmamain[nplasma].derived.rad_force_bf_persist); + rescale (plasmamain[nplasma].est.rad_force_bf, flux_persist_scale, flux_helper); + vadd (plasmamain[nplasma].derived.rad_force_bf_persist, flux_helper, plasmamain[nplasma].derived.rad_force_bf_persist); for (n = 0; n < NFLUX_ANGLES; n++) { - plasmamain[nplasma].F_UV_ang_theta_persist[n] = plasmamain[nplasma].F_UV_ang_theta_persist[n] * (1 - flux_persist_scale); - plasmamain[nplasma].F_UV_ang_phi_persist[n] = plasmamain[nplasma].F_UV_ang_phi_persist[n] * (1 - flux_persist_scale); - plasmamain[nplasma].F_UV_ang_r_persist[n] = plasmamain[nplasma].F_UV_ang_r_persist[n] * (1 - flux_persist_scale); - plasmamain[nplasma].F_UV_ang_theta_persist[n] = - plasmamain[nplasma].F_UV_ang_theta_persist[n] + plasmamain[nplasma].F_UV_ang_theta[n] * flux_persist_scale; - plasmamain[nplasma].F_UV_ang_phi_persist[n] = - plasmamain[nplasma].F_UV_ang_phi_persist[n] + plasmamain[nplasma].F_UV_ang_phi[n] * flux_persist_scale; - plasmamain[nplasma].F_UV_ang_r_persist[n] = - plasmamain[nplasma].F_UV_ang_r_persist[n] + plasmamain[nplasma].F_UV_ang_r[n] * flux_persist_scale; + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] * (1 - flux_persist_scale); + plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] = plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] * (1 - flux_persist_scale); + plasmamain[nplasma].derived.F_UV_ang_r_persist[n] = plasmamain[nplasma].derived.F_UV_ang_r_persist[n] * (1 - flux_persist_scale); + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_theta_persist[n] + plasmamain[nplasma].est.F_UV_ang_theta[n] * flux_persist_scale; + plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_phi_persist[n] + plasmamain[nplasma].est.F_UV_ang_phi[n] * flux_persist_scale; + plasmamain[nplasma].derived.F_UV_ang_r_persist[n] = + plasmamain[nplasma].derived.F_UV_ang_r_persist[n] + plasmamain[nplasma].est.F_UV_ang_r[n] * flux_persist_scale; } } - plasmamain[nplasma].F_vis_persistent[3] = length (plasmamain[nplasma].F_vis_persistent); - plasmamain[nplasma].F_UV_persistent[3] = length (plasmamain[nplasma].F_UV_persistent); - plasmamain[nplasma].F_Xray_persistent[3] = length (plasmamain[nplasma].F_Xray_persistent); - plasmamain[nplasma].rad_force_bf_persist[3] = length (plasmamain[nplasma].rad_force_bf_persist); + plasmamain[nplasma].derived.F_vis_persistent[3] = length (plasmamain[nplasma].derived.F_vis_persistent); + plasmamain[nplasma].derived.F_UV_persistent[3] = length (plasmamain[nplasma].derived.F_UV_persistent); + plasmamain[nplasma].derived.F_Xray_persistent[3] = length (plasmamain[nplasma].derived.F_Xray_persistent); + plasmamain[nplasma].derived.rad_force_bf_persist[3] = length (plasmamain[nplasma].derived.rad_force_bf_persist); } diff --git a/source/gridwind.c b/source/gridwind.c index b50843a48..4524d339a 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -434,103 +434,103 @@ calloc_estimators (nelem) for (n = 0; n < nelem; n++) { - if ((macromain[n].jbar = calloc (sizeof (double), size_Jbar_est)) == NULL) + if ((macromain[n].est.jbar = calloc (sizeof (double), size_Jbar_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].jbar_old = calloc (sizeof (double), size_Jbar_est)) == NULL) + if ((macromain[n].state.jbar_old = calloc (sizeof (double), size_Jbar_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].gamma = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].est.gamma = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].gamma_old = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].state.gamma_old = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].gamma_e = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].est.gamma_e = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].gamma_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].state.gamma_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].alpha_st = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].est.alpha_st = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].alpha_st_old = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].state.alpha_st_old = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].alpha_st_e = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].est.alpha_st_e = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].alpha_st_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) + if ((macromain[n].state.alpha_st_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].recomb_sp = calloc (sizeof (double), size_alpha_est)) == NULL) + if ((macromain[n].est.recomb_sp = calloc (sizeof (double), size_alpha_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].recomb_sp_e = calloc (sizeof (double), size_alpha_est)) == NULL) + if ((macromain[n].est.recomb_sp_e = calloc (sizeof (double), size_alpha_est)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].matom_emiss = calloc (sizeof (double), nlevels_macro)) == NULL) + if ((macromain[n].derived.matom_emiss = calloc (sizeof (double), nlevels_macro)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].matom_abs = calloc (sizeof (double), nlevels_macro)) == NULL) + if ((macromain[n].est.matom_abs = calloc (sizeof (double), nlevels_macro)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].cooling_bf = calloc (sizeof (double), nphot_total)) == NULL) + if ((macromain[n].est.cooling_bf = calloc (sizeof (double), nphot_total)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].cooling_bf_col = calloc (sizeof (double), nphot_total)) == NULL) + if ((macromain[n].est.cooling_bf_col = calloc (sizeof (double), nphot_total)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); } - if ((macromain[n].cooling_bb = calloc (sizeof (double), nlines)) == NULL) + if ((macromain[n].est.cooling_bb = calloc (sizeof (double), nlines)) == NULL) { Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); Exit (0); @@ -589,93 +589,93 @@ calloc_dyn_plasma (nelem) for (n = 0; n < nelem + 1; n++) { - if ((plasmamain[n].density = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].state.density = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for density\n"); Exit (0); } - if ((plasmamain[n].partition = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].state.partition = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for partition\n"); Exit (0); } - if ((plasmamain[n].ioniz = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].est.ioniz = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for ioniz\n"); Exit (0); } - if ((plasmamain[n].recomb = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.recomb = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for recomb\n"); Exit (0); } - if ((plasmamain[n].scatters = calloc (sizeof (int), nions)) == NULL) + if ((plasmamain[n].derived.scatters = calloc (sizeof (int), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for scatters\n"); Exit (0); } - if ((plasmamain[n].xscatters = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.xscatters = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for xscatters\n"); Exit (0); } - if ((plasmamain[n].heat_ion = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].est.heat_ion = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for heat_ion\n"); Exit (0); } - if ((plasmamain[n].heat_inner_ion = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].est.heat_inner_ion = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for heat_ion\n"); Exit (0); } - if ((plasmamain[n].cool_rr_ion = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.cool_rr_ion = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for cool_rr_ion\n"); Exit (0); } - if ((plasmamain[n].lum_rr_ion = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.lum_rr_ion = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for lum_rr_ion\n"); Exit (0); } - if ((plasmamain[n].inner_recomb = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.inner_recomb = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for inner_recomb\n"); Exit (0); } - if ((plasmamain[n].inner_ioniz = calloc (sizeof (double), n_inner_tot)) == NULL) + if ((plasmamain[n].est.inner_ioniz = calloc (sizeof (double), n_inner_tot)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for inner_ioniz\n"); Exit (0); } - if ((plasmamain[n].cool_dr_ion = calloc (sizeof (double), nions)) == NULL) + if ((plasmamain[n].derived.cool_dr_ion = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for lum_inner_recomb\n"); Exit (0); } - if ((plasmamain[n].levden = calloc (sizeof (double), nlte_levels)) == NULL) + if ((plasmamain[n].state.levden = calloc (sizeof (double), nlte_levels)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for levden\n"); Exit (0); } - if ((plasmamain[n].recomb_simple = calloc (sizeof (double), nphot_total)) == NULL) + if ((plasmamain[n].state.recomb_simple = calloc (sizeof (double), nphot_total)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for recomb_simple\n"); Exit (0); } - if ((plasmamain[n].recomb_simple_upweight = calloc (sizeof (double), nphot_total)) == NULL) + if ((plasmamain[n].state.recomb_simple_upweight = calloc (sizeof (double), nphot_total)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for recomb_simple_upweight\n"); Exit (0); } - if ((plasmamain[n].kbf_use = calloc (sizeof (double), nphot_total)) == NULL) + if ((plasmamain[n].state.kbf_use = calloc (sizeof (double), nphot_total)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for kbf_use\n"); Exit (0); @@ -721,9 +721,9 @@ calloc_matom_matrix (nelem) for (n = 0; n < nelem; n++) { - if (macromain[n].store_matom_matrix == TRUE) + if (macromain[n].state.store_matom_matrix == TRUE) { - allocate_macro_matrix (¯omain[n].matom_matrix, nrows); + allocate_macro_matrix (¯omain[n].derived.matom_matrix, nrows); nmatrices_allocated += 1; } } diff --git a/source/hydro_import.c b/source/hydro_import.c index 1b54f9454..497e17626 100644 --- a/source/hydro_import.c +++ b/source/hydro_import.c @@ -857,16 +857,16 @@ hydro_restart (ndom) { n = wmain[nwind].nplasma; stuff_v (wmain[nwind].xcen, x); - old_density = plasmamain[n].rho; - plasmamain[n].rho = model_rho (ndom, x) / zdom[ndom].fill; - plasmamain[n].t_r = plasmamain[n].t_e = hydro_temp (x); + old_density = plasmamain[n].state.rho; + plasmamain[n].state.rho = model_rho (ndom, x) / zdom[ndom].fill; + plasmamain[n].state.t_r = plasmamain[n].state.t_e = hydro_temp (x); for (nion = 0; nion < nions; nion++) //Change the absolute number densities, fractions remain the same { - plasmamain[n].density[nion] = plasmamain[n].density[nion] * (plasmamain[n].rho / old_density); + plasmamain[n].state.density[nion] = plasmamain[n].state.density[nion] * (plasmamain[n].state.rho / old_density); } - plasmamain[n].ne = get_ne (plasmamain[n].density); //get the new electron density + plasmamain[n].state.ne = get_ne (plasmamain[n].state.density); //get the new electron density partition_functions (&plasmamain[n], NEBULARMODE_LTE_GROUND); //set the level populations to ground state - this is because at the moment we dont know how to work out levels for cases that dont have a dilute BB radiation field. We need to set them to something however. Could do better in the future. } @@ -949,85 +949,85 @@ create_hydro_output_files (void) i = i - 1; //There is a radial 'ghost zone' in sirocco, we need to make our i,j agree with zeus vol = w[plasmamain[nplasma].nwind].vol; fprintf (fptr, "%d %d %e %e %e ", i, j, w[plasmamain[nplasma].nwind].rcen, w[plasmamain[nplasma].nwind].thetacen / RADIAN, vol); //output geometric things - fprintf (fptr, "%e %e %e ", plasmamain[nplasma].t_e, plasmamain[nplasma].xi, plasmamain[nplasma].ne); //output temp, xi and ne to ease plotting of heating rates - fprintf (fptr, "%e ", (plasmamain[nplasma].heat_photo + plasmamain[nplasma].heat_auger) / vol); //Xray heating - or photoionization - fprintf (fptr, "%e ", (plasmamain[nplasma].heat_comp) / vol); //Compton heating - fprintf (fptr, "%e ", (plasmamain[nplasma].heat_lines) / vol); //Line heating 28/10/15 - not currently used in zeus - fprintf (fptr, "%e ", (plasmamain[nplasma].heat_ff) / vol); //FF heating 28/10/15 - not currently used in zeus - fprintf (fptr, "%e ", (plasmamain[nplasma].cool_comp) / vol); //Compton cooling - fprintf (fptr, "%e ", (plasmamain[nplasma].lum_lines + plasmamain[nplasma].cool_rr + plasmamain[nplasma].cool_dr) / vol); //Line cooling must include all recombination cooling - fprintf (fptr, "%e ", (plasmamain[nplasma].lum_ff) / vol); //ff cooling - fprintf (fptr, "%e ", plasmamain[nplasma].rho); //density - fprintf (fptr, "%e ", plasmamain[nplasma].rho * rho2nh); //hydrogen number density - fprintf (fptr, "%e ", plasmamain[nplasma].rad_force_es[0]); //electron scattering radiation force in the w(x) direction - fprintf (fptr, "%e ", plasmamain[nplasma].rad_force_es[1]); //electron scattering radiation force in the phi(rotational) directionz direction - fprintf (fptr, "%e ", plasmamain[nplasma].rad_force_es[2]); //electron scattering radiation force in the z direction - fprintf (fptr, "%e ", plasmamain[nplasma].rad_force_bf[0]); //bound free scattering radiation force in the w(x) direction - fprintf (fptr, "%e ", plasmamain[nplasma].rad_force_bf[1]); //bound free scattering radiation force in the phi(rotational) direction - fprintf (fptr, "%e \n", plasmamain[nplasma].rad_force_bf[2]); //bound free scattering radiation force in the z direction + fprintf (fptr, "%e %e %e ", plasmamain[nplasma].state.t_e, plasmamain[nplasma].derived.xi, plasmamain[nplasma].state.ne); //output temp, xi and ne to ease plotting of heating rates + fprintf (fptr, "%e ", (plasmamain[nplasma].est.heat_photo + plasmamain[nplasma].est.heat_auger) / vol); //Xray heating - or photoionization + fprintf (fptr, "%e ", (plasmamain[nplasma].est.heat_comp) / vol); //Compton heating + fprintf (fptr, "%e ", (plasmamain[nplasma].est.heat_lines) / vol); //Line heating 28/10/15 - not currently used in zeus + fprintf (fptr, "%e ", (plasmamain[nplasma].est.heat_ff) / vol); //FF heating 28/10/15 - not currently used in zeus + fprintf (fptr, "%e ", (plasmamain[nplasma].derived.cool_comp) / vol); //Compton cooling + fprintf (fptr, "%e ", (plasmamain[nplasma].derived.lum_lines + plasmamain[nplasma].derived.cool_rr + plasmamain[nplasma].derived.cool_dr) / vol); //Line cooling must include all recombination cooling + fprintf (fptr, "%e ", (plasmamain[nplasma].derived.lum_ff) / vol); //ff cooling + fprintf (fptr, "%e ", plasmamain[nplasma].state.rho); //density + fprintf (fptr, "%e ", plasmamain[nplasma].state.rho * rho2nh); //hydrogen number density + fprintf (fptr, "%e ", plasmamain[nplasma].est.rad_force_es[0]); //electron scattering radiation force in the w(x) direction + fprintf (fptr, "%e ", plasmamain[nplasma].est.rad_force_es[1]); //electron scattering radiation force in the phi(rotational) directionz direction + fprintf (fptr, "%e ", plasmamain[nplasma].est.rad_force_es[2]); //electron scattering radiation force in the z direction + fprintf (fptr, "%e ", plasmamain[nplasma].est.rad_force_bf[0]); //bound free scattering radiation force in the w(x) direction + fprintf (fptr, "%e ", plasmamain[nplasma].est.rad_force_bf[1]); //bound free scattering radiation force in the phi(rotational) direction + fprintf (fptr, "%e \n", plasmamain[nplasma].est.rad_force_bf[2]); //bound free scattering radiation force in the z direction fprintf (fptr2, "%d %d ", i, j); //output geometric things - fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].F_vis[0], plasmamain[nplasma].F_vis[1], plasmamain[nplasma].F_vis[2]); //directional flux by band - fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].F_UV[0], plasmamain[nplasma].F_UV[1], plasmamain[nplasma].F_UV[2]); //directional flux by band - fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].F_Xray[0], plasmamain[nplasma].F_Xray[1], plasmamain[nplasma].F_Xray[2]); //directional flux by band + fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].est.F_vis[0], plasmamain[nplasma].est.F_vis[1], plasmamain[nplasma].est.F_vis[2]); //directional flux by band + fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].est.F_UV[0], plasmamain[nplasma].est.F_UV[1], plasmamain[nplasma].est.F_UV[2]); //directional flux by band + fprintf (fptr2, "%e %e %e ", plasmamain[nplasma].est.F_Xray[0], plasmamain[nplasma].est.F_Xray[1], plasmamain[nplasma].est.F_Xray[2]); //directional flux by band fprintf (fptr2, "\n"); fprintf (fptr3, "%d %d ", i, j); //output geometric things for (ii = 0; ii < nions; ii++) - fprintf (fptr3, "%e ", plasmamain[nplasma].density[ii]); + fprintf (fptr3, "%e ", plasmamain[nplasma].state.density[ii]); fprintf (fptr3, "\n"); fprintf (fptr4, "%d %d ", i, j); //output geometric things for (ii = 0; ii < geo.nxfreq; ii++) fprintf (fptr4, "%e %e %i %e %e %e %e ", - plasmamain[nplasma].fmin_mod[ii], plasmamain[nplasma].fmax_mod[ii], plasmamain[nplasma].spec_mod_type[ii], - plasmamain[nplasma].pl_log_w[ii], plasmamain[nplasma].pl_alpha[ii], plasmamain[nplasma].exp_w[ii], - plasmamain[nplasma].exp_temp[ii]); + plasmamain[nplasma].state.fmin_mod[ii], plasmamain[nplasma].state.fmax_mod[ii], + plasmamain[nplasma].state.spec_mod_type[ii], plasmamain[nplasma].state.pl_log_w[ii], + plasmamain[nplasma].state.pl_alpha[ii], plasmamain[nplasma].state.exp_w[ii], plasmamain[nplasma].state.exp_temp[ii]); fprintf (fptr4, "\n "); //We need to compute the g factor for this cell and output it. - v_th = pow ((2. * BOLTZMANN * plasmamain[nplasma].t_e / MPROT), 0.5); //We need the thermal velocity for hydrogen + v_th = pow ((2. * BOLTZMANN * plasmamain[nplasma].state.t_e / MPROT), 0.5); //We need the thermal velocity for hydrogen stuff_v (w[plasmamain[nplasma].nwind].xcen, ptest.x); //place our test photon at the centre of the cell ptest.grid = nwind; //We need our test photon to know where it is - kappa_es = THOMPSON * plasmamain[nplasma].ne / plasmamain[nplasma].rho; + kappa_es = THOMPSON * plasmamain[nplasma].state.ne / plasmamain[nplasma].state.rho; //First for the optical band (up to 4000AA) - if (length (plasmamain[nplasma].F_vis) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_vis) > 0.0) //Only makes sense if flux in this band is non-zero { - stuff_v (plasmamain[nplasma].F_vis, fhat); + stuff_v (plasmamain[nplasma].est.F_vis, fhat); renorm (fhat, 1.); //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_opt = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_opt = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } else t_opt = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. //Now for the UV band (up to 4000AA->100AA) - if (length (plasmamain[nplasma].F_UV) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_UV) > 0.0) //Only makes sense if flux in this band is non-zero { - stuff_v (plasmamain[nplasma].F_UV, fhat); + stuff_v (plasmamain[nplasma].est.F_UV, fhat); renorm (fhat, 1.); //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_UV = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_UV = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } else t_UV = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. //And finally for the Xray band (up to 100AA and up) - if (length (plasmamain[nplasma].F_Xray) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_Xray) > 0.0) //Only makes sense if flux in this band is non-zero { - stuff_v (plasmamain[nplasma].F_Xray, fhat); + stuff_v (plasmamain[nplasma].est.F_Xray, fhat); renorm (fhat, 1.); //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_Xray = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_Xray = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } else t_Xray = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. - fprintf (fptr5, "%i %i %e %e %e %e %e %e %e\n", i, j, plasmamain[nplasma].t_e, plasmamain[nplasma].rho, - plasmamain[nplasma].rho * rho2nh, plasmamain[nplasma].ne, t_opt, t_UV, t_Xray); + fprintf (fptr5, "%i %i %e %e %e %e %e %e %e\n", i, j, plasmamain[nplasma].state.t_e, plasmamain[nplasma].state.rho, + plasmamain[nplasma].state.rho * rho2nh, plasmamain[nplasma].state.ne, t_opt, t_UV, t_Xray); } } fclose (fptr); diff --git a/source/inspect_wind.c b/source/inspect_wind.c index 5515d1ee5..fe693720d 100644 --- a/source/inspect_wind.c +++ b/source/inspect_wind.c @@ -246,7 +246,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].jbar[i]); + fprintf (fptr, "%8.2e ", macromain[n].est.jbar[i]); } fprintf (fptr, "\n"); } @@ -264,7 +264,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].jbar_old[i]); + fprintf (fptr, "%8.2e ", macromain[n].state.jbar_old[i]); } fprintf (fptr, "\n"); } @@ -282,7 +282,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].gamma[i]); + fprintf (fptr, "%8.2e ", macromain[n].est.gamma[i]); } fprintf (fptr, "\n"); } @@ -301,7 +301,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].alpha_st[i]); + fprintf (fptr, "%8.2e ", macromain[n].est.alpha_st[i]); } fprintf (fptr, "\n"); } @@ -320,7 +320,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].recomb_sp[i]); + fprintf (fptr, "%8.2e ", macromain[n].est.recomb_sp[i]); } fprintf (fptr, "\n"); } @@ -339,7 +339,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].matom_abs[i]); + fprintf (fptr, "%8.2e ", macromain[n].est.matom_abs[i]); } fprintf (fptr, "\n"); } @@ -358,7 +358,7 @@ main (argc, argv) for (i = 0; i < nlevels_macro; i++) { - fprintf (fptr, "%8.2e ", macromain[n].matom_emiss[i]); + fprintf (fptr, "%8.2e ", macromain[n].derived.matom_emiss[i]); } fprintf (fptr, "\n"); } @@ -491,7 +491,7 @@ line_matom_lum (uplvl) n = wmain[nnwind].nplasma; line_matom_lum_single (lum, &plasmamain[n], uplvl); /* print the filled volume */ - fprintf (fptr, " %13.4e", plasmamain[n].vol); + fprintf (fptr, " %13.4e", plasmamain[n].state.vol); for (i = 0; i < nbbd; i++) fprintf (fptr, " %13.4e", lum[i]); } @@ -561,7 +561,7 @@ line_matom_lum_single (lum, xplasma, uplvl) else { eprbs[n] = eprbs[n] / penorm; - lum[n] = eprbs[n] * macromain[xplasma->nplasma].matom_emiss[uplvl]; + lum[n] = eprbs[n] * macromain[xplasma->nplasma].derived.matom_emiss[uplvl]; } lum_tot += lum[n]; } diff --git a/source/ionization.c b/source/ionization.c index 5d4ed9691..24877dd07 100644 --- a/source/ionization.c +++ b/source/ionization.c @@ -30,11 +30,11 @@ void update_old_plasma_variables (PlasmaPtr xplasma) { - xplasma->dt_e_old = xplasma->dt_e; - xplasma->dt_e = xplasma->t_e - xplasma->t_e_old; - xplasma->t_e_old = xplasma->t_e; - xplasma->lum_tot_old = xplasma->lum_tot; - xplasma->heat_tot_old = xplasma->heat_tot; + xplasma->derived.dt_e_old = xplasma->derived.dt_e; + xplasma->derived.dt_e = xplasma->state.t_e - xplasma->state.t_e_old; + xplasma->state.t_e_old = xplasma->state.t_e; + xplasma->derived.lum_tot_old = xplasma->derived.lum_tot; + xplasma->derived.heat_tot_old = xplasma->est.heat_tot; } @@ -70,7 +70,7 @@ ion_abundances (PlasmaPtr xplasma, int mode) if ((ireturn = nebular_concentrations (xplasma, NEBULARMODE_ML93))) { Error ("ionization_abundances: nebular_concentrations failed to converge\n"); - Error ("ionization_abundances: j %8.2e t_e %8.2e t_r %8.2e w %8.2e\n", xplasma->j, xplasma->t_e, xplasma->w); + Error ("ionization_abundances: j %8.2e t_e %8.2e t_r %8.2e w %8.2e\n", xplasma->est.j, xplasma->state.t_e, xplasma->state.w); } } else if (mode == IONMODE_LTE_TR) @@ -105,15 +105,15 @@ ion_abundances (PlasmaPtr xplasma, int mode) update_old_plasma_variables (xplasma); - double te_old = xplasma->t_e; - double gain = xplasma->gain; + double te_old = xplasma->state.t_e; + double gain = xplasma->derived.gain; /* Save the current ion densities for blending later */ double density_old[nions]; int nion; for (nion = 0; nion < nions; nion++) { - density_old[nion] = xplasma->density[nion]; + density_old[nion] = xplasma->state.density[nion]; } /* Find t_e where heating = cooling with coupled LTE ionization. @@ -122,15 +122,15 @@ ion_abundances (PlasmaPtr xplasma, int mode) double te_new = calc_te_lte (xplasma, 0.7 * te_old, 1.3 * te_old); /* Apply gain damping */ - xplasma->t_e = (1 - gain) * te_old + gain * te_new; + xplasma->state.t_e = (1 - gain) * te_old + gain * te_new; - if (xplasma->t_e > TMAX) + if (xplasma->state.t_e > TMAX) { - xplasma->t_e = TMAX; + xplasma->state.t_e = TMAX; } - if (xplasma->t_e < MIN_TEMP) + if (xplasma->state.t_e < MIN_TEMP) { - xplasma->t_e = MIN_TEMP; + xplasma->state.t_e = MIN_TEMP; } /* Recompute ionization and heating/cooling at the gain-damped temperature */ @@ -149,9 +149,9 @@ ion_abundances (PlasmaPtr xplasma, int mode) density_gain = 0.01; for (nion = 0; nion < nions; nion++) { - xplasma->density[nion] = (1 - density_gain) * density_old[nion] + density_gain * xplasma->density[nion]; + xplasma->state.density[nion] = (1 - density_gain) * density_old[nion] + density_gain * xplasma->state.density[nion]; } - xplasma->ne = get_ne (xplasma->density); + xplasma->state.ne = get_ne (xplasma->state.density); convergence (xplasma); @@ -167,17 +167,17 @@ ion_abundances (PlasmaPtr xplasma, int mode) { /* On the spot, setting te to 0.9 t_r before calculating densities */ - xplasma->dt_e_old = xplasma->dt_e; - xplasma->dt_e = xplasma->t_e - xplasma->t_e_old; - xplasma->t_e_old = xplasma->t_e; - xplasma->lum_tot_old = xplasma->lum_tot; - xplasma->heat_tot_old = xplasma->heat_tot; + xplasma->derived.dt_e_old = xplasma->derived.dt_e; + xplasma->derived.dt_e = xplasma->state.t_e - xplasma->state.t_e_old; + xplasma->state.t_e_old = xplasma->state.t_e; + xplasma->derived.lum_tot_old = xplasma->derived.lum_tot; + xplasma->derived.heat_tot_old = xplasma->est.heat_tot; ireturn = 0; - xplasma->t_e = 0.9 * xplasma->t_r; + xplasma->state.t_e = 0.9 * xplasma->state.t_r; if ((ireturn = nebular_concentrations (xplasma, NEBULARMODE_ML93))) { Error ("ionization_abundances: nebular_concentrations failed to converge\n"); - Error ("ionization_abundances: j %8.2e t_e %8.2e t_r %8.2e w %8.2e\n", xplasma->j, xplasma->t_e, xplasma->w); + Error ("ionization_abundances: j %8.2e t_e %8.2e t_r %8.2e w %8.2e\n", xplasma->est.j, xplasma->state.t_e, xplasma->state.w); } convergence (xplasma); @@ -214,7 +214,7 @@ ion_abundances (PlasmaPtr xplasma, int mode) for (kkk = 0; kkk < MAX_MULTISHOT; kkk++) { ireturn = one_shot (xplasma, NEBULARMODE_MATRIX_SPECTRALMODEL); - xte[kkk] = xplasma->t_e; + xte[kkk] = xplasma->state.t_e; if (kkk > 1) { delta[kkk] = (xte[kkk] - xte[kkk - 1]) / (0.5 * (xte[kkk] + xte[kkk - 1])); @@ -288,16 +288,16 @@ convergence (PlasmaPtr xplasma) epsilon = 0.05; trcheck = techeck = hccheck = CONVERGENCE_CHECK_PASS; - xplasma->trcheck = xplasma->techeck = xplasma->hccheck = CONVERGENCE_CHECK_PASS; // NSH 70g - zero the global variables + xplasma->derived.trcheck = xplasma->derived.techeck = xplasma->derived.hccheck = CONVERGENCE_CHECK_PASS; // NSH 70g - zero the global variables /* * Check the convergence of the radiation temperature */ - xplasma->converge_t_r = // Radiation temperature check - fabs (xplasma->t_r_old - xplasma->t_r) / (xplasma->t_r_old + xplasma->t_r); - if (xplasma->converge_t_r > epsilon) - xplasma->trcheck = trcheck = CONVERGENCE_CHECK_FAIL; + xplasma->derived.converge_t_r = // Radiation temperature check + fabs (xplasma->state.t_r_old - xplasma->state.t_r) / (xplasma->state.t_r_old + xplasma->state.t_r); + if (xplasma->derived.converge_t_r > epsilon) + xplasma->derived.trcheck = trcheck = CONVERGENCE_CHECK_FAIL; /* * Check the convergence for electron temperature and heat + cooling rates @@ -312,29 +312,30 @@ convergence (PlasmaPtr xplasma) * converge if we are hitting the maximum temperature */ - if (xplasma->t_e < TMAX) + if (xplasma->state.t_e < TMAX) { - xplasma->converge_t_e = // Electron temperature check - fabs (xplasma->t_e_old - xplasma->t_e) / (xplasma->t_e_old + xplasma->t_e); - if (xplasma->converge_t_e > epsilon) - xplasma->techeck = techeck = CONVERGENCE_CHECK_FAIL; - - xplasma->converge_hc = // Heating and cooling rates check - fabs (xplasma->heat_tot + xplasma->heat_shock - xplasma->cool_tot) / fabs (xplasma->heat_tot + xplasma->heat_shock + - xplasma->cool_tot); - if (xplasma->converge_hc > epsilon) - xplasma->hccheck = hccheck = CONVERGENCE_CHECK_FAIL; + xplasma->derived.converge_t_e = // Electron temperature check + fabs (xplasma->state.t_e_old - xplasma->state.t_e) / (xplasma->state.t_e_old + xplasma->state.t_e); + if (xplasma->derived.converge_t_e > epsilon) + xplasma->derived.techeck = techeck = CONVERGENCE_CHECK_FAIL; + + xplasma->derived.converge_hc = // Heating and cooling rates check + fabs (xplasma->est.heat_tot + xplasma->derived.heat_shock - xplasma->est.cool_tot) / fabs (xplasma->est.heat_tot + + xplasma->derived.heat_shock + + xplasma->est.cool_tot); + if (xplasma->derived.converge_hc > epsilon) + xplasma->derived.hccheck = hccheck = CONVERGENCE_CHECK_FAIL; } else // If the cell has reached the maximum temperature we mark it as over-limit { - xplasma->techeck = techeck = xplasma->hccheck = hccheck = CONVERGENCE_CHECK_OVER_TEMP; + xplasma->derived.techeck = techeck = xplasma->derived.hccheck = hccheck = CONVERGENCE_CHECK_OVER_TEMP; } /* * whole_check is the sum of the temperature checks and the heating check - the higher this is, the more convergence checks have failed. */ - xplasma->converge_whole = whole_check = trcheck + techeck + hccheck; + xplasma->derived.converge_whole = whole_check = trcheck + techeck + hccheck; /* * Now we check to see if a cell is converging: @@ -349,14 +350,15 @@ convergence (PlasmaPtr xplasma) * For LTE_ITERATE mode, any oscillation triggers damping because the ionization-opacity feedback * can cause self-reinforcing oscillations where increasing the gain makes things worse. */ - if (xplasma->dt_e_old * xplasma->dt_e < 0 && (fabs (xplasma->dt_e) < fabs (xplasma->dt_e_old) || geo.ioniz_mode == IONMODE_LTE_ITERATE)) + if (xplasma->derived.dt_e_old * xplasma->derived.dt_e < 0 + && (fabs (xplasma->derived.dt_e) < fabs (xplasma->derived.dt_e_old) || geo.ioniz_mode == IONMODE_LTE_ITERATE)) { - xplasma->converging = CELL_CONVERGING; + xplasma->derived.converging = CELL_CONVERGING; // TODO: is this optimal for converging cells? See discussion on Bug #631 - xplasma->gain *= gain_damp; - if (xplasma->gain < min_gain) - xplasma->gain = min_gain; + xplasma->derived.gain *= gain_damp; + if (xplasma->derived.gain < min_gain) + xplasma->derived.gain = min_gain; } /* * The cell is not converging, which means either that the temperature is consistently moving in one direction or @@ -371,7 +373,7 @@ convergence (PlasmaPtr xplasma) * to find the best numbers */ - xplasma->converging = CELL_NOT_CONVERGING; + xplasma->derived.converging = CELL_NOT_CONVERGING; cyc_frac = 0.5; @@ -386,9 +388,9 @@ convergence (PlasmaPtr xplasma) max_gain = 0.8; } - xplasma->gain *= gain_amp; - if (xplasma->gain > max_gain) - xplasma->gain = max_gain; + xplasma->derived.gain *= gain_amp; + if (xplasma->derived.gain > max_gain) + xplasma->derived.gain = max_gain; } return (whole_check); @@ -434,17 +436,17 @@ check_convergence (void) if (wmain[plasmamain[n].nwind].inwind == W_ALL_INWIND || modes.partial_cells == PC_INCLUDE) { ntot++; - if (plasmamain[n].converge_whole == CONVERGENCE_CHECK_PASS) + if (plasmamain[n].derived.converge_whole == CONVERGENCE_CHECK_PASS) nconverge++; - if (plasmamain[n].trcheck == CONVERGENCE_CHECK_PASS) + if (plasmamain[n].derived.trcheck == CONVERGENCE_CHECK_PASS) ntr++; - if (plasmamain[n].techeck == CONVERGENCE_CHECK_PASS) + if (plasmamain[n].derived.techeck == CONVERGENCE_CHECK_PASS) nte++; - if (plasmamain[n].hccheck == CONVERGENCE_CHECK_PASS) + if (plasmamain[n].derived.hccheck == CONVERGENCE_CHECK_PASS) nhc++; - if (plasmamain[n].techeck == CONVERGENCE_CHECK_OVER_TEMP) + if (plasmamain[n].derived.techeck == CONVERGENCE_CHECK_OVER_TEMP) nmax++; - if (plasmamain[n].converging == CELL_CONVERGING) + if (plasmamain[n].derived.converging == CELL_CONVERGING) nconverging++; } } @@ -513,9 +515,9 @@ one_shot (PlasmaPtr xplasma, int mode) double gain; - gain = xplasma->gain; + gain = xplasma->derived.gain; - te_old = xplasma->t_e; + te_old = xplasma->state.t_e; if (modes.zeus_connect == TRUE || modes.fixed_temp == TRUE) { @@ -527,25 +529,26 @@ one_shot (PlasmaPtr xplasma, int mode) else //Find a new teperature where heating and cooling match { te_new = calc_te (xplasma, 0.7 * te_old, 1.3 * te_old); //compute the new t_e - no limits on where it can go - xplasma->t_e = (1 - gain) * te_old + gain * te_new; /*Allow the temperature to move by a fraction gain towards - the equilibrium temperature */ + xplasma->state.t_e = (1 - gain) * te_old + gain * te_new; /*Allow the temperature to move by a fraction gain towards + the equilibrium temperature */ - if (xplasma->t_e > TMAX) //check to see if we have maxed out the temperature. + if (xplasma->state.t_e > TMAX) //check to see if we have maxed out the temperature. { - xplasma->t_e = TMAX; + xplasma->state.t_e = TMAX; } - zero_emit (xplasma->t_e); //Get the heating and cooling rates correctly for the new temperature + zero_emit (xplasma->state.t_e); //Get the heating and cooling rates correctly for the new temperature } if (nebular_concentrations (xplasma, mode)) { Error ("one_shot: nebular_concentrations failed to converge\n"); - Error ("one_shot: j %8.2e t_e %8.2e t_r %8.2e w %8.2e nphot %i\n", xplasma->j, xplasma->t_e, xplasma->t_r, xplasma->w, xplasma->ntot); + Error ("one_shot: j %8.2e t_e %8.2e t_r %8.2e w %8.2e nphot %i\n", xplasma->est.j, xplasma->state.t_e, xplasma->state.t_r, + xplasma->state.w, xplasma->est.ntot); } - if (xplasma->ne < 0 || VERY_BIG < xplasma->ne) + if (xplasma->state.ne < 0 || VERY_BIG < xplasma->state.ne) { - Error ("one_shot: ne = %8.2e out of range\n", xplasma->ne); + Error ("one_shot: ne = %8.2e out of range\n", xplasma->state.ne); } @@ -592,11 +595,11 @@ calc_te (PlasmaPtr xplasma, double tmin, double tmax) xxxplasma = xplasma; - xxxplasma->heat_tot += xxxplasma->heat_ch_ex; + xxxplasma->est.heat_tot += xxxplasma->est.heat_ch_ex; - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; z1 = zero_emit (tmin); - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; z2 = zero_emit (tmax); /* The way this works is that if we have a situation where the cooling @@ -606,7 +609,7 @@ calc_te (PlasmaPtr xplasma, double tmin, double tmax) if ((z1 * z2 < 0.0)) { // Then the interval is bracketed - xplasma->t_e = zero_find (zero_emit2, tmin, tmax, 50., &ierr); + xplasma->state.t_e = zero_find (zero_emit2, tmin, tmax, 50., &ierr); if (ierr) { Error ("calc_te: zero_find failed to find a temperature\n"); @@ -615,11 +618,11 @@ calc_te (PlasmaPtr xplasma, double tmin, double tmax) } else if (fabs (z1) < fabs (z2)) { - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; } else { - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; } /* With the new temperature in place for the cell, get the correct value of heat_tot. SS June 04 */ @@ -633,26 +636,26 @@ calc_te (PlasmaPtr xplasma, double tmin, double tmax) * We subtract the current value and then compute at the new temperature and * add this back */ - xplasma->heat_tot -= xplasma->heat_lines_macro; - xplasma->heat_lines -= xplasma->heat_lines_macro; + xplasma->est.heat_tot -= xplasma->est.heat_lines_macro; + xplasma->est.heat_lines -= xplasma->est.heat_lines_macro; - xplasma->heat_lines_macro = macro_bb_heating (xplasma, xplasma->t_e); + xplasma->est.heat_lines_macro = macro_bb_heating (xplasma, xplasma->state.t_e); - xplasma->heat_tot += xplasma->heat_lines_macro; - xplasma->heat_lines += xplasma->heat_lines_macro; + xplasma->est.heat_tot += xplasma->est.heat_lines_macro; + xplasma->est.heat_lines += xplasma->est.heat_lines_macro; /* Similaryly for macro_atom_bf_heating */ - xplasma->heat_tot -= xplasma->heat_photo_macro; - xplasma->heat_photo -= xplasma->heat_photo_macro; + xplasma->est.heat_tot -= xplasma->est.heat_photo_macro; + xplasma->est.heat_photo -= xplasma->est.heat_photo_macro; - xplasma->heat_photo_macro = macro_bf_heating (xplasma, xplasma->t_e); + xplasma->est.heat_photo_macro = macro_bf_heating (xplasma, xplasma->state.t_e); - xplasma->heat_tot += xplasma->heat_photo_macro; - xplasma->heat_photo += xplasma->heat_photo_macro; + xplasma->est.heat_tot += xplasma->est.heat_photo_macro; + xplasma->est.heat_photo += xplasma->est.heat_photo_macro; - return (xplasma->t_e); + return (xplasma->state.t_e); } @@ -703,32 +706,32 @@ zero_emit (double t) double difference; /*Original method */ - xxxplasma->t_e = t; + xxxplasma->state.t_e = t; /* Correct heat_tot for the change in temperature. SS June 04. */ - xxxplasma->heat_tot -= xxxplasma->heat_lines_macro; - xxxplasma->heat_lines -= xxxplasma->heat_lines_macro; + xxxplasma->est.heat_tot -= xxxplasma->est.heat_lines_macro; + xxxplasma->est.heat_lines -= xxxplasma->est.heat_lines_macro; - xxxplasma->heat_lines_macro = macro_bb_heating (xxxplasma, t); + xxxplasma->est.heat_lines_macro = macro_bb_heating (xxxplasma, t); - xxxplasma->heat_tot += xxxplasma->heat_lines_macro; - xxxplasma->heat_lines += xxxplasma->heat_lines_macro; + xxxplasma->est.heat_tot += xxxplasma->est.heat_lines_macro; + xxxplasma->est.heat_lines += xxxplasma->est.heat_lines_macro; - xxxplasma->heat_tot -= xxxplasma->heat_photo_macro; - xxxplasma->heat_photo -= xxxplasma->heat_photo_macro; + xxxplasma->est.heat_tot -= xxxplasma->est.heat_photo_macro; + xxxplasma->est.heat_photo -= xxxplasma->est.heat_photo_macro; - xxxplasma->heat_photo_macro = macro_bf_heating (xxxplasma, t); + xxxplasma->est.heat_photo_macro = macro_bf_heating (xxxplasma, t); - xxxplasma->heat_tot += xxxplasma->heat_photo_macro; - xxxplasma->heat_photo += xxxplasma->heat_photo_macro; + xxxplasma->est.heat_tot += xxxplasma->est.heat_photo_macro; + xxxplasma->est.heat_photo += xxxplasma->est.heat_photo_macro; /* Finished macro atom corrections */ cooling (xxxplasma, t); - difference = xxxplasma->heat_tot + xxxplasma->heat_shock - xxxplasma->cool_tot; + difference = xxxplasma->est.heat_tot + xxxplasma->derived.heat_shock - xxxplasma->est.cool_tot; @@ -790,7 +793,7 @@ zero_emit_lte (double t) int nion; double density_min = 1.e-30; - xxxplasma->t_e = t; + xxxplasma->state.t_e = t; /* Update ionization to LTE at this trial temperature */ nebular_concentrations (xxxplasma, NEBULARMODE_TE); @@ -800,7 +803,7 @@ zero_emit_lte (double t) the Saha equation has now changed them. We scale per-ion heating by the density ratio and ne-dependent heating by the ne ratio. */ - ne_ratio = (lte_ne_orig > 0) ? xxxplasma->ne / lte_ne_orig : 1.0; + ne_ratio = (lte_ne_orig > 0) ? xxxplasma->state.ne / lte_ne_orig : 1.0; /* Scale per-ion photoionization heating */ scaled_heat_photo = 0.0; @@ -808,14 +811,14 @@ zero_emit_lte (double t) { if (lte_density_orig[nion] > density_min) { - scaled_heat_photo += xxxplasma->heat_ion[nion] * xxxplasma->density[nion] / lte_density_orig[nion]; + scaled_heat_photo += xxxplasma->est.heat_ion[nion] * xxxplasma->state.density[nion] / lte_density_orig[nion]; } else { - scaled_heat_photo += xxxplasma->heat_ion[nion]; + scaled_heat_photo += xxxplasma->est.heat_ion[nion]; } } - xxxplasma->heat_photo = scaled_heat_photo; + xxxplasma->est.heat_photo = scaled_heat_photo; /* Scale per-ion Auger (inner shell) heating */ scaled_heat_auger = 0.0; @@ -823,48 +826,48 @@ zero_emit_lte (double t) { if (lte_density_orig[nion] > density_min) { - scaled_heat_auger += xxxplasma->heat_inner_ion[nion] * xxxplasma->density[nion] / lte_density_orig[nion]; + scaled_heat_auger += xxxplasma->est.heat_inner_ion[nion] * xxxplasma->state.density[nion] / lte_density_orig[nion]; } else { - scaled_heat_auger += xxxplasma->heat_inner_ion[nion]; + scaled_heat_auger += xxxplasma->est.heat_inner_ion[nion]; } } - xxxplasma->heat_auger = scaled_heat_auger; + xxxplasma->est.heat_auger = scaled_heat_auger; /* Scale ne-dependent heating */ - xxxplasma->heat_ff = lte_heat_ff_orig * ne_ratio; - xxxplasma->heat_comp = lte_heat_comp_orig * ne_ratio; - xxxplasma->heat_ind_comp = lte_heat_ind_comp_orig * ne_ratio; + xxxplasma->est.heat_ff = lte_heat_ff_orig * ne_ratio; + xxxplasma->est.heat_comp = lte_heat_comp_orig * ne_ratio; + xxxplasma->est.heat_ind_comp = lte_heat_ind_comp_orig * ne_ratio; /* Scale non-macro line heating by ne ratio */ double non_macro_lines = lte_heat_lines_orig - lte_heat_lines_macro_orig; - xxxplasma->heat_lines = non_macro_lines * ne_ratio; + xxxplasma->est.heat_lines = non_macro_lines * ne_ratio; /* Reconstruct heat_tot from scaled components (without macro yet) */ - xxxplasma->heat_tot = xxxplasma->heat_photo + xxxplasma->heat_auger - + xxxplasma->heat_ff + xxxplasma->heat_comp + xxxplasma->heat_ind_comp + xxxplasma->heat_lines + lte_heat_ch_ex_orig; + xxxplasma->est.heat_tot = xxxplasma->est.heat_photo + xxxplasma->est.heat_auger + + xxxplasma->est.heat_ff + xxxplasma->est.heat_comp + xxxplasma->est.heat_ind_comp + xxxplasma->est.heat_lines + lte_heat_ch_ex_orig; /* Now subtract the original macro contributions (which are included in the scaled heat_photo and heat_lines above) and replace with freshly computed macro heating at the new temperature and densities */ - xxxplasma->heat_photo -= lte_heat_photo_macro_orig; + xxxplasma->est.heat_photo -= lte_heat_photo_macro_orig; - xxxplasma->heat_photo_macro = macro_bf_heating (xxxplasma, t); + xxxplasma->est.heat_photo_macro = macro_bf_heating (xxxplasma, t); - xxxplasma->heat_photo += xxxplasma->heat_photo_macro; + xxxplasma->est.heat_photo += xxxplasma->est.heat_photo_macro; - xxxplasma->heat_lines_macro = macro_bb_heating (xxxplasma, t); + xxxplasma->est.heat_lines_macro = macro_bb_heating (xxxplasma, t); - xxxplasma->heat_lines += xxxplasma->heat_lines_macro; + xxxplasma->est.heat_lines += xxxplasma->est.heat_lines_macro; /* Reconstruct heat_tot with macro corrections */ - xxxplasma->heat_tot = xxxplasma->heat_photo + xxxplasma->heat_auger - + xxxplasma->heat_ff + xxxplasma->heat_comp + xxxplasma->heat_ind_comp + xxxplasma->heat_lines + lte_heat_ch_ex_orig; + xxxplasma->est.heat_tot = xxxplasma->est.heat_photo + xxxplasma->est.heat_auger + + xxxplasma->est.heat_ff + xxxplasma->est.heat_comp + xxxplasma->est.heat_ind_comp + xxxplasma->est.heat_lines + lte_heat_ch_ex_orig; cooling (xxxplasma, t); - difference = xxxplasma->heat_tot + xxxplasma->heat_shock - xxxplasma->cool_tot; + difference = xxxplasma->est.heat_tot + xxxplasma->derived.heat_shock - xxxplasma->est.cool_tot; return (difference); } @@ -916,7 +919,7 @@ calc_te_lte (PlasmaPtr xplasma, double tmin, double tmax) xxxplasma = xplasma; - xxxplasma->heat_tot += xxxplasma->heat_ch_ex; + xxxplasma->est.heat_tot += xxxplasma->est.heat_ch_ex; /* Save original MC-phase heating values and ion densities. These are used by zero_emit_lte to scale heating when Saha @@ -928,33 +931,33 @@ calc_te_lte (PlasmaPtr xplasma, double tmin, double tmax) } for (nion = 0; nion < nions; nion++) { - lte_density_orig[nion] = xplasma->density[nion]; + lte_density_orig[nion] = xplasma->state.density[nion]; } - lte_ne_orig = xplasma->ne; - lte_heat_photo_orig = xplasma->heat_photo; - lte_heat_ff_orig = xplasma->heat_ff; - lte_heat_comp_orig = xplasma->heat_comp; - lte_heat_ind_comp_orig = xplasma->heat_ind_comp; - lte_heat_lines_orig = xplasma->heat_lines; - lte_heat_auger_orig = xplasma->heat_auger; - lte_heat_lines_macro_orig = xplasma->heat_lines_macro; - lte_heat_photo_macro_orig = xplasma->heat_photo_macro; - lte_heat_ch_ex_orig = xplasma->heat_ch_ex; + lte_ne_orig = xplasma->state.ne; + lte_heat_photo_orig = xplasma->est.heat_photo; + lte_heat_ff_orig = xplasma->est.heat_ff; + lte_heat_comp_orig = xplasma->est.heat_comp; + lte_heat_ind_comp_orig = xplasma->est.heat_ind_comp; + lte_heat_lines_orig = xplasma->est.heat_lines; + lte_heat_auger_orig = xplasma->est.heat_auger; + lte_heat_lines_macro_orig = xplasma->est.heat_lines_macro; + lte_heat_photo_macro_orig = xplasma->est.heat_photo_macro; + lte_heat_ch_ex_orig = xplasma->est.heat_ch_ex; /* Evaluate heating-cooling difference at bracket endpoints */ - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; z1 = zero_emit_lte (tmin); - heat1 = xxxplasma->heat_tot; - cool1 = xxxplasma->cool_tot; + heat1 = xxxplasma->est.heat_tot; + cool1 = xxxplasma->est.cool_tot; - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; z2 = zero_emit_lte (tmax); - heat2 = xxxplasma->heat_tot; - cool2 = xxxplasma->cool_tot; + heat2 = xxxplasma->est.heat_tot; + cool2 = xxxplasma->est.cool_tot; if ((z1 * z2 < 0.0)) { // Then the interval is bracketed - xplasma->t_e = zero_find (zero_emit_lte2, tmin, tmax, 50., &ierr); + xplasma->state.t_e = zero_find (zero_emit_lte2, tmin, tmax, 50., &ierr); if (ierr) { Error ("calc_te_lte: zero_find failed to find a temperature\n"); @@ -973,22 +976,22 @@ calc_te_lte (PlasmaPtr xplasma, double tmin, double tmax) /* Choose the temperature that minimizes |heat - cool| */ if (fabs (z1) < fabs (z2)) { - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; Error ("calc_te_lte: Using tmin=%.0f K (smaller imbalance)\n", tmin); } else { - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; Error ("calc_te_lte: Using tmax=%.0f K (smaller imbalance)\n", tmax); } } /* Ensure ionization and heating/cooling are set correctly at the final temperature. zero_emit_lte will call nebular_concentrations and cooling. */ - zero_emit_lte (xplasma->t_e); + zero_emit_lte (xplasma->state.t_e); /* Store whether we found a proper solution */ - xplasma->trcheck = bracketed ? 0 : 1; + xplasma->derived.trcheck = bracketed ? 0 : 1; - return (xplasma->t_e); + return (xplasma->state.t_e); } diff --git a/source/janitor.c b/source/janitor.c index 27486543f..baded8488 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -87,23 +87,23 @@ free_plasma_grid (void) for (n_plasma = 0; n_plasma < NPLASMA + 1; ++n_plasma) { - free (plasmamain[n_plasma].density); - free (plasmamain[n_plasma].partition); - free (plasmamain[n_plasma].ioniz); - free (plasmamain[n_plasma].recomb); - free (plasmamain[n_plasma].scatters); - free (plasmamain[n_plasma].xscatters); - free (plasmamain[n_plasma].heat_ion); - free (plasmamain[n_plasma].heat_inner_ion); - free (plasmamain[n_plasma].cool_rr_ion); - free (plasmamain[n_plasma].lum_rr_ion); - free (plasmamain[n_plasma].inner_recomb); - free (plasmamain[n_plasma].inner_ioniz); - free (plasmamain[n_plasma].cool_dr_ion); - free (plasmamain[n_plasma].levden); - free (plasmamain[n_plasma].recomb_simple); - free (plasmamain[n_plasma].recomb_simple_upweight); - free (plasmamain[n_plasma].kbf_use); + free (plasmamain[n_plasma].state.density); + free (plasmamain[n_plasma].state.partition); + free (plasmamain[n_plasma].est.ioniz); + free (plasmamain[n_plasma].derived.recomb); + free (plasmamain[n_plasma].derived.scatters); + free (plasmamain[n_plasma].derived.xscatters); + free (plasmamain[n_plasma].est.heat_ion); + free (plasmamain[n_plasma].est.heat_inner_ion); + free (plasmamain[n_plasma].derived.cool_rr_ion); + free (plasmamain[n_plasma].derived.lum_rr_ion); + free (plasmamain[n_plasma].derived.inner_recomb); + free (plasmamain[n_plasma].est.inner_ioniz); + free (plasmamain[n_plasma].derived.cool_dr_ion); + free (plasmamain[n_plasma].state.levden); + free (plasmamain[n_plasma].state.recomb_simple); + free (plasmamain[n_plasma].state.recomb_simple_upweight); + free (plasmamain[n_plasma].state.kbf_use); } free (plasmamain); @@ -124,27 +124,27 @@ free_macro_grid (void) for (n_plasma = 0; n_plasma < NPLASMA + 1; n_plasma++) { - free (macromain[n_plasma].jbar); - free (macromain[n_plasma].jbar_old); - free (macromain[n_plasma].gamma); - free (macromain[n_plasma].gamma_old); - free (macromain[n_plasma].gamma_e); - free (macromain[n_plasma].gamma_e_old); - free (macromain[n_plasma].alpha_st); - free (macromain[n_plasma].alpha_st_old); - free (macromain[n_plasma].alpha_st_e); - free (macromain[n_plasma].alpha_st_e_old); - free (macromain[n_plasma].recomb_sp); - free (macromain[n_plasma].recomb_sp_e); - free (macromain[n_plasma].matom_emiss); - free (macromain[n_plasma].matom_abs); - free (macromain[n_plasma].cooling_bf); - free (macromain[n_plasma].cooling_bf_col); - free (macromain[n_plasma].cooling_bb); - if (macromain[n_plasma].store_matom_matrix == TRUE) + free (macromain[n_plasma].est.jbar); + free (macromain[n_plasma].state.jbar_old); + free (macromain[n_plasma].est.gamma); + free (macromain[n_plasma].state.gamma_old); + free (macromain[n_plasma].est.gamma_e); + free (macromain[n_plasma].state.gamma_e_old); + free (macromain[n_plasma].est.alpha_st); + free (macromain[n_plasma].state.alpha_st_old); + free (macromain[n_plasma].est.alpha_st_e); + free (macromain[n_plasma].state.alpha_st_e_old); + free (macromain[n_plasma].est.recomb_sp); + free (macromain[n_plasma].est.recomb_sp_e); + free (macromain[n_plasma].derived.matom_emiss); + free (macromain[n_plasma].est.matom_abs); + free (macromain[n_plasma].est.cooling_bf); + free (macromain[n_plasma].est.cooling_bf_col); + free (macromain[n_plasma].est.cooling_bb); + if (macromain[n_plasma].state.store_matom_matrix == TRUE) { - free (macromain[n_plasma].matom_matrix[0]); - free (macromain[n_plasma].matom_matrix); + free (macromain[n_plasma].derived.matom_matrix[0]); + free (macromain[n_plasma].derived.matom_matrix); } } diff --git a/source/levels.c b/source/levels.c index 21eb02eac..97ca980ff 100644 --- a/source/levels.c +++ b/source/levels.c @@ -62,29 +62,29 @@ levels (xplasma, mode) t = weight = 0.0; if (mode == NEBULARMODE_TR) // LTE with t_r { - t = xplasma->t_r; + t = xplasma->state.t_r; weight = 1; } else if (mode == NEBULARMODE_TE) // LTE with t_e { - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 1; } else if (mode == NEBULARMODE_ML93) // non_LTE with t_r and weights { - t = xplasma->t_r; - weight = xplasma->w; + t = xplasma->state.t_r; + weight = xplasma->state.w; } else if (mode == NEBULARMODE_NLTE_SIM) /* non_LTE with SS modification NSH 120912 - This mode is more or less defunct. It can be romoved once all the viestiges of the original PL ioinzation scheme are removed */ { - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 1; } else if (mode == NEBULARMODE_LTE_GROUND) /* A test mode - this is to allow all levels to be set to GS, in the event we dont have a good idea of what the radiation field shoulb be. */ { - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 0; } else @@ -108,7 +108,7 @@ levels (xplasma, mode) if (ion[nion].macro_info == FALSE || geo.macro_ioniz_mode == MACRO_IONIZ_MODE_NO_ESTIMATORS) { //Then calculate levels for this ion - z = xplasma->partition[nion]; + z = xplasma->state.partition[nion]; /* N.B. partition functions will most likely have been calculated from "lte" levels, at least for * now ?? */ @@ -116,12 +116,12 @@ levels (xplasma, mode) m = ion[nion].first_nlte_level; m_ground = m; //store the ground state index - allow for gs energy neq 0 (SS) nlevden = ion[nion].first_levden; - xplasma->levden[nlevden] = xconfig[m].g / z; //Assumes first level is ground state + xplasma->state.levden[nlevden] = xconfig[m].g / z; //Assumes first level is ground state for (n = 1; n < ion[nion].nlte; n++) { m++; nlevden++; - xplasma->levden[nlevden] = weight * xconfig[m].g * exp ((-xconfig[m].ex + xconfig[m_ground].ex) / kt) / z; + xplasma->state.levden[nlevden] = weight * xconfig[m].g * exp ((-xconfig[m].ex + xconfig[m_ground].ex) / kt) / z; } } } diff --git a/source/lines.c b/source/lines.c index ce74ab90b..d3d81c291 100644 --- a/source/lines.c +++ b/source/lines.c @@ -59,7 +59,7 @@ total_line_emission (xplasma, f1, f2) double lum; double t_e; - t_e = xplasma->t_e; + t_e = xplasma->state.t_e; if (t_e <= 0 || f2 < f1) return (0); @@ -113,11 +113,11 @@ lum_lines (xplasma, nmin, nmax) double q; double t_e; double foo1, foo2, foo3, foo4; - t_e = xplasma->t_e; + t_e = xplasma->state.t_e; lum = 0; for (n = nmin; n < nmax; n++) { - dd = xplasma->density[lin_ptr[n]->nion]; + dd = xplasma->state.density[lin_ptr[n]->nion]; if (dd > LDEN_MIN) { /* potentially dangerous step to avoid lines with no power */ @@ -133,7 +133,7 @@ lum_lines (xplasma, nmin, nmax) x *= foo2 = q * a21 (lin_ptr[n]) * z / (1. - z); - x *= foo3 = PLANCK * lin_ptr[n]->freq * xplasma->vol; + x *= foo3 = PLANCK * lin_ptr[n]->freq * xplasma->state.vol; if (geo.line_mode == LINE_MODE_ESC_PROB) x *= foo4 = p_escape (lin_ptr[n], xplasma); // Include effects of line trapping else @@ -146,7 +146,7 @@ lum_lines (xplasma, nmin, nmax) { Log ("lum_lines: foo %10.3g (%10.3g %10.3g %10.3g) %10.3g %10.3g %10.3g %10.3g %10.3g %10.3g %10.3g\n", - foo1, d1, d2, dd, foo2, foo3, foo4, lin_ptr[n]->el, xplasma->t_r, t_e, xplasma->w); + foo1, d1, d2, dd, foo2, foo3, foo4, lin_ptr[n]->el, xplasma->state.t_r, t_e, xplasma->state.w); } if (sane_check (x) != 0) { @@ -228,18 +228,18 @@ two_level_atom (line_ptr, xplasma, d1, d2) } /* Move variables used in the calculation from the xplasma structure into subroutine variables */ - ne = xplasma->ne; - te = xplasma->t_e; - tr = xplasma->t_r; - w = xplasma->w; + ne = xplasma->state.ne; + te = xplasma->state.t_e; + tr = xplasma->state.t_r; + w = xplasma->state.w; nion = line_ptr->nion; - dd = xplasma->density[nion]; + dd = xplasma->state.density[nion]; /* Calculate the number density of the lower level for the transition using the partition function */ ; if (ion[nion].nlevels > 0) { - dd *= xconfig[ion[nion].firstlevel].g / xplasma->partition[nion]; + dd *= xconfig[ion[nion].firstlevel].g / xplasma->state.partition[nion]; } if (old_line_ptr == line_ptr && old_ne == ne && old_te == te && old_w == w && old_tr == tr && old_dd == dd) @@ -435,9 +435,9 @@ scattering_fraction (line_ptr, xplasma) return (1.); //purely scattering atmosphere //Populate variable from previous calling structure - ne = xplasma->ne; - te = xplasma->t_e; - w = xplasma->w; + ne = xplasma->state.ne; + te = xplasma->state.t_e; + w = xplasma->state.w; c = (-H_OVER_K * line_ptr->freq / te); a = exp (c); @@ -506,12 +506,12 @@ p_escape (line_ptr, xplasma) double w, tr; /* the radiative weight, and radiation tempeature */ WindPtr one; - ne = xplasma->ne; - te = xplasma->t_e; - tr = xplasma->t_r; - w = xplasma->w; + ne = xplasma->state.ne; + te = xplasma->state.t_e; + tr = xplasma->state.t_r; + w = xplasma->state.w; - dd = xplasma->density[line_ptr->nion]; + dd = xplasma->state.density[line_ptr->nion]; one = &wmain[xplasma->nwind]; dvds = one->dvds_ave; @@ -606,7 +606,7 @@ p_escape_from_tau (tau) * @param [in] int nres The number of the resonance * @return Alway returns 0 f * - * xplasma->heat_lines and heat_total are updated. The weight of photon + * xplasma->est.heat_lines and heat_total are updated. The weight of photon * is decreased by the amount of its energy that goes into heating * * @details @@ -641,8 +641,8 @@ line_heat (xplasma, pp, nres) Error ("line_heat:sane_check scattering fraction %g\n", sf); } x = pp->w * (1. - sf); - xplasma->heat_lines += x; - xplasma->heat_tot += x; + xplasma->est.heat_lines += x; + xplasma->est.heat_tot += x; // Reduce the weight of the photon bundle diff --git a/source/macro_accelerate.c b/source/macro_accelerate.c index 4fc2a3b6c..993b7482d 100644 --- a/source/macro_accelerate.c +++ b/source/macro_accelerate.c @@ -49,8 +49,8 @@ calc_matom_matrix (xplasma, matom_matrix) mplasma = ¯omain[xplasma->nplasma]; //telling us where in the matom structure we are struct photon pdummy; - t_e = xplasma->t_e; //electron temperature - ne = xplasma->ne; //electron number density + t_e = xplasma->state.t_e; //electron temperature + ne = xplasma->state.ne; //electron number density /* allocate arrays for matrices and normalsiations we want to include all macro-atom levels + 1 kpacket levels */ @@ -140,7 +140,7 @@ calc_matom_matrix (xplasma, matom_matrix) cont_ptr = &phot_top[xconfig[uplvl].bfd_jump[n]]; //pointer to continuum - sp_rec_rate = mplasma->recomb_sp[xconfig[uplvl].bfd_indx_first + n]; //need this twice so store it + sp_rec_rate = mplasma->est.recomb_sp[xconfig[uplvl].bfd_indx_first + n]; //need this twice so store it bf_cont = (sp_rec_rate + q_recomb (cont_ptr, t_e) * ne) * ne; target_level = phot_top[xconfig[uplvl].bfd_jump[n]].nlev; @@ -167,7 +167,7 @@ calc_matom_matrix (xplasma, matom_matrix) for (n = 0; n < nbbu; n++) { line_ptr = &line[xconfig[uplvl].bbu_jump[n]]; - rad_rate = (b12 (line_ptr) * mplasma->jbar_old[xconfig[uplvl].bbu_indx_first + n]); + rad_rate = (b12 (line_ptr) * mplasma->state.jbar_old[xconfig[uplvl].bbu_indx_first + n]); coll_rate = q12 (line_ptr, t_e); // this is multiplied by ne below @@ -194,7 +194,7 @@ calc_matom_matrix (xplasma, matom_matrix) density_ratio = 0.0; target_level = phot_top[xconfig[uplvl].bfu_jump[n]].uplev; - Qcont = (mplasma->gamma_old[xconfig[uplvl].bfu_indx_first + n] - (mplasma->alpha_st_old[xconfig[uplvl].bfu_indx_first + n] * xplasma->ne * density_ratio) + (q_ioniz (cont_ptr, t_e) * ne)) * xconfig[uplvl].ex; //energy of lower state + Qcont = (mplasma->state.gamma_old[xconfig[uplvl].bfu_indx_first + n] - (mplasma->state.alpha_st_old[xconfig[uplvl].bfu_indx_first + n] * xplasma->state.ne * density_ratio) + (q_ioniz (cont_ptr, t_e) * ne)) * xconfig[uplvl].ex; //energy of lower state /* this error condition can happen in unconverged hot cells where T_R >> T_E. for the moment we set to 0 and hope spontaneous recombiantion takes care of things */ @@ -225,14 +225,14 @@ calc_matom_matrix (xplasma, matom_matrix) if (line[i].macro_info == 1 && geo.macro_simple == 0) //line is for a macro atom { target_level = line[i].nconfigu; - Q_matrix[nlevels_macro][target_level] += Qcont = mplasma->cooling_bb[i]; + Q_matrix[nlevels_macro][target_level] += Qcont = mplasma->est.cooling_bb[i]; Q_norm[nlevels_macro] += Qcont; } else { /* the idea here is that if it is a simple line then it *must* create an r-packet eventually, so this is essentially a k->r transition */ - kpacket_to_rpacket_rate += mplasma->cooling_bb[i]; + kpacket_to_rpacket_rate += mplasma->est.cooling_bb[i]; } } @@ -241,22 +241,22 @@ calc_matom_matrix (xplasma, matom_matrix) if (phot_top[i].macro_info == 1 && geo.macro_simple == 0) //part of macro atom { target_level = phot_top[i].uplev; - Q_matrix[nlevels_macro][target_level] += Qcont = mplasma->cooling_bf_col[i]; + Q_matrix[nlevels_macro][target_level] += Qcont = mplasma->est.cooling_bf_col[i]; Q_norm[nlevels_macro] += Qcont; } else { /* XXX - ask stuart about this! */ - kpacket_to_rpacket_rate += mplasma->cooling_bf_col[i]; + kpacket_to_rpacket_rate += mplasma->est.cooling_bf_col[i]; } } /* Cooling due to other processes will always contribute to k-packet -> r-packet channel */ - kpacket_to_rpacket_rate += mplasma->cooling_bftot; - kpacket_to_rpacket_rate += mplasma->cooling_adiabatic; - kpacket_to_rpacket_rate += mplasma->cooling_ff + mplasma->cooling_ff_lofreq; + kpacket_to_rpacket_rate += mplasma->est.cooling_bftot; + kpacket_to_rpacket_rate += mplasma->est.cooling_adiabatic; + kpacket_to_rpacket_rate += mplasma->est.cooling_ff + mplasma->est.cooling_ff_lofreq; R_matrix[nlevels_macro][nlevels_macro] += Rcont = kpacket_to_rpacket_rate; Q_norm[nlevels_macro] += Rcont; @@ -392,12 +392,12 @@ fill_kpkt_rates (xplasma, escape, p) mplasma = ¯omain[xplasma->nplasma]; one = &wmain[xplasma->nwind]; - electron_temperature = xplasma->t_e; + electron_temperature = xplasma->state.t_e; /* JM 1511 -- Fix for issue 187. We need band limits for free free packet generation (see call to one_ff below) */ freqmin = xband.f1[0]; - freqmax = ALPHA_FF * xplasma->t_e / H_OVER_K; + freqmax = ALPHA_FF * xplasma->state.t_e / H_OVER_K; /* ksl This is a Bandaid for when the temperatures are very low */ /* in this case cooling_ff should be low compared to cooling_ff_lofreq anyway */ @@ -409,14 +409,14 @@ fill_kpkt_rates (xplasma, escape, p) /* If the kpkt destruction rates for this cell are not known they are calculated here. This happens * every time the wind is updated */ - if (mplasma->kpkt_rates_known != TRUE) + if (mplasma->derived.kpkt_rates_known != TRUE) { cooling_normalisation = 0.0; cooling_bftot = 0.0; cooling_bbtot = 0.0; cooling_ff = 0.0; cooling_bf_coltot = 0.0; - mplasma->cooling_bb_simple_tot = 0.0; + mplasma->derived.cooling_bb_simple_tot = 0.0; /* Start of BF calculation */ /* JM 1503 -- we used to loop over ntop_phot here, @@ -430,14 +430,14 @@ fill_kpkt_rates (xplasma, escape, p) if (cont_ptr->macro_info == TRUE && geo.macro_simple == FALSE) { upper_density = den_config (xplasma, ulvl); - cooling_bf[i] = mplasma->cooling_bf[i] = - upper_density * PLANCK * cont_ptr->freq[0] * (mplasma->recomb_sp_e[xconfig[ulvl].bfd_indx_first + cont_ptr->down_index]); + cooling_bf[i] = mplasma->est.cooling_bf[i] = + upper_density * PLANCK * cont_ptr->freq[0] * (mplasma->est.recomb_sp_e[xconfig[ulvl].bfd_indx_first + cont_ptr->down_index]); } else { - upper_density = xplasma->density[cont_ptr->nion + 1]; + upper_density = xplasma->state.density[cont_ptr->nion + 1]; - cooling_bf[i] = mplasma->cooling_bf[i] = upper_density * PLANCK * cont_ptr->freq[0] * (xplasma->recomb_simple[i]); + cooling_bf[i] = mplasma->est.cooling_bf[i] = upper_density * PLANCK * cont_ptr->freq[0] * (xplasma->state.recomb_simple[i]); } if (cooling_bf[i] < 0) @@ -447,7 +447,7 @@ fill_kpkt_rates (xplasma, escape, p) Error ("i, ulvl, nphot_total, nion %d %d %d %d\n", i, ulvl, nphot_total, cont_ptr->nion); Error ("nlev, z, istate %d %d %d \n", cont_ptr->nlev, cont_ptr->z, cont_ptr->istate); Error ("freq[0] %g\n", cont_ptr->freq[0]); - cooling_bf[i] = mplasma->cooling_bf[i] = 0.0; + cooling_bf[i] = mplasma->est.cooling_bf[i] = 0.0; } else { @@ -461,7 +461,7 @@ fill_kpkt_rates (xplasma, escape, p) /* Include collisional ionization as a cooling term in macro atoms, but not simple atoms. */ lower_density = den_config (xplasma, cont_ptr->nlev); - cooling_bf_col[i] = mplasma->cooling_bf_col[i] = + cooling_bf_col[i] = mplasma->est.cooling_bf_col[i] = lower_density * PLANCK * cont_ptr->freq[0] * q_ioniz (cont_ptr, electron_temperature); cooling_bf_coltot += cooling_bf_col[i]; @@ -480,7 +480,7 @@ fill_kpkt_rates (xplasma, escape, p) line_ptr = &line[i]; if (line_ptr->macro_info == TRUE && geo.macro_simple == FALSE) { - cooling_bb[i] = mplasma->cooling_bb[i] = + cooling_bb[i] = mplasma->est.cooling_bb[i] = den_config (xplasma, line_ptr->nconfigl) * q12 (line_ptr, electron_temperature) * line_ptr->freq * PLANCK; } @@ -500,14 +500,14 @@ fill_kpkt_rates (xplasma, escape, p) the photon actually escapes - we don't to waste time by exciting a two-level macro atom only so that it makes another k-packet for us! (SS May 04) */ - cooling_bb[i] *= rad_rate / (rad_rate + (coll_rate * xplasma->ne)); - mplasma->cooling_bb[i] = cooling_bb[i]; - mplasma->cooling_bb_simple_tot += cooling_bb[i]; + cooling_bb[i] *= rad_rate / (rad_rate + (coll_rate * xplasma->state.ne)); + mplasma->est.cooling_bb[i] = cooling_bb[i]; + mplasma->derived.cooling_bb_simple_tot += cooling_bb[i]; } if (cooling_bb[i] < 0) { - cooling_bb[i] = mplasma->cooling_bb[i] = 0.0; + cooling_bb[i] = mplasma->est.cooling_bb[i] = 0.0; } else { @@ -521,16 +521,17 @@ fill_kpkt_rates (xplasma, escape, p) if (one->inwind >= 0) { -//Old cooling_ff = mplasma->cooling_ff = total_free (xplasma, xplasma->t_e, freqmin, freqmax) / xplasma->vol / xplasma->ne; -//Old cooling_ff += mplasma->cooling_ff_lofreq = total_free (xplasma, xplasma->t_e, 0.0, freqmin) / xplasma->vol / xplasma->ne; +//Old cooling_ff = mplasma->est.cooling_ff = total_free (xplasma, xplasma->state.t_e, freqmin, freqmax) / xplasma->state.vol / xplasma->state.ne; +//Old cooling_ff += mplasma->est.cooling_ff_lofreq = total_free (xplasma, xplasma->state.t_e, 0.0, freqmin) / xplasma->state.vol / xplasma->state.ne; // Next lines reset cooling_ff_lofreq to 0. - cooling_ff = mplasma->cooling_ff = total_free (xplasma, xplasma->t_e, 0.0, freqmax) / xplasma->vol / xplasma->ne; - mplasma->cooling_ff_lofreq = 0.0; + cooling_ff = mplasma->est.cooling_ff = + total_free (xplasma, xplasma->state.t_e, 0.0, freqmax) / xplasma->state.vol / xplasma->state.ne; + mplasma->est.cooling_ff_lofreq = 0.0; } else { /* This should never happen */ - cooling_ff = mplasma->cooling_ff = mplasma->cooling_ff_lofreq = 0.0; + cooling_ff = mplasma->est.cooling_ff = mplasma->est.cooling_ff_lofreq = 0.0; Error ("kpkt: np %d A scattering event in cell %d with vol = 0???\n", p->np, one->nwind); *escape = TRUE; p->istat = P_ERROR_MATOM; @@ -557,7 +558,7 @@ fill_kpkt_rates (xplasma, escape, p) /* note the units here- we divide the total luminosity of the cell by volume and ne to give cooling rate */ - cooling_adiabatic = xplasma->cool_adiabatic / xplasma->vol / xplasma->ne; // JM 1411 - changed to use filled volume + cooling_adiabatic = xplasma->derived.cool_adiabatic / xplasma->state.vol / xplasma->state.ne; // JM 1411 - changed to use filled volume if (geo.adiabatic == 0 && cooling_adiabatic > 0.0) @@ -579,12 +580,12 @@ fill_kpkt_rates (xplasma, escape, p) cooling_normalisation += cooling_adiabatic; - mplasma->cooling_bbtot = cooling_bbtot; - mplasma->cooling_bftot = cooling_bftot; - mplasma->cooling_bf_coltot = cooling_bf_coltot; - mplasma->cooling_adiabatic = cooling_adiabatic; - mplasma->cooling_normalisation = cooling_normalisation; - mplasma->kpkt_rates_known = TRUE; + mplasma->est.cooling_bbtot = cooling_bbtot; + mplasma->est.cooling_bftot = cooling_bftot; + mplasma->est.cooling_bf_coltot = cooling_bf_coltot; + mplasma->est.cooling_adiabatic = cooling_adiabatic; + mplasma->est.cooling_normalisation = cooling_normalisation; + mplasma->derived.kpkt_rates_known = TRUE; } @@ -629,8 +630,8 @@ f_matom_emit_accelerate (xplasma, upper, freq_min, freq_max) double bb_cont; double flast, fthresh, bf_int_full, bf_int_inrange; -//OLD t_e = xplasma->t_e; //electron temperature - ne = xplasma->ne; //electron number density +//OLD t_e = xplasma->state.t_e; //electron temperature + ne = xplasma->state.ne; //electron number density /* The first step is to identify the configuration that has been excited. */ @@ -807,12 +808,12 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) } mplasma = ¯omain[xplasma->nplasma]; -//OLD electron_temperature = xplasma->t_e; +//OLD electron_temperature = xplasma->state.t_e; /* JM 1511 -- Fix for issue 187. We need band limits for free free packet generation (see call to one_ff below) */ ff_freq_min = xband.f1[0]; - ff_freq_max = ALPHA_FF * xplasma->t_e / H_OVER_K; + ff_freq_max = ALPHA_FF * xplasma->state.t_e / H_OVER_K; /* ksl This is a Bandaid for when the temperatures are very low */ /* in this case cooling_ff should be low compared to cooling_ff_lofreq anyway */ @@ -836,11 +837,11 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) /* If the edge is above the frequency range we are interested in then we need not consider this bf process. */ - eprbs = mplasma->cooling_bf[i]; + eprbs = mplasma->est.cooling_bf[i]; penorm += eprbs; if (cont_ptr->freq[0] < freq_max && cont_ptr->freq[cont_ptr->np - 1] > freq_min) //means that it may contribute { - eprbs_band = mplasma->cooling_bf[i]; + eprbs_band = mplasma->est.cooling_bf[i]; fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list bf_int_full = scaled_alpha_sp_integral_band_limited (cont_ptr, xplasma, 0, fthresh, flast); @@ -877,7 +878,7 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) } else //line is not for a macro atom - use simple method { - penorm += eprbs = mplasma->cooling_bb[i]; + penorm += eprbs = mplasma->est.cooling_bb[i]; if ((line[i].freq > freq_min) && (line[i].freq < freq_max)) // correct range { penorm_band += eprbs_band = eprbs; @@ -888,10 +889,10 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) /* consult issues #187, #492 regarding free-free */ - penorm += eprbs = mplasma->cooling_ff + mplasma->cooling_ff_lofreq; + penorm += eprbs = mplasma->est.cooling_ff + mplasma->est.cooling_ff_lofreq; - total_ff_lofreq = total_free (xplasma, xplasma->t_e, 0, ff_freq_min); - total_ff = total_free (xplasma, xplasma->t_e, ff_freq_min, ff_freq_max); + total_ff_lofreq = total_free (xplasma, xplasma->state.t_e, 0, ff_freq_min); + total_ff = total_free (xplasma, xplasma->state.t_e, ff_freq_min, ff_freq_max); /* * Do not increment penorm_band when the total free-free luminosity is zero @@ -900,28 +901,28 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) if (freq_min > ff_freq_min) { if (total_ff > 0) - penorm_band += total_free (xplasma, xplasma->t_e, freq_min, freq_max) / total_ff * mplasma->cooling_ff; + penorm_band += total_free (xplasma, xplasma->state.t_e, freq_min, freq_max) / total_ff * mplasma->est.cooling_ff; } else if (freq_max > ff_freq_min) { if (total_ff > 0) - penorm_band += total_free (xplasma, xplasma->t_e, ff_freq_min, freq_max) / total_ff * mplasma->cooling_ff; + penorm_band += total_free (xplasma, xplasma->state.t_e, ff_freq_min, freq_max) / total_ff * mplasma->est.cooling_ff; if (total_ff_lofreq > 0) - penorm_band += total_free (xplasma, xplasma->t_e, freq_min, ff_freq_min) / total_ff_lofreq * mplasma->cooling_ff_lofreq; + penorm_band += total_free (xplasma, xplasma->state.t_e, freq_min, ff_freq_min) / total_ff_lofreq * mplasma->est.cooling_ff_lofreq; } else { if (total_ff_lofreq > 0) - penorm_band += total_free (xplasma, xplasma->t_e, freq_min, freq_max) / total_ff_lofreq * mplasma->cooling_ff_lofreq; + penorm_band += total_free (xplasma, xplasma->state.t_e, freq_min, freq_max) / total_ff_lofreq * mplasma->est.cooling_ff_lofreq; } - penorm += eprbs = mplasma->cooling_adiabatic; + penorm += eprbs = mplasma->est.cooling_adiabatic; for (i = 0; i < nphot_total; i++) { if (phot_top[i].macro_info == 0 || geo.macro_simple == 1) { - penorm += eprbs = mplasma->cooling_bf_col[i]; + penorm += eprbs = mplasma->est.cooling_bf_col[i]; } } @@ -963,9 +964,9 @@ matom_deactivation_from_matrix (xplasma, uplvl) mplasma = ¯omain[xplasma->nplasma]; - if (mplasma->matrix_rates_known == FALSE) + if (mplasma->derived.matrix_rates_known == FALSE) { - if (mplasma->store_matom_matrix == FALSE) + if (mplasma->state.store_matom_matrix == FALSE) { /* we aren't storing the macro-atom matrix, so we need to allocate and calculate it */ matom_matrix = (double **) calloc (sizeof (double *), nrows); @@ -976,21 +977,21 @@ matom_deactivation_from_matrix (xplasma, uplvl) } else { - matom_matrix = mplasma->matom_matrix; + matom_matrix = mplasma->derived.matom_matrix; } calc_matom_matrix (xplasma, matom_matrix); /* if we are storing the matrix, flag that we know the rates now */ - if (mplasma->store_matom_matrix == TRUE) + if (mplasma->state.store_matom_matrix == TRUE) { - mplasma->matrix_rates_known = TRUE; + mplasma->derived.matrix_rates_known = TRUE; } } -//OLD else if (mplasma->store_matom_matrix == TRUE) +//OLD else if (mplasma->state.store_matom_matrix == TRUE) else { - matom_matrix = mplasma->matom_matrix; + matom_matrix = mplasma->derived.matom_matrix; } /* Now use the B matrix to calculate the outgoing state from activating state "uplvl" */ @@ -1010,7 +1011,7 @@ matom_deactivation_from_matrix (xplasma, uplvl) j = j - 1; } - if (mplasma->store_matom_matrix == FALSE) + if (mplasma->state.store_matom_matrix == FALSE) { /* need to free each calloc-ed row of the matrixes */ for (i = 0; i < nrows; i++) @@ -1057,9 +1058,9 @@ calc_all_matom_matrices (void) xplasma = &plasmamain[n]; mplasma = ¯omain[n]; - if (mplasma->store_matom_matrix == TRUE) + if (mplasma->state.store_matom_matrix == TRUE) { - calc_matom_matrix (xplasma, mplasma->matom_matrix); + calc_matom_matrix (xplasma, mplasma->derived.matom_matrix); } } @@ -1073,7 +1074,7 @@ calc_all_matom_matrices (void) /* flag the matrix rates as known */ for (n = 0; n < NPLASMA; n++) { - macromain[n].matrix_rates_known = TRUE; + macromain[n].derived.matrix_rates_known = TRUE; } return (0); diff --git a/source/macro_gen_f.c b/source/macro_gen_f.c index 0f50ab3ed..307a2cb68 100644 --- a/source/macro_gen_f.c +++ b/source/macro_gen_f.c @@ -89,15 +89,15 @@ get_matom_f (mode) { for (m = 0; m < nlevels_macro; m++) { - norm += macromain[n].matom_abs[m]; - macromain[n].matom_emiss[m] = 0.0; - if (sane_check (macromain[n].matom_abs[m])) - Error ("matom_abs is %8.4e in matom %i level %i\n", macromain[n].matom_abs[m], n, m); + norm += macromain[n].est.matom_abs[m]; + macromain[n].derived.matom_emiss[m] = 0.0; + if (sane_check (macromain[n].est.matom_abs[m])) + Error ("matom_abs is %8.4e in matom %i level %i\n", macromain[n].est.matom_abs[m], n, m); } - norm += plasmamain[n].kpkt_abs; - plasmamain[n].kpkt_emiss = 0.0; - if (sane_check (plasmamain[n].kpkt_abs)) - Error ("kpkt_abs is %8.4e in matom %i\n", plasmamain[n].kpkt_abs, n); + norm += plasmamain[n].est.kpkt_abs; + plasmamain[n].derived.kpkt_emiss = 0.0; + if (sane_check (plasmamain[n].est.kpkt_abs)) + Error ("kpkt_abs is %8.4e in matom %i\n", plasmamain[n].est.kpkt_abs, n); } /* For MPI parallelisation, the following loop will be distributed over multiple tasks. @@ -139,13 +139,13 @@ get_matom_f (mode) for (m = 0; m < nlevels_macro + 1; m++) { - if ((m == nlevels_macro && plasmamain[n].kpkt_abs > 0) || (m < nlevels_macro && macromain[n].matom_abs[m] > 0)) + if ((m == nlevels_macro && plasmamain[n].est.kpkt_abs > 0) || (m < nlevels_macro && macromain[n].est.matom_abs[m] > 0)) { if (m < nlevels_macro) { - if (macromain[n].matom_abs[m] > 0) + if (macromain[n].est.matom_abs[m] > 0) { - n_tries_local = (n_tries * macromain[n].matom_abs[m] / norm) + 10; + n_tries_local = (n_tries * macromain[n].est.matom_abs[m] / norm) + 10; } else { @@ -154,9 +154,9 @@ get_matom_f (mode) } else if (m == nlevels_macro) { - if (plasmamain[n].kpkt_abs > 0) + if (plasmamain[n].est.kpkt_abs > 0) { - n_tries_local = (n_tries * plasmamain[n].kpkt_abs / norm) + 10; + n_tries_local = (n_tries * plasmamain[n].est.kpkt_abs / norm) + 10; } else { @@ -229,7 +229,7 @@ get_matom_f (mode) if (nres > NLINES + nphot_total) { Error ("Problem in get_matom_f (1). Abort. nres is %d, NLINES %d, nphot_total %d m %d %8.4e\n", - nres, NLINES, nphot_total, m, macromain[n].matom_abs[m]); + nres, NLINES, nphot_total, m, macromain[n].est.matom_abs[m]); Exit (0); } @@ -308,21 +308,21 @@ get_matom_f (mode) contribution = 0; if (m < nlevels_macro) { - macromain[n].matom_emiss[mm] += contribution = level_emit[mm] * macromain[n].matom_abs[m] / n_tries_local; + macromain[n].derived.matom_emiss[mm] += contribution = level_emit[mm] * macromain[n].est.matom_abs[m] / n_tries_local; } else if (m == nlevels_macro) { - macromain[n].matom_emiss[mm] += contribution = level_emit[mm] * plasmamain[n].kpkt_abs / n_tries_local; + macromain[n].derived.matom_emiss[mm] += contribution = level_emit[mm] * plasmamain[n].est.kpkt_abs / n_tries_local; } } if (m < nlevels_macro) { - plasmamain[n].kpkt_emiss += kpkt_emit * macromain[n].matom_abs[m] / n_tries_local; + plasmamain[n].derived.kpkt_emiss += kpkt_emit * macromain[n].est.matom_abs[m] / n_tries_local; } else if (m == nlevels_macro) { - plasmamain[n].kpkt_emiss += kpkt_emit * plasmamain[n].kpkt_abs / n_tries_local; + plasmamain[n].derived.kpkt_emiss += kpkt_emit * plasmamain[n].est.kpkt_abs / n_tries_local; } } } @@ -346,7 +346,7 @@ get_matom_f (mode) for (mm = 0; mm < nlevels_macro; mm++) { - lum += macromain[n].matom_emiss[mm]; + lum += macromain[n].derived.matom_emiss[mm]; } } @@ -428,13 +428,13 @@ get_matom_f_accelerate (mode) { for (m = 0; m < nlevels_macro; m++) { - macromain[n].matom_emiss[m] = 0.0; - if (sane_check (macromain[n].matom_abs[m])) - Error ("matom_abs is %8.4e in matom %i level %i\n", macromain[n].matom_abs[m], n, m); + macromain[n].derived.matom_emiss[m] = 0.0; + if (sane_check (macromain[n].est.matom_abs[m])) + Error ("matom_abs is %8.4e in matom %i level %i\n", macromain[n].est.matom_abs[m], n, m); } - plasmamain[n].kpkt_emiss = 0.0; - if (sane_check (plasmamain[n].kpkt_abs)) - Error ("kpkt_abs is %8.4e in matom %i\n", plasmamain[n].kpkt_abs, n); + plasmamain[n].derived.kpkt_emiss = 0.0; + if (sane_check (plasmamain[n].est.kpkt_abs)) + Error ("kpkt_abs is %8.4e in matom %i\n", plasmamain[n].est.kpkt_abs, n); } @@ -493,19 +493,19 @@ get_matom_f_accelerate (mode) { for (j = 0; j < nlevels_macro; j++) { - macromain[n].matom_emiss[j] += macromain[n].matom_abs[i] * matom_matrix[i][j]; + macromain[n].derived.matom_emiss[j] += macromain[n].est.matom_abs[i] * matom_matrix[i][j]; } - plasmamain[n].kpkt_emiss += macromain[n].matom_abs[i] * matom_matrix[i][nlevels_macro]; + plasmamain[n].derived.kpkt_emiss += macromain[n].est.matom_abs[i] * matom_matrix[i][nlevels_macro]; } /* do the same for the thermal pool. we also normalise by banded_emiss_frac here */ for (j = 0; j < nlevels_macro; j++) { - macromain[n].matom_emiss[j] += plasmamain[n].kpkt_abs * matom_matrix[nlevels_macro][j]; - macromain[n].matom_emiss[j] *= (1.0 * level_emit_doub[j]); + macromain[n].derived.matom_emiss[j] += plasmamain[n].est.kpkt_abs * matom_matrix[nlevels_macro][j]; + macromain[n].derived.matom_emiss[j] *= (1.0 * level_emit_doub[j]); } - plasmamain[n].kpkt_emiss += plasmamain[n].kpkt_abs * matom_matrix[nlevels_macro][nlevels_macro]; - plasmamain[n].kpkt_emiss *= (1.0 * kpkt_emit_doub); + plasmamain[n].derived.kpkt_emiss += plasmamain[n].est.kpkt_abs * matom_matrix[nlevels_macro][nlevels_macro]; + plasmamain[n].derived.kpkt_emiss *= (1.0 * kpkt_emit_doub); } /*This is the end of the update loop that is parallelised. We now need to exchange data between the tasks. @@ -526,7 +526,7 @@ get_matom_f_accelerate (mode) for (mm = 0; mm < nlevels_macro; mm++) { - lum += macromain[n].matom_emiss[mm]; + lum += macromain[n].derived.matom_emiss[mm]; } } diff --git a/source/macro_gov.c b/source/macro_gov.c index 5a98740cd..c28275928 100644 --- a/source/macro_gov.c +++ b/source/macro_gov.c @@ -137,7 +137,7 @@ macro_gov (p, nres, matom_or_kpkt, which_out) escape = FALSE; } - if (mplasma->matom_transition_mode == MATOM_MATRIX) + if (mplasma->state.matom_transition_mode == MATOM_MATRIX) { if (matom_or_kpkt == MATOM) { @@ -196,7 +196,7 @@ macro_gov (p, nres, matom_or_kpkt, which_out) } /* using the old MATOM_MC_JUMPS scheme */ - else if (mplasma->matom_transition_mode == MATOM_MC_JUMPS) + else if (mplasma->state.matom_transition_mode == MATOM_MC_JUMPS) { /* Beginning of the main loop for processing a macro-atom */ while (escape == FALSE) @@ -355,7 +355,7 @@ macro_pops (xplasma, xne) * hide errors in very extreme cases. */ - if (xplasma->ntot == 0) + if (xplasma->est.ntot == 0) { get_dilute_estimators (xplasma); } @@ -483,7 +483,7 @@ macro_pops (xplasma, xne) { Error ("macro_pops: iteration %d: unreasonable population(s) in plasma cell %i. Using dilute BBody excitation with w %8.4e t_r %8.4e\n", - n_iterations, xplasma->nplasma, xplasma->w, xplasma->t_r); + n_iterations, xplasma->nplasma, xplasma->state.w, xplasma->state.t_r); get_dilute_estimators (xplasma); } else @@ -587,12 +587,12 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in fast_line.gu = xconfig[index_fast_col + 1].g; fast_line.freq = (xconfig[index_fast_col + 1].ex - xconfig[index_lvl].ex) / PLANCK; fast_line.f = 1e4; - rate = q12 (&fast_line, xplasma->t_e) * xne; + rate = q12 (&fast_line, xplasma->state.t_e) * xne; lower = conf_to_matrix[index_lvl]; upper = conf_to_matrix[index_fast_col + 1]; rate_matrix[lower][lower] += -1. * rate; rate_matrix[upper][lower] += rate; - rate = q21 (&fast_line, xplasma->t_e) * xne; + rate = q21 (&fast_line, xplasma->state.t_e) * xne; rate_matrix[upper][upper] += -1. * rate; rate_matrix[lower][upper] += rate; } @@ -612,8 +612,8 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in including a collisional term (which depends on ne). */ line_ptr = &line[xconfig[index_lvl].bbu_jump[index_bbu]]; - rate = b12 (line_ptr) * mplasma->jbar_old[xconfig[index_lvl].bbu_indx_first + index_bbu]; - rate += q12 (line_ptr, xplasma->t_e) * xne; + rate = b12 (line_ptr) * mplasma->state.jbar_old[xconfig[index_lvl].bbu_indx_first + index_bbu]; + rate += q12 (line_ptr, xplasma->state.t_e) * xne; /* This is the rate out of the level in question. We need to add it to the matrix in two places: firstly as a -ve contribution to the @@ -646,7 +646,7 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in line_ptr = &line[xconfig[index_lvl].bbd_jump[index_bbd]]; rate = (a21 (line_ptr) * p_escape (line_ptr, xplasma)); - rate += q21 (line_ptr, xplasma->t_e) * xne; + rate += q21 (line_ptr, xplasma->state.t_e) * xne; /* This is the rate out of the level in question. We need to add it to the matrix in two places: firstly as a -ve contribution to the @@ -677,8 +677,8 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in gamma which has been computed as a Monte Carlo estimator. */ cont_ptr = &phot_top[xconfig[index_lvl].bfu_jump[index_bfu]]; - rate = mplasma->gamma_old[xconfig[index_lvl].bfu_indx_first + index_bfu]; - rate += q_ioniz (cont_ptr, xplasma->t_e) * xne; + rate = mplasma->state.gamma_old[xconfig[index_lvl].bfu_indx_first + index_bfu]; + rate += q_ioniz (cont_ptr, xplasma->state.t_e) * xne; /* This is the rate out of the level in question. We need to add it to the matrix in two places: firstly as a -ve contribution to the @@ -702,7 +702,7 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in /* Lower and upper are the same, but now it contributes in the other direction. */ - rate = mplasma->alpha_st_old[xconfig[index_lvl].bfu_indx_first + index_bfu] * xne; + rate = mplasma->state.alpha_st_old[xconfig[index_lvl].bfu_indx_first + index_bfu] * xne; rate_matrix[upper][upper] += -1. * rate; rate_matrix[lower][upper] += rate; @@ -719,10 +719,10 @@ macro_pops_fill_rate_matrix (MacroPtr mplasma, PlasmaPtr xplasma, double xne, in the alpha value. */ cont_ptr = &phot_top[xconfig[index_lvl].bfd_jump[index_bfd]]; /* Get new values of the recombination rates and store them. */ - mplasma->recomb_sp[xconfig[index_lvl].bfd_indx_first + index_bfd] = alpha_sp (cont_ptr, xplasma, 0); - mplasma->recomb_sp_e[xconfig[index_lvl].bfd_indx_first + index_bfd] = alpha_sp (cont_ptr, xplasma, 2); - rate = mplasma->recomb_sp[xconfig[index_lvl].bfd_indx_first + index_bfd] * xne; - rate += q_recomb (cont_ptr, xplasma->t_e) * xne * xne; + mplasma->est.recomb_sp[xconfig[index_lvl].bfd_indx_first + index_bfd] = alpha_sp (cont_ptr, xplasma, 0); + mplasma->est.recomb_sp_e[xconfig[index_lvl].bfd_indx_first + index_bfd] = alpha_sp (cont_ptr, xplasma, 2); + rate = mplasma->est.recomb_sp[xconfig[index_lvl].bfd_indx_first + index_bfd] * xne; + rate += q_recomb (cont_ptr, xplasma->state.t_e) * xne * xne; /* This is the rate out of the level in question. We need to add it to the matrix in two places: firstly as a -ve contribution to the @@ -840,7 +840,7 @@ macro_pops_check_densities_for_numerical_errors (PlasmaPtr xplasma, int index_el /* Check that the ion density is positive and finite */ - ion_density_temp = this_ion_density * ele[index_element].abun * xplasma->rho * rho2nh; + ion_density_temp = this_ion_density * ele[index_element].abun * xplasma->state.rho * rho2nh; if (sane_check (ion_density_temp) || ion_density_temp < 0.0) { Error ("macro_pops: iteration %d: ion %i has calculated a frac. pop. of %8.4e in plasma cell %i\n", n_iterations, index_ion, @@ -879,7 +879,7 @@ macro_pops_check_densities_for_numerical_errors (PlasmaPtr xplasma, int index_el * @details * The populations are now known. The populations need to be stored firstly as * ion populations and secondly as fractional level populations within an ion. - * Get the ion populations and write them to one->density[nion]. The level + * Get the ion populations and write them to one->state.density[nion]. The level * populations are to be put in "levden". * **********************************************************/ @@ -898,13 +898,13 @@ macro_pops_copy_to_xplasma (PlasmaPtr xplasma, int index_element, double *popula this_ion_density += populations[conf_to_matrix[index_lvl]]; } - xplasma->density[index_ion] = this_ion_density * ele[index_element].abun * xplasma->rho * rho2nh; + xplasma->state.density[index_ion] = this_ion_density * ele[index_element].abun * xplasma->state.rho * rho2nh; /* to maintain consistency with the higher level routines, only allow density to drop to DENSITY_MIN */ - if (xplasma->density[index_ion] < DENSITY_MIN) + if (xplasma->state.density[index_ion] < DENSITY_MIN) { - xplasma->density[index_ion] = DENSITY_MIN; + xplasma->state.density[index_ion] = DENSITY_MIN; } for (index_lvl = ion[index_ion].first_nlte_level; index_lvl < ion[index_ion].first_nlte_level + ion[index_ion].nlte; index_lvl++) @@ -912,11 +912,11 @@ macro_pops_copy_to_xplasma (PlasmaPtr xplasma, int index_element, double *popula fractional_population = populations[conf_to_matrix[index_lvl]] / this_ion_density; if (this_ion_density < DENSITY_MIN || fractional_population < DENSITY_MIN) { - xplasma->levden[xconfig[index_lvl].nden] = DENSITY_MIN; + xplasma->state.levden[xconfig[index_lvl].nden] = DENSITY_MIN; } else { - xplasma->levden[xconfig[index_lvl].nden] = fractional_population; + xplasma->state.levden[xconfig[index_lvl].nden] = fractional_population; } } } diff --git a/source/matom.c b/source/matom.c index b1c0540b7..acbf60273 100644 --- a/source/matom.c +++ b/source/matom.c @@ -103,8 +103,8 @@ matom (p, nres, escape) mplasma = ¯omain[xplasma->nplasma]; - t_e = xplasma->t_e; - ne = xplasma->ne; + t_e = xplasma->state.t_e; + ne = xplasma->state.ne; /* these are used later for stimulated recomb */ lower_density = density_ratio = 0.0; @@ -214,7 +214,7 @@ matom (p, nres, escape) cont_ptr = &phot_top[xconfig[uplvl].bfd_jump[n]]; //pointer to continuum - sp_rec_rate = mplasma->recomb_sp[xconfig[uplvl].bfd_indx_first + n]; + sp_rec_rate = mplasma->est.recomb_sp[xconfig[uplvl].bfd_indx_first + n]; bf_cont = (sp_rec_rate + q_recomb (cont_ptr, t_e) * ne) * ne; jprbs_known[uplvl][m] = jprbs[m] = bf_cont * xconfig[phot_top[xconfig[uplvl].bfd_jump[n]].nlev].ex; //energy of lower state @@ -256,7 +256,7 @@ matom (p, nres, escape) for (n = 0; n < nbbu; n++) { line_ptr = &line[xconfig[uplvl].bbu_jump[n]]; - rad_rate = (b12 (line_ptr) * mplasma->jbar_old[xconfig[uplvl].bbu_indx_first + n]); + rad_rate = (b12 (line_ptr) * mplasma->state.jbar_old[xconfig[uplvl].bbu_indx_first + n]); coll_rate = ne * q12 (line_ptr, t_e); // this is multiplied by ne below @@ -284,7 +284,7 @@ matom (p, nres, escape) else density_ratio = 0.0; - jprbs_known[uplvl][m] = jprbs[m] = (mplasma->gamma_old[xconfig[uplvl].bfu_indx_first + n] - (mplasma->alpha_st_old[xconfig[uplvl].bfu_indx_first + n] * xplasma->ne * density_ratio) + (q_ioniz (cont_ptr, t_e) * ne)) * xconfig[uplvl].ex; //energy of lower state + jprbs_known[uplvl][m] = jprbs[m] = (mplasma->state.gamma_old[xconfig[uplvl].bfu_indx_first + n] - (mplasma->state.alpha_st_old[xconfig[uplvl].bfu_indx_first + n] * xplasma->state.ne * density_ratio) + (q_ioniz (cont_ptr, t_e) * ne)) * xconfig[uplvl].ex; //energy of lower state /* this error condition can happen in unconverged hot cells where T_R >> T_E. for the moment we set to 0 and hope spontaneous recombiantion takes care of things */ @@ -447,7 +447,7 @@ matom (p, nres, escape) cont_ptr = &phot_top[xconfig[uplvl].bfd_jump[n - nbbd]]; - rad_rate = mplasma->recomb_sp[xconfig[uplvl].bfd_indx_first + n - nbbd]; //again using recomb_sp rather than alpha_sp (SS July 04) + rad_rate = mplasma->est.recomb_sp[xconfig[uplvl].bfd_indx_first + n - nbbd]; //again using recomb_sp rather than alpha_sp (SS July 04) coll_rate = ne * q_recomb (cont_ptr, t_e); choice = random_number (0.0, 1.0); @@ -572,7 +572,7 @@ xalpha_sp (cont_ptr, xplasma, ichoice) double fthresh, flast; temp_choice = ichoice; - temp_ext = xplasma->t_e; //external for use in alph_sp_integrand + temp_ext = xplasma->state.t_e; //external for use in alph_sp_integrand cont_ext_ptr = cont_ptr; //" fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -588,11 +588,11 @@ xalpha_sp (cont_ptr, xplasma, ichoice) through by the appropriate constant. */ if (cont_ptr->macro_info == TRUE && geo.macro_simple == FALSE) { - alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->t_e, -1.5); + alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->state.t_e, -1.5); } else //case for simple element { - alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->t_e, -1.5); //g for next ion up used + alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->state.t_e, -1.5); //g for next ion up used } alpha_sp_value = alpha_sp_value * ALPHA_SP_CONSTANT; @@ -643,7 +643,7 @@ alpha_sp (cont_ptr, xplasma, ichoice) double temp; temp_choice = ichoice; - temp = temp_ext = xplasma->t_e; //external for use in alph_sp_integrand + temp = temp_ext = xplasma->state.t_e; //external for use in alph_sp_integrand cont_ext_ptr = cont_ptr; //" fthresh = cont_ptr->freq[0]; //first frequency in list @@ -718,11 +718,11 @@ alpha_sp (cont_ptr, xplasma, ichoice) through by the appropriate constant. */ if (cont_ptr->macro_info == TRUE && geo.macro_simple == FALSE) { - alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->t_e, -1.5); + alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / xconfig[cont_ptr->uplev].g * pow (xplasma->state.t_e, -1.5); } else //case for simple element { - alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->t_e, -1.5); //g for next ion up used + alpha_sp_value = alpha_sp_value * xconfig[cont_ptr->nlev].g / ion[cont_ptr->nion + 1].g * pow (xplasma->state.t_e, -1.5); //g for next ion up used } alpha_sp_value = alpha_sp_value * ALPHA_SP_CONSTANT; @@ -780,7 +780,7 @@ scaled_alpha_sp_integral_band_limited (cont_ptr, xplasma, ichoice, freq_min, fre double fthresh, flast; temp_choice = ichoice; - temp_ext = xplasma->t_e; //external for use in alph_sp_integrand + temp_ext = xplasma->state.t_e; //external for use in alph_sp_integrand cont_ext_ptr = cont_ptr; //" fthresh = cont_ptr->freq[0]; //first frequency in list flast = cont_ptr->freq[cont_ptr->np - 1]; //last frequency in list @@ -904,14 +904,14 @@ kpkt (p, nres, escape, mode) mplasma = ¯omain[xplasma->nplasma]; -//OLD electron_temperature = xplasma->t_e; +//OLD electron_temperature = xplasma->state.t_e; /* Set maximum and minimum frequency limits. See #187. We need band limits for free free packet generation (see call to one_ff below). A bandaid is applied if there is not enough separation between freqmin and max */ freqmin = xband.f1[0]; - freqmax = ALPHA_FF * xplasma->t_e / H_OVER_K; + freqmax = ALPHA_FF * xplasma->state.t_e / H_OVER_K; if (freqmax < 1.1 * freqmin) { freqmax = 1.1 * freqmin; @@ -922,7 +922,7 @@ kpkt (p, nres, escape, mode) * of ne, since one power of ne applies to all of the cooling rates and we are only concerned * with relative cooling rates */ - if (mplasma->kpkt_rates_known != TRUE) + if (mplasma->derived.kpkt_rates_known != TRUE) { fill_kpkt_rates (xplasma, escape, p); } @@ -933,7 +933,8 @@ kpkt (p, nres, escape, mode) The next little section deals whith handling adiabatic cooling and shock heating. */ - cooling_normalisation = mplasma->cooling_normalisation - mplasma->cooling_adiabatic - mplasma->cooling_bbtot - mplasma->cooling_bf_coltot; + cooling_normalisation = + mplasma->est.cooling_normalisation - mplasma->est.cooling_adiabatic - mplasma->est.cooling_bbtot - mplasma->est.cooling_bf_coltot; cooling_adiabatic = 0.0; /* if kpkt mode is all processes, or continuum + adiabatic, then include adiabatic cooling */ @@ -941,26 +942,26 @@ kpkt (p, nres, escape, mode) { if (KPKT_NET_HEAT_MODE && geo.nonthermal) { - if (xplasma->cool_adiabatic > xplasma->heat_shock) + if (xplasma->derived.cool_adiabatic > xplasma->derived.heat_shock) { - cooling_adiabatic = (xplasma->cool_adiabatic - xplasma->heat_shock) / xplasma->vol / xplasma->ne; + cooling_adiabatic = (xplasma->derived.cool_adiabatic - xplasma->derived.heat_shock) / xplasma->state.vol / xplasma->state.ne; } } else { - cooling_adiabatic = mplasma->cooling_adiabatic; + cooling_adiabatic = mplasma->est.cooling_adiabatic; } } cooling_normalisation += cooling_adiabatic; if (mode == KPKT_MODE_ALL) { - cooling_bbtot = mplasma->cooling_bbtot; - cooling_bf_coltot = mplasma->cooling_bf_coltot; + cooling_bbtot = mplasma->est.cooling_bbtot; + cooling_bf_coltot = mplasma->est.cooling_bf_coltot; } else { - cooling_bbtot = mplasma->cooling_bb_simple_tot; + cooling_bbtot = mplasma->derived.cooling_bb_simple_tot; cooling_bf_coltot = 0.0; /* we don't conaider collisional ionization of simple ions as a cooling process */ } @@ -982,7 +983,7 @@ kpkt (p, nres, escape, mode) */ - if (destruction_choice < mplasma->cooling_bftot) + if (destruction_choice < mplasma->est.cooling_bftot) { //destruction by bf /* JM 1503 -- we used to loop over ntop_phot here, @@ -990,7 +991,7 @@ kpkt (p, nres, escape, mode) see #86, #141 */ for (i = 0; i < nphot_total; i++) { - if (destruction_choice < mplasma->cooling_bf[i]) + if (destruction_choice < mplasma->est.cooling_bf[i]) { if (i > nphot_total - 1) @@ -1016,11 +1017,11 @@ kpkt (p, nres, escape, mode) { if (phot_top[i].macro_info == FALSE || geo.macro_simple == TRUE) { - upweight_factor = xplasma->recomb_simple_upweight[i]; + upweight_factor = xplasma->state.recomb_simple_upweight[i]; p->w *= upweight_factor; /* record the amount of energy being extracted from the simple ion ionization pool */ - xplasma->bf_simple_ionpool_out += p->w - (p->w / upweight_factor); + xplasma->derived.bf_simple_ionpool_out += p->w - (p->w / upweight_factor); } } @@ -1028,24 +1029,24 @@ kpkt (p, nres, escape, mode) } else { - destruction_choice = destruction_choice - mplasma->cooling_bf[i]; + destruction_choice = destruction_choice - mplasma->est.cooling_bf[i]; } } } - else if (destruction_choice < (mplasma->cooling_bftot + cooling_bbtot)) + else if (destruction_choice < (mplasma->est.cooling_bftot + cooling_bbtot)) { /* a collisional destruction has occurred and so, if the line is associated with a macro atom, it must be excited. */ - destruction_choice = destruction_choice - mplasma->cooling_bftot; + destruction_choice = destruction_choice - mplasma->est.cooling_bftot; for (i = 0; i < nlines; i++) { /* this is a bit inelegant, but whether we want to consider the contribution here depends on the mode and type of line */ if (mode == KPKT_MODE_ALL || line[i].macro_info == FALSE || geo.macro_simple == TRUE) { - cooling_bb_use = mplasma->cooling_bb[i]; + cooling_bb_use = mplasma->est.cooling_bb[i]; } else { @@ -1073,7 +1074,7 @@ kpkt (p, nres, escape, mode) } } - else if (destruction_choice < (mplasma->cooling_bftot + cooling_bbtot + mplasma->cooling_ff)) + else if (destruction_choice < (mplasma->est.cooling_bftot + cooling_bbtot + mplasma->est.cooling_ff)) { /* If reached this point, it is a FF destruction event */ /* consult issues #187, #492 regarding free-free */ @@ -1082,7 +1083,7 @@ kpkt (p, nres, escape, mode) p->freq = one_ff (xplasma, freqmin, freqmax); return (0); } - else if (destruction_choice < (mplasma->cooling_bftot + cooling_bbtot + mplasma->cooling_ff + mplasma->cooling_ff_lofreq)) + else if (destruction_choice < (mplasma->est.cooling_bftot + cooling_bbtot + mplasma->est.cooling_ff + mplasma->est.cooling_ff_lofreq)) { /*this is ff at a frequency that is so low frequency that it is not worth tracking further */ *escape = TRUE; @@ -1093,7 +1094,7 @@ kpkt (p, nres, escape, mode) else if (destruction_choice < - (mplasma->cooling_bftot + cooling_bbtot + mplasma->cooling_ff + mplasma->cooling_ff_lofreq + cooling_adiabatic)) + (mplasma->est.cooling_bftot + cooling_bbtot + mplasma->est.cooling_ff + mplasma->est.cooling_ff_lofreq + cooling_adiabatic)) { /* It is a k-packat that is destroyed by adiabatic cooling */ @@ -1113,11 +1114,12 @@ kpkt (p, nres, escape, mode) { /* It is a k-packed destroyed by collisional ionization in a macro atom. */ destruction_choice = - destruction_choice - mplasma->cooling_bftot - cooling_bbtot - mplasma->cooling_ff - mplasma->cooling_ff_lofreq - cooling_adiabatic; + destruction_choice - mplasma->est.cooling_bftot - cooling_bbtot - mplasma->est.cooling_ff - mplasma->est.cooling_ff_lofreq - + cooling_adiabatic; for (i = 0; i < nphot_total; i++) { - if (destruction_choice < mplasma->cooling_bf_col[i]) + if (destruction_choice < mplasma->est.cooling_bf_col[i]) { if (i > nphot_total - 1) { @@ -1134,7 +1136,7 @@ kpkt (p, nres, escape, mode) } else { - destruction_choice = destruction_choice - mplasma->cooling_bf_col[i]; + destruction_choice = destruction_choice - mplasma->est.cooling_bf_col[i]; } } } @@ -1144,8 +1146,8 @@ kpkt (p, nres, escape, mode) Error ("kpkt: Failed to select a destruction process in kpkt. Abort.\n"); Error ("kpkt: choice %8.4e norm %8.4e cooling_bftot %g, cooling_bbtot %g, cooling_ff %g, cooling_ff_lofreq %g, cooling_bf_coltot %g cooling_adiabatic %g cooling_adiabatic %g\n", - destruction_choice, cooling_normalisation, mplasma->cooling_bftot, cooling_bbtot, mplasma->cooling_ff, - mplasma->cooling_ff_lofreq, cooling_bf_coltot, mplasma->cooling_adiabatic, cooling_adiabatic); + destruction_choice, cooling_normalisation, mplasma->est.cooling_bftot, cooling_bbtot, mplasma->est.cooling_ff, + mplasma->est.cooling_ff_lofreq, cooling_bf_coltot, mplasma->est.cooling_adiabatic, cooling_adiabatic); *escape = TRUE; p->istat = P_ERROR_MATOM; @@ -1199,7 +1201,7 @@ fake_matom_bb (p, nres, escape) xplasma = &plasmamain[one->nplasma]; line_ptr = lin_ptr[*nres]; - electron_temperature = xplasma->t_e; + electron_temperature = xplasma->state.t_e; /* Upon calling we know that the upper level of our fake two level macro atom is excited. Since it's only two-levels there are no jumping probabilities @@ -1222,7 +1224,7 @@ fake_matom_bb (p, nres, escape) rprb = a21 (line_ptr) * p_escape (line_ptr, xplasma); - kprb = q21 (line_ptr, electron_temperature) * xplasma->ne * (1. - exp (-H_OVER_K * line_ptr->freq / electron_temperature)); + kprb = q21 (line_ptr, electron_temperature) * xplasma->state.ne * (1. - exp (-H_OVER_K * line_ptr->freq / electron_temperature)); normalisation = kprb + rprb; @@ -1361,8 +1363,8 @@ emit_matom (w, p, nres, upper, freq_min, freq_max) xplasma = &plasmamain[one->nplasma]; mplasma = ¯omain[one->nplasma]; -//OLD t_e = xplasma->t_e; - ne = xplasma->ne; +//OLD t_e = xplasma->state.t_e; + ne = xplasma->state.ne; uplvl = upper; @@ -1417,7 +1419,7 @@ emit_matom (w, p, nres, upper, freq_min, freq_max) if (cont_ptr->freq[0] < freq_max) { - sp_rec_rate = mplasma->recomb_sp[xconfig[uplvl].bfd_indx_first + n]; + sp_rec_rate = mplasma->est.recomb_sp[xconfig[uplvl].bfd_indx_first + n]; eprbs[m] = sp_rec_rate * ne * (xconfig[uplvl].ex - xconfig[phot_top[xconfig[uplvl].bfd_jump[n]].nlev].ex); //energy difference penorm += eprbs[m]; diff --git a/source/matom_diag.c b/source/matom_diag.c index e84e19f62..575c90c47 100644 --- a/source/matom_diag.c +++ b/source/matom_diag.c @@ -46,8 +46,8 @@ matom_emiss_report () abs_sum = 0.0; for (n = 0; n < NPLASMA; n++) { - emiss_sum += macromain[n].matom_emiss[m]; - abs_sum += macromain[n].matom_abs[m]; + emiss_sum += macromain[n].derived.matom_emiss[m]; + abs_sum += macromain[n].est.matom_abs[m]; } Log ("Macro Atom level emissivities (summed): z %2d i %2d macro %2d n %2d matom_abs %8.4e matom_emiss %8.4e\n", @@ -62,8 +62,8 @@ matom_emiss_report () for (n = 0; n < NPLASMA; n++) { - emiss_sum += plasmamain[n].kpkt_emiss; - abs_sum += plasmamain[n].kpkt_abs; + emiss_sum += plasmamain[n].derived.kpkt_emiss; + abs_sum += plasmamain[n].est.kpkt_abs; } diff --git a/source/matrix_ion.c b/source/matrix_ion.c index 84bb9f09b..d825d1281 100644 --- a/source/matrix_ion.c +++ b/source/matrix_ion.c @@ -78,8 +78,8 @@ matrix_ion_populations (xplasma, mode) /* Copy some quantities from the cell into local variables */ - nh = xplasma->rho * rho2nh; // The number density of hydrogen ions - computed from density - t_e = xplasma->t_e; // The electron temperature in the cell - used for collisional processes + nh = xplasma->state.rho * rho2nh; // The number density of hydrogen ions - computed from density + t_e = xplasma->state.t_e; // The electron temperature in the cell - used for collisional processes /* We now calculate the total abundances for each element to allow us to use fractional abundances */ @@ -93,7 +93,7 @@ matrix_ion_populations (xplasma, mode) /* Now we populate the elemental abundance array */ for (mm = 0; mm < nions; mm++) { - elem_dens[ion[mm].z] = elem_dens[ion[mm].z] + xplasma->density[mm]; + elem_dens[ion[mm].z] = elem_dens[ion[mm].z] + xplasma->state.density[mm]; } /* Dielectronic recombination, collisional ionization coefficients, three body recombination and @@ -113,11 +113,11 @@ matrix_ion_populations (xplasma, mode) for (mm = 0; mm < nions; mm++) { - newden[mm] = xplasma->density[mm] / elem_dens[ion[mm].z]; // newden is our local fractional density array + newden[mm] = xplasma->state.density[mm] / elem_dens[ion[mm].z]; // newden is our local fractional density array xion[mm] = mm; // xion is an array we use to track which ion is in which row of the matrix if (mm != ele[ion[mm].nelem].firstion) // We can recombine since we are not in the first ionization stage { - rr_rates[mm] = total_rrate (mm, xplasma->t_e); // radiative recombination rates + rr_rates[mm] = total_rrate (mm, xplasma->state.t_e); // radiative recombination rates } if (ion[mm].istate != ele[ion[mm].nelem].istate_max) // we can photoionize, since we are not in the highest ionization state { @@ -131,7 +131,7 @@ matrix_ion_populations (xplasma, mode) } else if (mode == NEBULARMODE_MATRIX_ESTIMATORS) { - pi_rates[mm] = xplasma->ioniz[mm] / xplasma->density[mm]; // PI rate logged during the photon passage + pi_rates[mm] = xplasma->est.ioniz[mm] / xplasma->state.density[mm]; // PI rate logged during the photon passage } else { @@ -175,7 +175,7 @@ matrix_ion_populations (xplasma, mode) { if (inner_cross[mm].nion == inner_cross_ptr[nn]->nion && inner_cross[mm].freq[0] == inner_cross_ptr[nn]->freq[0]) //Check for a match { - inner_rates[mm] = xplasma->inner_ioniz[nn] / xplasma->density[inner_cross_ptr[nn]->nion]; + inner_rates[mm] = xplasma->est.inner_ioniz[nn] / xplasma->state.density[inner_cross_ptr[nn]->nion]; } } } @@ -206,7 +206,7 @@ matrix_ion_populations (xplasma, mode) the same result as the original procedure, or for successive calculations, it should be a better guess. I've leftin the original code, commented out... */ - xne = xxne = xxxne = get_ne (xplasma->density); //Even though the abundances are fractional, we need the real electron density + xne = xxne = xxxne = get_ne (xplasma->state.density); //Even though the abundances are fractional, we need the real electron density /* xne is the current working number xxne */ @@ -314,7 +314,7 @@ matrix_ion_populations (xplasma, mode) if ((ion[nn].macro_info == TRUE) && (geo.macro_simple == FALSE) && (geo.macro_ioniz_mode == MACRO_IONIZ_MODE_ESTIMATORS) && (modes.no_macro_pops_for_ions == FALSE)) { - newden[nn] = xplasma->density[nn] / elem_dens[ion[nn].z]; + newden[nn] = xplasma->state.density[nn] / elem_dens[ion[nn].z]; } /* if the ion is "simple" then find it's calculated ionization state in populations array */ @@ -366,13 +366,13 @@ matrix_ion_populations (xplasma, mode) Error ("matrix_ion_populations: failed to converge for cell %i t %e nh %e xnew %e\n", xplasma->nplasma, t_e, nh, xnew); - for (nn = 0; nn < xplasma->nbands; nn++) + for (nn = 0; nn < xplasma->state.nbands; nn++) { Log ("numin= %e (%e) numax= %e (%e) Model= %2d PL_log_w= %e PL_alpha= %e Exp_w= %e EXP_temp= %e\n", - xplasma->fmin_mod[nn], xplasma->f1[nn], xplasma->fmax_mod[nn], - xplasma->f2[nn], xplasma->spec_mod_type[nn], - xplasma->pl_log_w[nn], xplasma->pl_alpha[nn], xplasma->exp_w[nn], xplasma->exp_temp[nn]); + xplasma->state.fmin_mod[nn], xplasma->state.f1[nn], xplasma->state.fmax_mod[nn], + xplasma->state.f2[nn], xplasma->state.spec_mod_type[nn], + xplasma->state.pl_log_w[nn], xplasma->state.pl_alpha[nn], xplasma->state.exp_w[nn], xplasma->state.exp_temp[nn]); } Error ("matrix_ion_populations: xxne %e theta %e\n", xxne); @@ -382,24 +382,24 @@ matrix_ion_populations (xplasma, mode) } /* This is the end of the iteration loop */ - xplasma->ne = xnew; + xplasma->state.ne = xnew; for (nn = 0; nn < nions; nn++) { /* If statement added here to suppress interference with macro populations */ if (ion[nn].macro_info == FALSE || geo.macro_ioniz_mode == MACRO_IONIZ_MODE_NO_ESTIMATORS || geo.macro_simple == TRUE) { - xplasma->density[nn] = newden[nn] * elem_dens[ion[nn].z]; //We return to absolute densities here + xplasma->state.density[nn] = newden[nn] * elem_dens[ion[nn].z]; //We return to absolute densities here } - if ((sane_check (xplasma->density[nn])) || (xplasma->density[nn] < 0.0)) - Error ("matrix_ion_populations: ion %i has population %8.4e in cell %i\n", nn, xplasma->density[nn], xplasma->nplasma); + if ((sane_check (xplasma->state.density[nn])) || (xplasma->state.density[nn] < 0.0)) + Error ("matrix_ion_populations: ion %i has population %8.4e in cell %i\n", nn, xplasma->state.density[nn], xplasma->nplasma); } - xplasma->ne = get_ne (xplasma->density); + xplasma->state.ne = get_ne (xplasma->state.density); if (n_charge_exchange > 0) { - xplasma->heat_ch_ex = ch_ex_heat (&wmain[xplasma->nwind], xplasma->t_e); //Compute the charge exchange heating - xplasma->heat_tot += xplasma->heat_ch_ex; + xplasma->est.heat_ch_ex = ch_ex_heat (&wmain[xplasma->nwind], xplasma->state.t_e); //Compute the charge exchange heating + xplasma->est.heat_tot += xplasma->est.heat_ch_ex; } /*We now need to populate level densities in order to later calculate line emission (for example). diff --git a/source/modify_wind.c b/source/modify_wind.c index 0193629ce..56c28f7a3 100644 --- a/source/modify_wind.c +++ b/source/modify_wind.c @@ -303,7 +303,7 @@ put_ion (ndom, element, istate, den) for (n = 0; n < ndim2; n++) { nplasma = wmain[nstart + n].nplasma; - plasmamain[nplasma].density[nion] = den[n]; + plasmamain[nplasma].state.density[nion] = den[n]; } return (0); @@ -341,14 +341,14 @@ apply_model (ndom, filename) nplasma = wmain[n].nplasma; for (nion = 0; nion < nions; nion++) //Change the absolute number densities, fractions remain the same { - plasmamain[nplasma].density[nion] = - plasmamain[nplasma].density[nion] * (imported_model[ndom].mass_rho[n] / plasmamain[nplasma].rho); + plasmamain[nplasma].state.density[nion] = + plasmamain[nplasma].state.density[nion] * (imported_model[ndom].mass_rho[n] / plasmamain[nplasma].state.rho); } - plasmamain[nplasma].rho = imported_model[ndom].mass_rho[n]; + plasmamain[nplasma].state.rho = imported_model[ndom].mass_rho[n]; if (imported_model[ndom].init_temperature == FALSE) { - plasmamain[nplasma].t_e = imported_model[ndom].t_e[n]; - plasmamain[nplasma].t_r = imported_model[ndom].t_r[n]; + plasmamain[nplasma].state.t_e = imported_model[ndom].t_e[n]; + plasmamain[nplasma].state.t_r = imported_model[ndom].t_r[n]; } } } @@ -366,14 +366,14 @@ apply_model (ndom, filename) nplasma = wmain[n].nplasma; for (nion = 0; nion < nions; nion++) //Change the absolute number densities, fractions remain the same { - plasmamain[nplasma].density[nion] = - plasmamain[nplasma].density[nion] * (imported_model[ndom].mass_rho[n] / plasmamain[nplasma].rho); + plasmamain[nplasma].state.density[nion] = + plasmamain[nplasma].state.density[nion] * (imported_model[ndom].mass_rho[n] / plasmamain[nplasma].state.rho); } - plasmamain[nplasma].rho = imported_model[ndom].mass_rho[n]; + plasmamain[nplasma].state.rho = imported_model[ndom].mass_rho[n]; if (imported_model[ndom].init_temperature == FALSE) { - plasmamain[nplasma].t_e = imported_model[ndom].t_e[n]; - plasmamain[nplasma].t_r = imported_model[ndom].t_r[n]; + plasmamain[nplasma].state.t_e = imported_model[ndom].t_e[n]; + plasmamain[nplasma].state.t_r = imported_model[ndom].t_r[n]; } } } @@ -443,12 +443,12 @@ frame_transform (ndom) { printf ("This cell is in the wind - transforming plasma variables\n"); nplasma = wmain[n].nplasma; - plasmamain[nplasma].vol *= factor; - plasmamain[nplasma].rho /= factor; - plasmamain[nplasma].ne /= factor; + plasmamain[nplasma].state.vol *= factor; + plasmamain[nplasma].state.rho /= factor; + plasmamain[nplasma].state.ne /= factor; for (nion = 0; nion < nions; nion++) { - plasmamain[nplasma].density[nion] /= factor; + plasmamain[nplasma].state.density[nion] /= factor; } } diff --git a/source/partition.c b/source/partition.c index 3ad2c6c49..e67e09808 100644 --- a/source/partition.c +++ b/source/partition.c @@ -67,25 +67,25 @@ partition_functions (xplasma, mode) if (mode == NEBULARMODE_TR) { //LTE using t_r - t = xplasma->t_r; + t = xplasma->state.t_r; weight = 1; } else if (mode == NEBULARMODE_TE) { //LTE using t_e - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 1; } else if (mode == NEBULARMODE_ML93) { //Non LTE calculation with radiative weights - t = xplasma->t_r; - weight = xplasma->w; + t = xplasma->state.t_r; + weight = xplasma->state.w; } else if (mode == NEBULARMODE_NLTE_SIM) /*NSH 120912 This mode is more or less defunct. When the last vestigies of the mode 3 ionizetion scheme (the original sim PL correction) is removed, this can go too */ { //Non LTE calculation with non BB radiation field. Use T_e to get partition functions, same as mode 1- - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 1; } else if (mode == NEBULARMODE_LTE_GROUND) /*This is used to set partition functions to ground state only, used when @@ -94,7 +94,7 @@ partition_functions (xplasma, mode) the temperature is a moot point, so lest go with t_e, since this is only going to be called if we are doing a power law calculation */ { - t = xplasma->t_e; + t = xplasma->state.t_e; weight = 0; } @@ -159,7 +159,7 @@ partition_functions (xplasma, mode) } - xplasma->partition[nion] = z; + xplasma->state.partition[nion] = z; } @@ -197,7 +197,7 @@ partition_functions (xplasma, mode) * temperature for just two states of interest. It is * wasteful to calculate all of the states at each temperature. * - * The results are stored in xplasma->partition[nion] + * The results are stored in xplasma->state.partition[nion] * * ### Notes ### * @bug According to the historical notes, there is no need for the weight term in the calculation @@ -284,7 +284,7 @@ partition_functions_2 (xplasma, xnion, temp, weight) } - xplasma->partition[nion] = z; + xplasma->state.partition[nion] = z; } diff --git a/source/photon2d.c b/source/photon2d.c index c8c6dcde7..35e9945ca 100644 --- a/source/photon2d.c +++ b/source/photon2d.c @@ -486,20 +486,20 @@ translate_in_wind (w, p, tau_scat, tau, nres) if (p->nres == NRES_ES) { - xplasma->nscat_es++; + xplasma->derived.nscat_es++; } if (p->nres > NLINES) { - xplasma->nscat_bf++; + xplasma->derived.nscat_bf++; } else if (p->nres > 0) { - xplasma->nscat_res++; + xplasma->derived.nscat_res++; } else if (p->nres == NRES_FF) { - xplasma->nscat_ff++; + xplasma->derived.nscat_ff++; } diff --git a/source/photon_gen_matom.c b/source/photon_gen_matom.c index 1ae8bf30a..0be5db40a 100644 --- a/source/photon_gen_matom.c +++ b/source/photon_gen_matom.c @@ -40,7 +40,7 @@ get_kpkt_f () for (n = 0; n < NPLASMA; n++) { - lum += plasmamain[n].kpkt_emiss; + lum += plasmamain[n].derived.kpkt_emiss; } @@ -52,7 +52,7 @@ get_kpkt_f () * @brief returns the specific luminosity in kpkts from nonthermal ("shock") * heating. This is used to generate kpkts in the ionization cycles. * This also populates the cell-by-cell kpkt luminosities in the - * variable plasmamain[n].kpkt_emiss. + * variable plasmamain[n].derived.kpkt_emiss. * * @return double lum * The energy created by non-radiative heating throughout the @@ -76,21 +76,21 @@ get_kpkt_heating_f () /* what we do depends on how the "net heating mode" is defined */ if (KPKT_NET_HEAT_MODE) - shock_kpkt_luminosity = (shock_heating (one) - plasmamain[n].cool_adiabatic); + shock_kpkt_luminosity = (shock_heating (one) - plasmamain[n].derived.cool_adiabatic); else shock_kpkt_luminosity = shock_heating (one); if (shock_kpkt_luminosity > 0) { if (geo.ioniz_or_extract == CYCLE_IONIZ) - plasmamain[n].kpkt_emiss = shock_kpkt_luminosity; + plasmamain[n].derived.kpkt_emiss = shock_kpkt_luminosity; else - plasmamain[n].kpkt_abs += shock_kpkt_luminosity; + plasmamain[n].est.kpkt_abs += shock_kpkt_luminosity; lum += shock_kpkt_luminosity; } else - plasmamain[n].kpkt_emiss = 0.0; + plasmamain[n].derived.kpkt_emiss = 0.0; } return (lum); @@ -171,7 +171,7 @@ photo_gen_kpkt (p, weight, photstart, nphot) if (wmain[icell].inwind >= 0) { nplasma = wmain[icell].nplasma; - xlumsum += plasmamain[nplasma].kpkt_emiss; + xlumsum += plasmamain[nplasma].derived.kpkt_emiss; } icell++; } @@ -337,7 +337,7 @@ photo_gen_matom (p, weight, photstart, nphot) if (wmain[icell].inwind >= 0) { nplasma = wmain[icell].nplasma; - xlumsum += macromain[nplasma].matom_emiss[upper]; + xlumsum += macromain[nplasma].derived.matom_emiss[upper]; upper++; if (upper == nlevels_macro) { diff --git a/source/pi_rates.c b/source/pi_rates.c index 0eb97be77..6a067497d 100644 --- a/source/pi_rates.c +++ b/source/pi_rates.c @@ -139,17 +139,17 @@ calc_pi_rate (nion, xplasma, mode, type) { for (j = 0; j < geo.nxfreq; j++) //We loop over all the bands { - xpl_alpha = xplasma->pl_alpha[j]; //set the various model parameters to those for this model - xpl_logw = xplasma->pl_log_w[j]; - xexp_temp = xplasma->exp_temp[j]; - xexp_w = xplasma->exp_w[j]; - if (xplasma->spec_mod_type[j] != SPEC_MOD_FAIL) //Only bother doing the integrals if we have a model in this band + xpl_alpha = xplasma->state.pl_alpha[j]; //set the various model parameters to those for this model + xpl_logw = xplasma->state.pl_log_w[j]; + xexp_temp = xplasma->state.exp_temp[j]; + xexp_w = xplasma->state.exp_w[j]; + if (xplasma->state.spec_mod_type[j] != SPEC_MOD_FAIL) //Only bother doing the integrals if we have a model in this band { - f1 = xplasma->fmin_mod[j]; //NSH 131114 - Set the low frequency limit to the lowest frequency that the model applies to - f2 = xplasma->fmax_mod[j]; //NSH 131114 - Set the high frequency limit to the highest frequency that the model applies to + f1 = xplasma->state.fmin_mod[j]; //NSH 131114 - Set the low frequency limit to the lowest frequency that the model applies to + f2 = xplasma->state.fmax_mod[j]; //NSH 131114 - Set the high frequency limit to the highest frequency that the model applies to if (f1 < fthresh && fthresh < f2 && f1 < fmax && fmax < f2) //Case 1- { - if (xplasma->spec_mod_type[j] == SPEC_MOD_PL) + if (xplasma->state.spec_mod_type[j] == SPEC_MOD_PL) { pi_rate += num_int (tb_logpow, fthresh, fmax, pl_qromb); @@ -161,7 +161,7 @@ calc_pi_rate (nion, xplasma, mode, type) } else if (f1 < fthresh && fthresh < f2 && f2 < fmax) //case 2 { - if (xplasma->spec_mod_type[j] == SPEC_MOD_PL) + if (xplasma->state.spec_mod_type[j] == SPEC_MOD_PL) { pi_rate += num_int (tb_logpow, fthresh, f2, pl_qromb); } @@ -172,7 +172,7 @@ calc_pi_rate (nion, xplasma, mode, type) } else if (f1 > fthresh && f1 < fmax && fmax < f2) //case 3 { - if (xplasma->spec_mod_type[j] == SPEC_MOD_PL) + if (xplasma->state.spec_mod_type[j] == SPEC_MOD_PL) { pi_rate += num_int (tb_logpow, f1, fmax, pl_qromb); } @@ -183,7 +183,7 @@ calc_pi_rate (nion, xplasma, mode, type) } else if (f1 > fthresh && f2 < fmax) // case 4 { - if (xplasma->spec_mod_type[j] == SPEC_MOD_PL) + if (xplasma->state.spec_mod_type[j] == SPEC_MOD_PL) { pi_rate += num_int (tb_logpow, f1, f2, pl_qromb); } @@ -203,16 +203,16 @@ calc_pi_rate (nion, xplasma, mode, type) else if (mode == 2) //blackbody mode { fmaxtemp = xtop->freq[xtop->np - 1]; //Set the maximum frequency temporarily to the maximum cross section frequency - fmax = check_freq_max (fmaxtemp, xplasma->t_r); /*Check that the requested maximum frequency is sensible - if it is way - off the end of the wien tail then the integration can fail - reset if necessary. */ + fmax = check_freq_max (fmaxtemp, xplasma->state.t_r); /*Check that the requested maximum frequency is sensible - if it is way + off the end of the wien tail then the integration can fail - reset if necessary. */ if (fthresh > fmax) //The threshold for PI is above the maximum frequency of the radiation { pi_rate = 0.0; } else //We are OK - do the integral { - qromb_temp = xplasma->t_r; - pi_rate = xplasma->w * num_int (tb_planck, fthresh, fmax, 1.e-4); + qromb_temp = xplasma->state.t_r; + pi_rate = xplasma->state.w * num_int (tb_planck, fthresh, fmax, 1.e-4); } } diff --git a/source/rad_hydro_files.c b/source/rad_hydro_files.c index e25319862..a7ce857c5 100644 --- a/source/rad_hydro_files.c +++ b/source/rad_hydro_files.c @@ -326,9 +326,9 @@ main (argc, argv) } for (ii = 0; ii < NFLUX_ANGLES; ii++) { - fprintf (fptr_flux_theta, "%10.3e ", plasmamain[nplasma].F_UV_ang_theta_persist[ii]); - fprintf (fptr_flux_phi, "%10.3e ", plasmamain[nplasma].F_UV_ang_phi_persist[ii]); - fprintf (fptr_flux_r, "%10.3e ", plasmamain[nplasma].F_UV_ang_r_persist[ii]); + fprintf (fptr_flux_theta, "%10.3e ", plasmamain[nplasma].derived.F_UV_ang_theta_persist[ii]); + fprintf (fptr_flux_phi, "%10.3e ", plasmamain[nplasma].derived.F_UV_ang_phi_persist[ii]); + fprintf (fptr_flux_r, "%10.3e ", plasmamain[nplasma].derived.F_UV_ang_r_persist[ii]); } fprintf (fptr_flux_theta, "\n"); @@ -359,103 +359,103 @@ main (argc, argv) else if (zdom[domain].coord_type == CYLIND) fprintf (fptr_hc, "%d %d %e %e %e ", i, j, wmain[nwind].xcen[0], wmain[nwind].xcen[2], vol); //output geometric things - fprintf (fptr_hc, "%e %e %e ", plasmamain[nplasma].t_e, plasmamain[nplasma].xi, plasmamain[nplasma].ne); //output temp, xi and ne to ease plotting of heating rates - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].heat_photo + plasmamain[nplasma].heat_auger) / vol); //Xray heating - or photoionization - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].heat_comp) / vol); //Compton heating - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].heat_lines) / vol); //Line heating 28/10/15 - not currently used in zeus - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].heat_ff) / vol); //FF heating 28/10/15 - not currently used in zeus - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].cool_comp) / vol); //Compton cooling - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].lum_lines + plasmamain[nplasma].cool_rr + plasmamain[nplasma].cool_dr) / vol); //Line cooling must include all recombination cooling - fprintf (fptr_hc, "%e ", (plasmamain[nplasma].lum_ff) / vol); //ff cooling - fprintf (fptr_hc, "%e ", plasmamain[nplasma].rho); //density - fprintf (fptr_hc, "%e \n", plasmamain[nplasma].rho * rho2nh); //hydrogen number density + fprintf (fptr_hc, "%e %e %e ", plasmamain[nplasma].state.t_e, plasmamain[nplasma].derived.xi, plasmamain[nplasma].state.ne); //output temp, xi and ne to ease plotting of heating rates + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_photo + plasmamain[nplasma].est.heat_auger) / vol); //Xray heating - or photoionization + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_comp) / vol); //Compton heating + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_lines) / vol); //Line heating 28/10/15 - not currently used in zeus + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_ff) / vol); //FF heating 28/10/15 - not currently used in zeus + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].derived.cool_comp) / vol); //Compton cooling + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].derived.lum_lines + plasmamain[nplasma].derived.cool_rr + plasmamain[nplasma].derived.cool_dr) / vol); //Line cooling must include all recombination cooling + fprintf (fptr_hc, "%e ", (plasmamain[nplasma].derived.lum_ff) / vol); //ff cooling + fprintf (fptr_hc, "%e ", plasmamain[nplasma].state.rho); //density + fprintf (fptr_hc, "%e \n", plasmamain[nplasma].state.rho * rho2nh); //hydrogen number density if (zdom[domain].coord_type == SPHERICAL || zdom[domain].coord_type == RTHETA) { fprintf (fptr_drive, "%d %d %e %e %e ", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN, vol); //output geometric things fprintf (fptr_pcon, "%d %d %e %e ", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN); //output geometric things - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rho); //density - fprintf (fptr_drive, "%e ", plasmamain[nplasma].ne); + fprintf (fptr_drive, "%e ", plasmamain[nplasma].state.rho); //density + fprintf (fptr_drive, "%e ", plasmamain[nplasma].state.ne); fprintf (fptr_flux, "%d %d %e %e ", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN); //output geometric things } else if (zdom[domain].coord_type == CYLIND) { fprintf (fptr_drive, "%d %d %e %e %e ", i, j, wmain[nwind].xcen[0], wmain[nwind].xcen[2], vol); //output geometric things fprintf (fptr_pcon, "%d %d %e %e ", i, j, wmain[nwind].xcen[0], wmain[nwind].xcen[2]); //output geometric things - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rho); //density - fprintf (fptr_drive, "%e ", plasmamain[nplasma].ne); + fprintf (fptr_drive, "%e ", plasmamain[nplasma].state.rho); //density + fprintf (fptr_drive, "%e ", plasmamain[nplasma].state.ne); fprintf (fptr_flux, "%d %d %e %e ", i, j, wmain[nwind].xcen[0], wmain[nwind].xcen[2]); //output geometric things } if (zdom[domain].coord_type == SPHERICAL) { - fprintf (fptr_drive, "%e ", plasmamain[nplasma].F_vis[0]); //directional flux by band - fprintf (fptr_drive, "%e ", plasmamain[nplasma].F_UV[0]); //directional flux by band - fprintf (fptr_drive, "%e ", plasmamain[nplasma].F_Xray[0]); //directional flux by band - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_es[0]); //electron scattering radiation force in the w(x) direction - fprintf (fptr_drive, "%e\n", plasmamain[nplasma].rad_force_bf_persist[0]); //bound free scattering radiation force in the w(x) direction - fprintf (fptr_flux, "%e ", plasmamain[nplasma].F_vis[0]); //directional flux by band - fprintf (fptr_flux, "%e ", plasmamain[nplasma].F_UV[0]); //directional flux by band - fprintf (fptr_flux, "%e ", plasmamain[nplasma].F_Xray[0]); //directional flux by band + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.F_vis[0]); //directional flux by band + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.F_UV[0]); //directional flux by band + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.F_Xray[0]); //directional flux by band + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.rad_force_es[0]); //electron scattering radiation force in the w(x) direction + fprintf (fptr_drive, "%e\n", plasmamain[nplasma].derived.rad_force_bf_persist[0]); //bound free scattering radiation force in the w(x) direction + fprintf (fptr_flux, "%e ", plasmamain[nplasma].est.F_vis[0]); //directional flux by band + fprintf (fptr_flux, "%e ", plasmamain[nplasma].est.F_UV[0]); //directional flux by band + fprintf (fptr_flux, "%e ", plasmamain[nplasma].est.F_Xray[0]); //directional flux by band } else { { - fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].F_vis[0], plasmamain[nplasma].F_vis[1], plasmamain[nplasma].F_vis[2], plasmamain[nplasma].F_vis[3]); //directional flux by band - fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].F_UV[0], plasmamain[nplasma].F_UV[1], plasmamain[nplasma].F_UV[2], plasmamain[nplasma].F_UV[3]); //directional flux by band - fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].F_Xray[0], plasmamain[nplasma].F_Xray[1], plasmamain[nplasma].F_Xray[2], plasmamain[nplasma].F_Xray[3]); //directional flux by band - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_es[0]); //electron scattering radiation force in the w(x) direction - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_es[1]); //electron scattering radiation force in the phi(rotational) directionz direction - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_es[2]); //electron scattering radiation force in the z direction - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_es[3]); //sum of magnitude of electron scattering radiation force - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_bf_persist[0]); //bound free scattering radiation force in the w(x) direction - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_bf_persist[1]); //bound free scattering radiation force in the phi(rotational) direction - fprintf (fptr_drive, "%e ", plasmamain[nplasma].rad_force_bf_persist[2]); //bound free scattering radiation force in the z direction - fprintf (fptr_drive, "%e \n", plasmamain[nplasma].rad_force_bf_persist[3]); //sum of magnitude of bound free scattering radiation force + fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].est.F_vis[0], plasmamain[nplasma].est.F_vis[1], plasmamain[nplasma].est.F_vis[2], plasmamain[nplasma].est.F_vis[3]); //directional flux by band + fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].est.F_UV[0], plasmamain[nplasma].est.F_UV[1], plasmamain[nplasma].est.F_UV[2], plasmamain[nplasma].est.F_UV[3]); //directional flux by band + fprintf (fptr_drive, "%e %e %e %e ", plasmamain[nplasma].est.F_Xray[0], plasmamain[nplasma].est.F_Xray[1], plasmamain[nplasma].est.F_Xray[2], plasmamain[nplasma].est.F_Xray[3]); //directional flux by band + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.rad_force_es[0]); //electron scattering radiation force in the w(x) direction + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.rad_force_es[1]); //electron scattering radiation force in the phi(rotational) directionz direction + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.rad_force_es[2]); //electron scattering radiation force in the z direction + fprintf (fptr_drive, "%e ", plasmamain[nplasma].est.rad_force_es[3]); //sum of magnitude of electron scattering radiation force + fprintf (fptr_drive, "%e ", plasmamain[nplasma].derived.rad_force_bf_persist[0]); //bound free scattering radiation force in the w(x) direction + fprintf (fptr_drive, "%e ", plasmamain[nplasma].derived.rad_force_bf_persist[1]); //bound free scattering radiation force in the phi(rotational) direction + fprintf (fptr_drive, "%e ", plasmamain[nplasma].derived.rad_force_bf_persist[2]); //bound free scattering radiation force in the z direction + fprintf (fptr_drive, "%e \n", plasmamain[nplasma].derived.rad_force_bf_persist[3]); //sum of magnitude of bound free scattering radiation force } - fprintf (fptr_flux, "%e %e %e %e ", plasmamain[nplasma].F_vis_persistent[0], plasmamain[nplasma].F_vis_persistent[1], plasmamain[nplasma].F_vis_persistent[2], plasmamain[nplasma].F_vis_persistent[3]); //directional flux by band - fprintf (fptr_flux, "%e %e %e %e ", plasmamain[nplasma].F_UV_persistent[0], plasmamain[nplasma].F_UV_persistent[1], plasmamain[nplasma].F_UV_persistent[2], plasmamain[nplasma].F_UV_persistent[3]); //directional flux by band - fprintf (fptr_flux, "%e %e %e %e\n ", plasmamain[nplasma].F_Xray_persistent[0], plasmamain[nplasma].F_Xray_persistent[1], plasmamain[nplasma].F_Xray_persistent[2], plasmamain[nplasma].F_Xray_persistent[3]); //directional flux by band + fprintf (fptr_flux, "%e %e %e %e ", plasmamain[nplasma].derived.F_vis_persistent[0], plasmamain[nplasma].derived.F_vis_persistent[1], plasmamain[nplasma].derived.F_vis_persistent[2], plasmamain[nplasma].derived.F_vis_persistent[3]); //directional flux by band + fprintf (fptr_flux, "%e %e %e %e ", plasmamain[nplasma].derived.F_UV_persistent[0], plasmamain[nplasma].derived.F_UV_persistent[1], plasmamain[nplasma].derived.F_UV_persistent[2], plasmamain[nplasma].derived.F_UV_persistent[3]); //directional flux by band + fprintf (fptr_flux, "%e %e %e %e\n ", plasmamain[nplasma].derived.F_Xray_persistent[0], plasmamain[nplasma].derived.F_Xray_persistent[1], plasmamain[nplasma].derived.F_Xray_persistent[2], plasmamain[nplasma].derived.F_Xray_persistent[3]); //directional flux by band } fprintf (fptr_ion, "%d %d ", i, j); //output geometric things for (ii = 0; ii < nions; ii++) - fprintf (fptr_ion, "%e ", plasmamain[nplasma].density[ii]); + fprintf (fptr_ion, "%e ", plasmamain[nplasma].state.density[ii]); fprintf (fptr_ion, "\n"); fprintf (fptr_spec, "%d %d ", i, j); //output geometric things if (geo.ioniz_mode == IONMODE_MATRIX_SPECTRALMODEL) { for (ii = 0; ii < geo.nxfreq; ii++) fprintf (fptr_spec, "%e %e %i %e %e %e %e ", - plasmamain[nplasma].fmin_mod[ii], plasmamain[nplasma].fmax_mod[ii], plasmamain[nplasma].spec_mod_type[ii], - plasmamain[nplasma].pl_log_w[ii], plasmamain[nplasma].pl_alpha[ii], plasmamain[nplasma].exp_w[ii], - plasmamain[nplasma].exp_temp[ii]); + plasmamain[nplasma].state.fmin_mod[ii], plasmamain[nplasma].state.fmax_mod[ii], + plasmamain[nplasma].state.spec_mod_type[ii], plasmamain[nplasma].state.pl_log_w[ii], + plasmamain[nplasma].state.pl_alpha[ii], plasmamain[nplasma].state.exp_w[ii], plasmamain[nplasma].state.exp_temp[ii]); } else if (geo.ioniz_mode == IONMODE_MATRIX_BB) - fprintf (fptr_spec, "%e %e ", plasmamain[nplasma].t_r, plasmamain[nplasma].w); + fprintf (fptr_spec, "%e %e ", plasmamain[nplasma].state.t_r, plasmamain[nplasma].state.w); fprintf (fptr_spec, "\n "); //We need to compute the g factor for this cell and output it. - v_th = pow ((2. * BOLTZMANN * plasmamain[nplasma].t_e / MPROT), 0.5); //We need the thermal velocity for hydrogen + v_th = pow ((2. * BOLTZMANN * plasmamain[nplasma].state.t_e / MPROT), 0.5); //We need the thermal velocity for hydrogen // v_th = 4.2e5; stuff_v (wmain[nwind].xcen, ptest.x); //place our test photon at the centre of the cell ptest.grid = nwind; //We need our test photon to know where it is - kappa_es = THOMPSON * plasmamain[nplasma].ne / plasmamain[nplasma].rho; + kappa_es = THOMPSON * plasmamain[nplasma].state.ne / plasmamain[nplasma].state.rho; kappa_es = THOMPSON / MPROT; //First for the optcial band (up to 4000AA) - if (length (plasmamain[nplasma].F_vis) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_vis) > 0.0) //Only makes sense if flux in this band is non-zero { if (zdom[domain].coord_type == SPHERICAL) //We have to do something special here - because flux is r, theta, phi in sphericals { - fhat[0] = sqrt (length (plasmamain[nplasma].F_vis_persistent)); + fhat[0] = sqrt (length (plasmamain[nplasma].derived.F_vis_persistent)); fhat[1] = 0.0; - fhat[2] = sqrt (length (plasmamain[nplasma].F_vis_persistent)); + fhat[2] = sqrt (length (plasmamain[nplasma].derived.F_vis_persistent)); } else { - stuff_v (plasmamain[nplasma].F_vis_persistent, fhat); + stuff_v (plasmamain[nplasma].derived.F_vis_persistent, fhat); } if (renorm (fhat, 1.) == -1) //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon { @@ -464,24 +464,24 @@ main (argc, argv) else { stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_opt = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_opt = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } } else t_opt = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. //Now for the UV band (up to 4000AA->100AA) - if (length (plasmamain[nplasma].F_UV) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_UV) > 0.0) //Only makes sense if flux in this band is non-zero { if (zdom[domain].coord_type == SPHERICAL) //We have to do something special here - because flux is r, theta, phi in sphericals { - fhat[0] = sqrt (length (plasmamain[nplasma].F_UV_persistent)); + fhat[0] = sqrt (length (plasmamain[nplasma].derived.F_UV_persistent)); fhat[1] = 0.0; - fhat[2] = sqrt (length (plasmamain[nplasma].F_UV_persistent)); + fhat[2] = sqrt (length (plasmamain[nplasma].derived.F_UV_persistent)); } else { - stuff_v (plasmamain[nplasma].F_UV_persistent, fhat); + stuff_v (plasmamain[nplasma].derived.F_UV_persistent, fhat); } if (renorm (fhat, 1.) == -1) //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon { @@ -490,7 +490,7 @@ main (argc, argv) else { stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_UV = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_UV = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } } else @@ -498,17 +498,17 @@ main (argc, argv) //And finally for the Xray band (up to 100AA and up) - if (length (plasmamain[nplasma].F_Xray) > 0.0) //Only makes sense if flux in this band is non-zero + if (length (plasmamain[nplasma].est.F_Xray) > 0.0) //Only makes sense if flux in this band is non-zero { if (zdom[domain].coord_type == SPHERICAL) //We have to do something special here - because flux is r, theta, phi in sphericals { - fhat[0] = sqrt (length (plasmamain[nplasma].F_Xray_persistent)); + fhat[0] = sqrt (length (plasmamain[nplasma].derived.F_Xray_persistent)); fhat[1] = 0.0; - fhat[2] = sqrt (length (plasmamain[nplasma].F_Xray_persistent)); + fhat[2] = sqrt (length (plasmamain[nplasma].derived.F_Xray_persistent)); } else { - stuff_v (plasmamain[nplasma].F_Xray_persistent, fhat); + stuff_v (plasmamain[nplasma].derived.F_Xray_persistent, fhat); } if (renorm (fhat, 1.) == -1) //A unit vector in the direction of the flux - this can be treated as the lmn vector of a pretend photon { @@ -517,16 +517,16 @@ main (argc, argv) else { stuff_v (fhat, ptest.lmn); //place our test photon at the centre of the cell - t_Xray = kappa_es * plasmamain[nplasma].rho * v_th / fabs (dvwind_ds_cmf (&ptest)); + t_Xray = kappa_es * plasmamain[nplasma].state.rho * v_th / fabs (dvwind_ds_cmf (&ptest)); } } else t_Xray = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. - fprintf (fptr_pcon, " %e %e %e %e %e %e %e\n", plasmamain[nplasma].t_e, plasmamain[nplasma].rho, - plasmamain[nplasma].rho * rho2nh, plasmamain[nplasma].ne, t_opt, t_UV, t_Xray); + fprintf (fptr_pcon, " %e %e %e %e %e %e %e\n", plasmamain[nplasma].state.t_e, plasmamain[nplasma].state.rho, + plasmamain[nplasma].state.rho * rho2nh, plasmamain[nplasma].state.ne, t_opt, t_UV, t_Xray); - fprintf (fptr_debug, "%d %d %e %e %e %e %e\n", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN, v_th, fabs (dvwind_ds_cmf (&ptest)), plasmamain[nplasma].j); //output geometric things + fprintf (fptr_debug, "%d %d %e %e %e %e %e\n", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN, v_th, fabs (dvwind_ds_cmf (&ptest)), plasmamain[nplasma].est.j); //output geometric things } } fclose (fptr_hc); diff --git a/source/radiation.c b/source/radiation.c index 532a67917..196a1fa84 100644 --- a/source/radiation.c +++ b/source/radiation.c @@ -246,7 +246,7 @@ radiation (PhotPtr p, double ds) } else if (ion[nion].phot_info == 0) // verner - density = xplasma->density[nion]; + density = xplasma->state.density[nion]; else { @@ -312,7 +312,7 @@ radiation (PhotPtr p, double ds) nion = x_top_ptr->nion; if (ion[nion].phot_info == 0) // verner only ion { - density = xplasma->density[nion]; //All these rates are from the ground state, so we just need the density of the ion. + density = xplasma->state.density[nion]; //All these rates are from the ground state, so we just need the density of the ion. } else { @@ -416,8 +416,8 @@ radiation (PhotPtr p, double ds) /* Everything after this point is only needed for ionization calculations */ /* Update the radiation parameters used ultimately in calculating t_r */ - if (freq > xplasma->max_freq) // check if photon frequency exceeds maximum frequency - use doppler shifted frequency - xplasma->max_freq = freq; // set maximum frequency sen in the cell to the mean doppler shifted freq - see bug #391 + if (freq > xplasma->est.max_freq) // check if photon frequency exceeds maximum frequency - use doppler shifted frequency + xplasma->est.max_freq = freq; // set maximum frequency sen in the cell to the mean doppler shifted freq - see bug #391 if (modes.save_cell_stats && ncstat > 0) { @@ -435,9 +435,9 @@ radiation (PhotPtr p, double ds) update_flux_estimators (xplasma, &phot_mid, ds, w_ave_obs, ndom); - if (sane_check (xplasma->j) || sane_check (xplasma->ave_freq)) + if (sane_check (xplasma->est.j) || sane_check (xplasma->est.ave_freq)) { - Error ("radiation:sane_check Problem with j %g or ave_freq %g\n", xplasma->j, xplasma->ave_freq); + Error ("radiation:sane_check Problem with j %g or ave_freq %g\n", xplasma->est.j, xplasma->est.ave_freq); } if (kappa_tot > 0) @@ -446,46 +446,46 @@ radiation (PhotPtr p, double ds) // Use the cmf value of the energy aborbed z = (energy_abs_cmf) / kappa_tot; - xplasma->heat_ff += z * frac_ff; - xplasma->heat_tot += z * frac_ff; - xplasma->abs_tot += z * frac_ff; /* The energy absorbed from the photon field in this cell */ + xplasma->est.heat_ff += z * frac_ff; + xplasma->est.heat_tot += z * frac_ff; + xplasma->derived.abs_tot += z * frac_ff; /* The energy absorbed from the photon field in this cell */ - xplasma->heat_comp += z * frac_comp; /* Calculate the heating in the cell due to Compton heating */ - xplasma->heat_tot += z * frac_comp; /* Add the Compton heating to the total heating for the cell */ - xplasma->abs_tot += z * frac_comp; /* The energy absorbed from the photon field in this cell */ - xplasma->abs_tot += z * frac_ind_comp; /* The energy absorbed from the photon field in this cell */ + xplasma->est.heat_comp += z * frac_comp; /* Calculate the heating in the cell due to Compton heating */ + xplasma->est.heat_tot += z * frac_comp; /* Add the Compton heating to the total heating for the cell */ + xplasma->derived.abs_tot += z * frac_comp; /* The energy absorbed from the photon field in this cell */ + xplasma->derived.abs_tot += z * frac_ind_comp; /* The energy absorbed from the photon field in this cell */ - xplasma->heat_tot += z * frac_ind_comp; /* Calculate the heating in the cell due to induced Compton heating */ - xplasma->heat_ind_comp += z * frac_ind_comp; /* Increment the induced Compton heating counter for the cell */ + xplasma->est.heat_tot += z * frac_ind_comp; /* Calculate the heating in the cell due to induced Compton heating */ + xplasma->est.heat_ind_comp += z * frac_ind_comp; /* Increment the induced Compton heating counter for the cell */ if (freq > phot_freq_min) { - xplasma->abs_photo += z * frac_tot_abs; //Here we store the energy absorbed from the photon flux - different from the heating by the binding energy - xplasma->abs_auger += z * frac_auger_abs; //same for auger - xplasma->abs_tot += z * frac_tot_abs; /* The energy absorbed from the photon field in this cell */ - xplasma->abs_tot += z * frac_auger_abs; /* The energy absorbed from the photon field in this cell */ + xplasma->derived.abs_photo += z * frac_tot_abs; //Here we store the energy absorbed from the photon flux - different from the heating by the binding energy + xplasma->derived.abs_auger += z * frac_auger_abs; //same for auger + xplasma->derived.abs_tot += z * frac_tot_abs; /* The energy absorbed from the photon field in this cell */ + xplasma->derived.abs_tot += z * frac_auger_abs; /* The energy absorbed from the photon field in this cell */ - xplasma->heat_photo += z * frac_tot; - xplasma->heat_z += z * frac_z; - xplasma->heat_tot += z * frac_tot; //All of the photoinization opacities - xplasma->heat_auger += z * frac_auger; - xplasma->heat_tot += z * frac_auger; //All the inner shell opacities + xplasma->est.heat_photo += z * frac_tot; + xplasma->est.heat_z += z * frac_z; + xplasma->est.heat_tot += z * frac_tot; //All of the photoinization opacities + xplasma->est.heat_auger += z * frac_auger; + xplasma->est.heat_tot += z * frac_auger; //All the inner shell opacities - q = (z) / (PLANCK * freq * xplasma->vol); + q = (z) / (PLANCK * freq * xplasma->state.vol); - /* So xplasma->ioniz for each species is just + /* So xplasma->est.ioniz for each species is just (energy_abs)*kappa_h/kappa_tot / PLANCK*freq / volume or the number of photons absorbed in this bundle per unit volume by this ion */ for (nion = 0; nion < nions; nion++) { - xplasma->ioniz[nion] += kappa_ion[nion] * q; - xplasma->heat_ion[nion] += frac_ion[nion] * z; + xplasma->est.ioniz[nion] += kappa_ion[nion] * q; + xplasma->est.heat_ion[nion] += frac_ion[nion] * z; } for (n = 0; n < n_inner_tot; n++) { - xplasma->heat_inner_ion[inner_cross_ptr[n]->nion] += frac_inner_ion[n] * z; //This quantity is per ion - the ion number comes from the freq ordered cross section - xplasma->inner_ioniz[n] += kappa_inner_ion[n] * q; //This is the number of ionizations from this innershell cross section - at this point, inner_ioniz is ordered by frequency + xplasma->est.heat_inner_ion[inner_cross_ptr[n]->nion] += frac_inner_ion[n] * z; //This quantity is per ion - the ion number comes from the freq ordered cross section + xplasma->est.inner_ioniz[n] += kappa_inner_ion[n] * q; //This is the number of ionizations from this innershell cross section - at this point, inner_ioniz is ordered by frequency } } } @@ -551,19 +551,19 @@ kappa_ff (xplasma, freq) { if (nelements > 1) { - x = x1 = 3.692e8 * xplasma->ne * (xplasma->density[1] + 4. * xplasma->density[4]); + x = x1 = 3.692e8 * xplasma->state.ne * (xplasma->state.density[1] + 4. * xplasma->state.density[4]); } else { - x = x1 = 3.692e8 * xplasma->ne * (xplasma->density[1]); + x = x1 = 3.692e8 * xplasma->state.ne * (xplasma->state.density[1]); } } else { - x = x1 = xplasma->kappa_ff_factor; + x = x1 = xplasma->state.kappa_ff_factor; } - x *= x2 = (1. - exp (-H_OVER_K * freq / xplasma->t_e)); - x /= x3 = (sqrt (xplasma->t_e) * freq * freq * freq); + x *= x2 = (1. - exp (-H_OVER_K * freq / xplasma->state.t_e)); + x /= x3 = (sqrt (xplasma->state.t_e) * freq * freq * freq); x *= zdom[ndom].fill; @@ -679,14 +679,14 @@ den_config (xplasma, nconf) if (nnlev >= 0) { // Then a "non-lte" level with a density - density = xplasma->levden[nnlev] * xplasma->density[nion]; + density = xplasma->state.levden[nnlev] * xplasma->state.density[nion]; } else if (nconf == ion[nion].firstlevel) { /* Then we are using a Topbase photoionization x-section for this ion, but we are not storing any densities, and so we assume it is completely in the in the ground state */ - density = xplasma->density[nion]; + density = xplasma->state.density[nion]; } else { @@ -708,7 +708,7 @@ in the ground state */ * @return Always returns 0 * * @details - * The routine populates plasmamain[].kappa_ff_factor + * The routine populates plasmamain[].state.kappa_ff_factor * * The free-free multiplicative constant depends only * on the densities of ions in the cell, and the electron @@ -747,9 +747,9 @@ pop_kappa_ff_array () { if (ion[j].istate != 1) //The neutral ion does not contribute { - gsqrd = ((ion[j].istate - 1) * (ion[j].istate - 1) * RYD2ERGS) / (BOLTZMANN * plasmamain[i].t_e); + gsqrd = ((ion[j].istate - 1) * (ion[j].istate - 1) * RYD2ERGS) / (BOLTZMANN * plasmamain[i].state.t_e); gaunt = gaunt_ff (gsqrd); - sum += plasmamain[i].density[j] * (ion[j].istate - 1) * (ion[j].istate - 1) * gaunt; + sum += plasmamain[i].state.density[j] * (ion[j].istate - 1) * (ion[j].istate - 1) * gaunt; if (sane_check (sum)) { Error ("pop_kappa_ff_array:sane_check sum is %e this is a problem, possible in gaunt %e\n", sum, gaunt); @@ -761,7 +761,7 @@ pop_kappa_ff_array () } } - plasmamain[i].kappa_ff_factor = plasmamain[i].ne * sum * 3.692e8; + plasmamain[i].state.kappa_ff_factor = plasmamain[i].state.ne * sum * 3.692e8; } return (0); @@ -813,7 +813,7 @@ mean_intensity (xplasma, freq, mode) } else { - j_bar = mean_intensity_bb_estimate (freq, xplasma->t_r, xplasma->w); + j_bar = mean_intensity_bb_estimate (freq, xplasma->state.t_r, xplasma->state.w); } return j_bar; @@ -849,30 +849,30 @@ mean_intensity_from_models (PlasmaPtr xplasma, double freq, int mode) * cycles. */ - for (i = 0; i < xplasma->nbands; i++) + for (i = 0; i < xplasma->state.nbands; i++) { // Check that the band has the correct frequency range - if (xplasma->f1[i] < freq && freq <= xplasma->f2[i]) + if (xplasma->state.f1[i] < freq && freq <= xplasma->state.f2[i]) { // Check we have a model for this band - if (xplasma->spec_mod_type[i] > 0) + if (xplasma->state.spec_mod_type[i] > 0) { // Check the spectral model is defined for the frequency in question // todo: this seems redundant, but possibly can be important if the model // in question isn't complete due to photon statistics - if (freq > xplasma->fmin_mod[i] && freq < xplasma->fmax_mod[i]) + if (freq > xplasma->state.fmin_mod[i] && freq < xplasma->state.fmax_mod[i]) { - if (xplasma->spec_mod_type[i] == SPEC_MOD_PL) + if (xplasma->state.spec_mod_type[i] == SPEC_MOD_PL) { - j_bar = pow (10, (xplasma->pl_log_w[i] + log10 (freq) * xplasma->pl_alpha[i])); + j_bar = pow (10, (xplasma->state.pl_log_w[i] + log10 (freq) * xplasma->state.pl_alpha[i])); } - else if (xplasma->spec_mod_type[i] == SPEC_MOD_EXP) + else if (xplasma->state.spec_mod_type[i] == SPEC_MOD_EXP) { - j_bar = xplasma->exp_w[i] * exp ((-1 * PLANCK * freq) / (BOLTZMANN * xplasma->exp_temp[i])); + j_bar = xplasma->state.exp_w[i] * exp ((-1 * PLANCK * freq) / (BOLTZMANN * xplasma->state.exp_temp[i])); } else { - Error ("mean_intensity: unknown spectral model (%i) in band %i\n", xplasma->spec_mod_type[i], i); + Error ("mean_intensity: unknown spectral model (%i) in band %i\n", xplasma->state.spec_mod_type[i], i); j_bar = 0.0; } } @@ -905,7 +905,7 @@ mean_intensity_from_models (PlasmaPtr xplasma, double freq, int mode) if (mode == MEAN_INTENSITY_BB_MODEL) { - j_bar = mean_intensity_bb_estimate (freq, xplasma->t_r, xplasma->w); + j_bar = mean_intensity_bb_estimate (freq, xplasma->state.t_r, xplasma->state.w); } else { diff --git a/source/recomb.c b/source/recomb.c index 65919f06f..10d4397fe 100644 --- a/source/recomb.c +++ b/source/recomb.c @@ -466,8 +466,8 @@ total_fb (xplasma, t, f1, f2, fb_choice, mode) num_recomb (xplasma, t, mode); total = 0; - xplasma->cool_rr_metals = 0.0; - xplasma->lum_rr_metals = 0.0; + xplasma->derived.cool_rr_metals = 0.0; + xplasma->derived.lum_rr_metals = 0.0; /* * This loop is now over nions - 1, to avoid out of bounds access and above @@ -476,28 +476,28 @@ total_fb (xplasma, t, f1, f2, fb_choice, mode) for (nion = 0; nion < nions - 1; nion++) { - if (xplasma->density[nion] > DENSITY_PHOT_MIN) + if (xplasma->state.density[nion] > DENSITY_PHOT_MIN) { if (mode == OUTER_SHELL) { if (fb_choice == FB_FULL) // we are calculating a luminosity { - total += xplasma->lum_rr_ion[nion] = - xplasma->vol * xplasma->ne * xplasma->density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); + total += xplasma->derived.lum_rr_ion[nion] = + xplasma->state.vol * xplasma->state.ne * xplasma->state.density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); if (ion[nion].z > 2) - xplasma->lum_rr_metals += xplasma->lum_rr_ion[nion]; + xplasma->derived.lum_rr_metals += xplasma->derived.lum_rr_ion[nion]; } else // we are calculating a cooling rate { - total += xplasma->cool_rr_ion[nion] = - xplasma->vol * xplasma->ne * xplasma->density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); + total += xplasma->derived.cool_rr_ion[nion] = + xplasma->state.vol * xplasma->state.ne * xplasma->state.density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); if (ion[nion].z > 2) - xplasma->cool_rr_metals += xplasma->cool_rr_ion[nion]; + xplasma->derived.cool_rr_metals += xplasma->derived.cool_rr_ion[nion]; } } else if (mode == INNER_SHELL) // at present we do not compute a luminosity from DR - total += xplasma->cool_dr_ion[nion] = - xplasma->vol * xplasma->ne * xplasma->density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); + total += xplasma->derived.cool_dr_ion[nion] = + xplasma->state.vol * xplasma->state.ne * xplasma->state.density[nion + 1] * integ_fb (t, f1, f2, nion, fb_choice, mode); } } @@ -557,7 +557,7 @@ one_fb (xplasma, f1, f2) if (f2 < f1) { - Error ("one_fb: f2 %g < f1 %g Something is rotten t %g\n", f2, f1, xplasma->t_e); + Error ("one_fb: f2 %g < f1 %g Something is rotten t %g\n", f2, f1, xplasma->state.t_e); Exit (0); } @@ -565,7 +565,7 @@ one_fb (xplasma, f1, f2) and use that instead if possible */ - tt = xplasma->t_e; + tt = xplasma->state.t_e; if (xphot->n < NSTORE && xphot->f1 == f1 && xphot->f2 == f2 && xphot->t == tt) { freq = xphot->freq[xphot->n]; @@ -634,10 +634,10 @@ one_fb (xplasma, f1, f2) if (freq > fb_jumps[nn] && nn < fb_njumps) //The element we were going to make has a frequency abouve the jump { fb_x[nnn] = fb_jumps[nn] * (1. - DELTA_V / (2. * VLIGHT)); //We make one frequency point DELTA_V cm/s below the jump - fb_y[nnn] = fb (xplasma, xplasma->t_e, fb_x[nnn], nions, FB_FULL); //And the flux for that point + fb_y[nnn] = fb (xplasma, xplasma->state.t_e, fb_x[nnn], nions, FB_FULL); //And the flux for that point nnn = nnn + 1; //increase the index of the created array fb_x[nnn] = fb_jumps[nn] * (1. + DELTA_V / (2 * VLIGHT)); //And one frequency point just above the jump - fb_y[nnn] = fb (xplasma, xplasma->t_e, fb_x[nnn], nions, FB_FULL); //And the flux for that point + fb_y[nnn] = fb (xplasma, xplasma->state.t_e, fb_x[nnn], nions, FB_FULL); //And the flux for that point nn = nn + 1; //We heave dealt with this jump - on to the next one nnn = nnn + 1; //And we will be filling the next array element next time } @@ -646,7 +646,7 @@ one_fb (xplasma, f1, f2) if (freq > fb_x[nnn - 1]) //Deal with the unusual case where the upper point in our 'jump' pair is above the next regular point { fb_x[nnn] = freq; //Set the next array element frequency - fb_y[nnn] = fb (xplasma, xplasma->t_e, fb_x[nnn], nions, FB_FULL); //And the flux + fb_y[nnn] = fb (xplasma, xplasma->state.t_e, fb_x[nnn], nions, FB_FULL); //And the flux n = n + 1; //Increment the regular grid counter nnn = nnn + 1; //Increment the generated array counter } @@ -660,7 +660,7 @@ one_fb (xplasma, f1, f2) //Ensure the last point lines up exatly with f2 fb_x[nnn - 1] = f2; - fb_y[nnn - 1] = fb (xplasma, xplasma->t_e, f2, nions, FB_FULL); + fb_y[nnn - 1] = fb (xplasma, xplasma->state.t_e, f2, nions, FB_FULL); if (nnn > NCDF) @@ -676,11 +676,11 @@ one_fb (xplasma, f1, f2) if (cdf_gen_from_array (&cdf_fb, fb_x, fb_y, nnn, f1, f2) != 0) { Error ("one_fb after cdf_gen_from_array error: f1 %g f2 %g te %g ne %g nh %g vol %g\n", - f1, f2, xplasma->t_e, xplasma->ne, xplasma->density[1], xplasma->vol); + f1, f2, xplasma->state.t_e, xplasma->state.ne, xplasma->state.density[1], xplasma->state.vol); Error ("Giving up\n"); Exit (0); } - one_fb_te = xplasma->t_e; + one_fb_te = xplasma->state.t_e; one_fb_f1 = f1; one_fb_f2 = f2; /* Note that this may not be the best way to check for a previous cdf */ } @@ -724,7 +724,7 @@ one_fb (xplasma, f1, f2) * @param [in] double t_e The temperarture of interest * @param [in] int mode A switch indicating whether one wants normal radiative recombination (OUTER_SHELL) or * dielectronic recombination (INNER_SHELL) rates to be calculated. - * @return Always returns 0; the results are stored in xplasma->recomb or xplasma->inner_recomb, depending + * @return Always returns 0; the results are stored in xplasma->derived.recomb or xplasma->derived.inner_recomb, depending * on the mode * * @details @@ -755,17 +755,18 @@ num_recomb (xplasma, t_e, mode) imax = ele[nelem].lastion; for (i = imin; i < imax; i++) { - if (xplasma->density[i] > DENSITY_PHOT_MIN) + if (xplasma->state.density[i] > DENSITY_PHOT_MIN) { if (mode == OUTER_SHELL) //outer shell - xplasma->recomb[i] = xplasma->ne * xplasma->density[i + 1] * integ_fb (t_e, 0.0, VERY_BIG, i, FB_RATE, mode); + xplasma->derived.recomb[i] = xplasma->state.ne * xplasma->state.density[i + 1] * integ_fb (t_e, 0.0, VERY_BIG, i, FB_RATE, mode); else if (mode == INNER_SHELL) //innershell - xplasma->inner_recomb[i] = xplasma->ne * xplasma->density[i + 1] * integ_fb (t_e, 0.0, VERY_BIG, i, FB_RATE, mode); + xplasma->derived.inner_recomb[i] = + xplasma->state.ne * xplasma->state.density[i + 1] * integ_fb (t_e, 0.0, VERY_BIG, i, FB_RATE, mode); } } - xplasma->recomb[imax] = 0.0; // Can't recombine to highest i-state - xplasma->inner_recomb[imax] = 0.0; // Can't recombine to highest i-state + xplasma->derived.recomb[imax] = 0.0; // Can't recombine to highest i-state + xplasma->derived.inner_recomb[imax] = 0.0; // Can't recombine to highest i-state } @@ -888,10 +889,10 @@ fb (xplasma, t, freq, ion_choice, fb_choice) /* x is the emissivity from this ion. Add it to the total */ - fnu += xplasma->density[nion + 1] * x; // nion+1, the ion doing the recombining + fnu += xplasma->state.density[nion + 1] * x; // nion+1, the ion doing the recombining } - fnu *= xplasma->ne; /* Convert from specific emissivity to the total fb emissivity. */ + fnu *= xplasma->state.ne; /* Convert from specific emissivity to the total fb emissivity. */ return (fnu); @@ -1751,7 +1752,7 @@ matom_select_bf_freq (WindPtr one, int nconf) fb_xtop = &phot_top[nconf]; //set external pointer to the right bf process xplasma = &plasmamain[one->nplasma]; - te = xplasma->t_e; //electron temperature in cell + te = xplasma->state.t_e; //electron temperature in cell fbt = te; //set external temperature to the right value log_fbt = log (te); //set external temperature to the right value @@ -1810,7 +1811,7 @@ matom_select_bf_freq (WindPtr one, int nconf) if (cdf_gen_from_array (&cdf_fb, fb_x, fb_y, ARRAY_PDF, f1, f2) != 0) { - Error ("matom_select_bf_freq after cdf_gen_from_array: f1 %g f2 %g te %g \n", f1, f2, xplasma->t_e); + Error ("matom_select_bf_freq after cdf_gen_from_array: f1 %g f2 %g te %g \n", f1, f2, xplasma->state.t_e); Error ("matomc_selct_fb_freg: Printing inputs to macro_recomb.txt\n"); FILE *fptr; fptr = fopen ("macro_recomb.txt", "w"); diff --git a/source/resonate.c b/source/resonate.c index 67fbe0b20..74c1af02f 100644 --- a/source/resonate.c +++ b/source/resonate.c @@ -209,7 +209,7 @@ calculate_ds (w, p, tau_scat, tau, nres, smax, istat) * electron scattering is always treated as a scattering event. */ - kap_es = klein_nishina (mean_freq) * xplasma->ne * zdom[ndom].fill; + kap_es = klein_nishina (mean_freq) * xplasma->state.ne * zdom[ndom].fill; /* If in macro-atom mode, calculate the bf and ff opacities, because in * macro-atom mode everything including bf is calculated as a scattering @@ -498,7 +498,7 @@ select_continuum_scattering_process (kap_cont, kap_es, kap_ff, xplasma) ncont++; } /* When it gets here know that excitation is in photoionisation labelled by ncont */ - nres = NLINES + 1 + xplasma->kbf_use[ncont - 1]; //modified SS Nov 04 + nres = NLINES + 1 + xplasma->state.kbf_use[ncont - 1]; //modified SS Nov 04 } return (nres); } @@ -550,9 +550,9 @@ kappa_bf (xplasma, freq, macro_all) ndom = wmain[xplasma->nwind].ndom; - for (nn = 0; nn < xplasma->kbf_nuse; nn++) // Loop over photoionisation processes. + for (nn = 0; nn < xplasma->state.kbf_nuse; nn++) // Loop over photoionisation processes. { - n = xplasma->kbf_use[nn]; + n = xplasma->state.kbf_use[nn]; ft = phot_top[n].freq[0]; //This is the edge frequency (SS) kap_bf[nn] = 0.0; @@ -590,10 +590,10 @@ kappa_bf (xplasma, freq, macro_all) * ion is so low it will not contribute. * * For each cell, the routine determines what bf transitons are important - * and stores them in one->kbf_use[n]. + * and stores them in one->state.kbf_use[n]. * * The total number of such transitions - * is given in one->kbf_nuse. + * is given in one->state.kbf_nuse. * * @details * @@ -650,7 +650,7 @@ kbf_need (freq_min, freq_max) if (ion[nion].phot_info == 0) // vfky { - density = xplasma->density[nion]; + density = xplasma->state.density[nion]; } else { @@ -669,13 +669,13 @@ kbf_need (freq_min, freq_max) if (tau_test > 1.e-6 || phot_top[n].macro_info == TRUE || n == ion[nion].ntop_ground || ion[nion].phot_info == 0) { /* Store the bf transition and increment nuse */ - xplasma->kbf_use[nuse] = n; + xplasma->state.kbf_use[nuse] = n; nuse += 1; } } } - xplasma->kbf_nuse = nuse; + xplasma->state.kbf_nuse = nuse; } @@ -749,7 +749,7 @@ sobolev (one, x, den_ion, lptr, dvds) // macro atom case SS d1 = den_config (xplasma, lptr->nconfigl); d2 = den_config (xplasma, lptr->nconfigu); - levden_upper = xplasma->levden[xconfig[lptr->nconfigu].nden]; + levden_upper = xplasma->state.levden[xconfig[lptr->nconfigu].nden]; } else @@ -759,19 +759,19 @@ ion which was done above in calculate ds. It was made necessary by a change in calls to two_level atom */ - d_hold = xplasma->density[nion]; // Store the density of this ion in the cell + d_hold = xplasma->state.density[nion]; // Store the density of this ion in the cell if (den_ion < 0) { - xplasma->density[nion] = get_ion_density (ndom, x, lptr->nion); // Forced calculation of density + xplasma->state.density[nion] = get_ion_density (ndom, x, lptr->nion); // Forced calculation of density } else { - xplasma->density[nion] = den_ion; // Put den_ion into the density array + xplasma->state.density[nion] = den_ion; // Put den_ion into the density array } two_level_atom (lptr, xplasma, &d1, &d2); // Calculate d1 & d2 - xplasma->density[nion] = d_hold; // Restore w - levden_upper = d2 / xplasma->density[nion]; + xplasma->state.density[nion] = d_hold; // Restore w + levden_upper = d2 / xplasma->state.density[nion]; } /* At this point d1 and d2 are known for all of the various ways sobolev can be called, and whether @@ -1019,12 +1019,14 @@ scatter (p, nres, nnscat) /* Need to compute the factor needed for the stimulated term. */ - stim_fact = den_config (xplasma, ulvl) / den_config (xplasma, llvl) / xplasma->ne; + stim_fact = den_config (xplasma, ulvl) / den_config (xplasma, llvl) / xplasma->state.ne; gamma_twiddle = - mplasma->gamma_old[xconfig[llvl].bfu_indx_first + m] - (mplasma->alpha_st_old[xconfig[llvl].bfu_indx_first + m] * stim_fact); + mplasma->state.gamma_old[xconfig[llvl].bfu_indx_first + m] - + (mplasma->state.alpha_st_old[xconfig[llvl].bfu_indx_first + m] * stim_fact); gamma_twiddle_e = - mplasma->gamma_e_old[xconfig[llvl].bfu_indx_first + m] - (mplasma->alpha_st_e_old[xconfig[llvl].bfu_indx_first + m] * stim_fact); + mplasma->state.gamma_e_old[xconfig[llvl].bfu_indx_first + m] - + (mplasma->state.alpha_st_e_old[xconfig[llvl].bfu_indx_first + m] * stim_fact); /* Both gamma_twiddles must be greater that zero if this is going to work. If they are zero then it's probably because this is the first iteration and so the've not @@ -1091,7 +1093,7 @@ scatter (p, nres, nnscat) if (*nres - NLINES - 1 >= 0) { - xplasma->n_bf_in[*nres - NLINES - 1] += 1; + xplasma->derived.n_bf_in[*nres - NLINES - 1] += 1; // XXXXXXXXXXXXXXXXXX 117 had and inordinate @@ -1127,7 +1129,7 @@ scatter (p, nres, nnscat) to allow for the portion of the energy that went into the ionization pool before generating a kpkt. In this approach we always generate a kpkt */ - xplasma->bf_simple_ionpool_in += p->w * (1 - prob_kpkt); + xplasma->derived.bf_simple_ionpool_in += p->w * (1 - prob_kpkt); p->w *= prob_kpkt; macro_gov (p, nres, 2, &which_out); //routine to deal with kpkt @@ -1152,7 +1154,7 @@ scatter (p, nres, nnscat) if (*nres - NLINES - 1 >= 0) { - xplasma->n_bf_out[*nres - NLINES - 1] += 1; + xplasma->derived.n_bf_out[*nres - NLINES - 1] += 1; } } else @@ -1246,7 +1248,7 @@ if fixed. dp_cyl[2] *= (-1); for (i = 0; i < 3; i++) { - xplasma->dmo_dt[i] += dp_cyl[i]; + xplasma->derived.dmo_dt[i] += dp_cyl[i]; } } diff --git a/source/run.c b/source/run.c index c532b3fb0..acd2df05b 100644 --- a/source/run.c +++ b/source/run.c @@ -479,8 +479,8 @@ make_spectra (restart_stat) { for (n = 0; n < NPLASMA; n++) { - macromain[n].kpkt_rates_known = FALSE; - macromain[n].matrix_rates_known = FALSE; + macromain[n].derived.kpkt_rates_known = FALSE; + macromain[n].derived.matrix_rates_known = FALSE; } } diff --git a/source/saha.c b/source/saha.c index bd21d5c54..f20638ee3 100644 --- a/source/saha.c +++ b/source/saha.c @@ -161,15 +161,15 @@ concentrations (xplasma, mode) // if (mode == NEBULARMODE_TR) { - t = xplasma->t_r; + t = xplasma->state.t_r; } else if (mode == NEBULARMODE_TE) { - t = xplasma->t_e; + t = xplasma->state.t_e; } else if (mode == NEBULARMODE_ML93) { - t = sqrt (xplasma->t_e * xplasma->t_r); + t = sqrt (xplasma->state.t_e * xplasma->state.t_r); } else { @@ -178,7 +178,7 @@ concentrations (xplasma, mode) return (0); } - nh = xplasma->rho * rho2nh; + nh = xplasma->state.rho * rho2nh; /* make an initial estimate of ne based on H alone, Our guess assumes ion[0] is H1. Note that x below is the fractional @@ -241,12 +241,12 @@ concentrations (xplasma, mode) /*Set some floor so future divisions are sensible */ for (nion = 0; nion < nions; nion++) { - if (xplasma->density[nion] < DENSITY_MIN) - xplasma->density[nion] = DENSITY_MIN; + if (xplasma->state.density[nion] < DENSITY_MIN) + xplasma->state.density[nion] = DENSITY_MIN; } /* Now determine the new value of ne from the ion abundances */ - xnew = get_ne (xplasma->density); + xnew = get_ne (xplasma->state.density); if (xnew < DENSITY_MIN) xnew = DENSITY_MIN; @@ -265,7 +265,7 @@ concentrations (xplasma, mode) return (-1); } - xplasma->ne = xnew; + xplasma->state.ne = xnew; return (0); } @@ -313,10 +313,10 @@ saha (xplasma, ne, t) double sum, a, b; double big; - density = xplasma->density; - partition = xplasma->partition; + density = xplasma->state.density; + partition = xplasma->state.partition; - nh = xplasma->rho * rho2nh; //LTE + nh = xplasma->state.rho * rho2nh; //LTE xsaha = SAHA * pow (t, 1.5); for (nelem = 0; nelem < nelements; nelem++) @@ -434,21 +434,21 @@ lucy (xplasma) double t_r, nh; double t_e, www; - t_r = xplasma->t_r; - t_e = xplasma->t_e; - www = xplasma->w; + t_r = xplasma->state.t_r; + t_e = xplasma->state.t_e; + www = xplasma->state.w; /* Initally assume electron density from the LTE densities */ - xne = xplasma->ne; + xne = xplasma->state.ne; if (xne < DENSITY_MIN) { Error ("nebular_concentrations: Very low ionization: ne initially %8.2e\n", xne); xne = DENSITY_MIN; } - nh = xplasma->rho * rho2nh; //LTE -- Not clear needed at this level + nh = xplasma->state.rho * rho2nh; //LTE -- Not clear needed at this level /* Begin iteration loop to find ne */ niterate = 0; @@ -461,7 +461,7 @@ lucy (xplasma) which are contained in xplasma. These corrected abundances are copied to newden, which is transferred over to xplasma when we converge on ne */ - lucy_mazzali1 (nh, t_r, t_e, www, nelem, xplasma->ne, xplasma->density, xne, newden); + lucy_mazzali1 (nh, t_r, t_e, www, nelem, xplasma->state.ne, xplasma->state.density, xne, newden); } /* Re solve for the macro atom populations with the current guess for ne */ @@ -481,7 +481,7 @@ lucy (xplasma) /* if the ion is being treated by macro_pops then use the populations just computed */ if ((ion[nion].macro_info == TRUE) && (geo.macro_simple == FALSE) && (geo.macro_ioniz_mode == MACRO_IONIZ_MODE_ESTIMATORS)) { - newden[nion] = xplasma->density[nion]; + newden[nion] = xplasma->state.density[nion]; } /*Set some floor so future divisions are sensible */ @@ -510,13 +510,13 @@ lucy (xplasma) /* Finally transfer the calculated densities to the real density array */ - xplasma->ne = xnew; + xplasma->state.ne = xnew; for (nion = 0; nion < nions; nion++) { /* If statement added here to suppress interference with macro populations (SS Apr 04) */ if (ion[nion].macro_info == FALSE || geo.macro_ioniz_mode == MACRO_IONIZ_MODE_NO_ESTIMATORS || geo.macro_simple == TRUE) { - xplasma->density[nion] = newden[nion]; + xplasma->state.density[nion] = newden[nion]; } } return (0); @@ -738,7 +738,7 @@ fix_concentrations (xplasma, mode) double nh; - nh = xplasma->rho * rho2nh; + nh = xplasma->state.rho * rho2nh; /* Define the element and ion which will be present in the wind */ @@ -769,7 +769,7 @@ fix_concentrations (xplasma, mode) /* Set all the ion abundances to 0 and *ne to 0 */ for (nion = 0; nion < nions; nion++) - xplasma->density[nion] = 0; + xplasma->state.density[nion] = 0; /* Search for matches and if one is found set the density of that ion to be the density of that atom */ @@ -785,11 +785,11 @@ fix_concentrations (xplasma, mode) while (nelem < nelements && ele[nelem].z != con_force[n].z) nelem++; /* Increment the ion density and the electron density */ - xplasma->density[nion] = nh * ele[nelem].abun * con_force[n].frac; + xplasma->state.density[nion] = nh * ele[nelem].abun * con_force[n].frac; } } - xplasma->ne = get_ne (xplasma->density); + xplasma->state.ne = get_ne (xplasma->state.density); partition_functions (xplasma, NEBULARMODE_TR); diff --git a/source/setup_line_transfer.c b/source/setup_line_transfer.c index 47804477e..bd08a08bd 100644 --- a/source/setup_line_transfer.c +++ b/source/setup_line_transfer.c @@ -161,8 +161,8 @@ get_line_transfer_mode () { for (n = 0; n < NPLASMA; n++) { - macromain[n].store_matom_matrix = modes.store_matom_matrix; - macromain[n].matom_transition_mode = geo.matom_transition_mode; + macromain[n].state.store_matom_matrix = modes.store_matom_matrix; + macromain[n].state.matom_transition_mode = geo.matom_transition_mode; } } @@ -171,8 +171,8 @@ get_line_transfer_mode () { for (n = 0; n < NPLASMA; n++) { - macromain[n].store_matom_matrix = modes.store_matom_matrix = FALSE; - macromain[n].matom_transition_mode = geo.matom_transition_mode; + macromain[n].state.store_matom_matrix = modes.store_matom_matrix = FALSE; + macromain[n].state.matom_transition_mode = geo.matom_transition_mode; } } diff --git a/source/signal.c b/source/signal.c index af1e1194c..4fcb99a72 100644 --- a/source/signal.c +++ b/source/signal.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "log.h" #include "atomic.h" @@ -201,26 +202,13 @@ xsignal_rm (char *root) #endif char filename[LINELENGTH]; - char command[LINELENGTH]; - FILE *tmp_ptr; - /* Make the filemne */ + /* Make the filename */ strcpy (filename, ""); strcpy (filename, root); strcat (filename, ".sig"); - /* first check if the file exists */ - - if ((tmp_ptr = fopen (filename, "r")) == NULL) - { - return (0); - } - - - strcpy (command, "rm "); - strcat (command, filename); - - if (system (command) == -1) - Error ("xsignal_rm: '%s' returned error status\n", command); + if (remove (filename) != 0 && errno != ENOENT) + Error ("xsignal_rm: failed to remove '%s'\n", filename); #ifdef MPI_ON } diff --git a/source/sirocco.h b/source/sirocco.h index afe98c3aa..d87395aa9 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -869,252 +869,272 @@ extern WindPtr wmain; /*****************************PLASMA STRUCTURE**************************/ /** Plasma is a structure that contains information about the properties of the - * plasma in regions of the geometry that are actually included in the wind + * plasma in regions of the geometry that are actually included in the wind. + * + * The plasma struct is split into three sub-structures to document the + * communication pattern of each field and to prepare for future MPI-3 + * shared memory optimization: + * + * state - Read-only during photon transport. Set during initialization + * or wind update phase. Future: shared across ranks on a node. + * est - Estimators accumulated (+=) during photon transport. + * Reduced across MPI ranks after transport. Future: private per rank. + * derived - Computed from estimators during wind update phase. + * Broadcast to all ranks after computation. + * * Note that a number of the arrays are dynamically allocated. */ -typedef struct plasma +/* Constants used in plasma sub-structs (moved out of the struct body) */ +#define NFLUX_ANGLES 36 /**< The number of bins into which the directional flux is calculated */ +#define N_PHOT_PROC 500 +#define N_DMO_DT_DIRECTIONS 3 +#define NFORCE_DIRECTIONS 4 + +#define MEAN_INTENSITY_BB_MODEL 1 +#define MEAN_INTENSITY_ESTIMATOR_MODEL 2 + +#define CELL_CONVERGING 0 /* converging - temperature is oscillating and decreasing */ +#define CELL_NOT_CONVERGING 1 /* not converging (temperature is shooting off in one direction) */ +#define CONVERGENCE_CHECK_PASS 0 /* Cell has passed a convergence check */ +#define CONVERGENCE_CHECK_FAIL 1 /* Cell has failed a convergence check */ +#define CONVERGENCE_CHECK_OVER_TEMP 2 /* Cell has electron temperature is more than TMAX */ + +/** Enum for spectral model type per band (moved out of struct body) */ +enum spec_mod_type_enum { - int nwind; /**< A cross reference to the corresponding cell in the wind structure */ - int nplasma; /**< A self reference to this in the plasma structure */ + SPEC_MOD_PL = 1, + SPEC_MOD_EXP = 2, + SPEC_MOD_FAIL = -1 +}; + +/** + * plasma_state: fields that are read-only during photon transport. + * Set during initialization or wind update phase. + */ +typedef struct plasma_state +{ + /* Thermodynamic state */ double ne; /**< Electron density in the shell (CMF) */ double rho; /**< Density at the center of the cell. (CMF) For clumped models, this is rho of the clump */ double vol; /**< Volume of this cell in CMF frame (more specifically the volume that is filled with material which can differs from the valid volume of the cell due to clumping.) */ double xgamma; /**< 1./sqrt(1-beta**2) at center of cell */ + double t_r, t_r_old; /**< radiation temperature of cell */ + double t_e, t_e_old; /**< electron temperature of cell */ + double w; /**< The dilution factor of the wind */ + double kappa_ff_factor; /**< Multiplicative factor for calculating the FF heating for a photon. */ + + /* Ion/level populations (dynamically allocated) */ double *density; /**< The number density of a specific ion in the CMF. The order of the ions is the same as read in by the atomic data routines. */ double *partition; /**< The partition function for each ion. */ double *levden; /* The number density (occupation number?) of a specific level */ - double kappa_ff_factor; /**< Multiplicative factor for calculating the FF heating for a photon. */ - - + /* Bound-free process data (dynamically allocated) */ double *recomb_simple; /**< "alpha_e - alpha" (in Leon's notation) for b-f processes in simple atoms. */ double *recomb_simple_upweight; /* multiplicative factor to account for ratio of total to "cooling" energy for b-f processes in simple atoms. */ - -/* Beginning of macro information */ - double kpkt_emiss; /**< This is the luminosity produced due to the conversion k-packet -> r-packet in the cell - in the frequency range that is required for the final spectral synthesis. (SS) */ - - double kpkt_abs; /**< k-packet equivalent of matom_abs. (SS) */ - - /* kbf_use and kbf_nuse are set by the routine kbf_need, and they provide indices into the photoinization processes - * that are "significant" in a plasma cell, based on the density of a particular ion in a cell and the x-section - * at the photoinization edge. This process was introduced as a means to speed the program up by ignoring those - * bf processes that would contribute negligibly to the bf opacity - */ - int *kbf_use; /**< List of the indices of the photoionization processes to be used for kappa_bf. */ int kbf_nuse; /**< Total number of photoionization processes to be used for kappa_bf. (SS) */ -/* End of macro information */ - + /* Spectral model parameters (set during wind update) */ + int nbands; /* The number of spectral bands for this cell */ + double f1[NXBANDS + 1]; /* Spectral band boundaries for this cell */ + double f2[NXBANDS + 1]; /* Spectral band boundaries for this cell */ + enum spec_mod_type_enum spec_mod_type[NXBANDS]; /**< A switch to say which type of representation we are using for this band in this cell. + Negative means we have no useful representation, 0 means power law, 1 means exponential */ + double pl_alpha[NXBANDS]; /**< Computed spectral index for a power law spectrum representing this cell */ + double pl_log_w[NXBANDS]; /**< This is the log version of the power law weight. It is in an attempt to allow very large + values of alpha to work with the PL spectral model to avoide NAN problems. + The pl_w version can be deleted once testing is complete */ + double exp_temp[NXBANDS]; /**< The effective temperature of an exponential representation of the radiation field in a cell */ + double exp_w[NXBANDS]; /**< The prefactor of an exponential representation of the radiation field in a cell */ + double fmin_mod[NXBANDS]; /**< Minimum frequency of the band-limited model */ + double fmax_mod[NXBANDS]; /**< Maximum frequency of the band-limited model */ +} plasma_state; - double t_r, t_r_old; /**< radiation temperature of cell */ - double t_e, t_e_old; /**< electron temperature of cell */ - double dt_e, dt_e_old; /**< How much t_e changed in the previous iteration */ - double heat_tot, heat_tot_old; /**< heating from all sources */ - double abs_tot; +/** + * plasma_estimators: fields accumulated during photon transport. + * Reduced across MPI ranks via MPI_Allreduce after transport. + * In future shared-memory version, each rank has a private copy. + */ +typedef struct plasma_estimators +{ + /* Radiation field estimators */ + double j; /**< Mean (angle-averaged) total intensity */ + double j_direct, j_scatt; /**< Mean intensity due to direct and scattered photons */ + double ave_freq; /**< Intensity-averaged frequency */ + double max_freq; /**< Maximum frequency photon seen in this cell */ + double ip; /**< Ionization parameter (Cloudy definition) */ + double ip_direct, ip_scatt; /**< Ionization parameter due to direct and scattered photons */ + double mean_ds; /**< Mean photon path length in a cell */ + int n_ds; /**< Number of times a path length was added; needed to compute mean_ds */ + + /* Heating estimators */ + double heat_tot; /**< heating from all sources */ double heat_lines, heat_ff; double heat_comp; /**< The compton heating for the cell */ - double heat_ind_comp; /**< The induced compton heatingfor the cell */ - double heat_lines_macro, heat_photo_macro; /**< bb and bf heating due to macro atoms. Subset of heat_lines - and heat_photo. SS June 04. */ - double cool_lines_macro, cool_bf_macro; /**< bb and bf cooling due to macro atoms. Subset of heat_lines - and heat_photo. SS June 04. */ - double heat_photo, heat_z; /**< photoionization heating total and of metals */ + double heat_ind_comp; /**< The induced compton heating for the cell */ + double heat_photo, heat_z; /**< photoionization heating total and of metals */ double heat_auger; /**< photoionization heating due to inner shell ionizations */ double heat_ch_ex; - double abs_photo, abs_auger; /**< this is the energy absorbed from the photon due to these processes - different from - the heating rate because of the binding energy */ - double w; /**< The dilution factor of the wind */ + double heat_lines_macro, heat_photo_macro; /**< bb and bf heating due to macro atoms. Subset of heat_lines + and heat_photo. SS June 04. */ - int ntot; /**< Total number of photon passages */ + /* Cooling estimator */ + double cool_tot; /**< The total cooling in a cell */ + + /* Macro-atom heating (kpkt) */ + double kpkt_abs; /**< k-packet equivalent of matom_abs. (SS) */ - /* counters of the number of photon passages by origin */ + /* Banded estimators */ + double xj[NXBANDS]; /**< Frequency limited versions of j */ + double xave_freq[NXBANDS]; /**< Frequency limited versions of ave_freq */ + double xsd_freq[NXBANDS]; /**< The standard deviation of the frequency in the band */ + double fmin[NXBANDS]; /**< Minimum frequency photon observed in a band */ + double fmax[NXBANDS]; /**< Maximum frequency photon observed in a band */ + int nxtot[NXBANDS]; /**< The total number of photon passages in frequency bands */ + /* Photon passage counters */ + int ntot; /**< Total number of photon passages */ int ntot_star; int ntot_bl; int ntot_disk; int ntot_wind; int ntot_agn; - - - int nscat_es; /**< The number of electrons scatters in the cell */ - int nscat_res; /**< The number of resonant line scatters in the cell */ - int nscat_bf; /**< Number of bf scatters in the cell. (macro_only) */ - int nscat_ff; /**< Number of ff scatters in the cell. (macro_only) */ - - double mean_ds; /**< Mean photon path length in a cell. */ - int n_ds; /**< Number of times a path lengyh was added; needed to compute mean_ds */ - int nrad; /**< Total number of photons created within the cell */ int nioniz; /**< Total number of photon passages by photons capable of ionizing H */ - double *ioniz, *recomb; /**< Number of ionizations and recombinations for each ion. - The sense is ionization from ion[n], and recombinations - to each ion[n]. */ - double *inner_ioniz, *inner_recomb; - int *scatters; /**< The number of scatters in this cell for each ion. */ - double *xscatters; /**< Diagnostic measure of energy scattered out of beam on extract. */ - double *heat_ion; /**< The amount of energy being transferred to the electron pool - by this ion via photoionization. */ - double *heat_inner_ion; /**< The amount of energy being transferred to the electron pool - by this ion via photoionization. */ - double *cool_rr_ion; /**< The amount of energy being released from the electron pool - by this ion via recombination. */ - double *lum_rr_ion; /**< The recombination luminosity - by this ion via recombination. */ + /* Radiation force estimators */ + double rad_force_es[NFORCE_DIRECTIONS]; /**< Radiative force - electron scattering */ + double rad_force_bf[NFORCE_DIRECTIONS]; /**< Radiative force - bound-free */ + double rad_force_ff[NFORCE_DIRECTIONS]; /**< Radiative force - free-free */ -#define MEAN_INTENSITY_BB_MODEL 1 -#define MEAN_INTENSITY_ESTIMATOR_MODEL 2 - - double *cool_dr_ion; - double j, ave_freq; /**< Mean (angle-averaged) total intensity, intensity-averaged frequency */ - - /* Information related to spectral bands used for modelling */ - - double cell_spec_flux[NBINS_IN_CELL_SPEC]; /**< The array where the cell spectra are accumulated. */ - - /* ksl - for now this parallels the xband structure, but it is a bit unclear why two frequencies are needed */ - int nbands; /* The number of spectral bands for this cell */ - double f1[NXBANDS+1]; /*Spectral band boundaries for this cell */ - double f2[NXBANDS+1]; /*Spectral band boundaries for this cell */ - - /* The next section contains the results of chaacterizing the cell spectra, see spectral_estimators to see how this is used */ - - double xj[NXBANDS], xave_freq[NXBANDS]; /**< Frequency limited versions of j and ave_freq */ - double fmin[NXBANDS], fmax[NXBANDS]; /**< Minimum (Maximum) frequency photon observed in a band - - * this is incremented during photon flight */ - double fmin_mod[NXBANDS], fmax_mod[NXBANDS]; /**< Minimum (Maximum) frequency of the band-limited model - * after allowing possibility that the observed limit, - * is primarily due to photon statistics. */ - double xsd_freq[NXBANDS]; /**< The standard deviation of the frequency in the band */ - int nxtot[NXBANDS]; /**< The total number of photon passages in frequency bands */ - - enum spec_mod_type_enum - { - SPEC_MOD_PL = 1, - SPEC_MOD_EXP = 2, - SPEC_MOD_FAIL = -1 - } spec_mod_type[NXBANDS]; /**< A switch to say which type of representation we are using for this band in this cell. - Negative means we have no useful representation, 0 means power law, 1 means exponential */ - - double pl_alpha[NXBANDS]; /**< Computed spectral index for a power law spectrum representing this cell */ - double pl_log_w[NXBANDS]; /**< This is the log version of the power law weight. It is in an attempt to allow very large - values of alpha to work with the PL spectral model to avoide NAN problems. - The pl_w version can be deleted once testing is complete */ - - - double exp_temp[NXBANDS]; /**< The effective temperature of an exponential representation of the radiation field in a cell */ - double exp_w[NXBANDS]; /**< The prefactor of an exponential representation of the radiation field in a cell */ - - -#define NFLUX_ANGLES 36 /**< The number of bins into which the directional flux is calculated */ - - - /*Binned fluxes */ + /* Flux estimators */ + double F_vis[NFORCE_DIRECTIONS]; + double F_UV[NFORCE_DIRECTIONS]; + double F_Xray[NFORCE_DIRECTIONS]; double F_UV_ang_theta[NFLUX_ANGLES]; double F_UV_ang_phi[NFLUX_ANGLES]; double F_UV_ang_r[NFLUX_ANGLES]; + /* Cell spectrum (accumulated during ionization cycles) */ + double cell_spec_flux[NBINS_IN_CELL_SPEC]; /**< The array where the cell spectra are accumulated. */ - /*A version of the binned flux that is averaged over cycles */ - double F_UV_ang_theta_persist[NFLUX_ANGLES]; - double F_UV_ang_phi_persist[NFLUX_ANGLES]; - double F_UV_ang_r_persist[NFLUX_ANGLES]; + /* Ionization estimators (dynamically allocated) */ + double *ioniz; /**< Number of ionizations for each ion */ + double *inner_ioniz; + double *heat_ion; /**< The amount of energy being transferred to the electron pool + by this ion via photoionization. */ + double *heat_inner_ion; /**< The amount of energy being transferred to the electron pool + by this ion via inner shell photoionization. */ +} plasma_estimators; - /* The term direct here means from photons which have not been scattered. These are photons which have been - created by the central object, or the disk, or in the simple case the wind, but which have not undergone - any kind of interaction which would change their direction - */ - double j_direct, j_scatt; /**< Mean intensity due to direct photons and scattered photons. - Direct photons include photons created in the wind in simple mode. */ - double ip_direct, ip_scatt; /**< Ionization parameter due to direct photons and scattered photons. See ip */ - double max_freq; /**< The maximum frequency photon seen in this cell */ - double cool_tot; /**< The total cooling in a cell */ - /* The total luminosity of all processes in the cell, basically the emissivity of the cell times it volume. Not the same - as what escapes the cell, since photons can interact within the cell and lose weight or even be destroyed */ - double lum_lines, lum_ff, cool_adiabatic; +/** + * plasma_derived: fields computed from estimators during wind update phase. + * Broadcast to all ranks after computation. + */ +typedef struct plasma_derived +{ + /* Cooling rates (computed from estimators) */ + double cool_comp; /**< The compton cooling of the cell */ + double cool_di; /**< The direct ionization cooling */ + double cool_dr; /**< The dielectronic recombination cooling */ + double cool_adiabatic; + double cool_rr, cool_rr_metals; /**< fb cooling & fb of metals */ + double cool_lines_macro, cool_bf_macro; /**< bb and bf cooling due to macro atoms */ + + /* Luminosities */ + double lum_lines, lum_ff; double lum_rr, lum_rr_metals; /**< the radiative recombination luminosity - not the same as the cooling rate */ - double cool_comp; /**< The compton luminosity of the cell */ - double cool_di; /**< The direct ionization luminosity */ - double cool_dr; /**< The dielectronic recombination luminosity of the cell */ - double cool_rr, cool_rr_metals; /**< fb luminosity & fb of metals metals */ - double lum_tot, lum_tot_old; /**< The specific radiative luminosity in frequencies defined by freqmin - and freqmax. This will depend on the last call to total_emission */ + double lum_tot, lum_tot_old; /**< The specific radiative luminosity */ + + /* Ionization-band luminosities/cooling */ double cool_tot_ioniz; double lum_lines_ioniz, lum_ff_ioniz, cool_adiabatic_ioniz; double lum_rr_ioniz; - double cool_comp_ioniz; /**< The compton luminosity of the cell */ - double cool_di_ioniz; /**< The direct ionization luminosity */ - double cool_dr_ioniz; /**< The dielectronic recombination luminosity of the cell */ - double cool_rr_ioniz, cool_rr_metals_ioniz; /**< fb luminosity & fb of metals metals */ - double lum_tot_ioniz; /**< The specfic radiative luminosity in frequencies defined by freqmin - and freqmax. This will depend on the last call to total_emission */ - double heat_shock; /**< An extra heating term added to allow for shock heating of the plasma (Implementef for FU Ori Project */ - - double bf_simple_ionpool_in, bf_simple_ionpool_out; /** r-packet conversion (SS) */ -#define CELL_CONVERGING 0 /* converging - temperature is oscillating and decreasing */ -#define CELL_NOT_CONVERGING 1 /* not converging (temperature is shooting off in one direction) */ -#define CONVERGENCE_CHECK_PASS 0 /* Cell has passed a convergence check */ -#define CONVERGENCE_CHECK_FAIL 1 /* Cell has failed a convergence check */ -#define CONVERGENCE_CHECK_OVER_TEMP 2 /* Cell has electron temperature is more than TMAX */ + /* Scatter counters */ + int nscat_es; /**< The number of electron scatters in the cell */ + int nscat_res; /**< The number of resonant line scatters in the cell */ + int nscat_bf; /**< Number of bf scatters in the cell. (macro_only) */ + int nscat_ff; /**< Number of ff scatters in the cell. (macro_only) */ + int nrad; /**< Total number of photons created within the cell */ + + /* Ionization parameter (final merged value) */ + double xi; /**< Ionization parameter as defined by Tarter, Tucker, and Salpeter 1969 */ +} plasma_derived; - double ip; /**< Ionization parameter calculated as number of photons over the lyman limit entering a cell, - divided by the number density of hydrogen for the cell. This is the definnition used in Cloudy */ - double xi; /**< Ionization parameter as defined by Tarter, Tucker, and Salpeter 1969 (ApJ 156, 943). - It is the ionizing flux over the number of hydrogen atoms */ +/** + * The top-level plasma structure, containing cross-references and three + * sub-structures that categorize fields by their communication pattern. + */ +typedef struct plasma +{ + int nwind; /**< A cross reference to the corresponding cell in the wind structure */ + int nplasma; /**< A self reference to this in the plasma structure */ + struct plasma_state state; /**< Read-only during transport; shared in future */ + struct plasma_estimators est; /**< Accumulated during transport; private per rank */ + struct plasma_derived derived; /**< Computed during wind updates; broadcast */ } plasma_dummy, *PlasmaPtr; extern PlasmaPtr plasmamain; @@ -1150,69 +1170,82 @@ extern MatomPhotStorePtr matomphotstoremain; /*******************************MACRO STRUCTURE*****************************/ /** - The stucture used for storing infomration for macro atoms + The structure used for storing information for macro atoms. - The various arrays created here are organized sequentially by macro level - and so the number of elements in each is the number of macro levels. -*/ -typedef struct macro -{ - double *jbar; /**< This will store the Sobolev mean intensity in transitions which is needed - for Macro Atom jumping probabilities. The indexing is by configuration (the - NLTE_LEVELS) and then by the upward bound-bound jumps from that level - (the NBBJUMPS) (SS) */ + Split into three sub-structures following the same pattern as plasma: + state - Normalized rate coefficients, read-only during transport + est - Raw estimators accumulated during transport, reduced via MPI + derived - Quantities computed during wind updates, broadcast - double *jbar_old; /**rho; + density = c_plasma_cell->state.rho; } else { - density = c_plasma_cell->density[COLUMN_MODE_ION_NUMBER]; + density = c_plasma_cell->state.density[COLUMN_MODE_ION_NUMBER]; } smax = smax_in_cell (photon) * SMAX_FRAC; @@ -146,7 +146,7 @@ integrate_tau_across_cell (PhotPtr photon, double *c_column_density, double *c_o if (RUN_MODE != RUN_MODE_NO_ES_OPACITY) { - kappa_total += klein_nishina (mean_freq) * c_plasma_cell->ne * zdom[n_domain].fill; + kappa_total += klein_nishina (mean_freq) * c_plasma_cell->state.ne * zdom[n_domain].fill; } /* diff --git a/source/spectral_estimators.c b/source/spectral_estimators.c index 7aebe0f0f..a7f7e719f 100644 --- a/source/spectral_estimators.c +++ b/source/spectral_estimators.c @@ -103,14 +103,15 @@ spectral_estimators (xplasma) { Log_silent ("Starting out band %i in cell %i. mean=%e, sd=%e, minfreq=%e, maxfreq=%e, nphot=%i\n", - n, xplasma->nplasma, xplasma->xave_freq[n], xplasma->xsd_freq[n], xplasma->fmin[n], xplasma->fmax[n], xplasma->nxtot[n]); + n, xplasma->nplasma, xplasma->est.xave_freq[n], xplasma->est.xsd_freq[n], xplasma->est.fmin[n], xplasma->est.fmax[n], + xplasma->est.nxtot[n]); plflag = expflag = 1; //Both potential models are in the running - if (xplasma->nxtot[n] <= 1) /* Catch the situation where there are only 1 or 0 photons in a band - - we cannot reasonably try to model this situation */ + if (xplasma->est.nxtot[n] <= 1) /* Catch the situation where there are only 1 or 0 photons in a band - + we cannot reasonably try to model this situation */ { - if (xplasma->f1[n] >= genmax || xplasma->f2[n] <= genmin) + if (xplasma->state.f1[n] >= genmax || xplasma->state.f2[n] <= genmin) { /* The band is outside where photons were generated, so not very surprising that there are no photons - just generate a log */ @@ -125,26 +126,26 @@ spectral_estimators (xplasma) /* We also want to make sure that the weight will be zero, this way we make sure there is no contribution to the ionization balance from this frequency. */ - xplasma->pl_log_w[n] = -999; //A very tiny weight - xplasma->pl_alpha[n] = 999.9; //Give alpha a value that will show up as an error - xplasma->exp_w[n] = 0.0; //Make sure that w is zero, so no chance of mucking up ionization balance even if for some reason we end up integrating - xplasma->exp_temp[n] = 1e99; //Give the effective temperature a value that will show up as an error - xplasma->spec_mod_type[n] = SPEC_MOD_FAIL; //This tells the code that we have failed to model the spectrum in this band/cell/ + xplasma->state.pl_log_w[n] = -999; //A very tiny weight + xplasma->state.pl_alpha[n] = 999.9; //Give alpha a value that will show up as an error + xplasma->state.exp_w[n] = 0.0; //Make sure that w is zero, so no chance of mucking up ionization balance even if for some reason we end up integrating + xplasma->state.exp_temp[n] = 1e99; //Give the effective temperature a value that will show up as an error + xplasma->state.spec_mod_type[n] = SPEC_MOD_FAIL; //This tells the code that we have failed to model the spectrum in this band/cell/ } /* If all the photons in the cell are concentrated in a tiny range then we will also not expect to make a sensible model - this check could be reviewed later if lots of warning are produced */ - else if (xplasma->fmax[n] == xplasma->fmin[n]) + else if (xplasma->est.fmax[n] == xplasma->est.fmin[n]) { Error ("spectral_estimators: multiple photons but only one frequency seen in %d band %d\n", xplasma->nplasma, n); /* Flag as a warning, so one can see if it is an issue */ - xplasma->pl_log_w[n] = -999; //A very tiny weight - xplasma->pl_alpha[n] = 999.9; //Give alpha a value that will show up as an error - xplasma->exp_w[n] = 0.0; //Make sure that w is zero, s no chance of mucking up ionization balance - xplasma->exp_temp[n] = 1e99; //Give temp a value that will show up as an error - xplasma->spec_mod_type[n] = SPEC_MOD_FAIL; //This tells the code that we have failed to model the spectrum in this band/cell/ + xplasma->state.pl_log_w[n] = -999; //A very tiny weight + xplasma->state.pl_alpha[n] = 999.9; //Give alpha a value that will show up as an error + xplasma->state.exp_w[n] = 0.0; //Make sure that w is zero, s no chance of mucking up ionization balance + xplasma->state.exp_temp[n] = 1e99; //Give temp a value that will show up as an error + xplasma->state.spec_mod_type[n] = SPEC_MOD_FAIL; //This tells the code that we have failed to model the spectrum in this band/cell/ } @@ -158,30 +159,30 @@ spectral_estimators (xplasma) end of the band is 'surprisingly' empty then we wasume this is because absolutely no photons are here - its probably an edge so we should modify the model bands. */ - dfreq = (xplasma->f2[n] - xplasma->f1[n]) / sqrt (xplasma->nxtot[n]); //This is a measure of the spacing between photons on average - if ((xplasma->fmin[n] - xplasma->f1[n]) < dfreq) //If true, this check suggests that there are no edges + dfreq = (xplasma->state.f2[n] - xplasma->state.f1[n]) / sqrt (xplasma->est.nxtot[n]); //This is a measure of the spacing between photons on average + if ((xplasma->est.fmin[n] - xplasma->state.f1[n]) < dfreq) //If true, this check suggests that there are no edges { - spec_numin = xplasma->f1[n]; //Use the photon generation band edge to set the lower frequency band for the model + spec_numin = xplasma->state.f1[n]; //Use the photon generation band edge to set the lower frequency band for the model } else { - spec_numin = xplasma->fmin[n]; //There may be an edge, use the lowest observed photon frequency for the lower nu band in the model + spec_numin = xplasma->est.fmin[n]; //There may be an edge, use the lowest observed photon frequency for the lower nu band in the model } - if ((xplasma->f2[n] - xplasma->fmax[n]) < dfreq) //Repeat above but for upper band edge + if ((xplasma->state.f2[n] - xplasma->est.fmax[n]) < dfreq) //Repeat above but for upper band edge { - spec_numax = xplasma->f2[n]; + spec_numax = xplasma->state.f2[n]; } else { - spec_numax = xplasma->fmax[n]; + spec_numax = xplasma->est.fmax[n]; } - xplasma->fmin_mod[n] = spec_numin; //This is the low frequency limit of any model we might make - xplasma->fmax_mod[n] = spec_numax; //This is the high frequency limit of any model we might make + xplasma->state.fmin_mod[n] = spec_numin; //This is the low frequency limit of any model we might make + xplasma->state.fmax_mod[n] = spec_numax; //This is the high frequency limit of any model we might make lspec_numax = log10 (spec_numax); lspec_numin = log10 (spec_numin); - spec_numean = xplasma->xave_freq[n]; - j = xplasma->xj[n]; + spec_numean = xplasma->est.xave_freq[n]; + j = xplasma->est.xj[n]; /* Try to find the exponent of a power law model that fits the cell spectrum */ @@ -198,8 +199,8 @@ spectral_estimators (xplasma) { Error ("spectral_estimators: Alpha cannot be bracketed (%e %e)in band %i cell %i- setting w to zero\n", pl_alpha_min, pl_alpha_max, n, xplasma->nplasma); - xplasma->pl_log_w[n] = -999.0; - xplasma->pl_alpha[n] = -999.0; //Set this to a value that might let us diagnose the problem + xplasma->state.pl_log_w[n] = -999.0; + xplasma->state.pl_alpha[n] = -999.0; //Set this to a value that might let us diagnose the problem plflag = -1; //Discount a PL model } @@ -222,13 +223,13 @@ spectral_estimators (xplasma) pl_w_temp); plflag = -1; // Dont use this model - xplasma->pl_log_w[n] = -999.0; - xplasma->pl_alpha[n] = -999.0; + xplasma->state.pl_log_w[n] = -999.0; + xplasma->state.pl_alpha[n] = -999.0; } else //All is well, assign model parameters to the plasma structure - we still need to work out if this is the *best* model { - xplasma->pl_alpha[n] = pl_alpha_temp; - xplasma->pl_log_w[n] = pl_w_temp; + xplasma->state.pl_alpha[n] = pl_alpha_temp; + xplasma->state.pl_log_w[n] = pl_w_temp; } } @@ -256,8 +257,8 @@ spectral_estimators (xplasma) { Error ("spectral_estimators: Exponential temperature cannot be bracketed (%e %e) in band %i - setting w to zero\n", exp_temp_min, exp_temp_max, n); - xplasma->exp_w[n] = 0.0; - xplasma->exp_temp[n] = -1e99; + xplasma->state.exp_w[n] = 0.0; + xplasma->state.exp_temp[n] = -1e99; expflag = -1; //Discount an exponential model } @@ -288,62 +289,62 @@ spectral_estimators (xplasma) Error ("spectral_estimators: New exponential parameters (%e) unreasonable, using existing parameters. Check number of photons in this cell\n", exp_w_temp); //NSH 131108 - now a warning, this should no longer happen expflag = -1; //discount an exponential model - xplasma->exp_w[n] = 0.0; - xplasma->exp_temp[n] = -1e99; + xplasma->state.exp_w[n] = 0.0; + xplasma->state.exp_temp[n] = -1e99; } else //We have a reasonable exponential function model { - xplasma->exp_temp[n] = exp_temp_temp; - xplasma->exp_w[n] = exp_w_temp; + xplasma->state.exp_temp[n] = exp_temp_temp; + xplasma->state.exp_w[n] = exp_w_temp; } } /* compute standard deviations for exponential and power law models - these will be used to check the models */ - exp_sd = exp_stddev (xplasma->exp_temp[n], spec_numin, spec_numax); + exp_sd = exp_stddev (xplasma->state.exp_temp[n], spec_numin, spec_numax); - pl_sd = pl_log_stddev (xplasma->pl_alpha[n], lspec_numin, lspec_numax); + pl_sd = pl_log_stddev (xplasma->state.pl_alpha[n], lspec_numin, lspec_numax); Log_silent ("NSH in this cell %i band %i PL estimators are log(w)=%10.2e, alpha=%5.3f giving sd=%e compared to %e\n", - xplasma->nplasma, n, xplasma->pl_log_w[n], xplasma->pl_alpha[n], pl_sd, xplasma->xsd_freq[n]); + xplasma->nplasma, n, xplasma->state.pl_log_w[n], xplasma->state.pl_alpha[n], pl_sd, xplasma->est.xsd_freq[n]); Log_silent ("NSH in this cell %i band %i exp estimators are w=%10.2e, temp=%10.2e giving sd=%e compared to %e\n", - xplasma->nplasma, n, xplasma->exp_w[n], xplasma->exp_temp[n], exp_sd, xplasma->xsd_freq[n]); + xplasma->nplasma, n, xplasma->state.exp_w[n], xplasma->state.exp_temp[n], exp_sd, xplasma->est.xsd_freq[n]); /*Compute the fractionasl errors in standard dev */ - exp_sd = fabs ((exp_sd - xplasma->xsd_freq[n]) / xplasma->xsd_freq[n]); - pl_sd = fabs ((pl_sd - xplasma->xsd_freq[n]) / xplasma->xsd_freq[n]); + exp_sd = fabs ((exp_sd - xplasma->est.xsd_freq[n]) / xplasma->est.xsd_freq[n]); + pl_sd = fabs ((pl_sd - xplasma->est.xsd_freq[n]) / xplasma->est.xsd_freq[n]); /* These commands decide upon the best model, based upon how well the models predict the standard deviation */ if (expflag > 0 && plflag > 0) //Both models are in the running - see which has the lowest error in stdev { if (exp_sd < pl_sd) - xplasma->spec_mod_type[n] = SPEC_MOD_EXP; + xplasma->state.spec_mod_type[n] = SPEC_MOD_EXP; else - xplasma->spec_mod_type[n] = SPEC_MOD_PL; + xplasma->state.spec_mod_type[n] = SPEC_MOD_PL; } else if (plflag > 0) //Only PL model in running, no point in testing for STDEV { - xplasma->spec_mod_type[n] = SPEC_MOD_PL; + xplasma->state.spec_mod_type[n] = SPEC_MOD_PL; } else if (expflag > 0) //Only EXP model in running, no point in testing for STDEV { - xplasma->spec_mod_type[n] = SPEC_MOD_EXP; + xplasma->state.spec_mod_type[n] = SPEC_MOD_EXP; } else { - xplasma->spec_mod_type[n] = SPEC_MOD_FAIL; //Oh dear, there is no suitable model - this should be an error + xplasma->state.spec_mod_type[n] = SPEC_MOD_FAIL; //Oh dear, there is no suitable model - this should be an error Error ("No suitable model in band %i cell %i (nphot=%i fmin=%e fmax=%e)\n", - n, xplasma->nplasma, xplasma->nxtot[n], xplasma->fmin[n], xplasma->fmax[n]); + n, xplasma->nplasma, xplasma->est.nxtot[n], xplasma->est.fmin[n], xplasma->est.fmax[n]); /* We will set the applicable frequency bands for the model to values that will cause errors if the model is used */ - xplasma->fmin_mod[n] = spec_numax; - xplasma->fmax_mod[n] = spec_numin; + xplasma->state.fmin_mod[n] = spec_numax; + xplasma->state.fmax_mod[n] = spec_numin; } } //End of loop that does things if there are more than zero photons in the band. diff --git a/source/swind_ion.c b/source/swind_ion.c index 477608722..0a78b8382 100644 --- a/source/swind_ion.c +++ b/source/swind_ion.c @@ -90,24 +90,24 @@ ion_summary (w, element, istate, iswitch, rootname, ochoice) if (iswitch == 0) { sprintf (name, "Element %d (%s) ion %d fractions\n", element, ele[nelem].name, istate); - aaa[n] = plasmamain[nplasma].density[nion]; - nh = rho2nh * plasmamain[nplasma].rho; + aaa[n] = plasmamain[nplasma].state.density[nion]; + nh = rho2nh * plasmamain[nplasma].state.rho; aaa[n] /= (nh * ele[nelem].abun); } else if (iswitch == 1) { sprintf (name, "Element %d (%s) ion %d density\n", element, ele[nelem].name, istate); - aaa[n] = plasmamain[nplasma].density[nion]; + aaa[n] = plasmamain[nplasma].state.density[nion]; } else if (iswitch == 2) { sprintf (name, "Element %d (%s) ion %d #scatters\n", element, ele[nelem].name, istate); - aaa[n] = plasmamain[nplasma].scatters[nion]; + aaa[n] = plasmamain[nplasma].derived.scatters[nion]; } else if (iswitch == 3) { sprintf (name, "Element %d (%s) ion %d scattered flux\n", element, ele[nelem].name, istate); - aaa[n] = plasmamain[nplasma].xscatters[nion]; + aaa[n] = plasmamain[nplasma].derived.xscatters[nion]; } else { @@ -131,19 +131,19 @@ ion_summary (w, element, istate, iswitch, rootname, ochoice) if (w[n].inwind >= 0) { if (iswitch == 0) - x /= ((plasmamain[nplasma].density[0] + plasmamain[nplasma].density[1]) * ele[nelem].abun); + x /= ((plasmamain[nplasma].state.density[0] + plasmamain[nplasma].state.density[1]) * ele[nelem].abun); else if (iswitch == 1) { - x = plasmamain[nplasma].density[nion]; + x = plasmamain[nplasma].state.density[nion]; x = log10 (x); } else if (iswitch == 2) { - x = plasmamain[nplasma].scatters[nion]; + x = plasmamain[nplasma].derived.scatters[nion]; } else if (iswitch == 3) { - x = plasmamain[nplasma].xscatters[nion]; + x = plasmamain[nplasma].derived.xscatters[nion]; } else { @@ -248,7 +248,7 @@ tau_ave_summary (w, element, istate, freq, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = PI_E2_OVER_M * plasmamain[nplasma].density[nion] / freq / w[n].dvds_ave; + aaa[n] = PI_E2_OVER_M * plasmamain[nplasma].state.density[nion] / freq / w[n].dvds_ave; } } @@ -262,7 +262,7 @@ tau_ave_summary (w, element, istate, freq, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - w[n].x[1] = plasmamain[nplasma].density[nion] / (0.87 * plasmamain[nplasma].ne * ele[nelem].abun); + w[n].x[1] = plasmamain[nplasma].state.density[nion] / (0.87 * plasmamain[nplasma].state.ne * ele[nelem].abun); } else w[n].x[1] = 0; @@ -497,10 +497,10 @@ line_summary (w, rootname, ochoice) { /* the below code is essentially duplicated from lum_lines() in lines.c, see #643 */ x = lin_ptr[nline]->gu / lin_ptr[nline]->gl * d1 - d2; - z = exp (-H_OVER_K * lin_ptr[nline]->freq / plasmamain[nplasma].t_e); + z = exp (-H_OVER_K * lin_ptr[nline]->freq / plasmamain[nplasma].state.t_e); q = 1. - scattering_fraction (lin_ptr[nline], &plasmamain[nplasma]); x *= q * a21 (lin_ptr[nline]) * z / (1. - z); - x *= PLANCK * lin_ptr[nline]->freq * plasmamain[nplasma].vol; + x *= PLANCK * lin_ptr[nline]->freq * plasmamain[nplasma].state.vol; /* Include effects of line trapping */ if (geo.line_mode == LINE_MODE_ESC_PROB) @@ -527,9 +527,9 @@ line_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - omega = 5.13 * pow (plasmamain[nplasma].t_e / 1.e5, 0.18); - rb = 8.629e-6 * exp (-energy / (BOLTZMANN * plasmamain[nplasma].t_e)) / sqrt (plasmamain[nplasma].t_e) * omega; - w[n].x[1] = plasmamain[nplasma].density[nion] * plasmamain[nplasma].ne * rb * energy * w[n].vol; + omega = 5.13 * pow (plasmamain[nplasma].state.t_e / 1.e5, 0.18); + rb = 8.629e-6 * exp (-energy / (BOLTZMANN * plasmamain[nplasma].state.t_e)) / sqrt (plasmamain[nplasma].state.t_e) * omega; + w[n].x[1] = plasmamain[nplasma].state.density[nion] * plasmamain[nplasma].state.ne * rb * energy * w[n].vol; } else w[n].x[1] = 0; @@ -642,9 +642,9 @@ modify_te (w, rootname, ochoice) { nplasma = w[n].nplasma; aaa[n] = 0; - if (w[n].inwind >= 0 && (x = plasmamain[nplasma].heat_tot) > 1.0) + if (w[n].inwind >= 0 && (x = plasmamain[nplasma].est.heat_tot) > 1.0) { - aaa[n] = t_e = calc_te (&plasmamain[nplasma], MIN_TEMP, 1.2 * plasmamain[nplasma].t_r); + aaa[n] = t_e = calc_te (&plasmamain[nplasma], MIN_TEMP, 1.2 * plasmamain[nplasma].state.t_r); } } @@ -719,9 +719,9 @@ partial_measure_summary (w, element, istate, rootname, ochoice) { aaa[n] = 0; nplasma = w[n].nplasma; - if (plasmamain[nplasma].ne > 1.0 && w[n].inwind >= 0) + if (plasmamain[nplasma].state.ne > 1.0 && w[n].inwind >= 0) { - total += aaa[n] = plasmamain[nplasma].density[nion] * plasmamain[nplasma].ne * w[n].vol; + total += aaa[n] = plasmamain[nplasma].state.density[nion] * plasmamain[nplasma].state.ne * w[n].vol; } } @@ -735,8 +735,8 @@ partial_measure_summary (w, element, istate, rootname, ochoice) for (n = 0; n < NDIM2; n++) { nplasma = w[n].nplasma; - if (plasmamain[nplasma].ne > 1.0 && w[n].inwind >= 0) - w[n].x[1] = plasmamain[nplasma].density[nion] / (0.87 * plasmamain[nplasma].ne * ele[nelem].abun); + if (plasmamain[nplasma].state.ne > 1.0 && w[n].inwind >= 0) + w[n].x[1] = plasmamain[nplasma].state.density[nion] / (0.87 * plasmamain[nplasma].state.ne * ele[nelem].abun); else w[n].x[1] = 0; } diff --git a/source/swind_macro.c b/source/swind_macro.c index c76e89f51..e5996c6e6 100644 --- a/source/swind_macro.c +++ b/source/swind_macro.c @@ -56,7 +56,7 @@ xadiabatic_cooling_summary (w, rootname, ochoice) aaa[n] = 0; if (w[n].inwind >= 0) { - t_e = plasmamain[w[n].nplasma].t_e; + t_e = plasmamain[w[n].nplasma].state.t_e; num_recomb (&plasmamain[w[n].nplasma], t_e, 1); tot += aaa[n] = adiabatic_cooling (&w[n], t_e); } @@ -277,7 +277,7 @@ config_overview (n, icell) if (icell >= 0 && icell < NDIM2) { x = &plasmamain[icell]; - xden = x->levden[p->nden]; + xden = x->state.levden[p->nden]; } else { @@ -315,8 +315,8 @@ config_overview (n, icell) printf ("\n"); m = ¯omain[icell]; - printf ("matom_emis: %8.2e\n", m->matom_emiss[n]); - printf ("matom_abs : %8.2e\n", m->matom_abs[n]); + printf ("matom_emis: %8.2e\n", m->derived.matom_emiss[n]); + printf ("matom_abs : %8.2e\n", m->est.matom_abs[n]); /* Detailed information on the bb transitions */ printf ("bbu_jump:\n"); @@ -324,7 +324,7 @@ config_overview (n, icell) { //ii=p->bbu_jump[i]; ii = i; - printf (" %3d %8.2e %8.2e\n", ii, (m->jbar[xconfig[n].bbu_indx_first + ii]), (m->jbar_old[xconfig[n].bbu_indx_first + ii])); + printf (" %3d %8.2e %8.2e\n", ii, (m->est.jbar[xconfig[n].bbu_indx_first + ii]), (m->state.jbar_old[xconfig[n].bbu_indx_first + ii])); } printf ("bbd_jump:\n"); @@ -332,7 +332,7 @@ config_overview (n, icell) { // ii=p->bbd_jump[i]; ii = i; - printf (" %3d %8.2e %8.2e\n", ii, (m->jbar[xconfig[n].bbu_indx_first + ii]), (m->jbar_old[xconfig[n].bbu_indx_first + ii])); + printf (" %3d %8.2e %8.2e\n", ii, (m->est.jbar[xconfig[n].bbu_indx_first + ii]), (m->state.jbar_old[xconfig[n].bbu_indx_first + ii])); } /* Detailed information on the fb transitions */ @@ -343,13 +343,13 @@ config_overview (n, icell) // ii=p->bfu_jump[i]; ii = i; printf (" %3d %g %g %g %g %g %g %g %g\n", ii, - (m->gamma[xconfig[n].bfu_indx_first + ii]), - (m->gamma_old[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_old[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_e[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_e_old[xconfig[n].bfu_indx_first + ii]), - (m->recomb_sp[xconfig[n].bfd_indx_first + ii]), (m->recomb_sp_e[xconfig[n].bfd_indx_first + ii])); + (m->est.gamma[xconfig[n].bfu_indx_first + ii]), + (m->state.gamma_old[xconfig[n].bfu_indx_first + ii]), + (m->est.alpha_st[xconfig[n].bfu_indx_first + ii]), + (m->state.alpha_st_old[xconfig[n].bfu_indx_first + ii]), + (m->est.alpha_st_e[xconfig[n].bfu_indx_first + ii]), + (m->state.alpha_st_e_old[xconfig[n].bfu_indx_first + ii]), + (m->est.recomb_sp[xconfig[n].bfd_indx_first + ii]), (m->est.recomb_sp_e[xconfig[n].bfd_indx_first + ii])); } @@ -360,13 +360,13 @@ config_overview (n, icell) // ii=p->bfd_jump[i]; ii = i; printf (" %3d %g %g %g %g %g %g %g %g\n", ii, - (m->gamma[xconfig[n].bfu_indx_first + ii]), - (m->gamma_old[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_old[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_e[xconfig[n].bfu_indx_first + ii]), - (m->alpha_st_e_old[xconfig[n].bfu_indx_first + ii]), - (m->recomb_sp[xconfig[n].bfd_indx_first + ii]), (m->recomb_sp_e[xconfig[n].bfd_indx_first + ii])); + (m->est.gamma[xconfig[n].bfu_indx_first + ii]), + (m->state.gamma_old[xconfig[n].bfu_indx_first + ii]), + (m->est.alpha_st[xconfig[n].bfu_indx_first + ii]), + (m->state.alpha_st_old[xconfig[n].bfu_indx_first + ii]), + (m->est.alpha_st_e[xconfig[n].bfu_indx_first + ii]), + (m->state.alpha_st_e_old[xconfig[n].bfu_indx_first + ii]), + (m->est.recomb_sp[xconfig[n].bfd_indx_first + ii]), (m->est.recomb_sp_e[xconfig[n].bfd_indx_first + ii])); } @@ -416,7 +416,7 @@ depcoef_overview (icell) geo.macro_ioniz_mode = MACRO_IONIZ_MODE_NO_ESTIMATORS; partition_functions (xdummy, NEBULARMODE_TE); - saha (xdummy, xdummy->ne, xdummy->t_e); + saha (xdummy, xdummy->state.ne, xdummy->state.t_e); geo.macro_ioniz_mode = MACRO_IONIZ_MODE_ESTIMATORS; } else @@ -437,9 +437,10 @@ depcoef_overview (icell) { xden = den_config (x, n); lteden = den_config (xdummy, n); - // xden = x->levden[p->nden]; - //lteden = xdummy->levden[p->nden]; - printf ("%2d %2d %4d %5d %8.2e %8.2e %8.2e %8.2e\n", p->z, p->istate, p->nden, p->macro_info, (xden / lteden), xden, lteden, x->t_e); + // xden = x->state.levden[p->nden]; + //lteden = xdummy->state.levden[p->nden]; + printf ("%2d %2d %4d %5d %8.2e %8.2e %8.2e %8.2e\n", p->z, p->istate, p->nden, p->macro_info, (xden / lteden), xden, lteden, + x->state.t_e); } } @@ -466,36 +467,36 @@ copy_plasma (x1, x2) x2->nwind = x1->nwind; x2->nplasma = x1->nplasma; - x2->ne = x1->ne; - x2->rho = x1->rho; - x2->vol = x1->vol; - x2->t_r = x1->t_r; - x2->t_e = x1->t_e; - x2->w = x1->w; + x2->state.ne = x1->state.ne; + x2->state.rho = x1->state.rho; + x2->state.vol = x1->state.vol; + x2->state.t_r = x1->state.t_r; + x2->state.t_e = x1->state.t_e; + x2->state.w = x1->state.w; - if ((x2->density = calloc (sizeof (double), nions)) == NULL) + if ((x2->state.density = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for density\n"); exit (0); } - if ((x2->partition = calloc (sizeof (double), nions)) == NULL) + if ((x2->state.partition = calloc (sizeof (double), nions)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for partition\n"); exit (0); } - if ((x2->levden = calloc (sizeof (double), nlte_levels)) == NULL) + if ((x2->state.levden = calloc (sizeof (double), nlte_levels)) == NULL) { Error ("calloc_dyn_plasma: Error in allocating memory for levden\n"); exit (0); } for (i = 0; i < nions; i++) { - x2->density[i] = x1->density[i]; - x2->partition[i] = x1->partition[i]; + x2->state.density[i] = x1->state.density[i]; + x2->state.partition[i] = x1->state.partition[i]; } for (i = 0; i < nlte_levels; i++) { - x2->levden[i] = x1->levden[i]; + x2->state.levden[i] = x1->state.levden[i]; } @@ -520,8 +521,8 @@ int dealloc_copied_plasma (xcopy) PlasmaPtr xcopy; { - free (xcopy->density); - free (xcopy->partition); + free (xcopy->state.density); + free (xcopy->state.partition); return (0); } @@ -577,7 +578,7 @@ depcoef_overview_specific (version, nconfig, w, rootname, ochoice) geo.macro_ioniz_mode = MACRO_IONIZ_MODE_NO_ESTIMATORS; partition_functions (xdummy, NEBULARMODE_TE); - saha (xdummy, xdummy->ne, xdummy->t_e); + saha (xdummy, xdummy->state.ne, xdummy->state.t_e); geo.macro_ioniz_mode = MACRO_IONIZ_MODE_ESTIMATORS; @@ -585,7 +586,7 @@ depcoef_overview_specific (version, nconfig, w, rootname, ochoice) xden = den_config (xplasma, nconfig); lteden = den_config (xdummy, nconfig); - ion_density = xplasma->density[p->nion]; + ion_density = xplasma->state.density[p->nion]; if (version == 0) { @@ -688,28 +689,28 @@ level_popsoverview (nplasma, w, rootname, ochoice) if (ochoice) fprintf (f, "# Level, Pops, Dep coefs\n"); - Log ("# Cell %i Radiation field t_r %8.4e w %8.4e\n", nplasma, xplasma->t_r, xplasma->w); - Log ("# Cell %i Physical t_e %8.4e ne %8.4e\n", nplasma, xplasma->t_e, xplasma->ne); + Log ("# Cell %i Radiation field t_r %8.4e w %8.4e\n", nplasma, xplasma->state.t_r, xplasma->state.w); + Log ("# Cell %i Physical t_e %8.4e ne %8.4e\n", nplasma, xplasma->state.t_e, xplasma->state.ne); if (ochoice) { - fprintf (f, "# Cell %i Radiation field t_r %8.4e w %8.4e\n", nplasma, xplasma->t_r, xplasma->w); - fprintf (f, "# Cell %i Physical t_e %8.4e ne %8.4e\n", nplasma, xplasma->t_e, xplasma->ne); + fprintf (f, "# Cell %i Radiation field t_r %8.4e w %8.4e\n", nplasma, xplasma->state.t_r, xplasma->state.w); + fprintf (f, "# Cell %i Physical t_e %8.4e ne %8.4e\n", nplasma, xplasma->state.t_e, xplasma->state.ne); } for (i = 0; i < nlevels_macro; i++) { partition_functions (xdummy, NEBULARMODE_TE); - saha (xdummy, xdummy->ne, xdummy->t_e); + saha (xdummy, xdummy->state.ne, xdummy->state.t_e); geo.macro_ioniz_mode = MACRO_IONIZ_MODE_ESTIMATORS; //p = &config[i]; xden = den_config (xplasma, i); lteden = den_config (xdummy, i); - Log ("%i %8.4e %8.4e\n", i + 1, xplasma->levden[i], xden / lteden); + Log ("%i %8.4e %8.4e\n", i + 1, xplasma->state.levden[i], xden / lteden); if (ochoice) - fprintf (f, "%i %8.4e %8.4e\n", i + 1, xplasma->levden[i], xden / lteden); + fprintf (f, "%i %8.4e %8.4e\n", i + 1, xplasma->state.levden[i], xden / lteden); } fclose (f); dealloc_copied_plasma (xdummy); @@ -759,15 +760,15 @@ level_emissoverview (nlev, w, rootname, ochoice) aaa[n] = 0; nplasma = w[n].nplasma; - if (w[n].inwind >= 0 && plasmamain[nplasma].ne > 1.0) + if (w[n].inwind >= 0 && plasmamain[nplasma].state.ne > 1.0) { if (nlev != 0) { - aaa[n] = macromain[nplasma].matom_emiss[nlev - 1]; + aaa[n] = macromain[nplasma].derived.matom_emiss[nlev - 1]; } else { - aaa[n] = plasmamain[nplasma].kpkt_emiss; + aaa[n] = plasmamain[nplasma].derived.kpkt_emiss; } } } @@ -862,7 +863,7 @@ level_escapeoverview (nlev, w, rootname, ochoice) aaa[n] = 0; nplasma = w[n].nplasma; - if (w[n].inwind >= 0 && plasmamain[nplasma].ne > 1.0) + if (w[n].inwind >= 0 && plasmamain[nplasma].state.ne > 1.0) { xplasma = &plasmamain[nplasma]; aaa[n] = p_escape (lin_ptr[nline], xplasma); @@ -955,11 +956,11 @@ level_tauoverview (nlev, w, rootname, ochoice) aaa[n] = 0; nplasma = w[n].nplasma; - if (w[n].inwind >= 0 && plasmamain[nplasma].ne > 1.0) + if (w[n].inwind >= 0 && plasmamain[nplasma].state.ne > 1.0) { xplasma = &plasmamain[nplasma]; one = &wmain[xplasma->nwind]; - aaa[n] = sobolev (one, one->x, xplasma->density[lin_ptr[nline]->nion], lin_ptr[nline], one->dvds_ave); + aaa[n] = sobolev (one, one->x, xplasma->state.density[lin_ptr[nline]->nion], lin_ptr[nline], one->dvds_ave); } diff --git a/source/swind_sub.c b/source/swind_sub.c index 52025393b..3be6d9724 100644 --- a/source/swind_sub.c +++ b/source/swind_sub.c @@ -142,10 +142,10 @@ overview (w, rootname) for (n = 0; n < NPLASMA; n++) { - heating += plasmamain[n].heat_tot; - lines += plasmamain[n].heat_lines; - photo += plasmamain[n].heat_photo; - ff += plasmamain[n].heat_ff; + heating += plasmamain[n].est.heat_tot; + lines += plasmamain[n].est.heat_lines; + photo += plasmamain[n].est.heat_photo; + ff += plasmamain[n].est.heat_ff; } Log (" Total cooling %8.2e heating %8.2e\n", geo.cool_tot_ioniz, heating); Log (" Total emission %8.2e heating %8.2e\n", geo.lum_tot_ioniz, heating); @@ -216,7 +216,7 @@ a:Log ("Input x=0,y=0,z=0 to return to main routine\n"); Log ("Vertex position %8.2e %8.2e %8.2e rtheta %8.2e %8.2e \n", w[n].x[0], w[n].x[1], w[n].x[2], w[n].r, w[n].theta); Log ("Center position %8.2e %8.2e %8.2e rtheta %8.2e %8.2e \n", w[n].xcen[0], w[n].xcen[1], w[n].xcen[2], w[n].rcen, w[n].thetacen); - Log ("Electron density: %8.2e rho %8.2e\n", plasmamain[nplasma].ne, plasmamain[nplasma].rho); + Log ("Electron density: %8.2e rho %8.2e\n", plasmamain[nplasma].state.ne, plasmamain[nplasma].state.rho); Log ("Vel cell: %8.2e %8.2e %8.2e\n", w[n].v[0], w[n].v[1], w[n].v[2]); p.x[0] = x[0]; @@ -330,28 +330,28 @@ abs_summary (w, rootname, ochoice) { case 't': { /* Total heating */ - x = plasmamain[nplasma].heat_tot; + x = plasmamain[nplasma].est.heat_tot; break; case 'f': /* ff heating */ - x = plasmamain[nplasma].heat_ff; + x = plasmamain[nplasma].est.heat_ff; break; case 'b': /* photoionization heating */ - x = plasmamain[nplasma].heat_photo; + x = plasmamain[nplasma].est.heat_photo; break; case 'l': /* Line heating */ - x = plasmamain[nplasma].heat_lines; + x = plasmamain[nplasma].est.heat_lines; break; case 'h': /* H heating */ - x = plasmamain[nplasma].heat_ion[0]; + x = plasmamain[nplasma].est.heat_ion[0]; break; case 'i': /* He1 heating */ - x = plasmamain[nplasma].heat_ion[2]; + x = plasmamain[nplasma].est.heat_ion[2]; break; case 'j': /* He2 heating */ - x = plasmamain[nplasma].heat_ion[3]; + x = plasmamain[nplasma].est.heat_ion[3]; break; case 'z': /* Line heating of high z elements */ - x = plasmamain[nplasma].heat_z; + x = plasmamain[nplasma].est.heat_z; break; default: printf ("Not a valid choice\n"); @@ -481,7 +481,7 @@ adiabatic_cooling_summary (w, rootname, ochoice) aaa[n] = 0; if (w[n].inwind >= 0) { - t_e = plasmamain[w[n].nplasma].t_e; + t_e = plasmamain[w[n].nplasma].state.t_e; // ksl - I could not determine what the next line was supposed to do // num_recomb (&plasmamain[w[n].nplasma], t_e); tot += aaa[n] = adiabatic_cooling (&w[n], t_e); @@ -608,31 +608,31 @@ lum_summary (w, rootname, ochoice) switch (c) { case 't': /* Total luminosity */ - x = plasmamain[nplasma].lum_tot_ioniz; + x = plasmamain[nplasma].derived.lum_tot_ioniz; break; case 'r': /* Radiative energo loss total */ - x = plasmamain[nplasma].lum_tot_ioniz; + x = plasmamain[nplasma].derived.lum_tot_ioniz; break; case 'f': /* Radiative energo loss total */ - x = plasmamain[nplasma].lum_ff_ioniz; + x = plasmamain[nplasma].derived.lum_ff_ioniz; break; case 'b': /* Radiative energo loss total */ - x = plasmamain[nplasma].cool_rr_ioniz; + x = plasmamain[nplasma].derived.cool_rr_ioniz; break; case 'l': /* Line luminosity */ - x = plasmamain[nplasma].lum_lines_ioniz; + x = plasmamain[nplasma].derived.lum_lines_ioniz; break; case 'h': /* H luminosity */ - x = plasmamain[nplasma].cool_rr_ion[0]; + x = plasmamain[nplasma].derived.cool_rr_ion[0]; break; case 'i': /* Line luminosity */ - x = plasmamain[nplasma].cool_rr_ion[2]; + x = plasmamain[nplasma].derived.cool_rr_ion[2]; break; case 'j': /* Line luminosity */ - x = plasmamain[nplasma].cool_rr_ion[3]; + x = plasmamain[nplasma].derived.cool_rr_ion[3]; break; case 'z': /* Line luminosity */ - x = plasmamain[nplasma].cool_rr_metals_ioniz; + x = plasmamain[nplasma].derived.cool_rr_metals_ioniz; break; default: printf ("Not a valid choice\n"); @@ -703,7 +703,7 @@ photo_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].ioniz[ion] * plasmamain[nplasma].density[ion]; + aaa[n] = plasmamain[nplasma].est.ioniz[ion] * plasmamain[nplasma].state.density[ion]; } } display ("No of ionizations per second in cell"); @@ -762,8 +762,8 @@ recomb_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - num_recomb (&plasmamain[nplasma], plasmamain[nplasma].t_e, 1); - aaa[n] = plasmamain[nplasma].recomb[ion]; + num_recomb (&plasmamain[nplasma], plasmamain[nplasma].state.t_e, 1); + aaa[n] = plasmamain[nplasma].derived.recomb[ion]; } } @@ -819,7 +819,7 @@ electron_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].ne; + aaa[n] = plasmamain[nplasma].state.ne; } } display ("Electron densities"); @@ -874,7 +874,7 @@ rho_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].rho; + aaa[n] = plasmamain[nplasma].state.rho; } } display ("Rho (gm/cm**3)"); @@ -987,7 +987,7 @@ freq_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].ave_freq; + aaa[n] = plasmamain[nplasma].est.ave_freq; } } display ("Average freqency"); @@ -1057,32 +1057,32 @@ nphot_summary (w, rootname, ochoice) nplasma = w[n].nplasma; if (ichoice == 0) { - aaa[n] = plasmamain[nplasma].ntot; + aaa[n] = plasmamain[nplasma].est.ntot; strcpy (string, "Nphot tot per cell"); } else if (ichoice == 1) { - aaa[n] = plasmamain[nplasma].ntot_star; + aaa[n] = plasmamain[nplasma].est.ntot_star; strcpy (string, "Nphot star per cell"); } else if (ichoice == 2) { - aaa[n] = plasmamain[nplasma].ntot_bl; + aaa[n] = plasmamain[nplasma].est.ntot_bl; strcpy (string, "Nphot bl per cell"); } else if (ichoice == 3) { - aaa[n] = plasmamain[nplasma].ntot_disk; + aaa[n] = plasmamain[nplasma].est.ntot_disk; strcpy (string, "Nphot disk per cell"); } else if (ichoice == 4) { - aaa[n] = plasmamain[nplasma].ntot_wind; + aaa[n] = plasmamain[nplasma].est.ntot_wind; strcpy (string, "Nphot wind per cell"); } else if (ichoice == 5) { - aaa[n] = plasmamain[nplasma].ntot_agn; + aaa[n] = plasmamain[nplasma].est.ntot_agn; strcpy (string, "Nphot agn per cell"); } else @@ -1145,7 +1145,7 @@ temp_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].t_e; + aaa[n] = plasmamain[nplasma].state.t_e; } } display ("T_e"); @@ -1196,7 +1196,7 @@ temp_rad (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].t_r; + aaa[n] = plasmamain[nplasma].state.t_r; } } display ("T_rad"); @@ -1246,7 +1246,7 @@ weight_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].w; + aaa[n] = plasmamain[nplasma].state.w; } } display ("Radiative weights"); @@ -1425,14 +1425,14 @@ mo_summary (w, rootname, ochoice) { if (ichoice == 0) x = - sqrt (xplasma->dmo_dt[0] * xplasma->dmo_dt[0] + - xplasma->dmo_dt[1] * xplasma->dmo_dt[1] + xplasma->dmo_dt[2] * xplasma->dmo_dt[2]); + sqrt (xplasma->derived.dmo_dt[0] * xplasma->derived.dmo_dt[0] + + xplasma->derived.dmo_dt[1] * xplasma->derived.dmo_dt[1] + xplasma->derived.dmo_dt[2] * xplasma->derived.dmo_dt[2]); else if (ichoice == 1) - x = xplasma->rad_force_es[0]; + x = xplasma->est.rad_force_es[0]; else if (ichoice == 2) - x = xplasma->rad_force_es[1]; + x = xplasma->est.rad_force_es[1]; else - x = xplasma->rad_force_es[2]; + x = xplasma->est.rad_force_es[2]; } aaa[n] = x; } @@ -1584,12 +1584,13 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); Log ("Element %d (%d,%d) inwind %d plasma cell %d ntot %d nioniz %d nrad %d\n", - n, i, j, w[n].inwind, xplasma->nplasma, xplasma->ntot, xplasma->nioniz, xplasma->nrad); + n, i, j, w[n].inwind, xplasma->nplasma, xplasma->est.ntot, xplasma->est.nioniz, xplasma->derived.nrad); Log ("xyz %8.2e %8.2e %8.2e vel %8.2e %8.2e %8.2e\n", w[n].x[0], w[n].x[1], w[n].x[2], w[n].v[0], w[n].v[1], w[n].v[2]); Log ("r theta %12.6e %12.6e \n", w[n].rcen, w[n].thetacen / RADIAN); Log ("rho %8.2e nh %8.2e ne %8.2e t_r %8.2e t_e %8.2e w %8.2e vol %8.2e\n", - xplasma->rho, xplasma->rho * rho2nh, xplasma->ne, xplasma->t_r, xplasma->t_e, xplasma->w, w[n].vol); + xplasma->state.rho, xplasma->state.rho * rho2nh, xplasma->state.ne, xplasma->state.t_r, xplasma->state.t_e, xplasma->state.w, + w[n].vol); if (w[n].inwind < 0) Log ("\n# Cell is not inwind, expect all zeros to follow\n\n"); @@ -1598,44 +1599,51 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); DR cooling also added in to report */ Log ("t_e %8.2e lum_tot %8.2e lum_lines %8.2e lum_ff %8.2e lum_rr %8.2e \n", - xplasma->t_e, xplasma->lum_tot_ioniz, xplasma->lum_lines_ioniz, xplasma->lum_ff_ioniz, xplasma->lum_rr_ioniz); + xplasma->state.t_e, xplasma->derived.lum_tot_ioniz, xplasma->derived.lum_lines_ioniz, xplasma->derived.lum_ff_ioniz, + xplasma->derived.lum_rr_ioniz); Log ("t_e %8.2e cool_tot %8.2e lum_lines %8.2e lum_ff %8.2e cool_rr %8.2e cool_comp %8.2e cool_adiab %8.2e cool_DR %8.2e cool_DI %8.2e\n", - xplasma->t_e, xplasma->cool_tot_ioniz + xplasma->cool_comp_ioniz + xplasma->cool_adiabatic_ioniz + xplasma->cool_dr_ioniz, - xplasma->lum_lines_ioniz, xplasma->lum_ff_ioniz, xplasma->cool_rr_ioniz, xplasma->cool_comp_ioniz, xplasma->cool_adiabatic_ioniz, - xplasma->cool_dr_ioniz, xplasma->cool_di_ioniz); + xplasma->state.t_e, + xplasma->derived.cool_tot_ioniz + xplasma->derived.cool_comp_ioniz + xplasma->derived.cool_adiabatic_ioniz + + xplasma->derived.cool_dr_ioniz, xplasma->derived.lum_lines_ioniz, xplasma->derived.lum_ff_ioniz, xplasma->derived.cool_rr_ioniz, + xplasma->derived.cool_comp_ioniz, xplasma->derived.cool_adiabatic_ioniz, xplasma->derived.cool_dr_ioniz, + xplasma->derived.cool_di_ioniz); Log ("t_r %8.2e heat_tot %8.2e heat_lines %8.2e heat_ff %8.2e heat_photo %8.2e heat_auger %8.2e heat_comp %8.2e heat_icomp %8.2e\n", - xplasma->t_r, xplasma->heat_tot, xplasma->heat_lines, xplasma->heat_ff, xplasma->heat_photo, xplasma->heat_auger, xplasma->heat_comp, - xplasma->heat_ind_comp); + xplasma->state.t_r, xplasma->est.heat_tot, xplasma->est.heat_lines, xplasma->est.heat_ff, xplasma->est.heat_photo, + xplasma->est.heat_auger, xplasma->est.heat_comp, xplasma->est.heat_ind_comp); - Log ("Recombination cooling HII>HI %8.2e HeII>HeI %8.2e HeIII>HeII %8.2e Metals %8.2e\n", xplasma->cool_rr_ion[0], - xplasma->cool_rr_ion[2], xplasma->cool_rr_ion[3], xplasma->cool_rr_metals); - Log ("Photoionization heating HI>HII %8.2e HeI>HeII %8.2e HeII>HeIII %8.2e Metals %8.2e\n", xplasma->heat_ion[0], xplasma->heat_ion[2], - xplasma->heat_ion[3], xplasma->heat_z); + Log ("Recombination cooling HII>HI %8.2e HeII>HeI %8.2e HeIII>HeII %8.2e Metals %8.2e\n", xplasma->derived.cool_rr_ion[0], + xplasma->derived.cool_rr_ion[2], xplasma->derived.cool_rr_ion[3], xplasma->derived.cool_rr_metals); + Log ("Photoionization heating HI>HII %8.2e HeI>HeII %8.2e HeII>HeIII %8.2e Metals %8.2e\n", xplasma->est.heat_ion[0], + xplasma->est.heat_ion[2], xplasma->est.heat_ion[3], xplasma->est.heat_z); Log ("The ratio of rad (total) cooling to heating is %8.2f (%8.2f) \n", - xplasma->lum_tot_ioniz / xplasma->heat_tot, - (xplasma->lum_tot_ioniz + xplasma->cool_adiabatic_ioniz + xplasma->cool_comp_ioniz + xplasma->cool_dr_ioniz) / xplasma->heat_tot); - Log ("Adiabatic cooling %8.2e is %8.2g of total cooling\n", - xplasma->cool_adiabatic_ioniz, - xplasma->cool_adiabatic_ioniz / (xplasma->lum_tot + xplasma->cool_adiabatic + xplasma->cool_comp_ioniz + xplasma->cool_dr_ioniz)); + xplasma->derived.lum_tot_ioniz / xplasma->est.heat_tot, + (xplasma->derived.lum_tot_ioniz + xplasma->derived.cool_adiabatic_ioniz + xplasma->derived.cool_comp_ioniz + + xplasma->derived.cool_dr_ioniz) / xplasma->est.heat_tot); + Log ("Adiabatic cooling %8.2e is %8.2g of total cooling\n", xplasma->derived.cool_adiabatic_ioniz, + xplasma->derived.cool_adiabatic_ioniz / (xplasma->derived.lum_tot + xplasma->derived.cool_adiabatic + + xplasma->derived.cool_comp_ioniz + xplasma->derived.cool_dr_ioniz)); /*70g NSH compton and DR cooling are now reported seperately. */ Log ("Compton cooling %8.2e is %8.2g of total cooling\n", - xplasma->cool_comp_ioniz, - xplasma->cool_comp_ioniz / (xplasma->lum_tot + xplasma->cool_adiabatic + xplasma->cool_comp_ioniz + xplasma->cool_dr_ioniz)); - Log ("DR cooling %8.2e is %8.2g of total cooling\n", xplasma->cool_dr_ioniz, - xplasma->cool_dr_ioniz / (xplasma->lum_tot + xplasma->cool_adiabatic + xplasma->cool_comp_ioniz + xplasma->cool_dr_ioniz)); - Log ("Number of ionizing photons in cell nioniz %d\n", xplasma->nioniz); - Log ("Log Ionization parameter in this cell U %4.2f xi %4.2f\n", log10 (xplasma->ip), log10 (xplasma->xi)); //70h NSH computed ionizaion parameter + xplasma->derived.cool_comp_ioniz, + xplasma->derived.cool_comp_ioniz / (xplasma->derived.lum_tot + xplasma->derived.cool_adiabatic + xplasma->derived.cool_comp_ioniz + + xplasma->derived.cool_dr_ioniz)); + Log ("DR cooling %8.2e is %8.2g of total cooling\n", xplasma->derived.cool_dr_ioniz, + xplasma->derived.cool_dr_ioniz / (xplasma->derived.lum_tot + xplasma->derived.cool_adiabatic + xplasma->derived.cool_comp_ioniz + + xplasma->derived.cool_dr_ioniz)); + Log ("Number of ionizing photons in cell nioniz %d\n", xplasma->est.nioniz); + Log ("Log Ionization parameter in this cell U %4.2f xi %4.2f\n", log10 (xplasma->est.ip), log10 (xplasma->derived.xi)); //70h NSH computed ionizaion parameter Log ("ioniz %8.2e %8.2e %8.2e %8.2e %8.2e\n", - xplasma->ioniz[0], xplasma->ioniz[1], xplasma->ioniz[2], xplasma->ioniz[3], xplasma->ioniz[4]); + xplasma->est.ioniz[0], xplasma->est.ioniz[1], xplasma->est.ioniz[2], xplasma->est.ioniz[3], xplasma->est.ioniz[4]); Log ("Convergence status: whole %d converging %d t_r %8.2e t_e %8.2e hc %8.2e \n", - xplasma->converge_whole, xplasma->converging, xplasma->converge_t_r, xplasma->converge_t_e, xplasma->converge_hc); + xplasma->derived.converge_whole, xplasma->derived.converging, xplasma->derived.converge_t_r, xplasma->derived.converge_t_e, + xplasma->derived.converge_hc); Log ("Densities:\n"); for (nn = 0; nn < 5; nn++) @@ -1644,7 +1652,7 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); last = first + ele[nn].nions; Log ("%-5s ", ele[nn].name); for (m = first; m < last; m++) - Log (" %8.2e", xplasma->density[m]); + Log (" %8.2e", xplasma->state.density[m]); Log ("\n"); } @@ -1656,7 +1664,7 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); last = first + ele[nn].nions; Log ("%-5s ", ele[nn].name); for (m = first; m < last; m++) - Log (" %8.2e", xplasma->partition[m]); + Log (" %8.2e", xplasma->state.partition[m]); Log ("\n"); } @@ -1676,7 +1684,7 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); last = first + ion[mm].nlte; Log ("ion %3d %3d", ion[mm].z, ion[mm].istate); for (m = first; m < last; m++) - Log (" %8.2e", xplasma->levden[m]); + Log (" %8.2e", xplasma->state.levden[m]); Log ("\n"); mm++; } @@ -1685,14 +1693,14 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); for (nn = 0; nn < geo.nxfreq; nn++) { Log ("numin= %9.2e (%9.2e) numax= %9.2e (%9.2e) Model= %2d PL_log_w= %9.2e PL_alpha= %9.2e Exp_w= %9.2e EXP_temp= %9.2e\n", - xplasma->fmin_mod[nn], geo.xfreq[nn], xplasma->fmax_mod[nn], geo.xfreq[nn + 1], xplasma->spec_mod_type[nn], xplasma->pl_log_w[nn], - xplasma->pl_alpha[nn], xplasma->exp_w[nn], xplasma->exp_temp[nn]); + xplasma->state.fmin_mod[nn], geo.xfreq[nn], xplasma->state.fmax_mod[nn], geo.xfreq[nn + 1], xplasma->state.spec_mod_type[nn], + xplasma->state.pl_log_w[nn], xplasma->state.pl_alpha[nn], xplasma->state.exp_w[nn], xplasma->state.exp_temp[nn]); } Log ("Flux:\n"); - Log ("F_vis_w = %9.2e F_vis_phi = %9.2e F_vis_z = %9.2e \n", xplasma->F_vis[0], xplasma->F_vis[1], xplasma->F_vis[2]); - Log ("F_UV_w = %9.2e F_UV_phi = %9.2e F_UV_z = %9.2e \n", xplasma->F_UV[0], xplasma->F_UV[1], xplasma->F_UV[2]); - Log ("F_Xray_w= %9.2e F_Xray_phi= %9.2e F_Xray_z= %9.2e \n", xplasma->F_Xray[0], xplasma->F_Xray[1], xplasma->F_Xray[2]); + Log ("F_vis_w = %9.2e F_vis_phi = %9.2e F_vis_z = %9.2e \n", xplasma->est.F_vis[0], xplasma->est.F_vis[1], xplasma->est.F_vis[2]); + Log ("F_UV_w = %9.2e F_UV_phi = %9.2e F_UV_z = %9.2e \n", xplasma->est.F_UV[0], xplasma->est.F_UV[1], xplasma->est.F_UV[2]); + Log ("F_Xray_w= %9.2e F_Xray_phi= %9.2e F_Xray_z= %9.2e \n", xplasma->est.F_Xray[0], xplasma->est.F_Xray[1], xplasma->est.F_Xray[2]); @@ -1739,7 +1747,7 @@ tau_h_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = 6.e-18 * plasmamain[nplasma].density[0] * pow (w[n].vol, 0.333); + aaa[n] = 6.e-18 * plasmamain[nplasma].state.density[0] * pow (w[n].vol, 0.333); } } @@ -1785,7 +1793,7 @@ coolheat_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].lum_tot_ioniz / plasmamain[nplasma].heat_tot; + aaa[n] = plasmamain[nplasma].derived.lum_tot_ioniz / plasmamain[nplasma].est.heat_tot; } } @@ -2059,7 +2067,7 @@ IP_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = ((plasmamain[nplasma].ip)); + aaa[n] = ((plasmamain[nplasma].est.ip)); } } display ("Ionization parameter"); @@ -2080,7 +2088,7 @@ IP_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = ((plasmamain[nplasma].xi)); + aaa[n] = ((plasmamain[nplasma].derived.xi)); } } display ("Xi Ionization parameter"); @@ -2101,7 +2109,7 @@ IP_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = ((plasmamain[nplasma].ip_direct)); + aaa[n] = ((plasmamain[nplasma].est.ip_direct)); } } display ("Log Ionization parameter (direct)"); @@ -2120,7 +2128,7 @@ IP_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = ((plasmamain[nplasma].ip_scatt)); + aaa[n] = ((plasmamain[nplasma].est.ip_scatt)); } } display ("Log Ionization parameter (scattered)"); @@ -2170,7 +2178,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].pl_alpha[m]; + aaa[n] = plasmamain[nplasma].state.pl_alpha[m]; } } @@ -2194,7 +2202,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].pl_log_w[m]; + aaa[n] = plasmamain[nplasma].state.pl_log_w[m]; } } @@ -2219,7 +2227,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].exp_temp[m]; + aaa[n] = plasmamain[nplasma].state.exp_temp[m]; } } @@ -2243,7 +2251,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].exp_w[m]; + aaa[n] = plasmamain[nplasma].state.exp_w[m]; } } @@ -2267,7 +2275,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].spec_mod_type[m]; + aaa[n] = plasmamain[nplasma].state.spec_mod_type[m]; } } @@ -2293,7 +2301,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].fmin_mod[m]; + aaa[n] = plasmamain[nplasma].state.fmin_mod[m]; } } @@ -2317,7 +2325,7 @@ alpha_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].fmax_mod[m]; + aaa[n] = plasmamain[nplasma].state.fmax_mod[m]; } } @@ -2409,9 +2417,9 @@ J_summary (w, rootname, ochoice) { nplasma = w[n].nplasma; if (i == 0) - aaa[n] = macromain[nplasma].jbar_old[xconfig[llvl].bbu_indx_first + njump]; + aaa[n] = macromain[nplasma].state.jbar_old[xconfig[llvl].bbu_indx_first + njump]; else - aaa[n] = (plasmamain[nplasma].xj[i]); + aaa[n] = (plasmamain[nplasma].est.xj[i]); } } @@ -2465,7 +2473,7 @@ J_scat_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].j); + aaa[n] = (plasmamain[nplasma].est.j); } } display ("J in cell"); @@ -2483,7 +2491,7 @@ J_scat_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].j_direct); + aaa[n] = (plasmamain[nplasma].est.j_direct); } } display ("J in cell from direct photons"); @@ -2500,7 +2508,7 @@ J_scat_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].j_scatt); + aaa[n] = (plasmamain[nplasma].est.j_scatt); } } display ("J in cell from scattered photons"); @@ -2540,7 +2548,7 @@ phot_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].ntot_wind); + aaa[n] = (plasmamain[nplasma].est.ntot_wind); } } display ("Wind photons in cell"); @@ -2558,7 +2566,7 @@ phot_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].ntot_agn); + aaa[n] = (plasmamain[nplasma].est.ntot_agn); } } display ("AGN photons in cell"); @@ -2576,7 +2584,7 @@ phot_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].ntot_disk); + aaa[n] = (plasmamain[nplasma].est.ntot_disk); } } display ("Disk photons in cell"); @@ -2594,7 +2602,7 @@ phot_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = (plasmamain[nplasma].ntot_star); + aaa[n] = (plasmamain[nplasma].est.ntot_star); } } display ("Stellar photons in cell"); @@ -2627,7 +2635,7 @@ thompson (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - ne = plasmamain[nplasma].ne; + ne = plasmamain[nplasma].state.ne; aaa[n] = (THOMPSON * ne) * pow (w[n].vol, 0.333); } } @@ -2662,7 +2670,7 @@ nscat_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].nscat_es; + aaa[n] = plasmamain[nplasma].derived.nscat_es; } } display ("Thompson scatters"); @@ -2673,7 +2681,7 @@ nscat_split (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].nscat_res; + aaa[n] = plasmamain[nplasma].derived.nscat_res; } } display ("Resonant scatters"); @@ -2710,7 +2718,7 @@ convergence_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].converge_whole; + aaa[n] = plasmamain[nplasma].derived.converge_whole; } } display ("Convergence (0=converged. Higher numbers indicate one or more convergence tests failed)"); @@ -2752,7 +2760,7 @@ convergence_all (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].converge_t_e; + aaa[n] = plasmamain[nplasma].derived.converge_t_e; } } display ("t_e Convergence (0=converged)"); @@ -2770,7 +2778,7 @@ convergence_all (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].converge_hc; + aaa[n] = plasmamain[nplasma].derived.converge_hc; } } display ("hc Convergence (0=converged)"); @@ -2788,7 +2796,7 @@ convergence_all (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].converge_t_r; + aaa[n] = plasmamain[nplasma].derived.converge_t_r; } } display ("t_r Convergence (0=converged)"); @@ -2806,7 +2814,7 @@ convergence_all (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].converge_whole; + aaa[n] = plasmamain[nplasma].derived.converge_whole; } } display ("Convergence (0=converged)"); @@ -2848,7 +2856,7 @@ model_bands (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].nxtot[m]; + aaa[n] = plasmamain[nplasma].est.nxtot[m]; } } @@ -2881,7 +2889,7 @@ model_bands (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].xj[m]; + aaa[n] = plasmamain[nplasma].est.xj[m]; } } @@ -2908,7 +2916,7 @@ model_bands (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].xave_freq[m]; + aaa[n] = plasmamain[nplasma].est.xave_freq[m]; } } @@ -2935,7 +2943,7 @@ model_bands (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].nxtot[m]; + aaa[n] = plasmamain[nplasma].est.nxtot[m]; } } @@ -2976,10 +2984,10 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_tot; + aaa[n] = plasmamain[nplasma].est.heat_tot; if (w[n].div_v < 0.0) // add in if it is negative and hence a heating term { - aaa[n] += -1.0 * (plasmamain[nplasma].cool_adiabatic_ioniz); + aaa[n] += -1.0 * (plasmamain[nplasma].derived.cool_adiabatic_ioniz); } } } @@ -2998,7 +3006,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_lines; + aaa[n] = plasmamain[nplasma].est.heat_lines; } } display ("Line heating"); @@ -3016,7 +3024,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_ff; + aaa[n] = plasmamain[nplasma].est.heat_ff; } } display ("FF heating"); @@ -3034,7 +3042,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_comp; + aaa[n] = plasmamain[nplasma].est.heat_comp; } } display ("Compton heating"); @@ -3052,7 +3060,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_ind_comp; + aaa[n] = plasmamain[nplasma].est.heat_ind_comp; } } display ("Induced Compton heating"); @@ -3070,7 +3078,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].heat_photo; + aaa[n] = plasmamain[nplasma].est.heat_photo; } } display ("Photo heating"); @@ -3088,7 +3096,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].lum_lines_ioniz; + aaa[n] = plasmamain[nplasma].derived.lum_lines_ioniz; } } display ("Line Luminosity"); @@ -3108,7 +3116,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].cool_adiabatic_ioniz; + aaa[n] = plasmamain[nplasma].derived.cool_adiabatic_ioniz; } } display ("Adiabatic Luminosity"); @@ -3126,7 +3134,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].lum_ff_ioniz; + aaa[n] = plasmamain[nplasma].derived.lum_ff_ioniz; } } display ("Free Free Luminosity"); @@ -3144,7 +3152,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].cool_comp_ioniz; + aaa[n] = plasmamain[nplasma].derived.cool_comp_ioniz; } } display ("Compton Luminosity"); @@ -3162,7 +3170,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].cool_dr_ioniz; + aaa[n] = plasmamain[nplasma].derived.cool_dr_ioniz; } } display ("DR Luminosity"); @@ -3180,7 +3188,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].cool_rr_ioniz; + aaa[n] = plasmamain[nplasma].derived.cool_rr_ioniz; } } display ("FB Luminosity"); @@ -3203,11 +3211,12 @@ heatcool_summary (w, rootname, ochoice) { nplasma = w[n].nplasma; aaa[n] = - plasmamain[nplasma].cool_rr_ioniz + plasmamain[nplasma].cool_dr_ioniz + - plasmamain[nplasma].cool_comp_ioniz + plasmamain[nplasma].lum_ff_ioniz + plasmamain[nplasma].lum_lines_ioniz; + plasmamain[nplasma].derived.cool_rr_ioniz + plasmamain[nplasma].derived.cool_dr_ioniz + + plasmamain[nplasma].derived.cool_comp_ioniz + plasmamain[nplasma].derived.lum_ff_ioniz + + plasmamain[nplasma].derived.lum_lines_ioniz; if (w[n].div_v >= 0.0) //only add in if it is treated as a cooling term { - aaa[n] += plasmamain[nplasma].cool_adiabatic_ioniz; + aaa[n] += plasmamain[nplasma].derived.cool_adiabatic_ioniz; } } } @@ -3227,7 +3236,7 @@ heatcool_summary (w, rootname, ochoice) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - aaa[n] = plasmamain[nplasma].lum_tot_ioniz; + aaa[n] = plasmamain[nplasma].derived.lum_tot_ioniz; } } display ("Total Radiating Luminosity"); @@ -3353,13 +3362,13 @@ ionH1\tionH2\tionHe1\tionHe2\tionHe3\tionC3\tionC4\tionC5\tionN5\tionO6\tionSi4\ %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e \ %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e\n", n, np, w[n].inwind, ii, jj, w[n].x[0], w[n].x[2], vtot, w[n].v[0], w[n].v[1], w[n].v[2], w[n].dvds_ave, w[n].vol, - plasmamain[np].rho, plasmamain[np].ne, plasmamain[np].t_e, plasmamain[np].t_r, plasmamain[np].ntot, - plasmamain[np].w, plasmamain[np].ave_freq, plasmamain[np].ip, plasmamain[np].converge_whole, - plasmamain[np].converge_t_r, plasmamain[np].converge_t_e, plasmamain[np].converge_hc, - plasmamain[np].cool_tot_ioniz, plasmamain[np].lum_tot, plasmamain[np].cool_rr, - plasmamain[np].lum_ff, plasmamain[np].lum_lines, plasmamain[np].cool_adiabatic, - plasmamain[np].cool_comp, plasmamain[np].cool_dr, plasmamain[np].heat_tot, plasmamain[np].heat_photo, - plasmamain[np].heat_lines , plasmamain[np].heat_ff , plasmamain[np].heat_comp, plasmamain[np].heat_ind_comp, + plasmamain[np].state.rho, plasmamain[np].state.ne, plasmamain[np].state.t_e, plasmamain[np].state.t_r, plasmamain[np].est.ntot, + plasmamain[np].state.w, plasmamain[np].est.ave_freq, plasmamain[np].est.ip, plasmamain[np].derived.converge_whole, + plasmamain[np].derived.converge_t_r, plasmamain[np].derived.converge_t_e, plasmamain[np].derived.converge_hc, + plasmamain[np].derived.cool_tot_ioniz, plasmamain[np].derived.lum_tot, plasmamain[np].derived.cool_rr, + plasmamain[np].derived.lum_ff, plasmamain[np].derived.lum_lines, plasmamain[np].derived.cool_adiabatic, + plasmamain[np].derived.cool_comp, plasmamain[np].derived.cool_dr, plasmamain[np].est.heat_tot, plasmamain[np].est.heat_photo, + plasmamain[np].est.heat_lines , plasmamain[np].est.heat_ff , plasmamain[np].est.heat_comp, plasmamain[np].est.heat_ind_comp, h1den, h2den, he1den, he2den, he3den, c3den, c4den, c5den, n5den, o6den, si4den); */ @@ -3368,7 +3377,7 @@ ionH1\tionH2\tionHe1\tionHe2\tionHe3\tionC3\tionC4\tionC5\tionN5\tionO6\tionSi4\ %8.4e %8.4e %8.4e %i %8.4e %8.4e %8.4e %8.4e %i %8.4e %8.4e %8.4e %8.4e \ %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e\ %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e \ - %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e\n", n, np, w[n].inwind, ii, jj, w[n].x[0], w[n].x[2], w[n].rcen, w[n].thetacen / RADIAN, vtot, w[n].v[0], w[n].v[1], w[n].v[2], w[n].dvds_ave, w[n].vol, plasmamain[np].rho, plasmamain[np].ne, plasmamain[np].t_e, plasmamain[np].t_r, plasmamain[np].ntot, plasmamain[np].w, plasmamain[np].ave_freq, plasmamain[np].ip, plasmamain[np].xi, plasmamain[np].converge_whole, plasmamain[np].converge_t_r, plasmamain[np].converge_t_e, plasmamain[np].converge_hc, plasmamain[np].cool_tot_ioniz + plasmamain[np].cool_comp_ioniz + plasmamain[np].cool_adiabatic_ioniz + plasmamain[np].cool_dr_ioniz, plasmamain[np].lum_tot_ioniz, plasmamain[np].lum_rr_ioniz, plasmamain[np].cool_rr_ioniz, plasmamain[np].lum_ff_ioniz, plasmamain[np].lum_lines_ioniz, plasmamain[np].cool_adiabatic_ioniz, plasmamain[np].cool_comp_ioniz, plasmamain[np].cool_dr_ioniz, plasmamain[np].cool_di_ioniz, plasmamain[np].heat_tot, plasmamain[np].heat_photo, plasmamain[np].heat_auger, plasmamain[np].heat_lines, plasmamain[np].heat_ff, plasmamain[np].heat_comp, plasmamain[np].heat_ind_comp, plasmamain[np].heat_shock, h1den, h2den, he1den, he2den, he3den, c3den, c4den, c5den, n5den, o6den, si4den); + %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e %8.4e\n", n, np, w[n].inwind, ii, jj, w[n].x[0], w[n].x[2], w[n].rcen, w[n].thetacen / RADIAN, vtot, w[n].v[0], w[n].v[1], w[n].v[2], w[n].dvds_ave, w[n].vol, plasmamain[np].state.rho, plasmamain[np].state.ne, plasmamain[np].state.t_e, plasmamain[np].state.t_r, plasmamain[np].est.ntot, plasmamain[np].state.w, plasmamain[np].est.ave_freq, plasmamain[np].est.ip, plasmamain[np].derived.xi, plasmamain[np].derived.converge_whole, plasmamain[np].derived.converge_t_r, plasmamain[np].derived.converge_t_e, plasmamain[np].derived.converge_hc, plasmamain[np].derived.cool_tot_ioniz + plasmamain[np].derived.cool_comp_ioniz + plasmamain[np].derived.cool_adiabatic_ioniz + plasmamain[np].derived.cool_dr_ioniz, plasmamain[np].derived.lum_tot_ioniz, plasmamain[np].derived.lum_rr_ioniz, plasmamain[np].derived.cool_rr_ioniz, plasmamain[np].derived.lum_ff_ioniz, plasmamain[np].derived.lum_lines_ioniz, plasmamain[np].derived.cool_adiabatic_ioniz, plasmamain[np].derived.cool_comp_ioniz, plasmamain[np].derived.cool_dr_ioniz, plasmamain[np].derived.cool_di_ioniz, plasmamain[np].est.heat_tot, plasmamain[np].est.heat_photo, plasmamain[np].est.heat_auger, plasmamain[np].est.heat_lines, plasmamain[np].est.heat_ff, plasmamain[np].est.heat_comp, plasmamain[np].est.heat_ind_comp, plasmamain[np].derived.heat_shock, h1den, h2den, he1den, he2den, he3den, c3den, c4den, c5den, n5den, o6den, si4den); } else { @@ -3468,10 +3477,11 @@ a:printf ("There are %i wind elements in this model\n", NDIM2); for (mm = 0; mm < nions; mm++) { - printf ("%i %i %e %e\n", mm, ion[mm].z, xplasma->density[mm], xplasma->density[mm] / (xplasma->rho * rho2nh)); + printf ("%i %i %e %e\n", mm, ion[mm].z, xplasma->state.density[mm], xplasma->state.density[mm] / (xplasma->state.rho * rho2nh)); if (ochoice) { - fprintf (fptr, "%i %i %e %e\n", mm, ion[mm].z, xplasma->density[mm], xplasma->density[mm] / (xplasma->rho * rho2nh)); + fprintf (fptr, "%i %i %e %e\n", mm, ion[mm].z, xplasma->state.density[mm], + xplasma->state.density[mm] / (xplasma->state.rho * rho2nh)); } } @@ -3516,12 +3526,12 @@ get_density_or_frac (xplasma, element, istate, frac_choice) nelem = find_element (element); /* get density of ion */ - density = xplasma->density[nion]; + density = xplasma->state.density[nion]; /* we want an ion fraction, not a density, so divide by nh */ if (frac_choice) { - nh = xplasma->density[0] + xplasma->density[1]; + nh = xplasma->state.density[0] + xplasma->state.density[1]; density /= ele[nelem].abun * nh; } @@ -3842,9 +3852,9 @@ flux_summary (w, rootname, ochoice) { fprintf (fptr, "%i %i %i %i %i %8.4e %8.4e %8.4e %8.4e ", n, np, w[n].inwind, ii, jj, w[n].x[0], w[n].x[2], w[n].rcen, w[n].thetacen / RADIAN); - fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].F_vis[0], plasmamain[np].F_vis[1], plasmamain[np].F_vis[2]); - fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].F_UV[0], plasmamain[np].F_UV[1], plasmamain[np].F_UV[2]); - fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].F_Xray[0], plasmamain[np].F_Xray[1], plasmamain[np].F_Xray[2]); + fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].est.F_vis[0], plasmamain[np].est.F_vis[1], plasmamain[np].est.F_vis[2]); + fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].est.F_UV[0], plasmamain[np].est.F_UV[1], plasmamain[np].est.F_UV[2]); + fprintf (fptr, "%8.4e %8.4e %8.4e ", plasmamain[np].est.F_Xray[0], plasmamain[np].est.F_Xray[1], plasmamain[np].est.F_Xray[2]); fprintf (fptr, "\n"); diff --git a/source/test_cooling.c b/source/test_cooling.c index 4ec85a367..57a92dc65 100644 --- a/source/test_cooling.c +++ b/source/test_cooling.c @@ -174,11 +174,11 @@ xcalc_te (PlasmaPtr xplasma, double tmin, double tmax) xxxplasma = xplasma; - xxxplasma->heat_tot += xxxplasma->heat_ch_ex; + xxxplasma->est.heat_tot += xxxplasma->est.heat_ch_ex; - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; z1 = zero_emit (tmin); - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; z2 = zero_emit (tmax); /* The way this works is that if we have a situation where the cooling @@ -188,7 +188,7 @@ xcalc_te (PlasmaPtr xplasma, double tmin, double tmax) if ((z1 * z2 < 0.0)) { // Then the interval is bracketed - xplasma->t_e = zero_find (zero_emit2, tmin, tmax, 50., &ierr); + xplasma->state.t_e = zero_find (zero_emit2, tmin, tmax, 50., &ierr); if (ierr) { Error ("calc_te: zero_find failed to find a temperature\n"); @@ -197,11 +197,11 @@ xcalc_te (PlasmaPtr xplasma, double tmin, double tmax) } else if (fabs (z1) < fabs (z2)) { - xplasma->t_e = tmin; + xplasma->state.t_e = tmin; } else { - xplasma->t_e = tmax; + xplasma->state.t_e = tmax; } /* With the new temperature in place for the cell, get the correct value of heat_tot. SS June 04 */ @@ -215,26 +215,26 @@ xcalc_te (PlasmaPtr xplasma, double tmin, double tmax) * We subtract the current value and then compute at the new temperature and * add this back */ - xplasma->heat_tot -= xplasma->heat_lines_macro; - xplasma->heat_lines -= xplasma->heat_lines_macro; + xplasma->est.heat_tot -= xplasma->est.heat_lines_macro; + xplasma->est.heat_lines -= xplasma->est.heat_lines_macro; - xplasma->heat_lines_macro = macro_bb_heating (xplasma, xplasma->t_e); + xplasma->est.heat_lines_macro = macro_bb_heating (xplasma, xplasma->state.t_e); - xplasma->heat_tot += xplasma->heat_lines_macro; - xplasma->heat_lines += xplasma->heat_lines_macro; + xplasma->est.heat_tot += xplasma->est.heat_lines_macro; + xplasma->est.heat_lines += xplasma->est.heat_lines_macro; /* Similaryly for macro_atom_bf_heating */ - xplasma->heat_tot -= xplasma->heat_photo_macro; - xplasma->heat_photo -= xplasma->heat_photo_macro; + xplasma->est.heat_tot -= xplasma->est.heat_photo_macro; + xplasma->est.heat_photo -= xplasma->est.heat_photo_macro; - xplasma->heat_photo_macro = macro_bf_heating (xplasma, xplasma->t_e); + xplasma->est.heat_photo_macro = macro_bf_heating (xplasma, xplasma->state.t_e); - xplasma->heat_tot += xplasma->heat_photo_macro; - xplasma->heat_photo += xplasma->heat_photo_macro; + xplasma->est.heat_tot += xplasma->est.heat_photo_macro; + xplasma->est.heat_photo += xplasma->est.heat_photo_macro; - return (xplasma->t_e); + return (xplasma->state.t_e); } @@ -302,11 +302,11 @@ main (argc, argv) fprintf (fptr, "# Results for %s\n", infile); - printf ("te %.3e\n", plasmamain[0].t_e); - fprintf (fptr, "te %.3e\n", plasmamain[0].t_e); + printf ("te %.3e\n", plasmamain[0].state.t_e); + fprintf (fptr, "te %.3e\n", plasmamain[0].state.t_e); double t, t_new; - t = plasmamain[0].t_e; + t = plasmamain[0].state.t_e; t_new = xcalc_te (&plasmamain[0], 0.7 * t, 1.3 * t); printf ("te_new %.3e\n", t_new); diff --git a/source/tests/unit_test_model.c b/source/tests/unit_test_model.c index cc1cb1d42..1174e21a9 100644 --- a/source/tests/unit_test_model.c +++ b/source/tests/unit_test_model.c @@ -136,23 +136,23 @@ cleanup_model (const char *root_name) for (n_plasma = 0; n_plasma < NPLASMA + 1; ++n_plasma) { plasma_cell = &plasmamain[n_plasma]; - free (plasma_cell->density); - free (plasma_cell->partition); - free (plasma_cell->ioniz); - free (plasma_cell->recomb); - free (plasma_cell->scatters); - free (plasma_cell->xscatters); - free (plasma_cell->heat_ion); - free (plasma_cell->heat_inner_ion); - free (plasma_cell->cool_rr_ion); - free (plasma_cell->lum_rr_ion); - free (plasma_cell->inner_recomb); - free (plasma_cell->inner_ioniz); - free (plasma_cell->cool_dr_ion); - free (plasma_cell->levden); - free (plasma_cell->recomb_simple); - free (plasma_cell->recomb_simple_upweight); - free (plasma_cell->kbf_use); + free (plasma_cell->state.density); + free (plasma_cell->state.partition); + free (plasma_cell->est.ioniz); + free (plasma_cell->derived.recomb); + free (plasma_cell->derived.scatters); + free (plasma_cell->derived.xscatters); + free (plasma_cell->est.heat_ion); + free (plasma_cell->est.heat_inner_ion); + free (plasma_cell->derived.cool_rr_ion); + free (plasma_cell->derived.lum_rr_ion); + free (plasma_cell->derived.inner_recomb); + free (plasma_cell->est.inner_ioniz); + free (plasma_cell->derived.cool_dr_ion); + free (plasma_cell->state.levden); + free (plasma_cell->state.recomb_simple); + free (plasma_cell->state.recomb_simple_upweight); + free (plasma_cell->state.kbf_use); } free_and_null ((void **) &plasmamain); @@ -164,27 +164,27 @@ cleanup_model (const char *root_name) for (n_plasma = 0; n_plasma < NPLASMA + 1; n_plasma++) { macro_cell = ¯omain[n_plasma]; - free (macro_cell->jbar); - free (macro_cell->jbar_old); - free (macro_cell->gamma); - free (macro_cell->gamma_old); - free (macro_cell->gamma_e); - free (macro_cell->gamma_e_old); - free (macro_cell->alpha_st); - free (macro_cell->alpha_st_old); - free (macro_cell->alpha_st_e); - free (macro_cell->alpha_st_e_old); - free (macro_cell->recomb_sp); - free (macro_cell->recomb_sp_e); - free (macro_cell->matom_emiss); - free (macro_cell->matom_abs); - free (macro_cell->cooling_bf); - free (macro_cell->cooling_bf_col); - free (macro_cell->cooling_bb); - - if (macro_cell->store_matom_matrix == TRUE) + free (macro_cell->est.jbar); + free (macro_cell->state.jbar_old); + free (macro_cell->est.gamma); + free (macro_cell->state.gamma_old); + free (macro_cell->est.gamma_e); + free (macro_cell->state.gamma_e_old); + free (macro_cell->est.alpha_st); + free (macro_cell->state.alpha_st_old); + free (macro_cell->est.alpha_st_e); + free (macro_cell->state.alpha_st_e_old); + free (macro_cell->est.recomb_sp); + free (macro_cell->est.recomb_sp_e); + free (macro_cell->derived.matom_emiss); + free (macro_cell->est.matom_abs); + free (macro_cell->est.cooling_bf); + free (macro_cell->est.cooling_bf_col); + free (macro_cell->est.cooling_bb); + + if (macro_cell->state.store_matom_matrix == TRUE) { - free_and_null ((void **) ¯o_cell->matom_matrix); + free_and_null ((void **) ¯o_cell->derived.matom_matrix); } } diff --git a/source/trans_phot.c b/source/trans_phot.c index 79ef9b390..d72280d51 100644 --- a/source/trans_phot.c +++ b/source/trans_phot.c @@ -449,7 +449,7 @@ trans_phot_single (WindPtr w, PhotPtr p, int iextract) if (modes.track_resonant_scatters) track_scatters (&pp, wmain[n_grid].nplasma, "Resonant"); - plasmamain[wmain[n_grid].nplasma].scatters[line[current_nres].nion] += 1; + plasmamain[wmain[n_grid].nplasma].derived.scatters[line[current_nres].nion] += 1; if (geo.rt_mode == RT_MODE_2LEVEL) { diff --git a/source/unit_test.c b/source/unit_test.c index 254391da4..273bf09ea 100644 --- a/source/unit_test.c +++ b/source/unit_test.c @@ -378,9 +378,9 @@ par_wind_luminosity (f1, f2, mode) MPI_Pack (&n, 1, MPI_INT, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); // Log ("Position2 %d %d\n", n, position); // Now transimit the values we want (8) - MPI_Pack (&plasmamain[n].lum_lines, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n].lum_rr, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n].lum_ff, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n].derived.lum_lines, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n].derived.lum_rr, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); + MPI_Pack (&plasmamain[n].derived.lum_ff, 1, MPI_DOUBLE, commbuffer, size_of_commbuffer, &position, MPI_COMM_WORLD); // Log ("Position3 %d %d\n", n, position); } @@ -400,9 +400,9 @@ par_wind_luminosity (f1, f2, mode) for (n_mpi2 = 0; n_mpi2 < num_comm; n_mpi2++) { MPI_Unpack (commbuffer, size_of_commbuffer, &position, &n, 1, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].derived.lum_lines, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].derived.lum_rr, 1, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (commbuffer, size_of_commbuffer, &position, &plasmamain[n].derived.lum_ff, 1, MPI_DOUBLE, MPI_COMM_WORLD); } } @@ -418,13 +418,13 @@ par_wind_luminosity (f1, f2, mode) { if (mode == MODE_OBSERVER_FRAME_TIME) - factor = 1.0 / plasmamain[nplasma].xgamma; /* this is dt_cmf */ + factor = 1.0 / plasmamain[nplasma].state.xgamma; /* this is dt_cmf */ else if (mode == MODE_CMF_TIME) factor = 1.0; - lum_lines += plasmamain[nplasma].lum_lines * factor; - lum_rr += plasmamain[nplasma].lum_rr * factor; - lum_ff += plasmamain[nplasma].lum_ff * factor; + lum_lines += plasmamain[nplasma].derived.lum_lines * factor; + lum_rr += plasmamain[nplasma].derived.lum_rr * factor; + lum_ff += plasmamain[nplasma].derived.lum_ff * factor; } lum = lum_lines + lum_rr + lum_ff; diff --git a/source/wind2d.c b/source/wind2d.c index 9c929e906..0f5d13ac2 100644 --- a/source/wind2d.c +++ b/source/wind2d.c @@ -354,7 +354,7 @@ rho (w, x) for (nn = 0; nn < nelem; nn++) { nplasma = w[nnn[nn]].nplasma; - dd += plasmamain[nplasma].rho * frac[nn]; + dd += plasmamain[nplasma].state.rho * frac[nn]; } } @@ -536,7 +536,7 @@ zero_scatters () { for (j = 0; j < nions; j++) { - plasmamain[n].scatters[j] = 0; + plasmamain[n].derived.scatters[j] = 0; } } @@ -653,10 +653,10 @@ check_grid () ndom = one->ndom; /* Hydrogen density, ne should be roughly this */ - nh = xplasma->rho * rho2nh; + nh = xplasma->state.rho * rho2nh; /* thermal speed */ -//OLD vth = sqrt (1.5 * BOLTZMANN * xplasma->t_e / MPROT); +//OLD vth = sqrt (1.5 * BOLTZMANN * xplasma->state.t_e / MPROT); /* sobolev length -- this could be used for a check but isn't yet */ //OLD l_sob = vth / one->dvds_ave; diff --git a/source/wind_sum.c b/source/wind_sum.c index 3bff0616c..60c2d829b 100644 --- a/source/wind_sum.c +++ b/source/wind_sum.c @@ -105,7 +105,7 @@ xtemp_rad (w) { n = nstart + i; nplasma = w[n].nplasma; - Log ("%8.2e ", plasmamain[nplasma].t_r); + Log ("%8.2e ", plasmamain[nplasma].state.t_r); if (j % 10 == 0) { Log ("\n"); @@ -120,7 +120,7 @@ xtemp_rad (w) { n = nstart + i; nplasma = w[n].nplasma; - Log ("%8.2e ", plasmamain[nplasma].t_e); + Log ("%8.2e ", plasmamain[nplasma].state.t_e); if (j % 10 == 0) { Log ("\n"); @@ -137,7 +137,7 @@ xtemp_rad (w) nplasma = w[n].nplasma; if (wmain[n].inwind >= 0) { - ntot = plasmamain[nplasma].ntot; + ntot = plasmamain[nplasma].est.ntot; } else ntot = 0; @@ -176,7 +176,7 @@ xtemp_rad (w) if (w[n].inwind >= 0) { nplasma = w[n].nplasma; - x = plasmamain[nplasma].t_r; + x = plasmamain[nplasma].state.t_r; } else x = 0.0; @@ -201,7 +201,7 @@ xtemp_rad (w) nplasma = w[n].nplasma; if (wmain[n].inwind >= 0) { - x = plasmamain[nplasma].t_e; + x = plasmamain[nplasma].state.t_e; } else x = 0.0; @@ -226,7 +226,7 @@ xtemp_rad (w) nplasma = w[n].nplasma; if (wmain[n].inwind >= 0) { - ntot = plasmamain[nplasma].ntot; + ntot = plasmamain[nplasma].est.ntot; } else ntot = -99; diff --git a/source/wind_updates2d.c b/source/wind_updates2d.c index 2e38cae9d..1e30d6978 100644 --- a/source/wind_updates2d.c +++ b/source/wind_updates2d.c @@ -99,11 +99,11 @@ wind_update (WindPtr w) continue; } - if (plasmamain[n_plasma].ntot < 100) + if (plasmamain[n_plasma].est.ntot < 100) { Log ("!!wind_update: Cell %4d Dom %d Vol. %8.2e r %8.2e theta %8.2e has only %4d photons\n", - n_plasma, w[nwind].ndom, volume, w[nwind].rcen, w[nwind].thetacen, plasmamain[n_plasma].ntot); + n_plasma, w[nwind].ndom, volume, w[nwind].rcen, w[nwind].thetacen, plasmamain[n_plasma].est.ntot); } /* Start with a call to the routine which normalises all the macro atom @@ -132,20 +132,20 @@ wind_update (WindPtr w) if (geo.adiabatic) { - plasmamain[n_plasma].cool_adiabatic = adiabatic_cooling (&w[nwind], plasmamain[n_plasma].t_e); + plasmamain[n_plasma].derived.cool_adiabatic = adiabatic_cooling (&w[nwind], plasmamain[n_plasma].state.t_e); } else { - plasmamain[n_plasma].cool_adiabatic = 0.0; + plasmamain[n_plasma].derived.cool_adiabatic = 0.0; } if (geo.nonthermal) { - plasmamain[n_plasma].heat_shock = shock_heating (&w[nwind]); + plasmamain[n_plasma].derived.heat_shock = shock_heating (&w[nwind]); } else { - plasmamain[n_plasma].heat_shock = 0.0; + plasmamain[n_plasma].derived.heat_shock = 0.0; } /* Calculate the densities in various ways depending on the ioniz_mode */ @@ -228,47 +228,47 @@ wind_update (WindPtr w) { /* First we want to find the maximum change in temperature, which we will * use for reporting and to calculate the convergence */ - if ((fabs (plasmamain[n_plasma].t_r_old - plasmamain[n_plasma].t_r)) > fabs (dt_r)) + if ((fabs (plasmamain[n_plasma].state.t_r_old - plasmamain[n_plasma].state.t_r)) > fabs (dt_r)) { - dt_r = plasmamain[n_plasma].t_r - plasmamain[n_plasma].t_r_old; + dt_r = plasmamain[n_plasma].state.t_r - plasmamain[n_plasma].state.t_r_old; nmax_r = n_plasma; } - if ((fabs (plasmamain[n_plasma].t_e_old - plasmamain[n_plasma].t_e)) > fabs (dt_e)) + if ((fabs (plasmamain[n_plasma].state.t_e_old - plasmamain[n_plasma].state.t_e)) > fabs (dt_e)) { - dt_e = plasmamain[n_plasma].t_e - plasmamain[n_plasma].t_e_old; + dt_e = plasmamain[n_plasma].state.t_e - plasmamain[n_plasma].state.t_e_old; nmax_e = n_plasma; } - t_r_ave += plasmamain[n_plasma].t_r; - t_e_ave += plasmamain[n_plasma].t_e; - t_r_ave_old += plasmamain[n_plasma].t_r_old; - t_e_ave_old += plasmamain[n_plasma].t_e_old; + t_r_ave += plasmamain[n_plasma].state.t_r; + t_e_ave += plasmamain[n_plasma].state.t_e; + t_r_ave_old += plasmamain[n_plasma].state.t_r_old; + t_e_ave_old += plasmamain[n_plasma].state.t_e_old; check_heating_rates_for_plasma_cell (n_plasma); - plasmamain[n_plasma].cool_tot_ioniz = plasmamain[n_plasma].cool_tot; - plasmamain[n_plasma].lum_ff_ioniz = plasmamain[n_plasma].lum_ff; - plasmamain[n_plasma].cool_rr_ioniz = plasmamain[n_plasma].cool_rr; - plasmamain[n_plasma].lum_rr_ioniz = plasmamain[n_plasma].lum_rr; - plasmamain[n_plasma].cool_rr_metals_ioniz = plasmamain[n_plasma].cool_rr_metals; - plasmamain[n_plasma].lum_lines_ioniz = plasmamain[n_plasma].lum_lines; - plasmamain[n_plasma].cool_comp_ioniz = plasmamain[n_plasma].cool_comp; - plasmamain[n_plasma].cool_dr_ioniz = plasmamain[n_plasma].cool_dr; - plasmamain[n_plasma].cool_di_ioniz = plasmamain[n_plasma].cool_di; - plasmamain[n_plasma].lum_tot_ioniz = plasmamain[n_plasma].lum_tot; - plasmamain[n_plasma].cool_adiabatic_ioniz = plasmamain[n_plasma].cool_adiabatic; - - abstot += plasmamain[n_plasma].abs_tot; - xsum += plasmamain[n_plasma].heat_tot; - psum += plasmamain[n_plasma].heat_photo; - ausum += plasmamain[n_plasma].heat_auger; - fsum += plasmamain[n_plasma].heat_ff; - lsum += plasmamain[n_plasma].heat_lines; - csum += plasmamain[n_plasma].heat_comp; - icsum += plasmamain[n_plasma].heat_ind_comp; - apsum += plasmamain[n_plasma].abs_photo; - aausum += plasmamain[n_plasma].abs_auger; - chexsum += plasmamain[n_plasma].heat_ch_ex; + plasmamain[n_plasma].derived.cool_tot_ioniz = plasmamain[n_plasma].est.cool_tot; + plasmamain[n_plasma].derived.lum_ff_ioniz = plasmamain[n_plasma].derived.lum_ff; + plasmamain[n_plasma].derived.cool_rr_ioniz = plasmamain[n_plasma].derived.cool_rr; + plasmamain[n_plasma].derived.lum_rr_ioniz = plasmamain[n_plasma].derived.lum_rr; + plasmamain[n_plasma].derived.cool_rr_metals_ioniz = plasmamain[n_plasma].derived.cool_rr_metals; + plasmamain[n_plasma].derived.lum_lines_ioniz = plasmamain[n_plasma].derived.lum_lines; + plasmamain[n_plasma].derived.cool_comp_ioniz = plasmamain[n_plasma].derived.cool_comp; + plasmamain[n_plasma].derived.cool_dr_ioniz = plasmamain[n_plasma].derived.cool_dr; + plasmamain[n_plasma].derived.cool_di_ioniz = plasmamain[n_plasma].derived.cool_di; + plasmamain[n_plasma].derived.lum_tot_ioniz = plasmamain[n_plasma].derived.lum_tot; + plasmamain[n_plasma].derived.cool_adiabatic_ioniz = plasmamain[n_plasma].derived.cool_adiabatic; + + abstot += plasmamain[n_plasma].derived.abs_tot; + xsum += plasmamain[n_plasma].est.heat_tot; + psum += plasmamain[n_plasma].est.heat_photo; + ausum += plasmamain[n_plasma].est.heat_auger; + fsum += plasmamain[n_plasma].est.heat_ff; + lsum += plasmamain[n_plasma].est.heat_lines; + csum += plasmamain[n_plasma].est.heat_comp; + icsum += plasmamain[n_plasma].est.heat_ind_comp; + apsum += plasmamain[n_plasma].derived.abs_photo; + aausum += plasmamain[n_plasma].derived.abs_auger; + chexsum += plasmamain[n_plasma].est.heat_ch_ex; } /* We can now calculate the average of the t */ @@ -415,13 +415,13 @@ report_bf_simple_ionpool (void) for (n = 0; n < NPLASMA; n++) { - total_in += plasmamain[n].bf_simple_ionpool_in; - total_out += plasmamain[n].bf_simple_ionpool_out; + total_in += plasmamain[n].derived.bf_simple_ionpool_in; + total_out += plasmamain[n].derived.bf_simple_ionpool_out; - if (plasmamain[n].bf_simple_ionpool_out > plasmamain[n].bf_simple_ionpool_in) + if (plasmamain[n].derived.bf_simple_ionpool_out > plasmamain[n].derived.bf_simple_ionpool_in) { Error ("The net flow out of simple ion pool (%8.4e) > than the net flow in (%8.4e) in cell %d\n", - plasmamain[n].bf_simple_ionpool_out, plasmamain[n].bf_simple_ionpool_in, n); + plasmamain[n].derived.bf_simple_ionpool_out, plasmamain[n].derived.bf_simple_ionpool_in, n); } } @@ -433,8 +433,8 @@ report_bf_simple_ionpool (void) in_tot = out_tot = 0; for (n = 0; n < NPLASMA; n++) { - in_tot += plasmamain[n].n_bf_in[m]; - out_tot += plasmamain[n].n_bf_out[m]; + in_tot += plasmamain[n].derived.n_bf_in[m]; + out_tot += plasmamain[n].derived.n_bf_out[m]; } Log ("!! report_bf: %3d %3d %3d %7d %7d\n", m, phot_top[m].z, phot_top[m].istate, in_tot, out_tot); @@ -492,37 +492,37 @@ wind_rad_init () void check_heating_rates_for_plasma_cell (const int n_plasma) { - if (sane_check (plasmamain[n_plasma].heat_tot)) + if (sane_check (plasmamain[n_plasma].est.heat_tot)) { - Error ("wind_update:sane_check w(%d).heat_tot is %e\n", n_plasma, plasmamain[n_plasma].heat_tot); + Error ("wind_update:sane_check w(%d).heat_tot is %e\n", n_plasma, plasmamain[n_plasma].est.heat_tot); } - if (sane_check (plasmamain[n_plasma].heat_photo)) + if (sane_check (plasmamain[n_plasma].est.heat_photo)) { - Error ("wind_update:sane_check w(%d).heat_photo is %e\n", n_plasma, plasmamain[n_plasma].heat_photo); + Error ("wind_update:sane_check w(%d).heat_photo is %e\n", n_plasma, plasmamain[n_plasma].est.heat_photo); } - if (sane_check (plasmamain[n_plasma].heat_auger)) + if (sane_check (plasmamain[n_plasma].est.heat_auger)) { - Error ("wind_update:sane_check w(%d).heat_auger is %e\n", n_plasma, plasmamain[n_plasma].heat_auger); + Error ("wind_update:sane_check w(%d).heat_auger is %e\n", n_plasma, plasmamain[n_plasma].est.heat_auger); } - if (sane_check (plasmamain[n_plasma].heat_photo_macro)) + if (sane_check (plasmamain[n_plasma].est.heat_photo_macro)) { - Error ("wind_update:sane_check w(%d).heat_photo_macro is %e\n", n_plasma, plasmamain[n_plasma].heat_photo_macro); + Error ("wind_update:sane_check w(%d).heat_photo_macro is %e\n", n_plasma, plasmamain[n_plasma].est.heat_photo_macro); } - if (sane_check (plasmamain[n_plasma].heat_ff)) + if (sane_check (plasmamain[n_plasma].est.heat_ff)) { - Error ("wind_update:sane_check w(%d).heat_ff is %e\n", n_plasma, plasmamain[n_plasma].heat_ff); + Error ("wind_update:sane_check w(%d).heat_ff is %e\n", n_plasma, plasmamain[n_plasma].est.heat_ff); } - if (sane_check (plasmamain[n_plasma].heat_lines)) + if (sane_check (plasmamain[n_plasma].est.heat_lines)) { - Error ("wind_update:sane_check w(%d).heat_lines is %e\n", n_plasma, plasmamain[n_plasma].heat_lines); + Error ("wind_update:sane_check w(%d).heat_lines is %e\n", n_plasma, plasmamain[n_plasma].est.heat_lines); } - if (sane_check (plasmamain[n_plasma].heat_lines_macro)) + if (sane_check (plasmamain[n_plasma].est.heat_lines_macro)) { - Error ("wind_update:sane_check w(%d).heat_lines_macro is %e\n", n_plasma, plasmamain[n_plasma].heat_lines_macro); + Error ("wind_update:sane_check w(%d).heat_lines_macro is %e\n", n_plasma, plasmamain[n_plasma].est.heat_lines_macro); } - if (sane_check (plasmamain[n_plasma].heat_comp)) + if (sane_check (plasmamain[n_plasma].est.heat_comp)) { - Error ("wind_update:sane_check w(%d).heat_comp is %e\n", n_plasma, plasmamain[n_plasma].heat_comp); + Error ("wind_update:sane_check w(%d).heat_comp is %e\n", n_plasma, plasmamain[n_plasma].est.heat_comp); } } @@ -548,131 +548,131 @@ init_plasma_rad_properties (void) for (i = 0; i < NPLASMA; ++i) { /* Start by initialising integer fields */ - plasmamain[i].j = 0; - plasmamain[i].ave_freq = 0; - plasmamain[i].ntot = 0; - plasmamain[i].n_ds = 0; - plasmamain[i].ntot_disk = 0; - plasmamain[i].ntot_agn = 0; - plasmamain[i].ntot_star = 0; - plasmamain[i].ntot_bl = 0; - plasmamain[i].nscat_es = 0; - plasmamain[i].nscat_res = 0; - plasmamain[i].nscat_bf = 0; - plasmamain[i].nscat_ff = 0; - plasmamain[i].ntot_wind = 0; - plasmamain[i].nrad = 0; - plasmamain[i].nioniz = 0; + plasmamain[i].est.j = 0; + plasmamain[i].est.ave_freq = 0; + plasmamain[i].est.ntot = 0; + plasmamain[i].est.n_ds = 0; + plasmamain[i].est.ntot_disk = 0; + plasmamain[i].est.ntot_agn = 0; + plasmamain[i].est.ntot_star = 0; + plasmamain[i].est.ntot_bl = 0; + plasmamain[i].derived.nscat_es = 0; + plasmamain[i].derived.nscat_res = 0; + plasmamain[i].derived.nscat_bf = 0; + plasmamain[i].derived.nscat_ff = 0; + plasmamain[i].est.ntot_wind = 0; + plasmamain[i].derived.nrad = 0; + plasmamain[i].est.nioniz = 0; for (j = 0; j < nphot_total; j++) { - plasmamain[i].n_bf_in[j] = 0; - plasmamain[i].n_bf_out[j] = 0; + plasmamain[i].derived.n_bf_in[j] = 0; + plasmamain[i].derived.n_bf_out[j] = 0; } /* Next we'll initialise the rest of the fields, which are doubles */ - plasmamain[i].j_direct = 0.0; - plasmamain[i].j_scatt = 0.0; - plasmamain[i].ip = 0.0; - plasmamain[i].xi = 0.0; - plasmamain[i].ip_direct = 0.0; - plasmamain[i].ip_scatt = 0.0; - plasmamain[i].mean_ds = 0.0; - plasmamain[i].heat_tot = 0.0; - plasmamain[i].heat_ff = 0.0; - plasmamain[i].heat_photo = 0.0; - plasmamain[i].heat_lines = 0.0; - plasmamain[i].abs_tot = 0.0; - plasmamain[i].abs_auger = 0.0; - plasmamain[i].abs_photo = 0.0; - plasmamain[i].heat_z = 0.0; - plasmamain[i].max_freq = 0.0; - plasmamain[i].cool_tot = 0.0; - plasmamain[i].lum_tot = 0.0; - plasmamain[i].lum_lines = 0.0; - plasmamain[i].lum_ff = 0.0; - plasmamain[i].cool_rr = 0.0; - plasmamain[i].cool_rr_metals = 0.0; - plasmamain[i].lum_rr = 0.0; - plasmamain[i].comp_nujnu = -1e99; - plasmamain[i].cool_comp = 0.0; - plasmamain[i].heat_comp = 0.0; - plasmamain[i].heat_ind_comp = 0.0; - plasmamain[i].heat_auger = 0.0; - plasmamain[i].heat_ch_ex = 0.0; - plasmamain[i].bf_simple_ionpool_out = 0.0; - plasmamain[i].bf_simple_ionpool_in = 0.0; + plasmamain[i].est.j_direct = 0.0; + plasmamain[i].est.j_scatt = 0.0; + plasmamain[i].est.ip = 0.0; + plasmamain[i].derived.xi = 0.0; + plasmamain[i].est.ip_direct = 0.0; + plasmamain[i].est.ip_scatt = 0.0; + plasmamain[i].est.mean_ds = 0.0; + plasmamain[i].est.heat_tot = 0.0; + plasmamain[i].est.heat_ff = 0.0; + plasmamain[i].est.heat_photo = 0.0; + plasmamain[i].est.heat_lines = 0.0; + plasmamain[i].derived.abs_tot = 0.0; + plasmamain[i].derived.abs_auger = 0.0; + plasmamain[i].derived.abs_photo = 0.0; + plasmamain[i].est.heat_z = 0.0; + plasmamain[i].est.max_freq = 0.0; + plasmamain[i].est.cool_tot = 0.0; + plasmamain[i].derived.lum_tot = 0.0; + plasmamain[i].derived.lum_lines = 0.0; + plasmamain[i].derived.lum_ff = 0.0; + plasmamain[i].derived.cool_rr = 0.0; + plasmamain[i].derived.cool_rr_metals = 0.0; + plasmamain[i].derived.lum_rr = 0.0; + plasmamain[i].derived.comp_nujnu = -1e99; + plasmamain[i].derived.cool_comp = 0.0; + plasmamain[i].est.heat_comp = 0.0; + plasmamain[i].est.heat_ind_comp = 0.0; + plasmamain[i].est.heat_auger = 0.0; + plasmamain[i].est.heat_ch_ex = 0.0; + plasmamain[i].derived.bf_simple_ionpool_out = 0.0; + plasmamain[i].derived.bf_simple_ionpool_in = 0.0; for (j = 0; j < N_DMO_DT_DIRECTIONS; j++) { - plasmamain[i].dmo_dt[j] = 0.0; + plasmamain[i].derived.dmo_dt[j] = 0.0; } for (j = 0; j < NFORCE_DIRECTIONS; j++) { - plasmamain[i].rad_force_es[j] = 0.0; - plasmamain[i].rad_force_ff[j] = 0.0; - plasmamain[i].rad_force_bf[j] = 0.0; - plasmamain[i].F_vis[j] = 0.0; - plasmamain[i].F_UV[j] = 0.0; - plasmamain[i].F_Xray[j] = 0.0; + plasmamain[i].est.rad_force_es[j] = 0.0; + plasmamain[i].est.rad_force_ff[j] = 0.0; + plasmamain[i].est.rad_force_bf[j] = 0.0; + plasmamain[i].est.F_vis[j] = 0.0; + plasmamain[i].est.F_UV[j] = 0.0; + plasmamain[i].est.F_Xray[j] = 0.0; if (geo.wcycle == 0) // Persistent values, so only initialise for first ionisation cycle { - plasmamain[i].F_vis_persistent[j] = 0.0; - plasmamain[i].F_UV_persistent[j] = 0.0; - plasmamain[i].F_Xray_persistent[j] = 0.0; - plasmamain[i].rad_force_bf_persist[j] = 0.0; + plasmamain[i].derived.F_vis_persistent[j] = 0.0; + plasmamain[i].derived.F_UV_persistent[j] = 0.0; + plasmamain[i].derived.F_Xray_persistent[j] = 0.0; + plasmamain[i].derived.rad_force_bf_persist[j] = 0.0; } } for (j = 0; j < NFLUX_ANGLES; j++) { if (geo.wcycle == 0) // Persistent values, so only initialise for first ionisation cycle { - plasmamain[i].F_UV_ang_theta_persist[j] = 0.0; - plasmamain[i].F_UV_ang_phi_persist[j] = 0.0; - plasmamain[i].F_UV_ang_r_persist[j] = 0.0; + plasmamain[i].derived.F_UV_ang_theta_persist[j] = 0.0; + plasmamain[i].derived.F_UV_ang_phi_persist[j] = 0.0; + plasmamain[i].derived.F_UV_ang_r_persist[j] = 0.0; } - plasmamain[i].F_UV_ang_theta[j] = 0.0; - plasmamain[i].F_UV_ang_phi[j] = 0.0; - plasmamain[i].F_UV_ang_r[j] = 0.0; + plasmamain[i].est.F_UV_ang_theta[j] = 0.0; + plasmamain[i].est.F_UV_ang_phi[j] = 0.0; + plasmamain[i].est.F_UV_ang_r[j] = 0.0; } /* Initialise the frequency banded radiation estimators used for estimating the coarse spectra in each i */ - for (j = 0; j < plasmamain[i].nbands; j++) + for (j = 0; j < plasmamain[i].state.nbands; j++) { - plasmamain[i].nxtot[j] = 0; - plasmamain[i].xj[j] = 0.0; - plasmamain[i].xave_freq[j] = 0.0; - plasmamain[i].xsd_freq[j] = 0.0; - plasmamain[i].fmin[j] = plasmamain[i].f2[j]; /* Set the minium frequency to the max frequency in the band */ - plasmamain[i].fmax[j] = plasmamain[i].f1[j]; /* Set the maximum frequency to the min frequency in the band */ + plasmamain[i].est.nxtot[j] = 0; + plasmamain[i].est.xj[j] = 0.0; + plasmamain[i].est.xave_freq[j] = 0.0; + plasmamain[i].est.xsd_freq[j] = 0.0; + plasmamain[i].est.fmin[j] = plasmamain[i].state.f2[j]; /* Set the minium frequency to the max frequency in the band */ + plasmamain[i].est.fmax[j] = plasmamain[i].state.f1[j]; /* Set the maximum frequency to the min frequency in the band */ } /* Initialize unused band elements to safe values for MPI communication */ - for (j = plasmamain[i].nbands; j < NXBANDS; j++) + for (j = plasmamain[i].state.nbands; j < NXBANDS; j++) { - plasmamain[i].nxtot[j] = 0; - plasmamain[i].xj[j] = 0.0; - plasmamain[i].xave_freq[j] = 0.0; - plasmamain[i].xsd_freq[j] = 0.0; - plasmamain[i].fmin[j] = 0.0; - plasmamain[i].fmax[j] = 0.0; + plasmamain[i].est.nxtot[j] = 0; + plasmamain[i].est.xj[j] = 0.0; + plasmamain[i].est.xave_freq[j] = 0.0; + plasmamain[i].est.xsd_freq[j] = 0.0; + plasmamain[i].est.fmin[j] = 0.0; + plasmamain[i].est.fmax[j] = 0.0; } for (j = 0; j < NBINS_IN_CELL_SPEC; ++j) { - plasmamain[i].cell_spec_flux[j] = 0.0; + plasmamain[i].est.cell_spec_flux[j] = 0.0; } for (j = 0; j < nions; j++) { - plasmamain[i].ioniz[j] = 0.0; - plasmamain[i].recomb[j] = 0.0; - plasmamain[i].heat_ion[j] = 0.0; - plasmamain[i].cool_rr_ion[j] = 0.0; - plasmamain[i].lum_rr_ion[j] = 0.0; - plasmamain[i].heat_inner_ion[j] = 0.0; + plasmamain[i].est.ioniz[j] = 0.0; + plasmamain[i].derived.recomb[j] = 0.0; + plasmamain[i].est.heat_ion[j] = 0.0; + plasmamain[i].derived.cool_rr_ion[j] = 0.0; + plasmamain[i].derived.lum_rr_ion[j] = 0.0; + plasmamain[i].est.heat_inner_ion[j] = 0.0; } for (j = 0; j < n_inner_tot; j++) { - plasmamain[i].inner_ioniz[j] = 0.0; + plasmamain[i].est.inner_ioniz[j] = 0.0; } } } @@ -711,27 +711,27 @@ init_macro_rad_properties (void) { if (geo.rt_mode == RT_MODE_MACRO) { - macromain[n_plasma].kpkt_rates_known = FALSE; + macromain[n_plasma].derived.kpkt_rates_known = FALSE; } - plasmamain[n_plasma].kpkt_emiss = 0.0; - plasmamain[n_plasma].kpkt_abs = 0.0; + plasmamain[n_plasma].derived.kpkt_emiss = 0.0; + plasmamain[n_plasma].est.kpkt_abs = 0.0; for (macro_level = 0; macro_level < nlevels_macro; ++macro_level) { - macromain[n_plasma].matom_abs[macro_level] = 0.0; - macromain[n_plasma].matom_emiss[macro_level] = 0.0; + macromain[n_plasma].est.matom_abs[macro_level] = 0.0; + macromain[n_plasma].derived.matom_emiss[macro_level] = 0.0; for (k = 0; k < xconfig[macro_level].n_bbu_jump; ++k) { - macromain[n_plasma].jbar[xconfig[macro_level].bbu_indx_first + k] = 0.0; + macromain[n_plasma].est.jbar[xconfig[macro_level].bbu_indx_first + k] = 0.0; } for (k = 0; k < xconfig[macro_level].n_bfu_jump; ++k) { - macromain[n_plasma].gamma[xconfig[macro_level].bfu_indx_first + k] = 0.0; - macromain[n_plasma].gamma_e[xconfig[macro_level].bfu_indx_first + k] = 0.0; - macromain[n_plasma].alpha_st[xconfig[macro_level].bfd_indx_first + k] = 0.0; - macromain[n_plasma].alpha_st_e[xconfig[macro_level].bfd_indx_first + k] = 0.0; + macromain[n_plasma].est.gamma[xconfig[macro_level].bfu_indx_first + k] = 0.0; + macromain[n_plasma].est.gamma_e[xconfig[macro_level].bfu_indx_first + k] = 0.0; + macromain[n_plasma].est.alpha_st[xconfig[macro_level].bfd_indx_first + k] = 0.0; + macromain[n_plasma].est.alpha_st_e[xconfig[macro_level].bfd_indx_first + k] = 0.0; } } } @@ -753,17 +753,17 @@ init_macro_rad_properties (void) { for (k = 0; k < xconfig[macro_level].n_bfd_jump; ++k) { - if (plasmamain[n_plasma].t_e > 1.0) + if (plasmamain[n_plasma].state.t_e > 1.0) { - macromain[n_plasma].recomb_sp[xconfig[macro_level].bfd_indx_first + k] = + macromain[n_plasma].est.recomb_sp[xconfig[macro_level].bfd_indx_first + k] = alpha_sp (&phot_top[xconfig[macro_level].bfd_jump[k]], &plasmamain[n_plasma], 0); - macromain[n_plasma].recomb_sp_e[xconfig[macro_level].bfd_indx_first + k] = + macromain[n_plasma].est.recomb_sp_e[xconfig[macro_level].bfd_indx_first + k] = alpha_sp (&phot_top[xconfig[macro_level].bfd_jump[k]], &plasmamain[n_plasma], 2); } else { - macromain[n_plasma].recomb_sp[xconfig[macro_level].bfd_indx_first + k] = 0.0; - macromain[n_plasma].recomb_sp_e[xconfig[macro_level].bfd_indx_first + k] = 0.0; + macromain[n_plasma].est.recomb_sp[xconfig[macro_level].bfd_indx_first + k] = 0.0; + macromain[n_plasma].est.recomb_sp_e[xconfig[macro_level].bfd_indx_first + k] = 0.0; } } } @@ -771,14 +771,14 @@ init_macro_rad_properties (void) { if ((geo.macro_simple == FALSE && phot_top[macro_level].macro_info == TRUE) || geo.rt_mode == RT_MODE_2LEVEL) { - plasmamain[n_plasma].recomb_simple[macro_level] = 0.0; - plasmamain[n_plasma].recomb_simple_upweight[macro_level] = 1.0; + plasmamain[n_plasma].state.recomb_simple[macro_level] = 0.0; + plasmamain[n_plasma].state.recomb_simple_upweight[macro_level] = 1.0; } else // we want a macro approach, but not for this ion so need recomb_simple instead { - const double alpha_store = plasmamain[n_plasma].recomb_simple[macro_level] = + const double alpha_store = plasmamain[n_plasma].state.recomb_simple[macro_level] = alpha_sp (&phot_top[macro_level], &plasmamain[n_plasma], 2); - plasmamain[n_plasma].recomb_simple_upweight[macro_level] = + plasmamain[n_plasma].state.recomb_simple_upweight[macro_level] = alpha_sp (&phot_top[macro_level], &plasmamain[n_plasma], 1) / alpha_store; } } @@ -830,13 +830,14 @@ shell_output_wind_update_diagnostics (double xsum, double psum, double fsum, dou nshell = wmain[zdom[ndom].nstart + 1].nplasma; n = plasmamain[nshell].nwind; WindPtr w = &wmain[n]; - for (i = 0; i < plasmamain[nshell].nbands; i++) + for (i = 0; i < plasmamain[nshell].state.nbands; i++) { /*loop over number of bands */ Log ("Band %i f1 %e f2 %e model %i pl_alpha %f pl_log_w %e exp_t %e exp_w %e\n", - i, plasmamain[nshell].f1[i], plasmamain[nshell].f2[i], - plasmamain[nshell].spec_mod_type[i], - plasmamain[nshell].pl_alpha[i], plasmamain[nshell].pl_log_w[i], plasmamain[nshell].exp_temp[i], plasmamain[nshell].exp_w[i]); + i, plasmamain[nshell].state.f1[i], plasmamain[nshell].state.f2[i], + plasmamain[nshell].state.spec_mod_type[i], + plasmamain[nshell].state.pl_alpha[i], plasmamain[nshell].state.pl_log_w[i], plasmamain[nshell].state.exp_temp[i], + plasmamain[nshell].state.exp_w[i]); } /* Get some line diagnostics */ @@ -864,14 +865,14 @@ shell_output_wind_update_diagnostics (double xsum, double psum, double fsum, dou } agn_ip = geo.const_agn * (((pow (50000 / HEV, geo.alpha_agn + 1.0)) - pow (100 / HEV, geo.alpha_agn + 1.0)) / (geo.alpha_agn + 1.0)); agn_ip /= (w[n].r * w[n].r); - agn_ip /= plasmamain[nshell].rho * rho2nh; + agn_ip /= plasmamain[nshell].state.rho * rho2nh; /* Report luminosities, IP and other diagnositic quantities */ Log ("OUTPUT Lum_agn= %e T_e= %e N_h= %e N_e= %e alpha= %f IP(sim_2010)= %e Measured_IP(cloudy)= %e Measured_Xi= %e distance= %e volume= %e mean_ds=%e\n", - geo.lum_agn, plasmamain[nshell].t_e, - plasmamain[nshell].rho * rho2nh, plasmamain[nshell].ne, - geo.alpha_agn, agn_ip, plasmamain[nshell].ip, - plasmamain[nshell].xi, w[n].r, w[n].vol, plasmamain[nshell].mean_ds / plasmamain[nshell].n_ds); + geo.lum_agn, plasmamain[nshell].state.t_e, + plasmamain[nshell].state.rho * rho2nh, plasmamain[nshell].state.ne, + geo.alpha_agn, agn_ip, plasmamain[nshell].est.ip, + plasmamain[nshell].derived.xi, w[n].r, w[n].vol, plasmamain[nshell].est.mean_ds / plasmamain[nshell].est.n_ds); Log ("OUTPUT Absorbed_flux(ergs-1cm-3) %8.2e (photo %8.2e ff %8.2e compton %8.2e induced_compton %8.2e lines %8.2e auger %8.2e charge_ex %8.2e )\n", xsum / w[n].vol, psum / w[n].vol, fsum / w[n].vol, csum / w[n].vol, icsum / w[n].vol, lsum / w[n].vol, ausum / w[n].vol, @@ -904,49 +905,51 @@ shell_output_wind_update_diagnostics (double xsum, double psum, double fsum, dou { if (ion[nn].z == 6) { - c_dr = c_dr + plasmamain[nshell].cool_dr_ion[nn]; - c_rec = c_rec + plasmamain[nshell].cool_rr_ion[nn]; - c_lum = c_lum + plasmamain[nshell].lum_rr_ion[nn]; + c_dr = c_dr + plasmamain[nshell].derived.cool_dr_ion[nn]; + c_rec = c_rec + plasmamain[nshell].derived.cool_rr_ion[nn]; + c_lum = c_lum + plasmamain[nshell].derived.lum_rr_ion[nn]; } if (ion[nn].z == 7) { - n_dr = n_dr + plasmamain[nshell].cool_dr_ion[nn]; - n_rec = n_rec + plasmamain[nshell].cool_rr_ion[nn]; - n_lum = n_lum + plasmamain[nshell].lum_rr_ion[nn]; + n_dr = n_dr + plasmamain[nshell].derived.cool_dr_ion[nn]; + n_rec = n_rec + plasmamain[nshell].derived.cool_rr_ion[nn]; + n_lum = n_lum + plasmamain[nshell].derived.lum_rr_ion[nn]; } if (ion[nn].z == 8) { - o_dr = o_dr + plasmamain[nshell].cool_dr_ion[nn]; - o_rec = o_rec + plasmamain[nshell].cool_rr_ion[nn]; - o_lum = o_lum + plasmamain[nshell].lum_rr_ion[nn]; + o_dr = o_dr + plasmamain[nshell].derived.cool_dr_ion[nn]; + o_rec = o_rec + plasmamain[nshell].derived.cool_rr_ion[nn]; + o_lum = o_lum + plasmamain[nshell].derived.lum_rr_ion[nn]; } if (ion[nn].z == 26) { - fe_dr = fe_dr + plasmamain[nshell].cool_dr_ion[nn]; - fe_rec = fe_rec + plasmamain[nshell].cool_rr_ion[nn]; - fe_lum = fe_lum + plasmamain[nshell].lum_rr_ion[nn]; + fe_dr = fe_dr + plasmamain[nshell].derived.cool_dr_ion[nn]; + fe_rec = fe_rec + plasmamain[nshell].derived.cool_rr_ion[nn]; + fe_lum = fe_lum + plasmamain[nshell].derived.lum_rr_ion[nn]; } if (ion[nn].z > 2) { - cool_dr_metals = cool_dr_metals + plasmamain[nshell].cool_dr_ion[nn]; + cool_dr_metals = cool_dr_metals + plasmamain[nshell].derived.cool_dr_ion[nn]; } } Log ("Wind_line_cooling(ergs-1cm-3) H %8.2e He %8.2e C %8.2e N %8.2e O %8.2e Fe %8.2e Metals %8.2e\n", lum_h_line / w[n].vol, lum_he_line / w[n].vol, lum_c_line / w[n].vol, lum_n_line / w[n].vol, lum_o_line / w[n].vol, lum_fe_line / w[n].vol); Log ("Wind_recomb_cooling(ergs-1cm-3) H %8.2e He %8.2e C %8.2e N %8.2e O %8.2e Fe %8.2e Metals %8.2e\n", - plasmamain[nshell].cool_rr_ion[0] / w[n].vol, - (plasmamain[nshell].cool_rr_ion[2] + plasmamain[nshell].cool_rr_ion[3]) / w[n].vol, c_rec / w[n].vol, n_rec / w[n].vol, - o_rec / w[n].vol, fe_rec / w[n].vol, plasmamain[nshell].cool_rr_metals / w[n].vol); + plasmamain[nshell].derived.cool_rr_ion[0] / w[n].vol, + (plasmamain[nshell].derived.cool_rr_ion[2] + plasmamain[nshell].derived.cool_rr_ion[3]) / w[n].vol, c_rec / w[n].vol, + n_rec / w[n].vol, o_rec / w[n].vol, fe_rec / w[n].vol, plasmamain[nshell].derived.cool_rr_metals / w[n].vol); Log ("Wind_recomb_lum(ergs-1cm-3) H %8.2e He %8.2e C %8.2e N %8.2e O %8.2e Fe %8.2e Metals %8.2e\n", - plasmamain[nshell].lum_rr_ion[0] / w[n].vol, (plasmamain[nshell].lum_rr_ion[2] + plasmamain[nshell].lum_rr_ion[3]) / w[n].vol, - c_lum / w[n].vol, n_lum / w[n].vol, o_lum / w[n].vol, fe_lum / w[n].vol, plasmamain[nshell].lum_rr_metals / w[n].vol); + plasmamain[nshell].derived.lum_rr_ion[0] / w[n].vol, + (plasmamain[nshell].derived.lum_rr_ion[2] + plasmamain[nshell].derived.lum_rr_ion[3]) / w[n].vol, c_lum / w[n].vol, + n_lum / w[n].vol, o_lum / w[n].vol, fe_lum / w[n].vol, plasmamain[nshell].derived.lum_rr_metals / w[n].vol); Log ("Wind_dr_cooling(ergs-1cm-3) H %8.2e He %8.2e C %8.2e N %8.2e O %8.2e Fe %8.2e Metals %8.2e\n", - plasmamain[nshell].cool_dr_ion[0] / w[n].vol, - (plasmamain[nshell].cool_dr_ion[2] + plasmamain[nshell].cool_dr_ion[3]) / w[n].vol, c_dr / w[n].vol, n_dr / w[n].vol, - o_dr / w[n].vol, fe_dr / w[n].vol, cool_dr_metals / w[n].vol); + plasmamain[nshell].derived.cool_dr_ion[0] / w[n].vol, + (plasmamain[nshell].derived.cool_dr_ion[2] + plasmamain[nshell].derived.cool_dr_ion[3]) / w[n].vol, c_dr / w[n].vol, + n_dr / w[n].vol, o_dr / w[n].vol, fe_dr / w[n].vol, cool_dr_metals / w[n].vol); /* 1110 NSH Added this line to report all cooling mechanisms, including those that do not generate photons. */ - Log ("Balance Cooling=%8.2e Heating=%8.2e Lum=%8.2e T_e=%e after update\n", cool_sum, xsum, lum_sum, plasmamain[nshell].t_e); + Log ("Balance Cooling=%8.2e Heating=%8.2e Lum=%8.2e T_e=%e after update\n", cool_sum, xsum, lum_sum, + plasmamain[nshell].state.t_e); for (n = 0; n < nelements; n++) { @@ -956,21 +959,22 @@ shell_output_wind_update_diagnostics (double xsum, double psum, double fsum, dou total_density = 0; for (m = first_ion_index; m < last_ion_index; m++) { - total_density += plasmamain[nshell].density[m]; + total_density += plasmamain[nshell].state.density[m]; } for (m = first_ion_index; m < last_ion_index; m++) { - Log (" %8.2e", plasmamain[nshell].density[m] / total_density); + Log (" %8.2e", plasmamain[nshell].state.density[m] / total_density); } Log ("\n"); } - Log ("radial F_es %i %e \n", nshell, plasmamain[nshell].rad_force_es[0]); - Log ("radial F_bf %i %e \n", nshell, plasmamain[nshell].rad_force_bf[0]); - Log ("radial F_ff %i %e \n", nshell, plasmamain[nshell].rad_force_ff[0]); - Log ("Radial Visible flux %e \n", plasmamain[nshell].F_vis[0]); - Log ("Radial UV flux %e \n", plasmamain[nshell].F_UV[0]); - Log ("Radial Xray flux %e \n", plasmamain[nshell].F_Xray[0]); - Log ("Total Radial flux %e \n", plasmamain[nshell].F_vis[0] + plasmamain[nshell].F_UV[0] + plasmamain[nshell].F_Xray[0]); + Log ("radial F_es %i %e \n", nshell, plasmamain[nshell].est.rad_force_es[0]); + Log ("radial F_bf %i %e \n", nshell, plasmamain[nshell].est.rad_force_bf[0]); + Log ("radial F_ff %i %e \n", nshell, plasmamain[nshell].est.rad_force_ff[0]); + Log ("Radial Visible flux %e \n", plasmamain[nshell].est.F_vis[0]); + Log ("Radial UV flux %e \n", plasmamain[nshell].est.F_UV[0]); + Log ("Radial Xray flux %e \n", plasmamain[nshell].est.F_Xray[0]); + Log ("Total Radial flux %e \n", + plasmamain[nshell].est.F_vis[0] + plasmamain[nshell].est.F_UV[0] + plasmamain[nshell].est.F_Xray[0]); } } } diff --git a/source/windsave.c b/source/windsave.c index 2457c295b..cfb074713 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -102,21 +102,21 @@ in the plasma structure */ for (m = 0; m < NPLASMA; m++) { - n += fwrite (plasmamain[m].density, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].partition, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].ioniz, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].recomb, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].inner_recomb, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].scatters, sizeof (int), nions, fptr); - n += fwrite (plasmamain[m].xscatters, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].heat_ion, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].cool_rr_ion, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].cool_dr_ion, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].lum_rr_ion, sizeof (double), nions, fptr); - n += fwrite (plasmamain[m].levden, sizeof (double), nlte_levels, fptr); - n += fwrite (plasmamain[m].recomb_simple, sizeof (double), nphot_total, fptr); - n += fwrite (plasmamain[m].recomb_simple_upweight, sizeof (double), nphot_total, fptr); - n += fwrite (plasmamain[m].kbf_use, sizeof (double), nphot_total, fptr); + n += fwrite (plasmamain[m].state.density, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].state.partition, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].est.ioniz, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.recomb, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.inner_recomb, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.scatters, sizeof (int), nions, fptr); + n += fwrite (plasmamain[m].derived.xscatters, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].est.heat_ion, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.cool_rr_ion, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.cool_dr_ion, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].derived.lum_rr_ion, sizeof (double), nions, fptr); + n += fwrite (plasmamain[m].state.levden, sizeof (double), nlte_levels, fptr); + n += fwrite (plasmamain[m].state.recomb_simple, sizeof (double), nphot_total, fptr); + n += fwrite (plasmamain[m].state.recomb_simple_upweight, sizeof (double), nphot_total, fptr); + n += fwrite (plasmamain[m].state.kbf_use, sizeof (double), nphot_total, fptr); } /* Now write out the macro atom info */ @@ -126,20 +126,20 @@ in the plasma structure */ n += fwrite (macromain, sizeof (macro_dummy), NPLASMA, fptr); for (m = 0; m < NPLASMA; m++) { - n += fwrite (macromain[m].jbar, sizeof (double), size_Jbar_est, fptr); - n += fwrite (macromain[m].jbar_old, sizeof (double), size_Jbar_est, fptr); - n += fwrite (macromain[m].gamma, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].gamma_old, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].gamma_e, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].gamma_e_old, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].alpha_st, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].alpha_st_old, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].alpha_st_e, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].alpha_st_e_old, sizeof (double), size_gamma_est, fptr); - n += fwrite (macromain[m].recomb_sp, sizeof (double), size_alpha_est, fptr); - n += fwrite (macromain[m].recomb_sp_e, sizeof (double), size_alpha_est, fptr); - n += fwrite (macromain[m].matom_emiss, sizeof (double), nlevels_macro, fptr); - n += fwrite (macromain[m].matom_abs, sizeof (double), nlevels_macro, fptr); + n += fwrite (macromain[m].est.jbar, sizeof (double), size_Jbar_est, fptr); + n += fwrite (macromain[m].state.jbar_old, sizeof (double), size_Jbar_est, fptr); + n += fwrite (macromain[m].est.gamma, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].state.gamma_old, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].est.gamma_e, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].state.gamma_e_old, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].est.alpha_st, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].state.alpha_st_old, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].est.alpha_st_e, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].state.alpha_st_e_old, sizeof (double), size_gamma_est, fptr); + n += fwrite (macromain[m].est.recomb_sp, sizeof (double), size_alpha_est, fptr); + n += fwrite (macromain[m].est.recomb_sp_e, sizeof (double), size_alpha_est, fptr); + n += fwrite (macromain[m].derived.matom_emiss, sizeof (double), nlevels_macro, fptr); + n += fwrite (macromain[m].est.matom_abs, sizeof (double), nlevels_macro, fptr); } } @@ -273,25 +273,25 @@ wind_read (filename) for (m = 0; m < NPLASMA; m++) { - n += fread (plasmamain[m].density, sizeof (double), nions, fptr); - n += fread (plasmamain[m].partition, sizeof (double), nions, fptr); + n += fread (plasmamain[m].state.density, sizeof (double), nions, fptr); + n += fread (plasmamain[m].state.partition, sizeof (double), nions, fptr); - n += fread (plasmamain[m].ioniz, sizeof (double), nions, fptr); - n += fread (plasmamain[m].recomb, sizeof (double), nions, fptr); - n += fread (plasmamain[m].inner_recomb, sizeof (double), nions, fptr); + n += fread (plasmamain[m].est.ioniz, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.recomb, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.inner_recomb, sizeof (double), nions, fptr); - n += fread (plasmamain[m].scatters, sizeof (int), nions, fptr); - n += fread (plasmamain[m].xscatters, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.scatters, sizeof (int), nions, fptr); + n += fread (plasmamain[m].derived.xscatters, sizeof (double), nions, fptr); - n += fread (plasmamain[m].heat_ion, sizeof (double), nions, fptr); - n += fread (plasmamain[m].cool_rr_ion, sizeof (double), nions, fptr); - n += fread (plasmamain[m].cool_dr_ion, sizeof (double), nions, fptr); - n += fread (plasmamain[m].lum_rr_ion, sizeof (double), nions, fptr); + n += fread (plasmamain[m].est.heat_ion, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.cool_rr_ion, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.cool_dr_ion, sizeof (double), nions, fptr); + n += fread (plasmamain[m].derived.lum_rr_ion, sizeof (double), nions, fptr); - n += fread (plasmamain[m].levden, sizeof (double), nlte_levels, fptr); - n += fread (plasmamain[m].recomb_simple, sizeof (double), nphot_total, fptr); - n += fread (plasmamain[m].recomb_simple_upweight, sizeof (double), nphot_total, fptr); - n += fread (plasmamain[m].kbf_use, sizeof (double), nphot_total, fptr); + n += fread (plasmamain[m].state.levden, sizeof (double), nlte_levels, fptr); + n += fread (plasmamain[m].state.recomb_simple, sizeof (double), nphot_total, fptr); + n += fread (plasmamain[m].state.recomb_simple_upweight, sizeof (double), nphot_total, fptr); + n += fread (plasmamain[m].state.kbf_use, sizeof (double), nphot_total, fptr); } @@ -306,25 +306,25 @@ wind_read (filename) for (m = 0; m < NPLASMA; m++) { - n += fread (macromain[m].jbar, sizeof (double), size_Jbar_est, fptr); - n += fread (macromain[m].jbar_old, sizeof (double), size_Jbar_est, fptr); - n += fread (macromain[m].gamma, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].gamma_old, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].gamma_e, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].gamma_e_old, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].alpha_st, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].alpha_st_old, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].alpha_st_e, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].alpha_st_e_old, sizeof (double), size_gamma_est, fptr); - n += fread (macromain[m].recomb_sp, sizeof (double), size_alpha_est, fptr); - n += fread (macromain[m].recomb_sp_e, sizeof (double), size_alpha_est, fptr); - n += fread (macromain[m].matom_emiss, sizeof (double), nlevels_macro, fptr); - n += fread (macromain[m].matom_abs, sizeof (double), nlevels_macro, fptr); + n += fread (macromain[m].est.jbar, sizeof (double), size_Jbar_est, fptr); + n += fread (macromain[m].state.jbar_old, sizeof (double), size_Jbar_est, fptr); + n += fread (macromain[m].est.gamma, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].state.gamma_old, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].est.gamma_e, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].state.gamma_e_old, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].est.alpha_st, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].state.alpha_st_old, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].est.alpha_st_e, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].state.alpha_st_e_old, sizeof (double), size_gamma_est, fptr); + n += fread (macromain[m].est.recomb_sp, sizeof (double), size_alpha_est, fptr); + n += fread (macromain[m].est.recomb_sp_e, sizeof (double), size_alpha_est, fptr); + n += fread (macromain[m].derived.matom_emiss, sizeof (double), nlevels_macro, fptr); + n += fread (macromain[m].est.matom_abs, sizeof (double), nlevels_macro, fptr); /* Force recalculation of kpkt_rates and matrix rates */ - macromain[m].kpkt_rates_known = FALSE; - macromain[m].matrix_rates_known = FALSE; + macromain[m].derived.kpkt_rates_known = FALSE; + macromain[m].derived.matrix_rates_known = FALSE; } } diff --git a/source/windsave2fits.c b/source/windsave2fits.c index 9b0825881..e3a462de9 100644 --- a/source/windsave2fits.c +++ b/source/windsave2fits.c @@ -271,13 +271,13 @@ write_spectra_model_table (fitsfile *fptr) iplasma[k] = i; iwind[k] = plasmamain[i].nwind; iband[k] = j; - ichoice[k] = plasmamain[i].spec_mod_type[j]; - exp_w[k] = plasmamain[i].exp_w[j]; - exp_temp[k] = plasmamain[i].exp_temp[j]; - pl_log_w[k] = plasmamain[i].pl_log_w[j]; - pl_alpha[k] = plasmamain[i].pl_alpha[j]; - nxtot[k] = plasmamain[i].nxtot[j]; - printf ("nxtot %d\n", plasmamain[i].nxtot[j]); + ichoice[k] = plasmamain[i].state.spec_mod_type[j]; + exp_w[k] = plasmamain[i].state.exp_w[j]; + exp_temp[k] = plasmamain[i].state.exp_temp[j]; + pl_log_w[k] = plasmamain[i].state.pl_log_w[j]; + pl_alpha[k] = plasmamain[i].state.pl_alpha[j]; + nxtot[k] = plasmamain[i].est.nxtot[j]; + printf ("nxtot %d\n", plasmamain[i].est.nxtot[j]); k++; } } @@ -451,7 +451,7 @@ make_spec (inroot) for (int j = 0; j < spectra.num_wavelengths; j++) { // spectra.data[i][j] = (float) (i + j); - spectra.data[i][j] = (float) plasmamain[i].cell_spec_flux[j]; + spectra.data[i][j] = (float) plasmamain[i].est.cell_spec_flux[j]; } } diff --git a/source/windsave2table_sub.c b/source/windsave2table_sub.c index b499f4134..599e774b1 100644 --- a/source/windsave2table_sub.c +++ b/source/windsave2table_sub.c @@ -1235,58 +1235,58 @@ get_ion (ndom, element, istate, iswitch, name) { x[n] = 0; nplasma = wmain[nstart + n].nplasma; - if (wmain[nstart + n].inwind >= 0 && plasmamain[nplasma].rho > 0.0) + if (wmain[nstart + n].inwind >= 0 && plasmamain[nplasma].state.rho > 0.0) { if (iswitch == 0) { - x[n] = plasmamain[nplasma].density[nion]; - nh = rho2nh * plasmamain[nplasma].rho; + x[n] = plasmamain[nplasma].state.density[nion]; + nh = rho2nh * plasmamain[nplasma].state.rho; x[n] /= (nh * ele[nelem].abun); strcpy (name, "frac"); } else if (iswitch == 1) { - x[n] = plasmamain[nplasma].density[nion]; + x[n] = plasmamain[nplasma].state.density[nion]; strcpy (name, "den"); } else if (iswitch == 2) { - x[n] = (double) plasmamain[nplasma].scatters[nion] / plasmamain[nplasma].vol; + x[n] = (double) plasmamain[nplasma].derived.scatters[nion] / plasmamain[nplasma].state.vol; strcpy (name, "scat"); } else if (iswitch == 3) { - x[n] = plasmamain[nplasma].xscatters[nion]; + x[n] = plasmamain[nplasma].derived.xscatters[nion]; strcpy (name, "ion_frac"); } else if (iswitch == 4) { - x[n] = plasmamain[nplasma].ioniz[nion]; + x[n] = plasmamain[nplasma].est.ioniz[nion]; strcpy (name, "ioniz"); } else if (iswitch == 5) { - x[n] = plasmamain[nplasma].recomb[nion]; + x[n] = plasmamain[nplasma].derived.recomb[nion]; strcpy (name, "recomb"); } else if (iswitch == 6) { - x[n] = plasmamain[nplasma].heat_ion[nion]; + x[n] = plasmamain[nplasma].est.heat_ion[nion]; strcpy (name, "heat"); } else if (iswitch == 7) { - x[n] = plasmamain[nplasma].cool_rr_ion[nion]; + x[n] = plasmamain[nplasma].derived.cool_rr_ion[nion]; strcpy (name, "cool_rr"); } else if (iswitch == 8) { - x[n] = plasmamain[nplasma].lum_rr_ion[nion]; + x[n] = plasmamain[nplasma].derived.lum_rr_ion[nion]; strcpy (name, "lum_rr"); } else if (iswitch == 9) { - x[n] = plasmamain[nplasma].cool_dr_ion[nion]; + x[n] = plasmamain[nplasma].derived.cool_dr_ion[nion]; strcpy (name, "cool_dr"); } else @@ -1354,208 +1354,208 @@ get_one (ndom, variable_name) if (strcmp (variable_name, "ne") == 0) { - x[n] = plasmamain[nplasma].ne; + x[n] = plasmamain[nplasma].state.ne; } else if (strcmp (variable_name, "rho") == 0) { - x[n] = plasmamain[nplasma].rho; + x[n] = plasmamain[nplasma].state.rho; } else if (strcmp (variable_name, "vol") == 0) { - x[n] = plasmamain[nplasma].vol; + x[n] = plasmamain[nplasma].state.vol; } else if (strcmp (variable_name, "t_e") == 0) { - x[n] = plasmamain[nplasma].t_e; + x[n] = plasmamain[nplasma].state.t_e; } else if (strcmp (variable_name, "t_r") == 0) { - x[n] = plasmamain[nplasma].t_r; + x[n] = plasmamain[nplasma].state.t_r; } else if (strcmp (variable_name, "t_e_old") == 0) { - x[n] = plasmamain[nplasma].t_e_old; + x[n] = plasmamain[nplasma].state.t_e_old; } else if (strcmp (variable_name, "t_r_old") == 0) { - x[n] = plasmamain[nplasma].t_r_old; + x[n] = plasmamain[nplasma].state.t_r_old; } else if (strcmp (variable_name, "dt_e") == 0) { - x[n] = plasmamain[nplasma].dt_e; + x[n] = plasmamain[nplasma].derived.dt_e; } else if (strcmp (variable_name, "dt_e_old") == 0) { - x[n] = plasmamain[nplasma].dt_e_old; + x[n] = plasmamain[nplasma].derived.dt_e_old; } else if (strcmp (variable_name, "J") == 0) { - x[n] = plasmamain[nplasma].j; + x[n] = plasmamain[nplasma].est.j; } else if (strcmp (variable_name, "J_direct") == 0) { - x[n] = plasmamain[nplasma].j_direct; + x[n] = plasmamain[nplasma].est.j_direct; } else if (strcmp (variable_name, "J_scatt") == 0) { - x[n] = plasmamain[nplasma].j_scatt; + x[n] = plasmamain[nplasma].est.j_scatt; } else if (strcmp (variable_name, "ave_freq") == 0) { - x[n] = plasmamain[nplasma].ave_freq; + x[n] = plasmamain[nplasma].est.ave_freq; } else if (strcmp (variable_name, "converge") == 0) { - x[n] = plasmamain[nplasma].converge_whole; + x[n] = plasmamain[nplasma].derived.converge_whole; } else if (strcmp (variable_name, "dmo_dt_x") == 0) { - x[n] = plasmamain[nplasma].dmo_dt[0]; + x[n] = plasmamain[nplasma].derived.dmo_dt[0]; } else if (strcmp (variable_name, "dmo_dt_y") == 0) { - x[n] = plasmamain[nplasma].dmo_dt[1]; + x[n] = plasmamain[nplasma].derived.dmo_dt[1]; } else if (strcmp (variable_name, "dmo_dt_z") == 0) { - x[n] = plasmamain[nplasma].dmo_dt[2]; + x[n] = plasmamain[nplasma].derived.dmo_dt[2]; } else if (strcmp (variable_name, "ntot") == 0) { - x[n] = plasmamain[nplasma].ntot; + x[n] = plasmamain[nplasma].est.ntot; } else if (strcmp (variable_name, "ip") == 0) { - x[n] = plasmamain[nplasma].ip; + x[n] = plasmamain[nplasma].est.ip; } else if (strcmp (variable_name, "xi") == 0) { - x[n] = plasmamain[nplasma].xi; + x[n] = plasmamain[nplasma].derived.xi; } else if (strcmp (variable_name, "heat_tot") == 0) { - x[n] = plasmamain[nplasma].heat_tot; + x[n] = plasmamain[nplasma].est.heat_tot; } else if (strcmp (variable_name, "heat_tot_old") == 0) { - x[n] = plasmamain[nplasma].heat_tot_old; + x[n] = plasmamain[nplasma].derived.heat_tot_old; } else if (strcmp (variable_name, "heat_comp") == 0) { - x[n] = plasmamain[nplasma].heat_comp; + x[n] = plasmamain[nplasma].est.heat_comp; } else if (strcmp (variable_name, "heat_lines") == 0) { - x[n] = plasmamain[nplasma].heat_lines; + x[n] = plasmamain[nplasma].est.heat_lines; } else if (strcmp (variable_name, "heat_ff") == 0) { - x[n] = plasmamain[nplasma].heat_ff; + x[n] = plasmamain[nplasma].est.heat_ff; } else if (strcmp (variable_name, "heat_photo") == 0) { - x[n] = plasmamain[nplasma].heat_photo; + x[n] = plasmamain[nplasma].est.heat_photo; } else if (strcmp (variable_name, "heat_auger") == 0) { - x[n] = plasmamain[nplasma].heat_auger; + x[n] = plasmamain[nplasma].est.heat_auger; } else if (strcmp (variable_name, "cool_comp") == 0) { - x[n] = plasmamain[nplasma].cool_comp; + x[n] = plasmamain[nplasma].derived.cool_comp; } else if (strcmp (variable_name, "lum_tot") == 0) { - x[n] = plasmamain[nplasma].lum_tot; + x[n] = plasmamain[nplasma].derived.lum_tot; } else if (strcmp (variable_name, "lum_lines") == 0) { - x[n] = plasmamain[nplasma].lum_lines; + x[n] = plasmamain[nplasma].derived.lum_lines; } else if (strcmp (variable_name, "lum_ff") == 0) { - x[n] = plasmamain[nplasma].lum_ff; + x[n] = plasmamain[nplasma].derived.lum_ff; } else if (strcmp (variable_name, "lum_rr") == 0) { - x[n] = plasmamain[nplasma].lum_rr; + x[n] = plasmamain[nplasma].derived.lum_rr; } else if (strcmp (variable_name, "cool_rr") == 0) { - x[n] = plasmamain[nplasma].cool_rr; + x[n] = plasmamain[nplasma].derived.cool_rr; } else if (strcmp (variable_name, "cool_dr") == 0) { - x[n] = plasmamain[nplasma].cool_dr; + x[n] = plasmamain[nplasma].derived.cool_dr; } else if (strcmp (variable_name, "cool_tot") == 0) { - x[n] = plasmamain[nplasma].cool_tot; + x[n] = plasmamain[nplasma].est.cool_tot; } else if (strcmp (variable_name, "w") == 0) { - x[n] = plasmamain[nplasma].w; + x[n] = plasmamain[nplasma].state.w; } else if (strcmp (variable_name, "nrad") == 0) { - x[n] = plasmamain[nplasma].nrad; + x[n] = plasmamain[nplasma].derived.nrad; } else if (strcmp (variable_name, "nioniz") == 0) { - x[n] = plasmamain[nplasma].nioniz; + x[n] = plasmamain[nplasma].est.nioniz; } else if (strcmp (variable_name, "nscat_es") == 0) { - x[n] = plasmamain[nplasma].nscat_es; + x[n] = plasmamain[nplasma].derived.nscat_es; } else if (strcmp (variable_name, "nscat_res") == 0) { - x[n] = plasmamain[nplasma].nscat_res; + x[n] = plasmamain[nplasma].derived.nscat_res; } else if (strcmp (variable_name, "nscat_bf") == 0) { - x[n] = plasmamain[nplasma].nscat_bf; + x[n] = plasmamain[nplasma].derived.nscat_bf; } else if (strcmp (variable_name, "nscat_ff") == 0) { - x[n] = plasmamain[nplasma].nscat_ff; + x[n] = plasmamain[nplasma].derived.nscat_ff; } else if (strcmp (variable_name, "heat_shock") == 0) { - x[n] = plasmamain[nplasma].heat_shock; + x[n] = plasmamain[nplasma].derived.heat_shock; } else if (strcmp (variable_name, "cool_adiab") == 0) { - x[n] = plasmamain[nplasma].cool_adiabatic; + x[n] = plasmamain[nplasma].derived.cool_adiabatic; } else if (strcmp (variable_name, "heat_lines_macro") == 0) { - x[n] = plasmamain[nplasma].heat_lines_macro; + x[n] = plasmamain[nplasma].est.heat_lines_macro; } else if (strcmp (variable_name, "heat_photo_macro") == 0) { - x[n] = plasmamain[nplasma].heat_photo_macro; + x[n] = plasmamain[nplasma].est.heat_photo_macro; } else if (strcmp (variable_name, "cool_lines_macro") == 0) { - x[n] = plasmamain[nplasma].cool_lines_macro; + x[n] = plasmamain[nplasma].derived.cool_lines_macro; } else if (strcmp (variable_name, "cool_bf_macro") == 0) { - x[n] = plasmamain[nplasma].cool_bf_macro; + x[n] = plasmamain[nplasma].derived.cool_bf_macro; } else if (strcmp (variable_name, "gain") == 0) { - x[n] = plasmamain[nplasma].gain; + x[n] = plasmamain[nplasma].derived.gain; } else if (strcmp (variable_name, "macro_bf_in") == 0) { - x[n] = plasmamain[nplasma].bf_simple_ionpool_in; + x[n] = plasmamain[nplasma].derived.bf_simple_ionpool_in; } else if (strcmp (variable_name, "macro_bf_out") == 0) { - x[n] = plasmamain[nplasma].bf_simple_ionpool_out; + x[n] = plasmamain[nplasma].derived.bf_simple_ionpool_out; } else if (strcmp (variable_name, "dv_x_dx") == 0) { @@ -1610,7 +1610,7 @@ get_one (ndom, variable_name) x[n] = wmain[n].dfudge; } else if (strcmp (variable_name, "nh") == 0) - x[n] = rho2nh * plasmamain[nplasma].rho; + x[n] = rho2nh * plasmamain[nplasma].state.rho; else { Error ("get_one: Unknown variable %s\n", variable_name); @@ -1697,55 +1697,55 @@ get_one_array_element (ndom, variable_name, array_dim, xval) if (strcmp (variable_name, "xj") == 0) { - xval[m] = plasmamain[nplasma].xj[j]; + xval[m] = plasmamain[nplasma].est.xj[j]; } else if (strcmp (variable_name, "xave_freq") == 0) { - xval[m] = plasmamain[nplasma].xave_freq[j]; + xval[m] = plasmamain[nplasma].est.xave_freq[j]; } else if (strcmp (variable_name, "fmin") == 0) { - xval[m] = plasmamain[nplasma].fmin[j]; + xval[m] = plasmamain[nplasma].est.fmin[j]; } else if (strcmp (variable_name, "fmax") == 0) { - xval[m] = plasmamain[nplasma].fmax[j]; + xval[m] = plasmamain[nplasma].est.fmax[j]; } else if (strcmp (variable_name, "fmin_mod") == 0) { - xval[m] = plasmamain[nplasma].fmin_mod[j]; + xval[m] = plasmamain[nplasma].state.fmin_mod[j]; } else if (strcmp (variable_name, "fmax_mod") == 0) { - xval[m] = plasmamain[nplasma].fmax_mod[j]; + xval[m] = plasmamain[nplasma].state.fmax_mod[j]; } else if (strcmp (variable_name, "xsd_freq") == 0) { - xval[m] = plasmamain[nplasma].xsd_freq[j]; + xval[m] = plasmamain[nplasma].est.xsd_freq[j]; } else if (strcmp (variable_name, "nxtot") == 0) { - xval[m] = plasmamain[nplasma].nxtot[j]; + xval[m] = plasmamain[nplasma].est.nxtot[j]; } else if (strcmp (variable_name, "spec_mod_type") == 0) { - xval[m] = plasmamain[nplasma].spec_mod_type[j]; + xval[m] = plasmamain[nplasma].state.spec_mod_type[j]; } else if (strcmp (variable_name, "pl_alpha") == 0) { - xval[m] = plasmamain[nplasma].pl_alpha[j]; + xval[m] = plasmamain[nplasma].state.pl_alpha[j]; } else if (strcmp (variable_name, "pl_log_w") == 0) { - xval[m] = plasmamain[nplasma].pl_log_w[j]; + xval[m] = plasmamain[nplasma].state.pl_log_w[j]; } else if (strcmp (variable_name, "exp_temp") == 0) { - xval[m] = plasmamain[nplasma].exp_temp[j]; + xval[m] = plasmamain[nplasma].state.exp_temp[j]; } else if (strcmp (variable_name, "exp_w") == 0) { - xval[m] = plasmamain[nplasma].exp_w[j]; + xval[m] = plasmamain[nplasma].state.exp_w[j]; } else { @@ -2068,7 +2068,7 @@ create_detailed_cell_spec_table (ncell, rootname) for (i = 0; i < NBINS_IN_CELL_SPEC; i++) { - flux[i] = plasmamain[nplasma].cell_spec_flux[i]; + flux[i] = plasmamain[nplasma].est.cell_spec_flux[i]; } @@ -2211,7 +2211,7 @@ create_big_detailed_spec_table (ndom, rootname) for (n = nstart; n < nstop; n++) { - fprintf (fptr, "%10.3e ", plasmamain[nplasma[n]].cell_spec_flux[i]); + fprintf (fptr, "%10.3e ", plasmamain[nplasma[n]].est.cell_spec_flux[i]); } fprintf (fptr, "\n"); From 1c9d1ff4985897fbd80f1a41b12044be5640e95a Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Thu, 19 Mar 2026 19:56:35 -0500 Subject: [PATCH 02/33] Modernize function declarations: remove K&R style and empty-paren prototypes Convert ~300 K&R-style function definitions to ANSI C style across 102 source files, moving parameter type declarations into the function signature. Remove ~90 redundant local function declarations with empty parentheses (e.g., `double dot ();`) that are already prototyped in headers. For standalone files not including sirocco.h, replace removed declarations with properly typed forward declarations. Additional fixes: - Remove -Wno-deprecated-non-prototype from Makefile (no longer needed) - Add #include for mkdir() in parse.c and inspect_wind.c - Fix type mismatch in swind.c: char choice -> int choice (matches templates.h) - Initialize fptr=NULL in swind_sub.c to silence uninitialized warning - Remove unused f_base/f_cat variables in reverb.c This eliminates all Clang -Wdeprecated-non-prototype warnings and brings the codebase closer to C99/C23 compliance. The build now produces zero warnings across all targets (sirocco, swind, windsave2table, windsave2fits, inspect_wind, modify_wind, etc.). Co-Authored-By: Claude Opus 4.6 --- source/Makefile | 2 +- source/agn.c | 19 +- source/anisowind.c | 4 +- source/atomicdata.c | 3 +- source/atomicdata_sub.c | 29 +- source/bands.c | 9 +- source/bb.c | 21 +- source/bilinear.c | 8 +- source/brem.c | 3 +- source/cdf.c | 56 +-- source/compton.c | 29 +- source/continuum.c | 12 +- source/cooling.c | 11 +- source/corona.c | 11 +- source/cv.c | 17 +- source/cylind_var.c | 28 +- source/cylindrical.c | 22 +- source/density.c | 5 +- source/diag.c | 14 +- source/dielectronic.c | 3 +- source/direct_ion.c | 27 +- source/disk.c | 19 +- source/disk_init.c | 19 +- source/disk_photon_gen.c | 13 +- source/emission.c | 26 +- source/estimators_macro.c | 70 +--- source/estimators_simple.c | 24 +- source/extract.c | 11 +- source/foo.c | 691 +++++++++++++++++++++++++++++++++++ source/frame.c | 45 +-- source/get_models.c | 19 +- source/gradv.c | 6 +- source/gridwind.c | 22 +- source/homologous.c | 13 +- source/hydro_import.c | 32 +- source/import.c | 18 +- source/import_cylindrical.c | 16 +- source/import_rtheta.c | 16 +- source/import_spherical.c | 16 +- source/inspect_wind.c | 27 +- source/knigge.c | 18 +- source/levels.c | 4 +- source/lines.c | 31 +- source/macro_accelerate.c | 22 +- source/macro_gen_f.c | 6 +- source/macro_gov.c | 10 +- source/matom.c | 47 +-- source/matrix_ion.c | 16 +- source/modify_wind.c | 26 +- source/parse.c | 6 +- source/partition.c | 12 +- source/paths.c | 4 +- source/phot_util.c | 39 +- source/photon2d.c | 12 +- source/photon_gen.c | 29 +- source/photon_gen_matom.c | 11 +- source/pi_rates.c | 6 +- source/rad_hydro_files.c | 4 +- source/radiation.c | 19 +- source/random.c | 16 +- source/rdpar.c | 77 ++-- source/rdpar_init.c | 5 +- source/recipes.c | 17 +- source/recomb.c | 50 +-- source/resonate.c | 36 +- source/reverb.c | 5 +- source/roche.c | 11 +- source/rtheta.c | 22 +- source/run.c | 14 +- source/saha.c | 29 +- source/setup.c | 6 +- source/setup_domains.c | 12 +- source/setup_files.c | 5 +- source/setup_star_bh.c | 9 +- source/shell_wind.c | 3 +- source/signal.c | 2 +- source/sirocco.c | 4 +- source/spectra.c | 33 +- source/spectral_estimators.c | 11 +- source/spherical.c | 17 +- source/stellar_wind.c | 12 +- source/sv.c | 18 +- source/swind.c | 11 +- source/swind_ion.c | 41 +-- source/swind_macro.c | 60 +-- source/swind_sub.c | 225 +++--------- source/swind_write.c | 10 +- source/synonyms.c | 7 +- source/test_cooling.c | 13 +- source/time.c | 3 +- source/unit_test.c | 14 +- source/vvector.c | 47 +-- source/walls.c | 4 +- source/wind.c | 24 +- source/wind2d.c | 20 +- source/wind_sum.c | 3 +- source/wind_util.c | 14 +- source/windsave.c | 12 +- source/windsave2fits.c | 15 +- source/windsave2table.c | 4 +- source/windsave2table_sub.c | 53 +-- source/xlog.c | 24 +- source/xtest.c | 2 +- source/zeta.c | 4 +- 104 files changed, 1208 insertions(+), 1574 deletions(-) create mode 100644 source/foo.c diff --git a/source/Makefile b/source/Makefile index 3cc5d5fc4..4bea384cc 100644 --- a/source/Makefile +++ b/source/Makefile @@ -24,7 +24,7 @@ FC = g77 NVCC = # NVCC = nvcc # default (and only?) CUDA compiler # specify any extra compiler flags here -EXTRA_FLAGS = -Wno-deprecated-non-prototype -DMATOM_VER=$(MATOM_VER) +EXTRA_FLAGS = -DMATOM_VER=$(MATOM_VER) LDFLAGS = # Use the next line if you want to change the c compiler that mpicc uses, or diff --git a/source/agn.c b/source/agn.c index e5ca12acc..45a5ac346 100644 --- a/source/agn.c +++ b/source/agn.c @@ -51,10 +51,7 @@ **********************************************************/ double -agn_init (r, lum, alpha, freqmin, freqmax, ioniz_or_extract, f) - double r, lum, alpha, freqmin, freqmax; - int ioniz_or_extract; - double *f; +agn_init (double r, double lum, double alpha, double freqmin, double freqmax, int ioniz_or_extract, double *f) { double t; @@ -140,8 +137,7 @@ agn_init (r, lum, alpha, freqmin, freqmax, ioniz_or_extract, f) **********************************************************/ double -emittance_pow (freqmin, freqmax, alpha) - double freqmin, freqmax, alpha; +emittance_pow (double freqmin, double freqmax, double alpha) { double emit, this_fmin; @@ -203,8 +199,7 @@ emittance_pow (freqmin, freqmax, alpha) **********************************************************/ double -emittance_bpow (freqmin, freqmax, alpha) - double freqmin, freqmax, alpha; +emittance_bpow (double freqmin, double freqmax, double alpha) { double constant_low, constant_hi, emit; double e1, e2, e3; @@ -525,10 +520,10 @@ photo_gen_agn (p, r, alpha, weight, f1, f2, spectype, istart, nphot) else if (geo.pl_geometry == PL_GEOMETRY_ISO) { /* We want to generate photons isotropically from the surface of a sphere, - but with radial direction so it resembles an isotropic point source */ - randvec (p[i].x, r); // Simple random coordinate on the surface of a sphere - stuff_v (p[i].x, p[i].lmn); // we want photon to travel in the same direction as the random point on the sphere so it is isotropic - renorm (p[i].lmn, 1.0); // turn into a unit vector + but with radial direction so it resembles an isotropic point source */ + randvec (p[i].x, r); // Simple random coordinate on the surface of a sphere + stuff_v (p[i].x, p[i].lmn); // we want photon to travel in the same direction as the random point on the sphere so it is isotropic + renorm (p[i].lmn, 1.0); // turn into a unit vector } /* This is a diagnostic mode one can use to look at photon origins */ diff --git a/source/anisowind.c b/source/anisowind.c index 9dd1a35f8..e5a287a79 100644 --- a/source/anisowind.c +++ b/source/anisowind.c @@ -67,9 +67,7 @@ int -randwind_thermal_trapping (p, nnscat) - PhotPtr p; - int *nnscat; +randwind_thermal_trapping (PhotPtr p, int *nnscat) { double tau_norm, p_norm; double tau, dvds, z, ztest; diff --git a/source/atomicdata.c b/source/atomicdata.c index d70d36e00..12d8f1e47 100644 --- a/source/atomicdata.c +++ b/source/atomicdata.c @@ -94,8 +94,7 @@ **********************************************************/ int -get_atomic_data (masterfile) - char masterfile[]; +get_atomic_data (char masterfile[]) { FILE *fptr, *mptr; char aline[LINELENGTH]; diff --git a/source/atomicdata_sub.c b/source/atomicdata_sub.c index e6ed6a65d..db3392f81 100644 --- a/source/atomicdata_sub.c +++ b/source/atomicdata_sub.c @@ -157,7 +157,6 @@ index_lines () float *freqs, foo; int *index, ioo; int n; - void indexx (); /* Allocate memory for some modestly large arrays */ freqs = calloc (sizeof (foo), NLINES + 2); @@ -218,7 +217,6 @@ index_phot_top () float *freqs, foo; int *index, ioo; int n; - void indexx (); /* Allocate memory for some modestly large arrays */ freqs = calloc (sizeof (foo), ntop_phot + nxphot + 2); @@ -272,7 +270,6 @@ index_inner_cross () float *freqs, foo; int *index, ioo; int n; - void indexx (); /* Allocate memory for some modestly large arrays */ freqs = calloc (sizeof (foo), n_inner_tot + 2); @@ -328,9 +325,7 @@ index_inner_cross () **********************************************************/ void -indexx (n, arrin, indx) - int n, indx[]; - float arrin[]; +indexx (int n, float arrin[], int indx[]) { int l, j, ir, indxt, i; float q; @@ -423,8 +418,7 @@ indexx (n, arrin, indx) **********************************************************/ int -limit_lines (freqmin, freqmax) - double freqmin, freqmax; +limit_lines (double freqmin, double freqmax) { int nmin, nmax, n; @@ -571,14 +565,11 @@ double q21_a, q21_t_old; ************************************************************/ double -q21 (line_ptr, t) - struct lines *line_ptr; - double t; +q21 (struct lines *line_ptr, double t) { double gaunt; double omega; double u0; - double upsilon (); if (q21_line_ptr != line_ptr || t != q21_t_old) @@ -642,13 +633,9 @@ q21 (line_ptr, t) **********************************************************/ double -q12 (line_ptr, t) - struct lines *line_ptr; - double t; +q12 (struct lines *line_ptr, double t) { double x; - double q21 (); - double exp (); x = line_ptr->gu / line_ptr->gl * q21 (line_ptr, t) * exp (-H_OVER_K * line_ptr->freq / t); @@ -685,8 +672,7 @@ double a21_a; **********************************************************/ double -a21 (line_ptr) - struct lines *line_ptr; +a21 (struct lines *line_ptr) { double freq; @@ -723,14 +709,11 @@ a21 (line_ptr) **********************************************************/ double -upsilon (n_coll, u0) - int n_coll; - double u0; +upsilon (int n_coll, double u0) { double x; //The scaled temperature double y; //The scaled collision strength double upsilon; //The actual collision strength - int linterp (); /* first we compute x. This is the "reduced temperature" from Burgess & Tully 1992. */ diff --git a/source/bands.c b/source/bands.c index 5b926580e..55f7f3d58 100644 --- a/source/bands.c +++ b/source/bands.c @@ -664,10 +664,7 @@ bands_init (imode, band) #define MIN_N_IONBANDS 7 int -ion_bands_init (mode, freqmin, freqmax, band) - int mode; - double freqmin, freqmax; - struct xbands *band; +ion_bands_init (int mode, double freqmin, double freqmax, struct xbands *band) { int i, n, ngood, good[NXBANDS]; double xfreq[NXBANDS]; @@ -803,9 +800,7 @@ ion_bands_init (mode, freqmin, freqmax, band) **********************************************************/ void -check_appropriate_banding (band, mode) - struct xbands *band; - int mode; +check_appropriate_banding (struct xbands *band, int mode) { if (geo.system_type == SYSTEM_TYPE_AGN) { diff --git a/source/bb.c b/source/bb.c index a25d1cc37..c36696d1b 100644 --- a/source/bb.c +++ b/source/bb.c @@ -107,8 +107,7 @@ int error_bb_lo = 0; **********************************************************/ double -planck (t, freqmin, freqmax) - double t, freqmin, freqmax; +planck (double t, double freqmin, double freqmax) { double freq, alpha, y; int echeck; @@ -266,8 +265,7 @@ planck (t, freqmin, freqmax) **********************************************************/ double -get_rand_pow (x1, x2, alpha) - double x1, x2, alpha; +get_rand_pow (double x1, double x2, double alpha) { double r; double a; @@ -326,8 +324,7 @@ get_rand_pow (x1, x2, alpha) **********************************************************/ double -get_rand_exp (alpha_min, alpha_max) - double alpha_min, alpha_max; +get_rand_exp (double alpha_min, double alpha_max) { double r; double x; @@ -390,13 +387,11 @@ int i_integ_planck_d = 0; **********************************************************/ double -integ_planck_d (alphamin, alphamax) - double alphamin, alphamax; +integ_planck_d (double alphamin, double alphamax) { double x, z1, z2; int n; - int init_integ_planck_d (); /* If this is the first time, integ_plank_d is called, initilaize the integ_planck array */ if (i_integ_planck_d == 0) @@ -496,7 +491,6 @@ int init_integ_planck_d () { double x; - double planck_d (), qromb (); int n; for (n = 0; n < NMAX + 1; n++) { @@ -570,11 +564,9 @@ planck_d_2 (double alpha, void *params) **********************************************************/ double -emittance_bb (freqmin, freqmax, t) - double freqmin, freqmax, t; +emittance_bb (double freqmin, double freqmax, double t) { double alphamin, alphamax, q1; - double integ_planck_d (); q1 = 2. * PI * (BOLTZMANN * BOLTZMANN * BOLTZMANN * BOLTZMANN) / (PLANCK * PLANCK * PLANCK * VLIGHT * VLIGHT); alphamin = PLANCK * freqmin / (BOLTZMANN * t); @@ -631,8 +623,7 @@ emittance_bb (freqmin, freqmax, t) **********************************************************/ double -check_freq_max (freq_max, temp) - double freq_max, temp; +check_freq_max (double freq_max, double temp) { double bblim; diff --git a/source/bilinear.c b/source/bilinear.c index a8be0dd4e..4539ac1e1 100644 --- a/source/bilinear.c +++ b/source/bilinear.c @@ -103,17 +103,15 @@ **********************************************************/ int -bilin (x, x00, x01, x10, x11, f, g) - double x[], x00[], x01[], x10[], x11[]; - double *f, *g; - +bilin (double x[], double x00[], double x01[], double x10[], double x11[], double *f, double *g) { double z; double root[2]; double a, b, c, d; double q[3], r[3], s[3], t[3]; double zz[3]; - int i, quadratic (); + int i; + int quadratic (double a, double b, double c, double r[]); void Exit (int error_code); diff --git a/source/brem.c b/source/brem.c index aedad9a50..4e97deb79 100644 --- a/source/brem.c +++ b/source/brem.c @@ -161,8 +161,7 @@ double brem_set[] = { **********************************************************/ double -get_rand_brem (freqmin, freqmax) - double freqmin, freqmax; +get_rand_brem (double freqmin, double freqmax) { double freq, alpha, y, brem_alpha_tiny; int echeck; diff --git a/source/cdf.c b/source/cdf.c index 80ea6ccbe..029447f84 100644 --- a/source/cdf.c +++ b/source/cdf.c @@ -94,12 +94,7 @@ double *pdf_array; **********************************************************/ int -cdf_gen_from_func (cdf, func, xmin, xmax, njumps, jump) - CdfPtr cdf; - double (*func) (double, void *); - double xmin, xmax; - double jump[]; - int njumps; +cdf_gen_from_func (CdfPtr cdf, double (*func) (double, void *), double xmin, double xmax, int njumps, double jump[]) { double xstep; double y; @@ -281,10 +276,7 @@ cdf_gen_from_func (cdf, func, xmin, xmax, njumps, jump) **********************************************************/ double -gen_array_from_func (func, xmin, xmax, pdfsteps) - double (*func) (double, void *); - double xmin, xmax; - int pdfsteps; +gen_array_from_func (double (*func) (double, void *), double xmin, double xmax, int pdfsteps) { double x, z, xstep; @@ -413,11 +405,7 @@ int pdf_n; **********************************************************/ int -cdf_gen_from_array (cdf, x, y, n_xy, xmin, xmax) - CdfPtr cdf; - double x[], y[]; - int n_xy; - double xmin, xmax; +cdf_gen_from_array (CdfPtr cdf, double x[], double y[], int n_xy, double xmin, double xmax) { int allzero; int nmin, nmax, cdf_n; @@ -684,14 +672,13 @@ cdf_gen_from_array (cdf, x, y, n_xy, xmin, xmax) **********************************************************/ double -cdf_get_rand (cdf) - CdfPtr cdf; +cdf_get_rand (CdfPtr cdf) { double x, r; int i, j; double q; double a, b, c, s[2]; - int quadratic (); + int quadratic (double a, double b, double c, double r[]); /* Gnerate a random number and then find the interval n the cdf in which x lies */ r = random_number (0.0, 1.0); //This *excludes* 0.0 and 1.0. @@ -780,9 +767,7 @@ cdf_get_rand (cdf) **********************************************************/ int -cdf_limit (cdf, xmin, xmax) - CdfPtr cdf; - double xmin, xmax; +cdf_limit (CdfPtr cdf, double xmin, double xmax) { int i; double q; @@ -862,14 +847,13 @@ cdf_limit (cdf, xmin, xmax) **********************************************************/ double -cdf_get_rand_limit (cdf) - CdfPtr cdf; +cdf_get_rand_limit (CdfPtr cdf) { double x, r; int i, j; double q; double a, b, c, s[2]; - int quadratic (); + int quadratic (double a, double b, double c, double r[]); r = random_number (0.0, 1.0); r = r * cdf->limit2 + (1. - r) * cdf->limit1; @@ -926,11 +910,9 @@ int cdf_write_init = 0; **********************************************************/ int -cdf_to_file (cdf, comment) - CdfPtr cdf; - char comment[]; +cdf_to_file (CdfPtr cdf, char comment[]) { - FILE *fopen (), *fptr; + FILE *fptr; int n; if (cdf_write_init == 0) { @@ -970,13 +952,9 @@ cdf_to_file (cdf, comment) **********************************************************/ int -cdf_inputs_to_file (x, y, n_xy, xmin, xmax, filename) - double x[], y[]; - int n_xy; - double xmin, xmax; - char filename[]; +cdf_inputs_to_file (double x[], double y[], int n_xy, double xmin, double xmax, char filename[]) { - FILE *fopen (), *fptr; + FILE *fptr; int n; fptr = fopen (filename, "w"); fprintf (fptr, "# Number of samples in array %d\n", n_xy); @@ -1003,8 +981,7 @@ cdf_inputs_to_file (x, y, n_xy, xmin, xmax, filename) **********************************************************/ int -cdf_check (cdf) - CdfPtr cdf; +cdf_check (CdfPtr cdf) { int n; double x, y; @@ -1116,8 +1093,7 @@ cdf_check (cdf) **********************************************************/ int -calc_cdf_gradient (cdf) - CdfPtr cdf; +calc_cdf_gradient (CdfPtr cdf) { int n, istat; double dx1, dx2, dy1, dy2; @@ -1200,9 +1176,7 @@ calc_cdf_gradient (cdf) **********************************************************/ int -cdf_array_fixup (x, y, n_xy) - double *x, *y; - int n_xy; +cdf_array_fixup (double *x, double *y, int n_xy) { int n, m; size_t *order; diff --git a/source/compton.c b/source/compton.c index db750c010..659d91504 100644 --- a/source/compton.c +++ b/source/compton.c @@ -158,9 +158,7 @@ compton_scatter (p) **********************************************************/ double -kappa_comp (xplasma, freq) - PlasmaPtr xplasma; - double freq; +kappa_comp (PlasmaPtr xplasma, double freq) { double x; double sigma; /*The cross section, thompson, or KN if hnu/mec2 > 0.01 */ @@ -201,9 +199,7 @@ kappa_comp (xplasma, freq) **********************************************************/ double -kappa_ind_comp (xplasma, freq) - PlasmaPtr xplasma; - double freq; +kappa_ind_comp (PlasmaPtr xplasma, double freq) { double x; double sigma; /*The cross section, thompson, or KN if hnu/mec2 > 0.01 */ @@ -277,9 +273,7 @@ kappa_ind_comp (xplasma, freq) **********************************************************/ double -total_comp (one, t_e) - WindPtr one; - double t_e; +total_comp (WindPtr one, double t_e) { double x, f1, f2; int nplasma, j; @@ -566,8 +560,7 @@ pdf_thermal (double x, void *params) int -compton_get_thermal_velocity (t, v) - double t, *v; +compton_get_thermal_velocity (double t, double *v) { double vel; @@ -687,8 +680,7 @@ sigma_compton_partial (f, x) **********************************************************/ double -compton_alpha (nu) - double nu; +compton_alpha (double nu) { double alpha; if (nu < 1e17) @@ -719,8 +711,7 @@ compton_alpha (nu) **********************************************************/ double -compton_beta (nu) - double nu; +compton_beta (double nu) { double alp, beta; if (nu < 1e17) @@ -790,8 +781,7 @@ comp_cool_integrand (double nu, void *params) double -compton_reweight_norm (nu) - double nu; +compton_reweight_norm (double nu) { double v; double x1, x2, x3, x4, x5, xx; @@ -840,10 +830,7 @@ compton_reweight_norm (nu) int -compton_reweight (p_in, p_out) - PhotPtr p_in, p_out; - - +compton_reweight (PhotPtr p_in, PhotPtr p_out) { double nu_in, nu_out, xr, reweight; double theta, ctheta; diff --git a/source/continuum.c b/source/continuum.c index d97bd05cc..aba54ee57 100644 --- a/source/continuum.c +++ b/source/continuum.c @@ -62,16 +62,14 @@ double old_t, old_g, old_freqmin, old_freqmax; double -one_continuum (spectype, t, g, freqmin, freqmax) - int spectype; - double t, g, freqmin, freqmax; +one_continuum (int spectype, double t, double g, double freqmin, double freqmax) { double lambdamin, lambdamax; double w_local[NCDF], f_local[NCDF]; double f, y; int n, nwave; double par[2]; - int model (); + int model (int spectype, double par[]); /* Check if the parameters are the same as the stored ones, otherwise initialise */ if (old_t != t || old_g != g || old_freqmin != freqmin || old_freqmax != freqmax) @@ -223,15 +221,13 @@ one_continuum (spectype, t, g, freqmin, freqmax) int integ_spectype; //External variable pointing to the model for our Romburg interpolation. double -emittance_continuum (spectype, freqmin, freqmax, t, g) - int spectype; - double freqmin, freqmax, t, g; +emittance_continuum (int spectype, double freqmin, double freqmax, double t, double g) { int nwav, n; double x, lambdamin, lambdamax, w1, w2, f_interp; double par[2]; - int model (); + int model (int spectype, double par[]); lambdamin = VLIGHT / (freqmax * ANGSTROM); lambdamax = VLIGHT / (freqmin * ANGSTROM); diff --git a/source/cooling.c b/source/cooling.c index 96751caaf..227276008 100644 --- a/source/cooling.c +++ b/source/cooling.c @@ -37,9 +37,7 @@ * **********************************************************/ double -cooling (xplasma, t) - PlasmaPtr xplasma; - double t; +cooling (PlasmaPtr xplasma, double t) { xplasma->state.t_e = t; @@ -231,9 +229,7 @@ xtotal_emission (one, f1, f2) **********************************************************/ double -adiabatic_cooling (one, t) - WindPtr one; - double t; +adiabatic_cooling (WindPtr one, double t) { double cooling; int nplasma, nion; @@ -303,8 +299,7 @@ adiabatic_cooling (one, t) double -shock_heating (one) - WindPtr one; +shock_heating (WindPtr one) { int nplasma; double x, r; diff --git a/source/corona.c b/source/corona.c index 117ba9a48..7d60859f0 100644 --- a/source/corona.c +++ b/source/corona.c @@ -52,8 +52,7 @@ **********************************************************/ int -get_corona_params (ndom) - int ndom; +get_corona_params (int ndom) { Log ("Creating a corona above a disk\n"); @@ -155,9 +154,7 @@ get_corona_params (ndom) **********************************************************/ double -corona_velocity (ndom, x, v) - int ndom; - double x[], v[]; +corona_velocity (int ndom, double x[], double v[]) { double rho, speed; double xtest[3]; @@ -211,9 +208,7 @@ corona_velocity (ndom, x, v) **********************************************************/ double -corona_rho (ndom, x) - int ndom; - double x[]; +corona_rho (int ndom, double x[]) { double rho; diff --git a/source/cv.c b/source/cv.c index f903eaad7..a1a35a6ff 100644 --- a/source/cv.c +++ b/source/cv.c @@ -43,12 +43,11 @@ * **********************************************************/ double -wdrad (m) - double m; +wdrad (double m) { double r; - m /= MSOL; + m /= MSOL; r = pow ((m / 1.458), 4. / 3.); r = pow (1 - r, 0.47); @@ -82,13 +81,12 @@ wdrad (m) * **********************************************************/ double -diskrad (m1, m2, period) - double m1, m2, period; +diskrad (double m1, double m2, double period) { double t2p, x, a; double rlobe1, q; - double roche2 (); + double roche2 (double q, double a); q = m2 / m1; @@ -118,9 +116,7 @@ diskrad (m1, m2, period) * **********************************************************/ double -roche2 (q, a) - double q, a; - +roche2 (double q, double a) { double rouche; double x, y; @@ -152,8 +148,7 @@ roche2 (q, a) * **********************************************************/ double -logg (mass, rwd) - double mass, rwd; +logg (double mass, double rwd) { double gravity; gravity = GRAV * mass / (rwd * rwd); diff --git a/source/cylind_var.c b/source/cylind_var.c index f54fb44f8..2caec5090 100644 --- a/source/cylind_var.c +++ b/source/cylind_var.c @@ -57,11 +57,7 @@ **********************************************************/ double -cylvar_ds_in_cell (ndom, p) - int ndom; - PhotPtr p; - - +cylvar_ds_in_cell (int ndom, PhotPtr p) { int n, ix, iz, iroot; @@ -287,9 +283,7 @@ cylvar_make_grid (int ndom, WindPtr w) **********************************************************/ int -cylvar_wind_complete (ndom, w) - int ndom; - WindPtr w; +cylvar_wind_complete (int ndom, WindPtr w) { int i, j, n; double drho, dz; @@ -512,11 +506,7 @@ int ierr_cylvar_where_in_grid = 0; **********************************************************/ int -cylvar_where_in_grid (ndom, x, ichoice, fx, fz) - int ndom; - double x[]; - int ichoice; - double *fx, *fz; +cylvar_where_in_grid (int ndom, double x[], int ichoice, double *fx, double *fz) { int i, j, n, ii; double z[3]; @@ -774,9 +764,7 @@ cylvar_get_random_location (n, x) **********************************************************/ int -cylvar_extend_density (ndom, w) - int ndom; - WindPtr w; +cylvar_extend_density (int ndom, WindPtr w) { int i, j, n, m; @@ -880,13 +868,7 @@ cylvar_extend_density (ndom, w) **********************************************************/ int -cylvar_coord_fraction (ndom, ichoice, x, ii, frac, nelem) - int ndom; - int ichoice; - double x[]; - int ii[]; - double frac[]; - int *nelem; +cylvar_coord_fraction (int ndom, int ichoice, double x[], int ii[], double frac[], int *nelem) { double dr, dz; int n; diff --git a/source/cylindrical.c b/source/cylindrical.c index 081eced48..e15017a36 100644 --- a/source/cylindrical.c +++ b/source/cylindrical.c @@ -47,11 +47,7 @@ **********************************************************/ double -cylind_ds_in_cell (ndom, p) - int ndom; - PhotPtr p; - - +cylind_ds_in_cell (int ndom, PhotPtr p) { int n, ix, iz, iroot; @@ -262,9 +258,7 @@ cylind_make_grid (int ndom, WindPtr w) **********************************************************/ int -cylind_wind_complete (ndom, w) - int ndom; - WindPtr w; +cylind_wind_complete (int ndom, WindPtr w) { int i, j; int nstart, mdim, ndim; @@ -459,9 +453,7 @@ cylind_cell_volume (WindPtr w) **********************************************************/ int -cylind_where_in_grid (ndom, x) - int ndom; - double x[]; +cylind_where_in_grid (int ndom, double x[]) { int i, j, n; double z; @@ -529,9 +521,7 @@ cylind_where_in_grid (ndom, x) **********************************************************/ int -cylind_get_random_location (n, x) - int n; - double x[]; +cylind_get_random_location (int n, double x[]) { int i, j; int inwind; @@ -617,9 +607,7 @@ cylind_get_random_location (n, x) **********************************************************/ int -cylind_extend_density (ndom, w) - int ndom; - WindPtr w; +cylind_extend_density (int ndom, WindPtr w) { int i, j, n, m; diff --git a/source/density.c b/source/density.c index 78fa477d0..7d036ad97 100644 --- a/source/density.c +++ b/source/density.c @@ -43,10 +43,7 @@ **********************************************************/ double -get_ion_density (ndom, x, nion) - int ndom; - double x[]; - int nion; +get_ion_density (int ndom, double x[], int nion) { double dd; int nn, nnn[4], nelem; diff --git a/source/diag.c b/source/diag.c index c2373d487..f0ab242d0 100644 --- a/source/diag.c +++ b/source/diag.c @@ -429,10 +429,7 @@ init_extra_diagnostics () **********************************************************/ int -save_photon_stats (one, p, ds, w_ave) - WindPtr one; - PhotPtr p; - double ds, w_ave; +save_photon_stats (WindPtr one, PhotPtr p, double ds, double w_ave) { int i; @@ -475,9 +472,7 @@ int save_photon_number = 0; **********************************************************/ int -save_photons (p, comment) - PhotPtr p; - char comment[]; +save_photons (PhotPtr p, char comment[]) { save_photon_number += 1; @@ -513,10 +508,7 @@ save_photons (p, comment) **********************************************************/ int -track_scatters (p, nplasma, comment) - PhotPtr p; - int nplasma; - char *comment; +track_scatters (PhotPtr p, int nplasma, char *comment) { fprintf (epltptr, "Scattter %i %.2e %.2e %.2e %i %e %e %i %s\n", p->np, diff --git a/source/dielectronic.c b/source/dielectronic.c index 8433196af..fc51dab0d 100644 --- a/source/dielectronic.c +++ b/source/dielectronic.c @@ -36,8 +36,7 @@ **********************************************************/ int -compute_dr_coeffs (temp) - double temp; +compute_dr_coeffs (double temp) { int n, n1, n2; double Adi, Bdi, T0, T1; diff --git a/source/direct_ion.c b/source/direct_ion.c index 8b0f6b563..a5ecf73d3 100644 --- a/source/direct_ion.c +++ b/source/direct_ion.c @@ -48,8 +48,7 @@ **********************************************************/ int -compute_di_coeffs (T) - double T; +compute_di_coeffs (double T) { int n; @@ -88,9 +87,7 @@ compute_di_coeffs (T) **********************************************************/ double -q_ioniz_dere (nion, t_e) - int nion; - double t_e; +q_ioniz_dere (int nion, double t_e) { double coeff, t, scaled_t; double exp_int, dt, drdt, rate; @@ -181,10 +178,7 @@ q_ioniz_dere (nion, t_e) **********************************************************/ double -total_di (one, t_e) - WindPtr one; - double t_e; - +total_di (WindPtr one, double t_e) { double cooling_rate; int nplasma; @@ -237,8 +231,7 @@ total_di (one, t_e) **********************************************************/ int -compute_qrecomb_coeffs (T) - double T; +compute_qrecomb_coeffs (double T) { int n, nvmin, ntmin; struct topbase_phot *xtop; @@ -311,9 +304,7 @@ compute_qrecomb_coeffs (T) **********************************************************/ double -q_recomb_dere (cont_ptr, electron_temperature) - struct topbase_phot *cont_ptr; - double electron_temperature; +q_recomb_dere (struct topbase_phot *cont_ptr, double electron_temperature) { int nion; double u0; @@ -384,9 +375,7 @@ q_recomb_dere (cont_ptr, electron_temperature) **********************************************************/ double -q_ioniz (cont_ptr, electron_temperature) - struct topbase_phot *cont_ptr; - double electron_temperature; +q_ioniz (struct topbase_phot *cont_ptr, double electron_temperature) { double coeff; double gaunt; @@ -447,9 +436,7 @@ q_ioniz (cont_ptr, electron_temperature) **********************************************************/ double -q_recomb (cont_ptr, electron_temperature) - struct topbase_phot *cont_ptr; - double electron_temperature; +q_recomb (struct topbase_phot *cont_ptr, double electron_temperature) { double coeff; double gaunt, u0; diff --git a/source/disk.c b/source/disk.c index ebd472744..94afbd337 100644 --- a/source/disk.c +++ b/source/disk.c @@ -57,13 +57,11 @@ **********************************************************/ double -teff (x) - double x; +teff (double x) { double q = 0; double theat, r; double temp; - double pow (); int kkk; @@ -161,8 +159,7 @@ teff (x) **********************************************************/ double -geff (x) - double x; +geff (double x) { double q; double r; @@ -232,9 +229,7 @@ double north[] = { 0.0, 0.0, 1.0 }; **********************************************************/ double -vdisk (x, v) - double x[]; - double v[]; +vdisk (double x[], double v[]) { double xhold[3]; double r, speed; @@ -280,8 +275,7 @@ vdisk (x, v) **********************************************************/ double -zdisk (r) - double r; +zdisk (double r) { double z; z = geo.disk_z0 * pow (r / geo.disk_rad_max, geo.disk_z1) * geo.disk_rad_max; @@ -362,10 +356,7 @@ struct plane diskplane, disktop, diskbottom; **********************************************************/ double -ds_to_disk (p, allow_negative, hit) - struct photon *p; - int allow_negative; - int *hit; +ds_to_disk (struct photon *p, int allow_negative, int *hit) { /* diff --git a/source/disk_init.c b/source/disk_init.c index f56a66ea1..1ec041bd7 100644 --- a/source/disk_init.c +++ b/source/disk_init.c @@ -61,9 +61,7 @@ **********************************************************/ double -disk_init (rmin, rmax, m, mdot, freqmin, freqmax, ioniz_or_extract, ftot) - double rmin, rmax, m, mdot, freqmin, freqmax, *ftot; - int ioniz_or_extract; +disk_init (double rmin, double rmax, double m, double mdot, double freqmin, double freqmax, int ioniz_or_extract, double *ftot) { double t; double log_g; @@ -310,8 +308,7 @@ disk_init (rmin, rmax, m, mdot, freqmin, freqmax, ioniz_or_extract, ftot) **********************************************************/ int -qdisk_init (rmin, rmax, m, mdot) - double rmin, rmax, m, mdot; +qdisk_init (double rmin, double rmax, double m, double mdot) { int nrings; double log_rmin, log_rmax, dlog_r, log_r; @@ -379,8 +376,7 @@ qdisk_init (rmin, rmax, m, mdot) **********************************************************/ int -qdisk_reinit (p) - PhotPtr p; +qdisk_reinit (PhotPtr p) { int nphot, i, n; double rho; @@ -457,9 +453,7 @@ qdisk_reinit (p) **********************************************************/ int -qdisk_save (diskfile, ichoice) - char *diskfile; - int ichoice; +qdisk_save (char *diskfile, int ichoice) { FILE *qptr; int n; @@ -559,11 +553,10 @@ qdisk_save (diskfile, ichoice) **********************************************************/ int -read_non_standard_disk_profile (tprofile) - char *tprofile; +read_non_standard_disk_profile (char *tprofile) { - FILE *fopen (), *fptr; + FILE *fptr; int n; float r, t, g; int one, two; diff --git a/source/disk_photon_gen.c b/source/disk_photon_gen.c index c63df7588..65ace394b 100644 --- a/source/disk_photon_gen.c +++ b/source/disk_photon_gen.c @@ -46,17 +46,11 @@ **********************************************************/ int -photo_gen_disk (p, weight, f1, f2, spectype, istart, nphot) - PhotPtr p; - double weight; - double f1, f2; - int spectype; - int istart, nphot; +photo_gen_disk (PhotPtr p, double weight, double f1, double f2, int spectype, int istart, int nphot) { double freqmin, freqmax; int i, iend; - double planck (); double r, z, theta, phi; int nring = 0; double north[3]; @@ -260,10 +254,9 @@ photo_gen_disk (p, weight, f1, f2, spectype, istart, nphot) **********************************************************/ int -disk_photon_summary (filename, mode) - char filename[], mode[]; +disk_photon_summary (char filename[], char mode[]) { - FILE *fopen (), *ptr; + FILE *ptr; int n; double x; if (mode[0] == 'a') diff --git a/source/emission.c b/source/emission.c index ae6710131..6a3d9d4f4 100644 --- a/source/emission.c +++ b/source/emission.c @@ -172,9 +172,7 @@ wind_luminosity (double f1, double f2, int mode) **********************************************************/ double -total_emission (xplasma, f1, f2) - PlasmaPtr xplasma; - double f1, f2; +total_emission (PlasmaPtr xplasma, double f1, double f2) { double t_e; @@ -270,11 +268,7 @@ total_emission (xplasma, f1, f2) #define BOUND_BOUND 2 int -photo_gen_wind (p, weight, freqmin, freqmax, photstart, nphot) - PhotPtr p; - double weight; - double freqmin, freqmax; - int photstart, nphot; +photo_gen_wind (PhotPtr p, double weight, double freqmin, double freqmax, int photstart, int nphot) { int nn, np; int kkk; @@ -486,9 +480,7 @@ photo_gen_wind (p, weight, freqmin, freqmax, photstart, nphot) **********************************************************/ double -one_line (xplasma, nres) - PlasmaPtr xplasma; - int *nres; +one_line (PlasmaPtr xplasma, int *nres) { double xlum, xlumsum; int m; @@ -554,10 +546,7 @@ one_line (xplasma, nres) **********************************************************/ double -total_free (xplasma, t_e, f1, f2) - PlasmaPtr xplasma; - double t_e; - double f1, f2; +total_free (PlasmaPtr xplasma, double t_e, double f1, double f2) { double g_ff_h, g_ff_he; double gaunt; @@ -649,9 +638,7 @@ int ff_nplasma = -100; double ff_t_e = -100.; double -ff (xplasma, t_e, freq) - PlasmaPtr xplasma; - double t_e, freq; +ff (PlasmaPtr xplasma, double t_e, double freq) { double g_ff_h, g_ff_he; double fnu; @@ -813,8 +800,7 @@ one_ff (xplasma, f1, f2) **********************************************************/ double -gaunt_ff (gsquared) - double gsquared; +gaunt_ff (double gsquared) { int i, index; double gaunt; diff --git a/source/estimators_macro.c b/source/estimators_macro.c index 01cfced89..64dab65f8 100644 --- a/source/estimators_macro.c +++ b/source/estimators_macro.c @@ -66,11 +66,7 @@ double temp_ext_rad; //radiation temperature passed externally **********************************************************/ int -bf_estimators_increment (one, p, ds) - WindPtr one; - PhotPtr p; - double ds; - +bf_estimators_increment (WindPtr one, PhotPtr p, double ds) { double freq_av; double weight_of_packet; @@ -286,13 +282,7 @@ bf_estimators_increment (one, p, ds) **********************************************************/ int -bb_estimators_increment (one, p, tau_sobolev, dvds, nn) - WindPtr one; - PhotPtr p; - double tau_sobolev; - double dvds; - int nn; - +bb_estimators_increment (WindPtr one, PhotPtr p, double tau_sobolev, double dvds, int nn) { int llvl; int n; @@ -587,17 +577,13 @@ normalise_macro_estimators (PlasmaPtr xplasma) **********************************************************/ double -total_fb_matoms (xplasma, t_e, f1, f2) - PlasmaPtr xplasma; - double t_e; - double f1, f2; +total_fb_matoms (PlasmaPtr xplasma, double t_e, double f1, double f2) { double cool_contribution; double t_e_store; struct topbase_phot *cont_ptr; double total, density; int i, j; - double q_ioniz (); MacroPtr mplasma; mplasma = ¯omain[xplasma->nplasma]; @@ -668,9 +654,7 @@ total_fb_matoms (xplasma, t_e, f1, f2) **********************************************************/ double -total_bb_cooling (xplasma, t_e) - PlasmaPtr xplasma; - double t_e; +total_bb_cooling (PlasmaPtr xplasma, double t_e) { double cool_contribution; struct lines *line_ptr; @@ -734,9 +718,7 @@ total_bb_cooling (xplasma, t_e) **********************************************************/ double -macro_bb_heating (xplasma, t_e) - PlasmaPtr xplasma; - double t_e; +macro_bb_heating (PlasmaPtr xplasma, double t_e) { double heat_contribution; struct lines *line_ptr; @@ -779,14 +761,11 @@ macro_bb_heating (xplasma, t_e) **********************************************************/ double -macro_bf_heating (xplasma, t_e) - PlasmaPtr xplasma; - double t_e; +macro_bf_heating (PlasmaPtr xplasma, double t_e) { double heat_contribution; double total, upper_density, lower_density; int i, j; - double q_recomb (); MacroPtr mplasma; mplasma = ¯omain[xplasma->nplasma]; @@ -847,12 +826,7 @@ macro_bf_heating (xplasma, t_e) **********************************************************/ int -bb_simple_heat (xplasma, p, tau_sobolev, nn) - PlasmaPtr xplasma; - PhotPtr p; - double tau_sobolev; - int nn; - +bb_simple_heat (PlasmaPtr xplasma, PhotPtr p, double tau_sobolev, int nn) { double heat_contribution; double weight_of_packet; @@ -899,8 +873,7 @@ bb_simple_heat (xplasma, p, tau_sobolev, nn) **********************************************************/ int -check_stimulated_recomb (xplasma) - PlasmaPtr xplasma; +check_stimulated_recomb (PlasmaPtr xplasma) { int i, j; struct topbase_phot *cont_ptr; @@ -948,8 +921,7 @@ check_stimulated_recomb (xplasma) **********************************************************/ int -get_dilute_estimators (xplasma) - PlasmaPtr xplasma; +get_dilute_estimators (PlasmaPtr xplasma) { int i, j; @@ -992,14 +964,10 @@ get_dilute_estimators (xplasma) **********************************************************/ double -get_gamma (cont_ptr, xplasma) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; +get_gamma (struct topbase_phot *cont_ptr, PlasmaPtr xplasma) { double gamma_value; double fthresh, flast; - double qromb (); - double gamma_integrand (); temp_ext2 = xplasma->state.t_r; //external temperature cont_ext_ptr2 = cont_ptr; //external cont pointer @@ -1073,14 +1041,10 @@ gamma_integrand (double freq, void *params) **********************************************************/ double -get_gamma_e (cont_ptr, xplasma) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; +get_gamma_e (struct topbase_phot *cont_ptr, PlasmaPtr xplasma) { double gamma_e_value; double fthresh, flast; - double qromb (); - double gamma_e_integrand (); temp_ext2 = xplasma->state.t_r; //external temperature cont_ext_ptr2 = cont_ptr; //external cont pointer @@ -1153,14 +1117,10 @@ gamma_e_integrand (double freq, void *params) **********************************************************/ double -get_alpha_st (cont_ptr, xplasma) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; +get_alpha_st (struct topbase_phot *cont_ptr, PlasmaPtr xplasma) { double alpha_st_value; double fthresh, flast; - double qromb (); - double alpha_st_integrand (); temp_ext2 = xplasma->state.t_e; //external for use in integrand temp_ext_rad = xplasma->state.t_r; @@ -1250,14 +1210,10 @@ alpha_st_integrand (double freq, void *params) **********************************************************/ double -get_alpha_st_e (cont_ptr, xplasma) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; +get_alpha_st_e (struct topbase_phot *cont_ptr, PlasmaPtr xplasma) { double alpha_st_e_value; double fthresh, flast; - double qromb (); - double alpha_st_e_integrand (); temp_ext2 = xplasma->state.t_e; //external for use in integrand temp_ext_rad = xplasma->state.t_r; //" diff --git a/source/estimators_simple.c b/source/estimators_simple.c index 697cdcb9d..362f7937d 100644 --- a/source/estimators_simple.c +++ b/source/estimators_simple.c @@ -75,12 +75,7 @@ int previous_nplasma = -1; int previous_np = -1; int -update_banded_estimators (xplasma, p, ds, w_ave, ndom) - PlasmaPtr xplasma; - PhotPtr p; - double ds; - double w_ave; - int ndom; +update_banded_estimators (PlasmaPtr xplasma, PhotPtr p, double ds, double w_ave, int ndom) { int i; double log_freq; @@ -266,12 +261,7 @@ update_banded_estimators (xplasma, p, ds, w_ave, ndom) int -update_flux_estimators (xplasma, phot_mid, ds_obs, w_ave, ndom) - PlasmaPtr xplasma; - PhotPtr phot_mid; - double ds_obs; - double w_ave; - int ndom; +update_flux_estimators (PlasmaPtr xplasma, PhotPtr phot_mid, double ds_obs, double w_ave, int ndom) { double flux[3]; double flux_orig[3]; @@ -394,11 +384,8 @@ update_flux_estimators (xplasma, phot_mid, ds_obs, w_ave, ndom) int -update_force_estimators (xplasma, p, phot_mid, ds, w_ave, ndom, z, frac_ff, frac_auger, frac_tot) - PlasmaPtr xplasma; - PhotPtr p, phot_mid; - double ds, w_ave, z, frac_ff, frac_tot, frac_auger; - int ndom; +update_force_estimators (PlasmaPtr xplasma, PhotPtr p, PhotPtr phot_mid, double ds, double w_ave, int ndom, double z, double frac_ff, + double frac_auger, double frac_tot) { int i; double p_out[3], dp_cyl[3]; @@ -579,8 +566,7 @@ estimate_temperature_from_mean_frequency (double mean_nu_target, double nu_min, #define BAND_CORRECTED_TRAD FALSE int -normalise_simple_estimators (xplasma) - PlasmaPtr xplasma; +normalise_simple_estimators (PlasmaPtr xplasma) { int i, j, nwind; double radiation_temperature, nh, wtest; diff --git a/source/extract.c b/source/extract.c index 514942358..490b809eb 100644 --- a/source/extract.c +++ b/source/extract.c @@ -81,10 +81,7 @@ int -extract (w, p, itype) - WindPtr w; - PhotPtr p; - int itype; +extract (WindPtr w, PhotPtr p, int itype) { int n, mscat, mtopbot; struct photon pp, p_in, p_dummy; @@ -445,11 +442,7 @@ extract (w, p, itype) int -extract_one (w, pp, nspec) - WindPtr w; - PhotPtr pp; - int nspec; - +extract_one (WindPtr w, PhotPtr pp, int nspec) { int istat, nres; diff --git a/source/foo.c b/source/foo.c new file mode 100644 index 000000000..9e2d1575b --- /dev/null +++ b/source/foo.c @@ -0,0 +1,691 @@ + +/***********************************************************/ +/** @file run.c + * @author ksl + * @date May, 2018 + * + * @brief the driving routines to carry out calculation of + * the ionization of the plasma and also to extract detailed + * spectra after the inputs have been collected. + * + * ### Programming Comment ### + * The name of this file is not really acurate. The routines + * here do drive the major portions of the calculation but they + * are still run from sirocco.c. It might be better to move even + * more of the running of the code to here. Alternatively, one + * might make sirocco.c simpler, so that developers could see + * the structure better, but moving the input section + * into it's own file. + * + ***********************************************************/ + +#include +#include +#include +#include + +#include "atomic.h" +#include "sirocco.h" + +/**********************************************************/ +/** + * @brief run the ionization cycles for a + * sirocco model + * + * @param [in] int restart_stat FALSE if the is run is beginning from + * scratch, TRUE if this was a restart + * @return Always returns 0 + * + * @details + * This is the main routine for running the ionization + * cycles in Sirocco + * + * ### Notes ### + * + **********************************************************/ + +int +calculate_ionization (int restart_stat) +{ + int nn; + double zz, z_abs_all, z_abs_all_orig, z_orig[N_ISTAT], z_abs[N_ISTAT], z_else, z_else_orig; + double radiated[20], radiated_orig[20]; + int nphot_istat[N_ISTAT]; + WindPtr w; + PhotPtr p; + + char dummy[LINELENGTH]; + double freqmin, freqmax, x; + long nphot_to_define, nphot_min; + int iwind; + + + /* Save the the windfile before the first ionization cycle in order to + * allow investigation of issues that may have arisen at the very beginning + */ + +#ifdef MPI_ON + if (rank_global == 0) + { +#endif + wind_save (files.windsave); +#ifdef MPI_ON + } +#endif + + + + p = photmain; + w = wmain; + + freqmin = xband.f1[0]; + freqmax = xband.f2[xband.nbands - 1]; + + +/* THE CALCULATION OF THE IONIZATION OF THE WIND */ + + geo.ioniz_or_extract = CYCLE_IONIZ; + + + + if (geo.wcycle == geo.wcycles) + xsignal (files.root, "%-20s No ionization needed: wcycles(%d)==wcyeles(%d)\n", "COMMENT", geo.wcycle, geo.wcycles); + else + { + geo.pcycle = 0; /* Set the spectrum cycles executed to 0, because + we are going to modify the wind and hence any + previously calculated spectra must be recreated + */ + } + + /* SWM - Setup for path tracking */ + if (geo.reverb > REV_NONE) + { + reverb_init (wmain); + delay_dump_prep (restart_stat); + } + + +/* BEGINNING OF CYCLE TO CALCULATE THE IONIZATION OF THE WIND */ + + if (modes.load_rng && geo.wcycle > 0) + { + reload_gsl_rng_state (); + modes.load_rng = FALSE; + } + + while (geo.wcycle < geo.wcycles) + { /* This allows you to build up photons in bunches */ + + xsignal (files.root, "%-20s Starting %3d of %3d ionization cycles \n", "NOK", geo.wcycle + 1, geo.wcycles); + + Log ("!!Sirocco: Beginning cycle %d of %d for defining wind\n", geo.wcycle + 1, geo.wcycles); + Log_flush (); + + /* Initialize all of the arrays, etc, that need initialization for each cycle + */ + + spectrum_init (freqmin, freqmax, geo.nangles, geo.angle, geo.phase, + geo.scat_select, geo.top_bot_select, geo.select_extract, geo.rho_select, geo.z_select, geo.az_select, geo.r_select); + + xsignal (files.root, "%-20s Begin wind radiative property initialisation\n", "NOK"); + wind_rad_init (); /*Zero the parameters pertaining to the radiation field */ + xsignal (files.root, "%-20s Finished wind radiative property initialisation\n", "OK"); + + /* calculate the B matrices if we are using the matrix macro-atom transition mode, + and we are choosing to store the matrix in at least some cells and there are + macro-atom levels */ + + if (geo.rt_mode == RT_MODE_MACRO && geo.matom_transition_mode == MATOM_MATRIX && nlevels_macro > 0 && modes.store_matom_matrix) + { + xsignal (files.root, "%-20s Begin state machine calculation in cycle %3d \n", "NOK", geo.wcycle + 1); + calc_all_matom_matrices (); + xsignal (files.root, "%-20s Finished state machine calculation in cycle %3d \n", "OK", geo.wcycle + 1); + } + + geo.n_ioniz = 0.0; + geo.cool_tot_ioniz = 0.0; + geo.lum_star_back = 0; + geo.lum_disk_back = 0; + + + /* kbf_need determines how many & which bf processes one needs to consider. + * It has to be recalculated evey time one changes + * freqmin and freqmax or ion densities. pop_kappa_ff also deppends on + * the densities; it immmediately returns of associated data is not read in + */ + + kbf_need (freqmin, freqmax); + pop_kappa_ff_array (); + + + + if (!geo.wind_radiation || (geo.wcycle == 0 && geo.run_type != RUN_TYPE_PREVIOUS)) + iwind = -1; /* Do not generate photons from wind */ + else + iwind = 1; /* Create wind photons and force a reinitialization of wind parms */ + + + /* If we are using photon speed up mode then the number of photons varies by cycle in the + * ionization phase. We set this up here + */ + + if (modes.photon_speedup) + { + nphot_min = NPHOT_MAX / pow (10., PHOT_RANGE); + + x = log10 (NPHOT_MAX / nphot_min) / (geo.wcycles - 1); + NPHOT = nphot_min * pow (10., (x * geo.wcycle)); + if (NPHOT > NPHOT_MAX) + { + NPHOT = NPHOT_MAX; + } + } + + Log ("!!Sirocco: %1.2e photons will be transported for cycle %i\n", (double) NPHOT, geo.wcycle + 1); + + /* Create the photons that need to be transported through the wind + * + * NPHOT is the number of photon bundles which will equal the luminosity; + * 0 => for ionization calculation + */ + + nphot_to_define = (long) NPHOT; + + xsignal (files.root, "%-20s Creating photons before transport\n", "NOK"); + define_phot (p, freqmin, freqmax, nphot_to_define, CYCLE_IONIZ, iwind, 1); + photon_checks (p, freqmin, freqmax, "Check before transport"); + + /* Prepare qdisk for recording photon pages; recoords where photons were created on disk */ + qdisk_reinit (p); + + + + zz = 0.0; + for (nn = 0; nn < NPHOT; nn++) + { + zz += p[nn].w; + } + + Log ("!!sirocco: Total photon luminosity before transphot %18.12e\n", zz); + Log_flush (); + + /* Transport the photons through the wind */ + trans_phot (w, p, FALSE); + + photon_checks (p, freqmin, freqmax, "Check after transport"); + spectrum_create (p, geo.nangles, geo.select_extract); + Log ("!!sirocco: Number of ionizing photons %g lum of ionizing photons %g\n", geo.n_ioniz, geo.cool_tot_ioniz); + +stats_phot_post(p,NPHOT); + + /* Determine how much energy was absorbed in the wind. first zero counters. + There are counters for total energy absorbed and for each entry in the istat enum, + The second loop is for the energy radiated (i.e. that actually escapes) */ + z_abs_all = z_else = z_abs_all_orig = z_else_orig = 0.0; + for (nn = 0; nn < N_ISTAT; nn++) + { + z_abs[nn] = 0.0; + z_orig[nn] = 0.0; + nphot_istat[nn] = 0; + } + for (nn = 0; nn < 20; nn++) + { + radiated[nn] = 0.0; + radiated_orig[nn] = 0.0; + } + + /* loop over the different photon istats to determine where the luminosity went */ + for (nn = 0; nn < NPHOT; nn++) + { + + z_abs_all += p[nn].w; + z_abs_all_orig += p[nn].w_orig; + + /* we want the istat to be >1 (not P_SCAT or P_INWIND) */ + if (p[nn].istat < N_ISTAT) + { + z_abs[p[nn].istat] += p[nn].w; + z_orig[p[nn].istat] += p[nn].w_orig; + nphot_istat[p[nn].istat]++; + } + if (p[nn].istat == P_ESCAPE) + { + radiated[p[nn].origin] += p[nn].w; + radiated_orig[p[nn].origin] += p[nn].w_orig; + } + else + { + z_else += p[nn].w; + z_else_orig += p[nn].w_orig; + } + } + + for (nn = 0; nn < N_ISTAT; nn++) + { + Log ("XXX stat %8d %8d %12.3e %12.3e\n", nn, nphot_istat[nn], z_abs[nn], z_orig[nn]); + } + for (nn = 0; nn < 20; nn++) + { + Log ("XXX rad %8d %12.3e %12.3e\n", nn, radiated[nn], radiated_orig[nn]); + } + Log ("XXX rad abs_all %12.3e %12.3e\n", z_abs_all, z_abs_all_orig); + Log ("XXX rad else l %12.3e %12.3e\n", z_else, z_else_orig); + + Log + ("!!sirocco: luminosity (radiated or lost) after transphot %18.12e (absorbed or lost %18.12e %18.12e). \n", + z_abs_all, z_abs_all - zz, z_abs_all - z_abs_all_orig); + Log ("\n"); + Log ("!!sirocco: luminosity escaping %18.12e\n", z_abs[P_ESCAPE]); + Log ("!!sirocco: stellar photon luminosity escaping %18.12e \n", radiated[PTYPE_STAR] + radiated[PTYPE_STAR_MATOM]); + Log ("!!sirocco: boundary layer photon luminosity escaping %18.12e \n", radiated[PTYPE_BL] + radiated[PTYPE_BL_MATOM]); + Log ("!!sirocco: disk photon luminosity escaping %18.12e \n", radiated[PTYPE_DISK] + radiated[PTYPE_DISK_MATOM]); + Log ("!!sirocco: wind photon luminosity escaping %18.12e \n", radiated[PTYPE_WIND] + radiated[PTYPE_WIND_MATOM]); + Log ("!!sirocco: agn photon luminosity escaping %18.12e \n", radiated[PTYPE_AGN] + radiated[PTYPE_AGN_MATOM]); + Log ("!!sirocco: luminosity lost by any process %18.12e \n", z_else); + Log ("\n"); + Log ("!!sirocco: luminosity lost by being completely absorbed %18.12e \n", z_abs[P_ABSORB]); + Log ("!!sirocco: luminosity lost by too many scatters %18.12e \n", z_abs[P_TOO_MANY_SCATTERS]); + Log ("!!sirocco: luminosity lost by hitting the central object %18.12e \n", z_abs[P_HIT_STAR]); + Log ("!!sirocco: luminosity lost by hitting the disk %18.12e \n", z_abs[P_HIT_DISK]); + if (geo.rt_mode == RT_MODE_MACRO) + { + Log ("!!sirocco: luminosity lost by adiabatic kpkt destruction %18.12e number of packets %d\n", z_abs[P_ADIABATIC], + nphot_istat[P_ADIABATIC]); + Log ("!!sirocco: luminosity lost to low-frequency free-free %18.12e number of packets %d\n", z_abs[P_LOFREQ_FF], + nphot_istat[P_LOFREQ_FF]); + } + Log ("!!sirocco: luminosity lost by errors %18.12e \n", + z_abs[P_ERROR] + z_abs[P_ERROR_MATOM] + z_abs[P_REPOSITION_ERROR]); + if (geo.binary == TRUE) + Log ("!!sirocco: luminosity lost by hitting the secondary %18.12e \n", z_abs[P_SEC]); + + +#ifdef MPI_ON + /* At this point we should communicate all the useful information + that has been accumulated on different MPI tasks */ + reduce_simple_estimators (); + reduce_macro_atom_estimators (); + + /* Calculate and store the amount of heating of the disk due to radiation impinging on the disk */ + /* We only want one process to write to the file, and we only do this if there is a disk */ + + if (rank_global == 0) + { +#endif + if (geo.disk_type != DISK_NONE) + { + qdisk_save (files.disk, 1); + if (modes.make_tables) + { + strcpy (dummy, ""); + sprintf (dummy, "diag_%.100s/%.100s.%02d.disk.diag", files.root, files.root, geo.wcycle + 1); + qdisk_save (dummy, 0); + + } + } +#ifdef MPI_ON + } +#endif + +/* Completed writing file describing disk heating */ + + wind_update (w); + Log ("Completed ionization cycle %d : The elapsed TIME was %f\n", geo.wcycle + 1, timer ()); + +#ifdef MPI_ON + /* Do an MPI reduce to get the spectra all gathered to the master thread */ + normalize_spectra_across_ranks (); + + if (rank_global == 0) + { +#endif + +/* The variables for spectrum_sumamry are the filename, the attribute for the file write, the minimum and maximum spectra to write out, + * the type of spectrum (RAW meaning internal luminosity units, the amount by which to renormalize (1 means use the existing + * values, loglin (0=linear, 1=log for the wavelength scale), all photons or just wind photons + */ + + spectrum_summary (files.lwspec, 0, 6, SPECTYPE_RAW, 1., 1, 0); /* .log_spec_tot */ + spectrum_summary (files.lwspec_wind, 0, 6, SPECTYPE_RAW, 1., 1, 1); /* .log_spec_tot_wind */ + disk_photon_summary (files.phot, "w"); /* Save info about the way photons are created and absorbed + by the disk */ +#ifdef MPI_ON + } +#endif + + /* Save everything after each cycle and prepare for the next cycle + JM1304: moved geo.wcycle++ after xsignal to record cycles correctly. First cycle is cycle 0. */ + /* NSH1306 - moved geo.wcycle++ back, but moved the log and xsignal statements */ + + + xsignal (files.root, "%-20s Finished %3d of %3d ionization cycles \n", "OK", geo.wcycle + 1, geo.wcycles); + geo.wcycle++; //Increment ionisation cycles + + +/* Save only the windsave file from thread 0, to prevent many processors from writing to the same + * file. + + Note that if one wants to write out the files from all threads, then one should comment out the + MPI specific if statements below, leving MPI_Barrier, and replace the sprintf statment with + + sprintf (dummy, "sirocco%02d.%02d.wind_save", geo.wcycle, rank_global); + + */ + +#ifdef MPI_ON + if (rank_global == 0) + { +#endif + xsignal (files.root, "%-20s Checkpoint wind structure\n", "NOK"); + wind_save (files.windsave); + Log_silent ("Saved wind structure in %s after cycle %d\n", files.windsave, geo.wcycle); + + /* In a diagnostic mode save the wind file for each cycle (from thread 0) */ + + if (modes.keep_ioncycle_windsaves) + { + strcpy (dummy, ""); + sprintf (dummy, "sirocco%02d.wind_save", geo.wcycle); + wind_save (dummy); + Log ("Saved wind structure in %s\n", dummy); + } + if (modes.make_tables) + { + strcpy (dummy, ""); + sprintf (dummy, "diag_%.100s/%.100s.%02d", files.root, files.root, geo.wcycle); + do_windsave2table (dummy, 0, FALSE); + } + if (modes.keep_ioncycle_spectra) + { + strcpy (dummy, ""); + sprintf (dummy, "sirocco%02d.log_spec_tot", geo.wcycle); + spectrum_summary (dummy, 0, 6, SPECTYPE_RAW, 1., 1, 0); /* .log_spec_tot */ + } +#ifdef MPI_ON + } +#endif + + if (modes.save_rng) + { + save_gsl_rng_state (); + } + + check_time (files.root); + Log_flush (); /*Flush the logfile */ + + } // End of Cycle loop + +/* END OF CYCLE TO CALCULATE THE IONIZATION OF THE WIND */ + + Log (" Completed wind creation. The elapsed TIME was %f\n", timer ()); + + /* SWM - Evaluate wind paths for last iteration */ + if (geo.reverb == REV_WIND || geo.reverb == REV_MATOM) + { + wind_paths_evaluate (w, rank_global); + } + + return (0); +} + + + +/**********************************************************/ +/** + * @brief generates the detailed spectra + * + * @param [in] int restart_stat FALSE if the is run is beginning from + * scratch, TRUE if this was a restart + * @return Always returns EXIT_SUCCESS + * + * @details + * This is the main routine for calculation detailed + * spectra in Sirocco. + * + * ### Notes ### + * + **********************************************************/ + +int +make_spectra (int restart_stat) +{ + WindPtr w; + PhotPtr p; + + double freqmin, freqmax; + double renorm; + long nphot_to_define; + int iwind; + int n; + + int icheck; + + p = photmain; + w = wmain; + + freqmax = VLIGHT / (geo.swavemin * ANGSTROM); + freqmin = VLIGHT / (geo.swavemax * ANGSTROM); + + /* Perform the initilizations required to handle macro-atoms during the detailed + calculation of the spectrum. + + Next lines turns off macro atom estimators and other portions of the code that are + unnecessary during spectrum cycles. */ + + geo.ioniz_or_extract = CYCLE_EXTRACT; + +/* Next steps to speed up extraction stage */ + if (!modes.keep_photoabs) + { + DENSITY_PHOT_MIN = -1.0; // Do not calculated photoabsorption in detailed spectrum + } + + /*Switch on k-packet/macro atom emissivities SS June 04 */ + + if (geo.rt_mode == RT_MODE_MACRO) + { + geo.matom_radiation = 1; + } + + /* Finished initializations required for macro-atom approach */ + + /* Calculate and store which bf processess need to be considered in each cell + * Note that this is not macro-specific but is just to speed the program up. + */ + + kbf_need (freqmin, freqmax); + + /* force recalculation of kpacket rates and matrices, if applicable */ + if (geo.rt_mode == RT_MODE_MACRO) + { + for (n = 0; n < NPLASMA; n++) + { + macromain[n].derived.kpkt_rates_known = FALSE; + macromain[n].derived.matrix_rates_known = FALSE; + } + } + + /* BEGIN CYCLES TO CREATE THE DETAILED SPECTRUM */ + + /* the next section initializes the spectrum array in two cases, for the + * standard one where one is calulating the spectrum for the first time + * and in the somewhat abnormal case where additional ionization cycles + * were calculated for the wind + */ + + if (geo.pcycle == 0) + { + spectrum_init (freqmin, freqmax, geo.nangles, geo.angle, geo.phase, + geo.scat_select, geo.top_bot_select, geo.select_extract, geo.rho_select, geo.z_select, geo.az_select, geo.r_select); + + /* zero the portion of plasma main that records the numbers of scatters by + * each ion in a cell + */ + + zero_scatters (); + + } + + /* the next condition should only occur when one has nothing more to do */ + + else if (geo.pcycle >= geo.pcycles) + xsignal (files.root, "%-20s No spectrum needed: pcycles(%d)==pcycles(%d)\n", "COMMENT", geo.pcycle, geo.pcycles); + else + { + /* Then we are restarting a run with more spectral cycles, but we + have already completed some. The memory for the spectral arrays + should already have been allocated, and the spectrum was initialised + on the original run, so we just need to renormalise the saved spectrum */ + /* See issue #134 and #503 */ + + if (restart_stat == FALSE) + Error ("Not restarting, but geo.pcycle = %i and trying to renormalise!\n", geo.pcycle); + + spectrum_restart_renormalise (geo.nangles); + } + + if (modes.load_rng && geo.pcycle > 0) + { + reload_gsl_rng_state (); + modes.load_rng = FALSE; + } + + while (geo.pcycle < geo.pcycles) + { /* This allows you to build up photons in bunches */ + + xsignal (files.root, "%-20s Starting %3d of %3d spectrum cycles \n", "NOK", geo.pcycle + 1, geo.pcycles); + + Log ("!!Cycle %d of %d to calculate a detailed spectrum\n", geo.pcycle + 1, geo.pcycles); + Log_flush (); + + if (!geo.wind_radiation) + iwind = -1; /* Do not generate photons from wind */ + else if (geo.pcycle == 0) + iwind = 1; /* Create wind photons and force a reinitialization of wind parms */ + else + iwind = 0; /* Create wind photons but do not force reinitialization */ + + /* Create the initial photon bundles which need to be transported through the wind + + For the detailed spectra, NPHOT*pcycles is the number of photon bundles which will equal the luminosity, + 1 implies that detailed spectra, as opposed to the ionization of the wind is being calculated + + JM 130306 must convert NPHOT and pcycles to double precision variable nphot_to_define + + */ + + NPHOT = NPHOT_MAX; // Assure that we really are creating as many photons as we expect. + + nphot_to_define = (long) NPHOT *(long) geo.pcycles; + define_phot (p, freqmin, freqmax, nphot_to_define, CYCLE_EXTRACT, iwind, 0); + +// if (modes.save_photons || modes.save_extract_photons) +// { +// for (n = 0; n < NPHOT; n++) +// save_photons (&p[n], "B4Extract"); +// } + + + for (icheck = 0; icheck < NPHOT; icheck++) + { + if (sane_check (p[icheck].freq)) + { + Error ("sirocco after define phot:sane_check unnatural frequency for photon %d\n", icheck); + } + } + + + /* Tranport photons through the wind */ + + trans_phot (w, p, geo.select_extract); + + spectrum_create (p, geo.nangles, geo.select_extract); + +/* Write out the detailed spectrum each cycle so that one can see the statistics build up! */ + renorm = ((double) (geo.pcycles)) / (geo.pcycle + 1.0); + + /* Do an MPI reduce to get the spectra all gathered to the master thread */ +#ifdef MPI_ON + normalize_spectra_across_ranks (); + + if (rank_global == 0) + { +#endif + + spectrum_summary (files.spec, 0, nspectra - 1, geo.select_spectype, renorm, 0, 0); + spectrum_summary (files.lspec, 0, nspectra - 1, geo.select_spectype, renorm, 1, 0); + + /* Next lines produce spectra from photons in the wind only */ + spectrum_summary (files.spec_wind, 0, nspectra - 1, geo.select_spectype, renorm, 0, 1); + spectrum_summary (files.lspec_wind, 0, nspectra - 1, geo.select_spectype, renorm, 1, 1); + +#ifdef MPI_ON + } +#endif + Log ("Completed spectrum cycle %3d : The elapsed TIME was %f\n", geo.pcycle + 1, timer ()); + + /* JM1304: moved geo.pcycle++ after xsignal to record cycles correctly. First cycle is cycle 0. */ + + xsignal (files.root, "%-20s Finished %3d of %3d spectrum cycles \n", "OK", geo.pcycle + 1, geo.pcycles); + + geo.pcycle++; // Increment the spectral cycles + +#ifdef MPI_ON + if (rank_global == 0) + { +#endif + wind_save (files.windsave); // This is only needed to update pcycle + spec_save (files.specsave); +#ifdef MPI_ON + } +#endif + if (modes.save_rng) + { + save_gsl_rng_state (); + } + + check_time (files.root); + } + + +/* END CYCLE TO CALCULATE DETAILED SPECTRUM */ + +#ifdef MPI_ON + if (rank_global == 0) + { +#endif + disk_photon_summary (files.phot, "a"); +#ifdef MPI_ON + } +#endif + + /* SWM0215: Dump the last photon path details to file */ + if (geo.reverb != REV_NONE) + delay_dump_finish (); // Each thread dumps to file +#ifdef MPI_ON + MPI_Barrier (MPI_COMM_WORLD); // Once all done + if (rank_global == 0 && geo.reverb != REV_NONE) + delay_dump_combine (np_mpi_global); // Combine results if necessary +#endif + + return EXIT_SUCCESS; +} + + +int stats_phot_post(p,nphot) + PhotPtr p; + int nphot; +{ + double zz, z_abs_all, z_abs_all_orig, z_orig[N_ISTAT], z_abs[N_ISTAT], z_else, z_else_orig; + double radiated[20], radiated_orig[20]; + zz = 0.0; + for (nn = 0; nn < NPHOT; nn++) + { + zz += p[nn].w; + } + + Log ("!!sirocco: Total photon luminosity after transphot %18.12e\n", zz); + +} + diff --git a/source/frame.c b/source/frame.c index 036e679b3..5fce09d38 100644 --- a/source/frame.c +++ b/source/frame.c @@ -43,10 +43,7 @@ **********************************************************/ int -check_frame (p, desired_frame, msg) - PhotPtr p; - enum frame desired_frame; - char *msg; +check_frame (PhotPtr p, enum frame desired_frame, char *msg) { if (p->frame == desired_frame) { @@ -109,8 +106,7 @@ calculate_gamma_factor (double vel[3]) **********************************************************/ int -observer_to_local_frame (p_in, p_out) - PhotPtr p_in, p_out; +observer_to_local_frame (PhotPtr p_in, PhotPtr p_out) { WindPtr one; int ndom; @@ -168,8 +164,7 @@ observer_to_local_frame (p_in, p_out) int -local_to_observer_frame (p_in, p_out) - PhotPtr p_in, p_out; +local_to_observer_frame (PhotPtr p_in, PhotPtr p_out) { WindPtr one; int ndom; @@ -230,8 +225,7 @@ local_to_observer_frame (p_in, p_out) int -observer_to_local_frame_disk (p_in, p_out) - PhotPtr p_in, p_out; +observer_to_local_frame_disk (PhotPtr p_in, PhotPtr p_out) { // WindPtr one; //int ndom; @@ -292,8 +286,7 @@ observer_to_local_frame_disk (p_in, p_out) int -local_to_observer_frame_disk (p_in, p_out) - PhotPtr p_in, p_out; +local_to_observer_frame_disk (PhotPtr p_in, PhotPtr p_out) { double v[3]; int ierr; @@ -339,9 +332,7 @@ local_to_observer_frame_disk (p_in, p_out) **********************************************************/ double -observer_to_local_frame_ds (p_obs, ds_obs) - PhotPtr p_obs; - double ds_obs; +observer_to_local_frame_ds (PhotPtr p_obs, double ds_obs) { WindPtr one; int ndom; @@ -397,9 +388,7 @@ observer_to_local_frame_ds (p_obs, ds_obs) **********************************************************/ double -local_to_observer_frame_ds (p_obs, ds_cmf) - PhotPtr p_obs; - double ds_cmf; +local_to_observer_frame_ds (PhotPtr p_obs, double ds_cmf) { WindPtr one; int ndom; @@ -454,10 +443,7 @@ local_to_observer_frame_ds (p_obs, ds_cmf) **********************************************************/ double -observer_to_local_frame_velocity (v_obs, v, v_cmf) - double *v_obs; - double *v; - double *v_cmf; +observer_to_local_frame_velocity (double *v_obs, double *v, double *v_cmf) { double gamma, c1, c2; double a[3], b[3]; @@ -517,10 +503,7 @@ observer_to_local_frame_velocity (v_obs, v, v_cmf) **********************************************************/ double -local_to_observer_frame_velocity (v_cmf, v, v_obs) - double *v_cmf; - double *v; - double *v_obs; +local_to_observer_frame_velocity (double *v_cmf, double *v, double *v_obs) { double gamma, c1, c2; double a[3], b[3]; @@ -579,8 +562,7 @@ local_to_observer_frame_velocity (v_cmf, v, v_obs) **********************************************************/ int -local_to_observer_frame_ruler_transform (v, dx_cmf, dx_obs) - double v[], dx_cmf[], dx_obs[]; +local_to_observer_frame_ruler_transform (double v[], double dx_cmf[], double dx_obs[]) { double beta, gamma, speed; @@ -642,8 +624,7 @@ local_to_observer_frame_ruler_transform (v, dx_cmf, dx_obs) int -observer_to_local_frame_ruler_transform (v, dx_obs, dx_cmf) - double v[], dx_obs[], dx_cmf[]; +observer_to_local_frame_ruler_transform (double v[], double dx_obs[], double dx_cmf[]) { double beta, gamma, speed; @@ -710,9 +691,7 @@ observer_to_local_frame_ruler_transform (v, dx_obs, dx_cmf) int -lorentz_transform (p_in, p_out, v) - PhotPtr p_in, p_out; - double v[]; +lorentz_transform (PhotPtr p_in, PhotPtr p_out, double v[]) { double f_out, f_in; double x; diff --git a/source/get_models.c b/source/get_models.c index 9a5a281d2..fd660c4af 100644 --- a/source/get_models.c +++ b/source/get_models.c @@ -48,7 +48,7 @@ #include #include #include "atomic.h" -#include "sirocco.h" //This needs to come before modlel.h so that what is in models.h is used +#include "sirocco.h" //This needs to come before modlel.h so that what is in models.h is used #include "models.h" #define BIG 1e32 @@ -74,8 +74,7 @@ int get_models_init = 0; **********************************************************/ int -calloc_models (nmods) - int nmods; +calloc_models (int nmods) { if (mods != NULL) @@ -167,12 +166,12 @@ get_models (modellist, npars, spectype) { - FILE *mptr, *fopen (); + FILE *mptr; char dummy[LINELENGTH]; int n, m, mm, nxpar; double xpar[NPARS], xmin[NPARS], xmax[NPARS]; - int get_one_model (); int nw, nwaves; + int get_one_model (char filename[], struct Model *onemod); nwaves = 0; @@ -339,9 +338,7 @@ get_models (modellist, npars, spectype) **********************************************************/ int -get_one_model (filename, onemod) - char filename[]; - struct Model *onemod; +get_one_model (char filename[], struct Model *onemod) { FILE *ptr; char dummy[LINELEN]; @@ -431,11 +428,7 @@ int nmodel_terror = 0; * **********************************************************/ int -model (spectype, par) - int spectype; - double par[]; - - +model (int spectype, double par[]) { int j, n; int good_models[NMODS]; // Used to establish which models are to be included in creating output model diff --git a/source/gradv.c b/source/gradv.c index 321fbf345..ee8801355 100644 --- a/source/gradv.c +++ b/source/gradv.c @@ -50,8 +50,7 @@ **********************************************************/ double -dvwind_ds_cmf (p) - PhotPtr p; +dvwind_ds_cmf (PhotPtr p) { double v_grad[3][3]; double lmn[3], dvel_ds[3], dvds; @@ -413,8 +412,7 @@ calculate_cell_dvds_max (int ndom, WindPtr cell) double -get_dvds_max (p) - PhotPtr p; +get_dvds_max (PhotPtr p) { int ndom, nn, nnn[4], nelem; double frac[4]; diff --git a/source/gridwind.c b/source/gridwind.c index 4524d339a..a675c787a 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -147,8 +147,7 @@ create_wind_and_plasma_cell_maps () **********************************************************/ int -calloc_wind (nelem) - int nelem; +calloc_wind (int nelem) { if (wmain != NULL) @@ -204,8 +203,7 @@ calloc_wind (nelem) **********************************************************/ int -calloc_plasma (nelem) - int nelem; +calloc_plasma (int nelem) { if (plasmamain != NULL) @@ -298,9 +296,7 @@ calloc_plasma (nelem) **********************************************************/ int -check_plasma (xplasma, message) - PlasmaPtr xplasma; - char message[]; +check_plasma (PlasmaPtr xplasma, char message[]) { if (xplasma->nplasma == NPLASMA) { @@ -337,8 +333,7 @@ check_plasma (xplasma, message) **********************************************************/ int -calloc_macro (nelem) - int nelem; +calloc_macro (int nelem) { /* JM 1502 -- commented out this if loop because we want @@ -395,8 +390,7 @@ calloc_macro (nelem) **********************************************************/ int -calloc_estimators (nelem) - int nelem; +calloc_estimators (int nelem) { int n; @@ -578,8 +572,7 @@ calloc_estimators (nelem) **********************************************************/ int -calloc_dyn_plasma (nelem) - int nelem; +calloc_dyn_plasma (int nelem) { int n; @@ -706,8 +699,7 @@ calloc_dyn_plasma (nelem) **********************************************************/ int -calloc_matom_matrix (nelem) - int nelem; +calloc_matom_matrix (int nelem) { int nrows = nlevels_macro + 1; int n; diff --git a/source/homologous.c b/source/homologous.c index 2548c077a..aef095215 100644 --- a/source/homologous.c +++ b/source/homologous.c @@ -50,8 +50,7 @@ **********************************************************/ int -get_homologous_params (ndom) - int ndom; +get_homologous_params (int ndom) { DomainPtr one_dom; one_dom = &zdom[ndom]; @@ -136,9 +135,7 @@ get_homologous_params (ndom) **********************************************************/ double -homologous_velocity (ndom, x, v) - int ndom; - double x[], v[]; +homologous_velocity (int ndom, double x[], double v[]) { double r, speed; @@ -185,11 +182,9 @@ homologous_velocity (ndom, x, v) **********************************************************/ double -homologous_rho (ndom, x) - int ndom; - double x[]; +homologous_rho (int ndom, double x[]) { - double r, rho, length (); + double r, rho; DomainPtr one_dom; one_dom = &zdom[ndom]; diff --git a/source/hydro_import.c b/source/hydro_import.c index 497e17626..324adce29 100644 --- a/source/hydro_import.c +++ b/source/hydro_import.c @@ -76,8 +76,7 @@ HydroPtr hydro_ptr; int -get_hydro_wind_params (ndom) - int ndom; +get_hydro_wind_params (int ndom) { Log ("Creating a wind model using a Hydro calculation = domain %i\n", ndom); @@ -144,11 +143,10 @@ get_hydro_wind_params (ndom) int -get_hydro (ndom) - int ndom; +get_hydro (int ndom) { - FILE *fopen (), *fptr; + FILE *fptr; char datafile[LINE]; char aline[LINE]; char word[LINE]; @@ -325,12 +323,8 @@ get_hydro (ndom) double -hydro_velocity (ndom, x, v) - int ndom; - double x[]; - double v[]; +hydro_velocity (int ndom, double x[], double v[]) { - double length (); int ii, jj; int im, jm; double f1, f2; @@ -433,10 +427,8 @@ hydro_velocity (ndom, x, v) double -hydro_rho (x) - double x[]; +hydro_rho (double x[]) { - double length (); int ii, jj; int im, jm; double r, theta; @@ -492,10 +484,8 @@ hydro_rho (x) double -hydro_temp (x) - double x[]; +hydro_temp (double x[]) { - double length (); int ii, jj; int im, jm; double r, theta, temp; @@ -717,12 +707,7 @@ rtheta_hydro_cell_volume (WindPtr w) int -hydro_frac (coord, coord_array, imax, cell1, cell2, frac) - double coord; - double coord_array[]; - int imax; - int *cell1, *cell2; - double *frac; +hydro_frac (double coord, double coord_array[], int imax, int *cell1, int *cell2, double *frac) { int ii; ii = 0; @@ -828,8 +813,7 @@ hydro_interp_value (array, im, ii, jm, jj, f1, f2) int -hydro_restart (ndom) - int ndom; +hydro_restart (int ndom) { int n, nion; int nwind; diff --git a/source/import.c b/source/import.c index a1db5db1c..35601e553 100644 --- a/source/import.c +++ b/source/import.c @@ -48,8 +48,7 @@ **********************************************************/ int -import_wind (ndom) - int ndom; +import_wind (int ndom) { char filename[LINELENGTH]; @@ -63,9 +62,7 @@ import_wind (ndom) } int -import_wind2 (ndom, filename) - int ndom; - char *filename; +import_wind2 (int ndom, char *filename) { calloc_import (zdom[ndom].coord_type, ndom); @@ -115,8 +112,7 @@ import_wind2 (ndom, filename) **********************************************************/ int -import_set_wind_boundaries (ndom) - int ndom; +import_set_wind_boundaries (int ndom) { if (zdom[ndom].coord_type == SPHERICAL) { @@ -206,9 +202,7 @@ import_make_grid (int ndom, WindPtr w) **********************************************************/ double -import_velocity (ndom, x, v) - int ndom; - double *x, *v; +import_velocity (int ndom, double *x, double *v) { double speed = 0.0; @@ -258,9 +252,7 @@ import_velocity (ndom, x, v) **********************************************************/ double -import_rho (ndom, x) - int ndom; - double *x; +import_rho (int ndom, double *x) { double rho = 0.0; diff --git a/source/import_cylindrical.c b/source/import_cylindrical.c index 2cd24233a..3bd381bfa 100644 --- a/source/import_cylindrical.c +++ b/source/import_cylindrical.c @@ -57,9 +57,7 @@ **********************************************************/ int -import_cylindrical (ndom, filename) - int ndom; - char *filename; +import_cylindrical (int ndom, char *filename) { FILE *fptr; char line[LINELENGTH]; @@ -352,9 +350,7 @@ import_cylindrical_setup_boundaries (int ndom) **********************************************************/ int -cylindrical_make_grid_import (w, ndom) - WindPtr w; - int ndom; +cylindrical_make_grid_import (WindPtr w, int ndom) { int n; int nn; @@ -425,9 +421,7 @@ cylindrical_make_grid_import (w, ndom) **********************************************************/ double -velocity_cylindrical (ndom, x, v) - int ndom; - double *x, *v; +velocity_cylindrical (int ndom, double *x, double *v) { int j; int nn; @@ -482,9 +476,7 @@ velocity_cylindrical (ndom, x, v) **********************************************************/ double -rho_cylindrical (ndom, x) - int ndom; - double *x; +rho_cylindrical (int ndom, double *x) { double rho = 0; double r, z; diff --git a/source/import_rtheta.c b/source/import_rtheta.c index e04f43d76..210e4e189 100644 --- a/source/import_rtheta.c +++ b/source/import_rtheta.c @@ -70,9 +70,7 @@ **********************************************************/ int -import_rtheta (ndom, filename) - int ndom; - char *filename; +import_rtheta (int ndom, char *filename) { FILE *fptr; char line[LINELENGTH]; @@ -357,9 +355,7 @@ import_rtheta_setup_boundaries (int ndom) **********************************************************/ int -rtheta_make_grid_import (w, ndom) - WindPtr w; - int ndom; +rtheta_make_grid_import (WindPtr w, int ndom) { int n, nn; double theta; @@ -463,9 +459,7 @@ rtheta_make_grid_import (w, ndom) **********************************************************/ double -velocity_rtheta (ndom, x, v) - int ndom; - double *x, *v; +velocity_rtheta (int ndom, double *x, double *v) { int j; int nn; @@ -519,9 +513,7 @@ velocity_rtheta (ndom, x, v) **********************************************************/ double -rho_rtheta (ndom, x) - int ndom; - double *x; +rho_rtheta (int ndom, double *x) { double rho = 0; double r, z; diff --git a/source/import_spherical.c b/source/import_spherical.c index dccf3f2fa..13e0495c3 100644 --- a/source/import_spherical.c +++ b/source/import_spherical.c @@ -66,9 +66,7 @@ **********************************************************/ int -import_1d (ndom, filename) - int ndom; - char *filename; +import_1d (int ndom, char *filename) { FILE *fptr; char line[LINELENGTH]; @@ -221,9 +219,7 @@ import_spherical_setup_boundaries (int ndom) **********************************************************/ int -spherical_make_grid_import (w, ndom) - WindPtr w; - int ndom; +spherical_make_grid_import (WindPtr w, int ndom) { int j, n; @@ -307,9 +303,7 @@ spherical_make_grid_import (w, ndom) **********************************************************/ double -velocity_1d (ndom, x, v) - int ndom; - double *x, *v; +velocity_1d (int ndom, double *x, double *v) { double speed; double r; @@ -365,9 +359,7 @@ velocity_1d (ndom, x, v) **********************************************************/ double -rho_1d (ndom, x) - int ndom; - double *x; +rho_1d (int ndom, double *x) { double rho = 0; double r; diff --git a/source/inspect_wind.c b/source/inspect_wind.c index fe693720d..b02ed4e41 100644 --- a/source/inspect_wind.c +++ b/source/inspect_wind.c @@ -23,17 +23,18 @@ #include #include #include +#include #include "atomic.h" #include "sirocco.h" +int create_matom_level_map (void); char inroot[LINELENGTH], outroot[LINELENGTH], model_file[LINELENGTH], folder[LINELENGTH]; int model_flag, ksl_flag, cmf2obs_flag, obs2cmf_flag; double line_matom_lum_single (double lum[], PlasmaPtr xplasma, int uplvl); int line_matom_lum (int uplvl); -int create_matom_level_map (); /**********************************************************/ /** @@ -56,14 +57,11 @@ int create_matom_level_map (); **********************************************************/ int -xparse_command_line (argc, argv) - int argc; - char *argv[]; +xparse_command_line (int argc, char *argv[]) { int j = 0; int i; char dummy[LINELENGTH]; - int mkdir (); char *fgets_rc; @@ -178,16 +176,13 @@ xparse_command_line (argc, argv) int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { char infile[LINELENGTH], outfile[LINELENGTH]; int n, i; - FILE *fptr, *fopen (); + FILE *fptr; int ii, jj, ndom, nnwind; - int mkdir (); xparse_command_line (argc, argv); @@ -398,7 +393,7 @@ create_matom_level_map () { int uplvl, nbbd, n; char outfile[LINELENGTH]; - FILE *fptr, *fopen (); + FILE *fptr; /* open a file in the folder where we store the matom line luminosities */ sprintf (outfile, "%.200s/line_map.txt", folder); @@ -430,13 +425,12 @@ create_matom_level_map () **********************************************************/ int -line_matom_lum (uplvl) - int uplvl; +line_matom_lum (int uplvl) { int n, nbbd, i, ii, jj, nnwind, ndom, inwind; double lum[NBBJUMPS]; char outfile[LINELENGTH]; - FILE *fptr, *fopen (); + FILE *fptr; nbbd = xconfig[uplvl].n_bbd_jump; @@ -516,10 +510,7 @@ line_matom_lum (uplvl) **********************************************************/ double -line_matom_lum_single (lum, xplasma, uplvl) - double lum[]; - PlasmaPtr xplasma; - int uplvl; +line_matom_lum_single (double lum[], PlasmaPtr xplasma, int uplvl) { int n, nbbd, m; double penorm, bb_cont; diff --git a/source/knigge.c b/source/knigge.c index 02868d62f..5548d7db5 100644 --- a/source/knigge.c +++ b/source/knigge.c @@ -71,8 +71,7 @@ double kn_lambda; **********************************************************/ int -get_knigge_wind_params (ndom) - int ndom; +get_knigge_wind_params (int ndom) { double dmin; double rmin, rmax; @@ -193,9 +192,7 @@ get_knigge_wind_params (ndom) **********************************************************/ double -kn_velocity (ndom, x, v) - int ndom; - double x[], v[]; +kn_velocity (int ndom, double x[], double v[]) { double r, rzero, theta; double ldist, zzz, v_escape, vl; @@ -346,9 +343,7 @@ test programs. **********************************************************/ double -kn_rho (ndom, x) - int ndom; - double x[]; +kn_rho (int ndom, double x[]) { double r, rzero; double dd; @@ -429,8 +424,7 @@ kn_rho (ndom, x) **********************************************************/ double -kn_vzero (r) - double r; +kn_vzero (double r) { double t; double ratio, v; @@ -501,9 +495,7 @@ kn_wind_mdot_integral (double r, void *params) **********************************************************/ double -kn_rho_zero (ndom, r) - double r; - int ndom; +kn_rho_zero (int ndom, double r) { double t; double x, ratio; diff --git a/source/levels.c b/source/levels.c index 97ca980ff..ba432600d 100644 --- a/source/levels.c +++ b/source/levels.c @@ -47,9 +47,7 @@ **********************************************************/ int -levels (xplasma, mode) - PlasmaPtr xplasma; - int mode; +levels (PlasmaPtr xplasma, int mode) { double t, weight; int n, m; diff --git a/source/lines.c b/source/lines.c index d3d81c291..367498a86 100644 --- a/source/lines.c +++ b/source/lines.c @@ -200,13 +200,10 @@ double old_d1, old_d2, old_n2_over_n1; double -two_level_atom (line_ptr, xplasma, d1, d2) - struct lines *line_ptr; - PlasmaPtr xplasma; - double *d1, *d2; +two_level_atom (struct lines *line_ptr, PlasmaPtr xplasma, double *d1, double *d2) { - double a, a21 (); - double q, q21 (), c12, c21; + double a; + double q, c12, c21; double freq; double g2_over_g1; double n2_over_n1; @@ -359,9 +356,7 @@ ERROR -- or conceptually **********************************************************/ double -line_nsigma (line_ptr, xplasma) - struct lines *line_ptr; - PlasmaPtr xplasma; +line_nsigma (struct lines *line_ptr, PlasmaPtr xplasma) { double d1, d2, x; @@ -418,9 +413,7 @@ excited by radiation and return to the ground state via spontaneous emission. **********************************************************/ double -scattering_fraction (line_ptr, xplasma) - struct lines *line_ptr; - PlasmaPtr xplasma; +scattering_fraction (struct lines *line_ptr, PlasmaPtr xplasma) { double q, escape; double a, c, z; @@ -494,11 +487,9 @@ double pe_escape; **********************************************************/ double -p_escape (line_ptr, xplasma) - struct lines *line_ptr; - PlasmaPtr xplasma; +p_escape (struct lines *line_ptr, PlasmaPtr xplasma) { - double tau, two_level_atom (); + double tau; double escape; double ne, te; double dd; /* density of the relevent ion */ @@ -574,8 +565,7 @@ p_escape (line_ptr, xplasma) **********************************************************/ double -p_escape_from_tau (tau) - double tau; +p_escape_from_tau (double tau) { double escape; @@ -620,10 +610,7 @@ p_escape_from_tau (tau) **********************************************************/ int -line_heat (xplasma, pp, nres) - PlasmaPtr xplasma; - PhotPtr pp; - int nres; +line_heat (PlasmaPtr xplasma, PhotPtr pp, int nres) { double x, sf; diff --git a/source/macro_accelerate.c b/source/macro_accelerate.c index 993b7482d..e1d62b0cb 100644 --- a/source/macro_accelerate.c +++ b/source/macro_accelerate.c @@ -28,9 +28,7 @@ **********************************************************/ void -calc_matom_matrix (xplasma, matom_matrix) - PlasmaPtr xplasma; - double **matom_matrix; +calc_matom_matrix (PlasmaPtr xplasma, double **matom_matrix) { MacroPtr mplasma; double t_e, ne; @@ -363,10 +361,7 @@ calc_matom_matrix (xplasma, matom_matrix) **********************************************************/ int -fill_kpkt_rates (xplasma, escape, p) - PlasmaPtr xplasma; - int *escape; - PhotPtr p; +fill_kpkt_rates (PlasmaPtr xplasma, int *escape, PhotPtr p) { int i; @@ -612,10 +607,7 @@ fill_kpkt_rates (xplasma, escape, p) ***********************************************************/ double -f_matom_emit_accelerate (xplasma, upper, freq_min, freq_max) - PlasmaPtr xplasma; - int upper; - double freq_min, freq_max; +f_matom_emit_accelerate (PlasmaPtr xplasma, int upper, double freq_min, double freq_max) { struct lines *line_ptr; struct topbase_phot *cont_ptr; @@ -783,9 +775,7 @@ f_matom_emit_accelerate (xplasma, upper, freq_min, freq_max) ************************************************************/ double -f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) - PlasmaPtr xplasma; - double freq_min, freq_max; +f_kpkt_emit_accelerate (PlasmaPtr xplasma, double freq_min, double freq_max) { int i; @@ -952,9 +942,7 @@ f_kpkt_emit_accelerate (xplasma, freq_min, freq_max) **********************************************************/ int -matom_deactivation_from_matrix (xplasma, uplvl) - PlasmaPtr xplasma; - int uplvl; +matom_deactivation_from_matrix (PlasmaPtr xplasma, int uplvl) { double z, total; int j, i; diff --git a/source/macro_gen_f.c b/source/macro_gen_f.c index 307a2cb68..b215317c0 100644 --- a/source/macro_gen_f.c +++ b/source/macro_gen_f.c @@ -45,8 +45,7 @@ **********************************************************/ double -get_matom_f (mode) - int mode; +get_matom_f (int mode) { int n, m, mm; double lum; @@ -388,8 +387,7 @@ get_matom_f (mode) **********************************************************/ double -get_matom_f_accelerate (mode) - int mode; +get_matom_f_accelerate (int mode) { int n, m, mm; double lum; diff --git a/source/macro_gov.c b/source/macro_gov.c index c28275928..fb8811257 100644 --- a/source/macro_gov.c +++ b/source/macro_gov.c @@ -53,11 +53,7 @@ **********************************************************/ int -macro_gov (p, nres, matom_or_kpkt, which_out) - PhotPtr p; - int *nres; - int matom_or_kpkt; - int *which_out; +macro_gov (PhotPtr p, int *nres, int matom_or_kpkt, int *which_out) { int escape; //this tells us when the r-packet is escaping int n_jump = 0; @@ -333,9 +329,7 @@ macro_gov (p, nres, matom_or_kpkt, which_out) **********************************************************/ int -macro_pops (xplasma, xne) - PlasmaPtr xplasma; - double xne; +macro_pops (PlasmaPtr xplasma, double xne) { int i, j, index_element, index_lvl; int matrix_err, numerical_error, populations_ok; diff --git a/source/matom.c b/source/matom.c index acbf60273..fe4d924eb 100644 --- a/source/matom.c +++ b/source/matom.c @@ -64,10 +64,7 @@ int matom_cycle = -1; ***********************************************************/ int -matom (p, nres, escape) - PhotPtr p; - int *nres; - int *escape; +matom (PhotPtr p, int *nres, int *escape) { struct lines *line_ptr; struct topbase_phot *cont_ptr; @@ -505,8 +502,7 @@ struct lines *b12_line_ptr; double b12_a; double -b12 (line_ptr) - struct lines *line_ptr; +b12 (struct lines *line_ptr) { double freq; @@ -563,10 +559,7 @@ int temp_choice; //choice of type of calcualation for alpha_sp #define ALPHA_SP_CONSTANT 5.79618e-36 double -xalpha_sp (cont_ptr, xplasma, ichoice) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; - int ichoice; +xalpha_sp (struct topbase_phot *cont_ptr, PlasmaPtr xplasma, int ichoice) { double alpha_sp_value; double fthresh, flast; @@ -633,10 +626,7 @@ xalpha_sp (cont_ptr, xplasma, ichoice) ***********************************************************/ double -alpha_sp (cont_ptr, xplasma, ichoice) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; - int ichoice; +alpha_sp (struct topbase_phot *cont_ptr, PlasmaPtr xplasma, int ichoice) { double alpha_sp_value; double fthresh, flast; @@ -770,11 +760,7 @@ alpha_sp (cont_ptr, xplasma, ichoice) #define ALPHA_SP_CONSTANT 5.79618e-36 double -scaled_alpha_sp_integral_band_limited (cont_ptr, xplasma, ichoice, freq_min, freq_max) - struct topbase_phot *cont_ptr; - PlasmaPtr xplasma; - int ichoice; - double freq_min, freq_max; +scaled_alpha_sp_integral_band_limited (struct topbase_phot *cont_ptr, PlasmaPtr xplasma, int ichoice, double freq_min, double freq_max) { double alpha_sp_value; double fthresh, flast; @@ -864,11 +850,7 @@ alpha_sp_integrand (double freq, void *params) ************************************************************/ int -kpkt (p, nres, escape, mode) - PhotPtr p; - int *nres; - int *escape; - int mode; +kpkt (PhotPtr p, int *nres, int *escape, int mode) { int i; @@ -1184,10 +1166,7 @@ kpkt (p, nres, escape, mode) ************************************************************/ int -fake_matom_bb (p, nres, escape) - PhotPtr p; - int *nres; - int *escape; +fake_matom_bb (PhotPtr p, int *nres, int *escape) { double kprb, rprb; WindPtr one; @@ -1286,10 +1265,7 @@ fake_matom_bb (p, nres, escape) ************************************************************/ int -fake_matom_bf (p, nres, escape) - PhotPtr p; - int *nres; - int *escape; +fake_matom_bf (PhotPtr p, int *nres, int *escape) { WindPtr one; //OLD PlasmaPtr xplasma; @@ -1335,12 +1311,7 @@ fake_matom_bf (p, nres, escape) ***********************************************************/ int -emit_matom (w, p, nres, upper, freq_min, freq_max) - WindPtr w; - PhotPtr p; - int *nres; - int upper; - double freq_min, freq_max; +emit_matom (WindPtr w, PhotPtr p, int *nres, int upper, double freq_min, double freq_max) { struct lines *line_ptr; struct topbase_phot *cont_ptr; diff --git a/source/matrix_ion.c b/source/matrix_ion.c index d825d1281..0bbcdc3d2 100644 --- a/source/matrix_ion.c +++ b/source/matrix_ion.c @@ -52,10 +52,7 @@ **********************************************************/ int -matrix_ion_populations (xplasma, mode) - PlasmaPtr xplasma; - int mode; - +matrix_ion_populations (PlasmaPtr xplasma, int mode) { double elem_dens[NELEMENTS]; //The density of each element int nn, mm, nrows; @@ -442,15 +439,8 @@ matrix_ion_populations (xplasma, mode) **********************************************************/ int -populate_ion_rate_matrix (rate_matrix, pi_rates, inner_rates, rr_rates, b_temp, xne, nh1, nh2) - double rate_matrix[nions][nions]; - double pi_rates[nions]; - double inner_rates[n_inner_tot]; - double rr_rates[nions]; - double xne; - double b_temp[nions]; - double nh1, nh2; - +populate_ion_rate_matrix (double rate_matrix[nions][nions], double pi_rates[nions], double inner_rates[n_inner_tot], double rr_rates[nions], + double b_temp[nions], double xne, double nh1, double nh2) { // int nn, mm, zcount; int nn, mm; diff --git a/source/modify_wind.c b/source/modify_wind.c index 56c28f7a3..2413cb151 100644 --- a/source/modify_wind.c +++ b/source/modify_wind.c @@ -57,14 +57,11 @@ int model_flag, ksl_flag, cmf2obs_flag, obs2cmf_flag; **********************************************************/ int -xparse_command_line (argc, argv) - int argc; - char *argv[]; +xparse_command_line (int argc, char *argv[]) { int j = 0; int i; char dummy[LINELENGTH]; - int mkdir (); char *fgets_rc; @@ -179,17 +176,15 @@ xparse_command_line (argc, argv) int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { double *den; char name[LINELENGTH]; /* file name extension */ char infile[LINELENGTH], outfile[LINELENGTH]; - int put_ion (); - int apply_model (); - int frame_transform (); + int put_ion (int ndom, int element, int istate, double *den); + int apply_model (int ndom, char *filename); + int frame_transform (int ndom); int ndom; int i; @@ -272,9 +267,7 @@ main (argc, argv) **********************************************************/ int -put_ion (ndom, element, istate, den) - int ndom, element, istate; - double *den; +put_ion (int ndom, int element, int istate, double *den) { int i, n; int nion; @@ -312,9 +305,7 @@ put_ion (ndom, element, istate, den) int -apply_model (ndom, filename) - int ndom; - char *filename; +apply_model (int ndom, char *filename) { int ndim, mdim; //OLD int nstart, n, nion, nplasma; @@ -389,8 +380,7 @@ apply_model (ndom, filename) int -frame_transform (ndom) - int ndom; +frame_transform (int ndom) { int n, nion; double factor; //This will either be gamma or 1/gamma diff --git a/source/parse.c b/source/parse.c index fd5af12ee..4876e8027 100644 --- a/source/parse.c +++ b/source/parse.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "atomic.h" #include "sirocco.h" @@ -47,14 +48,11 @@ **********************************************************/ int -parse_command_line (argc, argv) - int argc; - char *argv[]; +parse_command_line (int argc, char *argv[]) { int restart_stat, verbosity, max_errors, i; int j = 0; char dummy[LINELENGTH]; - int mkdir (); double time_max; char *fgets_rc; double x; diff --git a/source/partition.c b/source/partition.c index e67e09808..bdd24580e 100644 --- a/source/partition.c +++ b/source/partition.c @@ -51,12 +51,9 @@ **********************************************************/ int -partition_functions (xplasma, mode) - PlasmaPtr xplasma; - int mode; +partition_functions (PlasmaPtr xplasma, int mode) { int nion; - double partition (); double t, weight; int n, m; @@ -215,14 +212,9 @@ partition_functions (xplasma, mode) **********************************************************/ int -partition_functions_2 (xplasma, xnion, temp, weight) - PlasmaPtr xplasma; - int xnion; - double temp; - double weight; +partition_functions_2 (PlasmaPtr xplasma, int xnion, double temp, double weight) { int nion; - double partition (); int n, m; int m_ground; diff --git a/source/paths.c b/source/paths.c index 96ddca2d3..7d6578805 100644 --- a/source/paths.c +++ b/source/paths.c @@ -590,7 +590,7 @@ wind_paths_evaluate (WindPtr wind) int wind_paths_dump (WindPtr wind, int rank_global) { - FILE *fopen (), *fptr; + FILE *fptr; char c_file[LINELENGTH]; int j, k; @@ -736,7 +736,7 @@ wind_paths_sphere_point_index (int i, int j, int k) int wind_paths_output_vtk (WindPtr wind, int ndom) { - FILE *fopen (), *fptr; + FILE *fptr; char c_file[LINELENGTH]; int i, j, k, n, i_obs, i_cells, i_points; double r_azi, r_inc, r_x, r_y, r_z, r_err; diff --git a/source/phot_util.c b/source/phot_util.c index 513c35be5..2d70736ca 100644 --- a/source/phot_util.c +++ b/source/phot_util.c @@ -43,8 +43,7 @@ size_t sizeofphot; int -init_dummy_phot (p) - PhotPtr p; +init_dummy_phot (PhotPtr p) { p->x[0] = p->x[1] = p->x[2] = 0.0; p->lmn[0] = p->lmn[1] = 0; @@ -78,8 +77,7 @@ init_dummy_phot (p) **********************************************************/ int -stuff_phot (pin, pout) - PhotPtr pin, pout; +stuff_phot (PhotPtr pin, PhotPtr pout) { pout->x[0] = pin->x[0]; pout->x[1] = pin->x[1]; @@ -138,9 +136,7 @@ stuff_phot (pin, pout) **********************************************************/ int -move_phot (pp, ds) - PhotPtr pp; - double ds; +move_phot (PhotPtr pp, double ds) { int ierr; @@ -175,8 +171,7 @@ move_phot (pp, ds) **********************************************************/ int -comp_phot (p1, p2) - PhotPtr p1, p2; +comp_phot (PhotPtr p1, PhotPtr p2) { if (p1->x[0] != p2->x[0] || p1->lmn[0] != p2->lmn[0]) return (1); @@ -222,9 +217,7 @@ comp_phot (p1, p2) **********************************************************/ double -ds_to_cone (cc, p) - ConePtr cc; - struct photon *p; +ds_to_cone (ConePtr cc, struct photon *p) { double dz, dzdr2; double a, b, c, root[2]; @@ -294,9 +287,7 @@ ds_to_cone (cc, p) **********************************************************/ double -ds_to_sphere (r, p) - double r; - struct photon *p; +ds_to_sphere (double r, struct photon *p) { int i; double a, b, c, root[2]; @@ -347,13 +338,10 @@ both roots were imaginary */ **********************************************************/ double -ds_to_sphere2 (x, r, p) - double x[], r; - struct photon *p; +ds_to_sphere2 (double x[], double r, struct photon *p) { double a, b, c, root[2], delta[3]; int i; - double dot (); vsub (p->x, x, delta); @@ -400,8 +388,7 @@ ds_to_sphere2 (x, r, p) **********************************************************/ int -quadratic (a, b, c, r) - double a, b, c, r[]; +quadratic (double a, double b, double c, double r[]) { double q, z; @@ -471,10 +458,7 @@ quadratic (a, b, c, r) **********************************************************/ double -ds_to_plane (pl, p, force_positive_z) - struct plane *pl; - struct photon *p; - int force_positive_z; +ds_to_plane (struct plane *pl, struct photon *p, int force_positive_z) { double denom, diff[3], numer; struct photon ptest; @@ -524,7 +508,6 @@ ds_to_closest_approach (x, p, impact_parameter) double *impact_parameter; /* distance of ray to point a closest approach */ { double diff[3], s, result[3]; - double length (), dot (); vsub (p->x, x, diff); s = -dot (diff, p->lmn); @@ -559,9 +542,7 @@ ds_to_closest_approach (x, p, impact_parameter) **********************************************************/ double -ds_to_cylinder (rho, p) - double rho; - struct photon *p; +ds_to_cylinder (double rho, struct photon *p) { double a, b, c, root[2]; int i; diff --git a/source/photon2d.c b/source/photon2d.c index 35e9945ca..e9e774b02 100644 --- a/source/photon2d.c +++ b/source/photon2d.c @@ -139,8 +139,7 @@ translate (w, pp, tau_scat, tau, nres) **********************************************************/ int -translate_in_space (pp) - PhotPtr pp; +translate_in_space (PhotPtr pp) { //OLD double ds, delta, s, smax, prhosq; double ds, delta, s, smax; @@ -277,9 +276,7 @@ translate_in_space (pp) **********************************************************/ double -ds_to_wind (pp, ndom_current) - PhotPtr pp; - int *ndom_current; +ds_to_wind (PhotPtr pp, int *ndom_current) { struct photon ptest, qtest; double ds, x, rho, z; @@ -671,10 +668,7 @@ smax_in_cell (PhotPtr p) **********************************************************/ double -ds_in_cell (ndom, p) - int ndom; - PhotPtr p; - +ds_in_cell (int ndom, PhotPtr p) { int n; double smax; diff --git a/source/photon_gen.c b/source/photon_gen.c index 07ba89598..21ba8e027 100644 --- a/source/photon_gen.c +++ b/source/photon_gen.c @@ -238,11 +238,7 @@ define_phot (p, f1, f2, nphot_tot, ioniz_or_extract, iwind, freq_sampling) **********************************************************/ double -populate_bands (ioniz_or_extract, iwind, band) - int ioniz_or_extract; - int iwind; - struct xbands *band; - +populate_bands (int ioniz_or_extract, int iwind, struct xbands *band) { double ftot, frac_used, z; int n, nphot, most, nphot_rad; @@ -355,12 +351,7 @@ populate_bands (ioniz_or_extract, iwind, band) **********************************************************/ int -xdefine_phot (f1, f2, ioniz_or_extract, iwind, print_mode, tot_flag) - double f1, f2; - int ioniz_or_extract; - int iwind; - int print_mode; - int tot_flag; +xdefine_phot (double f1, double f2, int ioniz_or_extract, int iwind, int print_mode, int tot_flag) { /* First determine if you need to reinitialize because the frequency boundaries are different than previously */ @@ -818,12 +809,10 @@ stellar photons */ **********************************************************/ int -star_init (freqmin, freqmax, ioniz_or_extract, f) - double freqmin, freqmax, *f; - int ioniz_or_extract; +star_init (double freqmin, double freqmax, int ioniz_or_extract, double *f) { double r, tstar, log_g; - double emit, emittance_bb (), emittance_continuum (); + double emit; int spectype; log_g = geo.gstar = log10 (GRAV * geo.mstar / (geo.rstar * geo.rstar)); @@ -1023,12 +1012,9 @@ photo_gen_star (p, r, t, weight, f1, f2, spectype, istart, nphot) **********************************************************/ double -bl_init (lum_bl, t_bl, freqmin, freqmax, ioniz_or_extract, f) - double lum_bl, t_bl, freqmin, freqmax, *f; - int ioniz_or_extract; +bl_init (double lum_bl, double t_bl, double freqmin, double freqmax, int ioniz_or_extract, double *f) { //OLD double q1; - double integ_planck_d (); //OLD double alphamin, alphamax; //OLD q1 = 2. * PI * (BOLTZMANN * BOLTZMANN * BOLTZMANN * BOLTZMANN) / (PLANCK * PLANCK * PLANCK * VLIGHT * VLIGHT); @@ -1085,10 +1071,7 @@ bl_init (lum_bl, t_bl, freqmin, freqmax, ioniz_or_extract, f) **********************************************************/ int -photon_checks (p, freqmin, freqmax, comment) - char *comment; - PhotPtr p; - double freqmin, freqmax; +photon_checks (PhotPtr p, double freqmin, double freqmax, char *comment) { int nnn, nn; int nlabel; diff --git a/source/photon_gen_matom.c b/source/photon_gen_matom.c index 0be5db40a..23c8d1747 100644 --- a/source/photon_gen_matom.c +++ b/source/photon_gen_matom.c @@ -121,10 +121,7 @@ get_kpkt_heating_f () **********************************************************/ int -photo_gen_kpkt (p, weight, photstart, nphot) - PhotPtr p; - double weight; - int photstart, nphot; +photo_gen_kpkt (PhotPtr p, double weight, int photstart, int nphot) { int photstop; int icell; @@ -299,10 +296,7 @@ photo_gen_kpkt (p, weight, photstart, nphot) **********************************************************/ int -photo_gen_matom (p, weight, photstart, nphot) - PhotPtr p; - double weight; - int photstart, nphot; +photo_gen_matom (PhotPtr p, double weight, int photstart, int nphot) { int photstop; int icell; @@ -310,7 +304,6 @@ photo_gen_matom (p, weight, photstart, nphot) struct photon pp; int nres; int n; - double dot (); //OLD double test; int upper; int nnscat; diff --git a/source/pi_rates.c b/source/pi_rates.c index 6a067497d..adc4b6bc6 100644 --- a/source/pi_rates.c +++ b/source/pi_rates.c @@ -59,11 +59,7 @@ double xexp_temp, xexp_w; **********************************************************/ double -calc_pi_rate (nion, xplasma, mode, type) - int nion; - PlasmaPtr xplasma; - int mode; - int type; +calc_pi_rate (int nion, PlasmaPtr xplasma, int mode, int type) { int j; double pi_rate; diff --git a/source/rad_hydro_files.c b/source/rad_hydro_files.c index a7ce857c5..5cdac32d2 100644 --- a/source/rad_hydro_files.c +++ b/source/rad_hydro_files.c @@ -128,9 +128,7 @@ xparse_arguments (int argc, char *argv[], char root[], int *ion_switch) **********************************************************/ int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { char root[LINELENGTH]; char outputfile[LINELENGTH]; diff --git a/source/radiation.c b/source/radiation.c index 196a1fa84..5fdedcbf4 100644 --- a/source/radiation.c +++ b/source/radiation.c @@ -528,12 +528,9 @@ radiation (PhotPtr p, double ds) **********************************************************/ double -kappa_ff (xplasma, freq) - PlasmaPtr xplasma; - double freq; +kappa_ff (PlasmaPtr xplasma, double freq) { double x; - double exp (); double x1, x2, x3; int ndom; @@ -598,14 +595,11 @@ kappa_ff (xplasma, freq) **********************************************************/ double -sigma_phot (x_ptr, freq) - struct topbase_phot *x_ptr; - double freq; +sigma_phot (struct topbase_phot *x_ptr, double freq) { int nmax; double xsection; double frac, fbot, ftop; - int linterp (); int nlast; if (freq < x_ptr->freq[0]) @@ -667,9 +661,7 @@ sigma_phot (x_ptr, freq) **********************************************************/ double -den_config (xplasma, nconf) - PlasmaPtr xplasma; - int nconf; +den_config (PlasmaPtr xplasma, int nconf) { double density; int nnlev, nion; @@ -800,10 +792,7 @@ pop_kappa_ff_array () **********************************************************/ double -mean_intensity (xplasma, freq, mode) - PlasmaPtr xplasma; - double freq; - int mode; +mean_intensity (PlasmaPtr xplasma, double freq, int mode) { double j_bar; diff --git a/source/random.c b/source/random.c index bd6e41256..dd578bb29 100644 --- a/source/random.c +++ b/source/random.c @@ -64,8 +64,7 @@ char rngsave_file[LINELENGTH]; int -randvec (a, r) - double a[], r; +randvec (double a[], double r) { double costheta, sintheta, phi, sinphi, cosphi; @@ -122,8 +121,7 @@ int init_vcos = 0; **********************************************************/ int -randvcos (lmn, north) - double lmn[], north[]; +randvcos (double lmn[], double north[]) { double x[3]; /* the photon direction in the rotated frame */ double l, m, n; /* the individual direction cosines in the rotated frame */ @@ -272,8 +270,7 @@ int init_vdipole = 0; **********************************************************/ int -randvdipole (lmn, north) - double lmn[], north[]; +randvdipole (double lmn[], double north[]) { double x[3]; /* the photon direction in the rotated frame */ double l, m, n; /* the individual direction cosines in the rotated frame */ @@ -419,8 +416,7 @@ vdipole (double cos_theta, void *params) int -init_rand (seed) - int seed; +init_rand (int seed) { rng = gsl_rng_alloc (gsl_rng_mt19937); gsl_rng_set (rng, seed); @@ -439,9 +435,7 @@ init_rand (seed) **********************************************************/ void -init_rng_directory (root, rank) - char *root; - int rank; +init_rng_directory (char *root, int rank) { int err; char dir_name[LINELENGTH]; diff --git a/source/rdpar.c b/source/rdpar.c index 85a71f155..7d0e43f4d 100644 --- a/source/rdpar.c +++ b/source/rdpar.c @@ -221,11 +221,9 @@ int strict = 0; // Initialize to a value that indicates everytin **********************************************************/ int -opar (filename) - char filename[]; +opar (char filename[]) { - FILE *fopen (), *tmp_ptr; - int rdpar_init (); + FILE *tmp_ptr; /* Check that an input file is not currently open */ if (rdpar_stat == 2) @@ -290,10 +288,8 @@ opar (filename) **********************************************************/ int -add_par (filename) - char filename[]; +add_par (char filename[]) { - int rdpar_init (); /* Check that an input file is not currently open */ if (rdpar_stat != 2) @@ -340,8 +336,7 @@ add_par (filename) **********************************************************/ int -cpar (filename) - char filename[]; +cpar (char filename[]) { char old_filename[LINELEN]; @@ -389,7 +384,6 @@ cpar (filename) int rdpar_init () { - FILE *fopen (); rdin_ptr = stdin; /* Initialize rdin_ptr to standard input */ if ((rdout_ptr = fopen ("tmp.rdpar", "w")) == NULL) { @@ -471,8 +465,7 @@ check_and_fix_string (char *s) **********************************************************/ int -string_process (question, dummy) - char question[], dummy[]; +string_process (char question[], char dummy[]) { if (rdpar_stat == 0) @@ -523,8 +516,7 @@ string_process (question, dummy) **********************************************************/ int -string_process_from_command_line (question, dummy) - char question[], dummy[]; +string_process_from_command_line (char question[], char dummy[]) { char tdummy[LINELEN]; fprintf (stderr, "%s (%s) :", question, dummy); @@ -603,13 +595,12 @@ string_process_from_command_line (question, dummy) **********************************************************/ int -string_process_from_file (question, dummy) - char question[], dummy[]; +string_process_from_file (char question[], char dummy[]) { char firstword[LINELEN], secondword[LINELEN]; char *line, *fgets_rc; - char *ccc, *index (), *fgets (); + char *ccc; int nwords = 0; // Initialise to avoid warning int wordlength; char xfirstword[LINELEN], xquestion[LINELEN]; @@ -779,8 +770,7 @@ string_process_from_file (question, dummy) **********************************************************/ int -rdpar_store_record (name, value) - char *name, *value; +rdpar_store_record (char *name, char *value) { strcpy (rdpar_record[rdpar_nrec].name, name); strcpy (rdpar_record[rdpar_nrec].value, value); @@ -814,8 +804,7 @@ rdpar_store_record (name, value) **********************************************************/ int -rdpar_save (file_ptr) - FILE *file_ptr; +rdpar_save (FILE *file_ptr) { int i; @@ -885,8 +874,7 @@ rdpar_comment (char *format, ...) **********************************************************/ int -message (string) - char string[]; +message (char string[]) { fprintf (stderr, "%s\n", string); fflush (stderr); @@ -912,8 +900,7 @@ message (string) **********************************************************/ int -rdstr (question, answer) - char question[], answer[]; +rdstr (char question[], char answer[]) { int query; char dummy[LINELEN]; @@ -955,9 +942,7 @@ rdstr (question, answer) **********************************************************/ int -rdchar (question, answer) - char question[]; - char *answer; +rdchar (char question[], char *answer) { int query; char dummy[LINELEN]; @@ -999,9 +984,7 @@ rdchar (question, answer) **********************************************************/ int -rdint (question, answer) - char question[]; - int *answer; +rdint (char question[], int *answer) { int query; char dummy[LINELEN]; @@ -1043,9 +1026,7 @@ rdint (question, answer) **********************************************************/ int -rdflo (question, answer) - char question[]; - float *answer; +rdflo (char question[], float *answer) { int query; char dummy[LINELEN]; @@ -1086,9 +1067,7 @@ rdflo (question, answer) **********************************************************/ int -rddoub (question, answer) - char question[]; - double *answer; +rddoub (char question[], double *answer) { int query; char dummy[LINELEN]; @@ -1130,9 +1109,7 @@ rddoub (question, answer) **********************************************************/ int -rdline (question, answer) - char question[]; - char answer[]; +rdline (char question[], char answer[]) { int query; char dummy[LINELEN]; @@ -1192,11 +1169,7 @@ rdline (question, answer) #define MAX_CHOICES 10 int -string2int (word, string_choices, string_values, string_answer) - char *word; - char *string_choices; - char *string_values; - char *string_answer; +string2int (char *word, char *string_choices, char *string_values, char *string_answer) { int i; int nchoices; @@ -1369,10 +1342,7 @@ string2int (word, string_choices, string_values, string_answer) **********************************************************/ int -rdchoice (question, answers, answer) - char question[]; - char answers[]; - char *answer; +rdchoice (char question[], char answers[], char *answer) { char dummy[LINELEN]; char string_answer[LINELEN]; @@ -1472,8 +1442,7 @@ rdchoice (question, answers, answer) **********************************************************/ int -get_root (root, total) - char root[], total[]; +get_root (char root[], char total[]) { int j; char *pf; @@ -1525,8 +1494,7 @@ get_root (root, total) **********************************************************/ int -rdpar_set_mpi_rank (rank) - int rank; +rdpar_set_mpi_rank (int rank) { rd_rank = rank; return (0); @@ -1556,8 +1524,7 @@ rdpar_set_mpi_rank (rank) **********************************************************/ int -rdpar_set_verbose (vlevel) - int vlevel; +rdpar_set_verbose (int vlevel) { if (vlevel < 2) verbose = 0; diff --git a/source/rdpar_init.c b/source/rdpar_init.c index b1722ad43..88087cee2 100644 --- a/source/rdpar_init.c +++ b/source/rdpar_init.c @@ -156,10 +156,7 @@ init_choices () * **********************************************************/ int -get_choices (question, choices, qstruct) - char *question; - char *choices; - struct rdpar_choices *qstruct; +get_choices (char *question, char *choices, struct rdpar_choices *qstruct) { char cur_choices[MAX_RDPAR_CHOICES][LINELENGTH]; int cur_values[MAX_RDPAR_CHOICES] = { -999 }; diff --git a/source/recipes.c b/source/recipes.c index 598e0e8e6..259f13ac5 100644 --- a/source/recipes.c +++ b/source/recipes.c @@ -60,10 +60,7 @@ double -num_int (func, a, b, eps) - double (*func) (double, void *); - double a, b; - double eps; +num_int (double (*func) (double, void *), double a, double b, double eps) { double result, error, result2; double alpha = 0.0; @@ -151,11 +148,7 @@ num_int (func, a, b, eps) double -zero_find (func, x1, x2, tol, ierr) - double (*func) (double, void *); - double x1, x2; - double tol; - int *ierr; +zero_find (double (*func) (double, void *), double x1, double x2, double tol, int *ierr) { double result; double x_below, x_above; @@ -263,11 +256,7 @@ zero_find (func, x1, x2, tol, ierr) double -find_function_minimum (a, m, b, func, tol, xmin) - double (*func) (double, void *); - double a, m, b; - double tol, *xmin; - +find_function_minimum (double a, double m, double b, double (*func) (double, void *), double tol, double *xmin) { int status = 0; void *test = NULL; diff --git a/source/recomb.c b/source/recomb.c index 10d4397fe..9e8b8f61f 100644 --- a/source/recomb.c +++ b/source/recomb.c @@ -119,8 +119,7 @@ int fbfr; **********************************************************/ double -fb_topbase_partial (freq) - double freq; +fb_topbase_partial (double freq) { int nion; double partial, log_freq; @@ -446,11 +445,7 @@ integ_fb (t, f1, f2, nion, fb_choice, mode) **********************************************************/ double -total_fb (xplasma, t, f1, f2, fb_choice, mode) - PlasmaPtr xplasma; - double t, f1, f2; - int fb_choice; - int mode; +total_fb (PlasmaPtr xplasma, double t, double f1, double f2, int fb_choice, int mode) { double total; int nion; @@ -742,10 +737,7 @@ one_fb (xplasma, f1, f2) **********************************************************/ int -num_recomb (xplasma, t_e, mode) - PlasmaPtr xplasma; - double t_e; - int mode; +num_recomb (PlasmaPtr xplasma, double t_e, int mode) { int nelem; int i, imin, imax; @@ -813,12 +805,7 @@ num_recomb (xplasma, t_e, mode) **********************************************************/ double -fb (xplasma, t, freq, ion_choice, fb_choice) - PlasmaPtr xplasma; - double t; - double freq; - int ion_choice; - int fb_choice; +fb (PlasmaPtr xplasma, double t, double freq, int ion_choice, int fb_choice) { int n; double fnu, x; @@ -947,13 +934,11 @@ int init_freebound_nfb; **********************************************************/ int -init_freebound (t1, t2, f1, f2) - double t1, t2, f1, f2; +init_freebound (double t1, double t2, double f1, double f2) { double t; int i, j, nion; double ltmin, ltmax, dlt; - double xinteg_fb (); int nput; @@ -1075,12 +1060,8 @@ on the assumption that the fb information will be reused. **********************************************************/ double -get_nrecomb (t, nion, mode) - double t; - int nion; - int mode; +get_nrecomb (double t, int nion, int mode) { - int linterp (); double x = -99.; if (mode == OUTER_SHELL) linterp (t, fb_t, xnrecomb[nion], NTEMPS, &x, 0); //Interpolate in linear space @@ -1130,14 +1111,8 @@ get_nrecomb (t, nion, mode) **********************************************************/ double -get_fb (t, nion, narray, fb_choice, mode) - double t; - int nion; - int narray; - int fb_choice; - int mode; +get_fb (double t, int nion, int narray, int fb_choice, int mode) { - int linterp (); double x = -99.; if (mode == OUTER_SHELL) { @@ -1205,9 +1180,7 @@ xinteg_fb (t, f1, f2, nion, fb_choice) double fnu; double dnu; //NSH 140120 - a parameter to allow one to restrict the integration limits. double fthresh, fmax; - double den_config (); int nmin, nmax; // These are the limits over which number xsections we will use - double qromb (); dnu = 0.0; //Avoid compilation errors. @@ -1336,7 +1309,6 @@ xinteg_inner_fb (t, f1, f2, nion, fb_choice) double fnu; double dnu; // a parameter to allow one to restrict the integration limits. double fthresh, fmax; - double den_config (); dnu = 0.0; //Avoid compilation errors. @@ -1431,9 +1403,7 @@ xinteg_inner_fb (t, f1, f2, nion, fb_choice) **********************************************************/ double -total_rrate (nion, T) - int nion; - double T; +total_rrate (int nion, double T) { @@ -1524,9 +1494,7 @@ total_rrate (nion, T) **********************************************************/ double -gs_rrate (nion, T) - int nion; - double T; +gs_rrate (int nion, double T) { double rate, drdt, dt; int i, imin, imax; diff --git a/source/resonate.c b/source/resonate.c index 74c1af02f..57ade4c0b 100644 --- a/source/resonate.c +++ b/source/resonate.c @@ -76,13 +76,7 @@ const double MAXDIFF = VCHECK / VLIGHT; double -calculate_ds (w, p, tau_scat, tau, nres, smax, istat) - WindPtr w; - PhotPtr p; - double tau_scat, *tau; - int *nres; - double smax; - int *istat; +calculate_ds (WindPtr w, PhotPtr p, double tau_scat, double *tau, int *nres, double smax, int *istat) { int nion_for_resonance; int n, current_res_number, nstart, ndelt; @@ -455,9 +449,7 @@ calculate_ds (w, p, tau_scat, tau, nres, smax, istat) **********************************************************/ int -select_continuum_scattering_process (kap_cont, kap_es, kap_ff, xplasma) - double kap_cont, kap_es, kap_ff; - PlasmaPtr xplasma; +select_continuum_scattering_process (double kap_cont, double kap_es, double kap_ff, PlasmaPtr xplasma) { int nres; double threshold; @@ -528,12 +520,7 @@ select_continuum_scattering_process (kap_cont, kap_es, kap_ff, xplasma) **********************************************************/ double -kappa_bf (xplasma, freq, macro_all) - PlasmaPtr xplasma; - double freq; - int macro_all; - - +kappa_bf (PlasmaPtr xplasma, double freq, int macro_all) { double kap_bf_tot; double ft; @@ -617,10 +604,7 @@ kappa_bf (xplasma, freq, macro_all) **********************************************************/ int -kbf_need (freq_min, freq_max) - double freq_min, freq_max; - - +kbf_need (double freq_min, double freq_max) { int nconf; double density; @@ -711,12 +695,7 @@ int sobolev_error_counter = 0; * **********************************************************/ double -sobolev (one, x, den_ion, lptr, dvds) - WindPtr one; - double x[]; - double den_ion; - struct lines *lptr; - double dvds; +sobolev (WindPtr one, double x[], double den_ion, struct lines *lptr, double dvds) { double tau, xden_ion, tau_x_dvds, levden_upper; double d1, d2; @@ -884,10 +863,7 @@ calls to two_level atom **********************************************************/ int -scatter (p, nres, nnscat) - PhotPtr p; - int *nres; - int *nnscat; +scatter (PhotPtr p, int *nres, int *nnscat) { double z_prime[3]; int which_out; diff --git a/source/reverb.c b/source/reverb.c index 69724d632..11fdfddbc 100644 --- a/source/reverb.c +++ b/source/reverb.c @@ -162,8 +162,7 @@ delay_dump_finish (void) int delay_dump_combine (int i_ranks) { - FILE *fopen (); //, *f_base, *f_cat; - char c_call[LINELENGTH]; //, c_cat[LINELENGTH], c_char; + char c_call[LINELENGTH]; //int i; /* f_base = fopen(delay_dump_file, 'a'); @@ -215,7 +214,7 @@ delay_dump_combine (int i_ranks) int delay_dump (PhotPtr p, int np) { - FILE *fopen (), *fptr; + FILE *fptr; int nphot, mscat, mtopbot, i, subzero; double delay; subzero = 0; diff --git a/source/roche.c b/source/roche.c index 33fdb0fb6..f11b8abbc 100644 --- a/source/roche.c +++ b/source/roche.c @@ -187,8 +187,7 @@ binary_basics () **********************************************************/ int -hit_secondary (p) - PhotPtr p; +hit_secondary (PhotPtr p) { double smin, smax, smid, s; double potential; @@ -277,9 +276,7 @@ hit_secondary (p) **********************************************************/ double -pillbox (p, smin, smax) - PhotPtr p; - double *smin, *smax; +pillbox (PhotPtr p, double *smin, double *smax) { double x1, x2; double a, b, c; @@ -428,7 +425,6 @@ phi (double s, void *params) { struct photon pp; double x1, x2, z, z1, z2, z3; - double length (); if (phi_init == 0) { @@ -490,7 +486,7 @@ phi (double s, void *params) double dphi_ds (double s, void *params) { - double phi (), x1, x2; + double x1, x2; void *dummy_par = NULL; double dx, z; if ((dx = 0.001 * geo.a) < EPS) @@ -580,7 +576,6 @@ roche2_half_width () { double xmin, xmax, xmid, xbest; double rmin; - double roche_width (); xmin = geo.l1 + 1.e5; xmax = geo.r2_far + geo.a - 1.e5; diff --git a/source/rtheta.c b/source/rtheta.c index 8eb733f95..0edc2ffff 100644 --- a/source/rtheta.c +++ b/source/rtheta.c @@ -40,11 +40,7 @@ **********************************************************/ double -rtheta_ds_in_cell (ndom, p) - int ndom; - PhotPtr p; - - +rtheta_ds_in_cell (int ndom, PhotPtr p) { int n, ix, iz; @@ -249,9 +245,7 @@ rtheta_make_grid (int ndom, WindPtr w) **********************************************************/ int -rtheta_make_cones (ndom, w) - int ndom; - WindPtr w; +rtheta_make_cones (int ndom, WindPtr w) { int n; int mdim; @@ -306,9 +300,7 @@ rtheta_make_cones (ndom, w) **********************************************************/ int -rtheta_wind_complete (ndom, w) - int ndom; - WindPtr w; +rtheta_wind_complete (int ndom, WindPtr w) { int i, j; int ndim, mdim, nstart; @@ -509,9 +501,7 @@ rtheta_cell_volume (WindPtr w) **********************************************************/ int -rtheta_where_in_grid (ndom, x) - int ndom; - double x[]; +rtheta_where_in_grid (int ndom, double x[]) { int i, j, n; double r, theta; @@ -660,9 +650,7 @@ rtheta_get_random_location (n, x) **********************************************************/ int -rtheta_extend_density (ndom, w) - int ndom; - WindPtr w; +rtheta_extend_density (int ndom, WindPtr w) { int i, j, n, m; int ndim, mdim; diff --git a/source/run.c b/source/run.c index acd2df05b..8348c38ab 100644 --- a/source/run.c +++ b/source/run.c @@ -45,8 +45,7 @@ **********************************************************/ int -calculate_ionization (restart_stat) - int restart_stat; +calculate_ionization (int restart_stat) { WindPtr w; PhotPtr p; @@ -425,8 +424,7 @@ calculate_ionization (restart_stat) **********************************************************/ int -make_spectra (restart_stat) - int restart_stat; +make_spectra (int restart_stat) { WindPtr w; PhotPtr p; @@ -690,9 +688,7 @@ make_spectra (restart_stat) **********************************************************/ int -stats_phot_pre (p, nphot) - PhotPtr p; - int nphot; +stats_phot_pre (PhotPtr p, int nphot) { int nn; double zz; @@ -724,9 +720,7 @@ stats_phot_pre (p, nphot) **********************************************************/ int -stats_phot_post (p, nphot) - PhotPtr p; - int nphot; +stats_phot_post (PhotPtr p, int nphot) { int nn; double zz, z_abs_all, z_abs_all_orig, z_orig[N_ISTAT], z_abs[N_ISTAT], z_else, z_else_orig; diff --git a/source/saha.c b/source/saha.c index f20638ee3..698c5262e 100644 --- a/source/saha.c +++ b/source/saha.c @@ -40,9 +40,7 @@ **********************************************************/ int -nebular_concentrations (xplasma, mode) - PlasmaPtr xplasma; - int mode; +nebular_concentrations (PlasmaPtr xplasma, int mode) { int m; @@ -144,16 +142,12 @@ nebular_concentrations (xplasma, mode) **********************************************************/ int -concentrations (xplasma, mode) - PlasmaPtr xplasma; - int mode; +concentrations (PlasmaPtr xplasma, int mode) { int nion, niterate; double xne, xxne, xnew, xsaha; double theta, x; - double get_ne (); double t, nh; - int saha (); // This needs to be moved up into nebular_concentrations given that we @@ -299,10 +293,7 @@ concentrations (xplasma, mode) **********************************************************/ int -saha (xplasma, ne, t) - PlasmaPtr xplasma; - double ne, t; - +saha (PlasmaPtr xplasma, double ne, double t) { double nh; int nelem; @@ -425,8 +416,7 @@ saha (xplasma, ne, t) **********************************************************/ int -lucy (xplasma) - PlasmaPtr xplasma; +lucy (PlasmaPtr xplasma) { int nelem, nion, niterate; double xne, xnew; @@ -559,10 +549,7 @@ lucy (xplasma) **********************************************************/ int -lucy_mazzali1 (nh, t_r, t_e, www, nelem, ne, density, xne, newden) - double nh, t_r, t_e, www; - int nelem; - double ne, density[], xne, newden[]; +lucy_mazzali1 (double nh, double t_r, double t_e, double www, int nelem, double ne, double density[], double xne, double newden[]) { double fudge; double fudge2, q; @@ -732,8 +719,7 @@ fix_concentrations (xplasma, mode) { int nelem, nion; int n; - double get_ne (); - FILE *fopen (), *cptr; + FILE *cptr; char line[LINELENGTH]; double nh; @@ -818,8 +804,7 @@ fix_concentrations (xplasma, mode) **********************************************************/ double -get_ne (density) - double density[]; +get_ne (double density[]) { int n; double ne; diff --git a/source/setup.c b/source/setup.c index db0aa860f..5b142f085 100644 --- a/source/setup.c +++ b/source/setup.c @@ -186,17 +186,13 @@ char get_spectype_oldname[LINELENGTH] = "data/kurucz91.ls"; **********************************************************/ int -get_spectype (yesno, question, spectype) - int yesno; - char *question; - int *spectype; +get_spectype (int yesno, char *question, int *spectype) { char model_list[LINELENGTH]; char one_choice[LINELENGTH]; char choices[LINELENGTH]; int get_models (); // Note: Needed because get_models cannot be included in templates.h int i; - int init_choices (), get_choices (); if (yesno) diff --git a/source/setup_domains.c b/source/setup_domains.c index 2f0d610a9..08988e8b4 100644 --- a/source/setup_domains.c +++ b/source/setup_domains.c @@ -43,8 +43,7 @@ int -get_domain_params (ndom) - int ndom; +get_domain_params (int ndom) { char answer[LINELENGTH]; @@ -217,8 +216,7 @@ allocate_domain_wind_coords (int ndom) ***********************************************************/ int -get_wind_params (ndom) - int ndom; +get_wind_params (int ndom) { int import_t_init = FALSE; @@ -489,11 +487,7 @@ setup_windcone () int -init_windcone (r, z, dzdr, allow_negative_dzdr, one_windcone) - double r, z, dzdr; - int allow_negative_dzdr; - ConePtr one_windcone; - +init_windcone (double r, double z, double dzdr, int allow_negative_dzdr, ConePtr one_windcone) { diff --git a/source/setup_files.c b/source/setup_files.c index b033df7c0..eee002a51 100644 --- a/source/setup_files.c +++ b/source/setup_files.c @@ -47,10 +47,9 @@ **********************************************************/ int -init_log_and_windsave (restart_stat) - int restart_stat; +init_log_and_windsave (int restart_stat) { - FILE *fopen (), *qptr; + FILE *qptr; if (restart_stat == FALSE) { // Then we are simply running from a new model diff --git a/source/setup_star_bh.c b/source/setup_star_bh.c index a831f98f4..8d091408f 100644 --- a/source/setup_star_bh.c +++ b/source/setup_star_bh.c @@ -109,7 +109,7 @@ get_stellar_params () strcpy (answer, "yes"); geo.star_radiation = rdchoice ("Central_object.radiation(yes,no)", "1,0", answer); get_spectype (geo.star_radiation, "Central_object.rad_type_to_make_wind(bb,models)", &geo.star_ion_spectype); - + if (geo.star_ion_spectype == SPECTYPE_BB_FCOL) { Error ("Colour corrected BB not implemented for star at this stage. Exiting."); @@ -182,8 +182,7 @@ get_stellar_params () **********************************************************/ int -get_bl_and_agn_params (lstar) - double lstar; +get_bl_and_agn_params (double lstar) { double xbl; double temp_const_agn; @@ -215,7 +214,7 @@ get_bl_and_agn_params (lstar) if (geo.bl_radiation) get_spectype (geo.bl_radiation, "Boundary_layer.rad_type_to_make_wind(bb,models,power)", &geo.bl_ion_spectype); - + if (geo.bl_ion_spectype == SPECTYPE_BB_FCOL) { Error ("Colour corrected BB not implemented for boundary layer. Exiting."); @@ -352,7 +351,7 @@ get_bl_and_agn_params (lstar) geo.bubble_size *= GRAV * geo.mstar / VLIGHT / VLIGHT; //get it in CGS units Log ("bubble size in cm is %g\n", geo.bubble_size); } - else if (geo.pl_geometry != PL_GEOMETRY_SPHERE && geo.pl_geometry != PL_GEOMETRY_ISO) // only four options at the moment + else if (geo.pl_geometry != PL_GEOMETRY_SPHERE && geo.pl_geometry != PL_GEOMETRY_ISO) // only four options at the moment { Error ("Did not understand power law geometry %i. Fatal.\n", geo.pl_geometry); Exit (0); diff --git a/source/shell_wind.c b/source/shell_wind.c index efdc40f79..bd969571d 100644 --- a/source/shell_wind.c +++ b/source/shell_wind.c @@ -84,8 +84,7 @@ allocate_shell_domain (int ndom) **********************************************************/ int -get_shell_wind_params (ndom) - int ndom; +get_shell_wind_params (int ndom) { double vtemp[3]; double rhotemp[200]; diff --git a/source/signal.c b/source/signal.c index 4fcb99a72..f33e56d7c 100644 --- a/source/signal.c +++ b/source/signal.c @@ -77,7 +77,7 @@ xsignal (char *root, char *format, ...) char curtime[LINELENGTH]; char message[LINELENGTH]; - FILE *fopen (), *sptr; + FILE *sptr; char filename[LINELENGTH]; double elapsed_time; diff --git a/source/sirocco.c b/source/sirocco.c index 8d5e36b72..53884be00 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -64,9 +64,7 @@ **********************************************************/ int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { //OLD WindPtr w; diff --git a/source/spectra.c b/source/spectra.c index 475a43ad9..d697ea60e 100644 --- a/source/spectra.c +++ b/source/spectra.c @@ -124,13 +124,8 @@ spectrum_allocate (int nspec) * **********************************************************/ int -spectrum_init (f1, f2, nangle, angle, phase, scat_select, top_bot_select, select_extract, rho_select, z_select, az_select, r_select) - double f1, f2; - int nangle; - double angle[], phase[]; - int scat_select[], top_bot_select[]; - int select_extract; - double rho_select[], z_select[], az_select[], r_select[]; +spectrum_init (double f1, double f2, int nangle, double angle[], double phase[], int scat_select[], int top_bot_select[], + int select_extract, double rho_select[], double z_select[], double az_select[], double r_select[]) { int i, n; int nspec; @@ -388,11 +383,7 @@ spectrum_init (f1, f2, nangle, angle, phase, scat_select, top_bot_select, select **********************************************************/ int -spectrum_create (p, nangle, select_extract) - PhotPtr p; - int nangle; - int select_extract; - +spectrum_create (PhotPtr p, int nangle, int select_extract) { int nphot, istat, j, k, k1, n; int nspec, nwave, spectype; @@ -747,9 +738,7 @@ spectrum_create (p, nangle, select_extract) int -spec_add_one (p, spec_type) - PhotPtr p; - int spec_type; +spec_add_one (PhotPtr p, int spec_type) { int k; int iwind; @@ -850,16 +839,9 @@ spec_add_one (p, spec_type) **********************************************************/ int -spectrum_summary (filename, nspecmin, nspecmax, select_spectype, renorm, loglin, iwind) - char filename[]; - int loglin; - int nspecmin, nspecmax; - int select_spectype; - double renorm; - int iwind; - +spectrum_summary (char filename[], int nspecmin, int nspecmax, int select_spectype, double renorm, int loglin, int iwind) { - FILE *fopen (), *fptr; + FILE *fptr; int i, n; int nwave; char string[LINELENGTH]; @@ -1053,8 +1035,7 @@ spectrum_summary (filename, nspecmin, nspecmax, select_spectype, renorm, loglin, **********************************************************/ int -spectrum_restart_renormalise (nangle) - int nangle; +spectrum_restart_renormalise (int nangle) { double renorm_factor; int n, m, nspec; diff --git a/source/spectral_estimators.c b/source/spectral_estimators.c index a7f7e719f..77f55f9ab 100644 --- a/source/spectral_estimators.c +++ b/source/spectral_estimators.c @@ -53,8 +53,7 @@ double lspec_numin, lspec_numax; **********************************************************/ int -spectral_estimators (xplasma) - PlasmaPtr xplasma; +spectral_estimators (PlasmaPtr xplasma) { double pl_alpha_min, pl_alpha_max, pl_alpha_temp, pl_w_temp, j; double exp_temp_min, exp_temp_max, exp_temp_store; /* The 'temperature' range we are going to search for an effective temperature for the exponential model */ @@ -410,9 +409,7 @@ pl_alpha_func_log2 (double alpha, void *params) **********************************************************/ double -pl_logmean (alpha, lnumin, lnumax) - double alpha; - double lnumin, lnumax; +pl_logmean (double alpha, double lnumin, double lnumax) { double k, answer, numerator, denominator, a, b, c, d; @@ -578,9 +575,7 @@ exp_temp_func2 (double exp_temp, void *params) **********************************************************/ double -exp_mean (exp_temp, numin, numax) - double exp_temp; - double numin, numax; +exp_mean (double exp_temp, double numin, double numax) { double answer, numerator, denominator; double exp1; /* We supply a temperature, but actually we expect the correct function to be of the form e^-hnu/kt, so this will hold -1*h/kt */ diff --git a/source/spherical.c b/source/spherical.c index 286107f2d..a22702476 100644 --- a/source/spherical.c +++ b/source/spherical.c @@ -56,10 +56,7 @@ **********************************************************/ double -spherical_ds_in_cell (ndom, p) - int ndom; - PhotPtr p; - +spherical_ds_in_cell (int ndom, PhotPtr p) { int n, ix; @@ -197,9 +194,7 @@ spherical_make_grid (int ndom, WindPtr w) **********************************************************/ int -spherical_wind_complete (ndom, w) - int ndom; - WindPtr w; +spherical_wind_complete (int ndom, WindPtr w) { int i; int ndim, nstart; @@ -355,9 +350,7 @@ spherical_cell_volume (WindPtr w) **********************************************************/ int -spherical_where_in_grid (ndom, x) - int ndom; - double x[]; +spherical_where_in_grid (int ndom, double x[]) { int n; double r; @@ -480,9 +473,7 @@ spherical_get_random_location (n, x) **********************************************************/ int -spherical_extend_density (ndom, w) - int ndom; - WindPtr w; +spherical_extend_density (int ndom, WindPtr w) { int j, n, m; diff --git a/source/stellar_wind.c b/source/stellar_wind.c index 149fbf5c8..3ec8982f4 100644 --- a/source/stellar_wind.c +++ b/source/stellar_wind.c @@ -40,8 +40,7 @@ **********************************************************/ int -get_stellar_wind_params (ndom) - int ndom; +get_stellar_wind_params (int ndom) { Log ("Creating a wind model for a Star\n"); @@ -128,12 +127,9 @@ get_stellar_wind_params (ndom) **********************************************************/ double -stellar_velocity (ndom, x, v) - int ndom; - double x[], v[]; +stellar_velocity (int ndom, double x[], double v[]) { double r, speed, zzz; - double length (); if ((r = length (x)) == 0.0) { @@ -176,9 +172,7 @@ stellar_velocity (ndom, x, v) **********************************************************/ double -stellar_rho (ndom, x) - int ndom; - double x[]; +stellar_rho (int ndom, double x[]) { double r, rho, v[3]; diff --git a/source/sv.c b/source/sv.c index 1569ab7fe..f865486b4 100644 --- a/source/sv.c +++ b/source/sv.c @@ -38,8 +38,7 @@ int sv_zero_r_ndom; **********************************************************/ int -get_sv_wind_params (ndom) - int ndom; +get_sv_wind_params (int ndom) { double windmin, windmax, theta_min, theta_max; char answer[LINELENGTH]; @@ -153,9 +152,7 @@ get_sv_wind_params (ndom) **********************************************************/ double -sv_velocity (x, v, ndom) - double x[], v[]; - int ndom; +sv_velocity (double x[], double v[], int ndom) { double r, rzero, theta, speed; double ldist, zzz, v_escape, vl = 0.0; @@ -275,9 +272,7 @@ sv_velocity (x, v, ndom) **********************************************************/ double -sv_rho (ndom, x) - double x[]; - int ndom; +sv_rho (int ndom, double x[]) { double r, rzero, theta; double ldist; @@ -462,8 +457,7 @@ double zero_p[3]; **********************************************************/ int -sv_zero_init (p) - double p[]; +sv_zero_init (double p[]) { stuff_v (p, zero_p); zero_p[2] = fabs (zero_p[2]); /* Required to get correct @@ -540,9 +534,7 @@ sv_zero_r (double r, void *params) **********************************************************/ double -sv_theta_wind (ndom, r) - int ndom; - double r; +sv_theta_wind (int ndom, double r) { double theta; diff --git a/source/swind.c b/source/swind.c index 920b07e57..6b8ef97d1 100644 --- a/source/swind.c +++ b/source/swind.c @@ -139,9 +139,7 @@ char *choice_options = "\n\ **********************************************************/ int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { @@ -236,7 +234,7 @@ main (argc, argv) /* Initialize other variables here */ - swind_project = 1; // The default is to try to project onto a yz plane + swind_project = 1; // The default is to try to project onto a yz plane /* Read in the wind file */ @@ -393,10 +391,7 @@ I did not change this now. Though it could be done. 02apr ksl */ **********************************************************/ int -one_choice (choice, root, ochoice) - char choice; - char *root; - int ochoice; +one_choice (int choice, char *root, int ochoice) { double lambda, freq; int n, istate, iswitch; diff --git a/source/swind_ion.c b/source/swind_ion.c index 0a78b8382..07df0002f 100644 --- a/source/swind_ion.c +++ b/source/swind_ion.c @@ -48,12 +48,7 @@ * **********************************************************/ int -ion_summary (w, element, istate, iswitch, rootname, ochoice) - WindPtr w; - int element, istate; - int iswitch; - char rootname[]; - int ochoice; +ion_summary (WindPtr w, int element, int istate, int iswitch, char rootname[], int ochoice) { int nion, nelem; int n; @@ -210,12 +205,7 @@ ion_summary (w, element, istate, iswitch, rootname, ochoice) * **********************************************************/ int -tau_ave_summary (w, element, istate, freq, rootname, ochoice) - WindPtr w; - int element, istate; - double freq; - char rootname[]; - int ochoice; +tau_ave_summary (WindPtr w, int element, int istate, double freq, char rootname[], int ochoice) { int nion, nelem; int n; @@ -311,10 +301,7 @@ tau_ave_summary (w, element, istate, freq, rootname, ochoice) * **********************************************************/ int -line_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +line_summary (WindPtr w, char rootname[], int ochoice) { int nion, nelem; int element, istate, iline, levu, levl, i_matom_search; @@ -574,9 +561,7 @@ line_summary (w, rootname, ochoice) * **********************************************************/ int -total_emission_summary (rootname, ochoice) - char rootname[]; - int ochoice; +total_emission_summary (char rootname[], int ochoice) { double tot; int n; @@ -626,14 +611,11 @@ total_emission_summary (rootname, ochoice) * **********************************************************/ int -modify_te (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +modify_te (WindPtr w, char rootname[], int ochoice) { int n; double x; - double t_e, calc_te (); + double t_e; char filename[LINELENGTH]; int nplasma; @@ -683,11 +665,7 @@ modify_te (w, rootname, ochoice) **********************************************************/ int -partial_measure_summary (w, element, istate, rootname, ochoice) - WindPtr w; - int element, istate; - char rootname[]; - int ochoice; +partial_measure_summary (WindPtr w, int element, int istate, char rootname[], int ochoice) { int nion, nelem; int n; @@ -774,10 +752,7 @@ partial_measure_summary (w, element, istate, rootname, ochoice) **********************************************************/ int -collision_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +collision_summary (WindPtr w, char rootname[], int ochoice) { int nline, int_te; double t_e, qup, qdown, A, wavelength; diff --git a/source/swind_macro.c b/source/swind_macro.c index e5996c6e6..561566763 100644 --- a/source/swind_macro.c +++ b/source/swind_macro.c @@ -37,14 +37,10 @@ **********************************************************/ int -xadiabatic_cooling_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +xadiabatic_cooling_summary (WindPtr w, char rootname[], int ochoice) { int n; double tot; - double adiabatic_cooling (); char filename[LINELENGTH]; double t_e; @@ -90,10 +86,7 @@ xadiabatic_cooling_summary (w, rootname, ochoice) **********************************************************/ int -macro_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +macro_summary (WindPtr w, char rootname[], int ochoice) { //OLD int nmacro; int nconfig; @@ -227,8 +220,7 @@ emissivities (2) P_escapes (3) Detailed Pops (4) taus (5) estimators (6)", &choo **********************************************************/ int -ion_overview (icell) - int icell; +ion_overview (int icell) { int n; IonPtr p; @@ -261,8 +253,7 @@ ion_overview (icell) **********************************************************/ int -config_overview (n, icell) - int n, icell; +config_overview (int n, int icell) { ConfigPtr p; PlasmaPtr x; @@ -393,15 +384,13 @@ config_overview (n, icell) **********************************************************/ int -depcoef_overview (icell) - int icell; +depcoef_overview (int icell) { ConfigPtr p; PlasmaPtr x, xdummy; double xden, lteden; int n; - int copy_plasma (); plasma_dummy pdum; @@ -460,8 +449,7 @@ depcoef_overview (icell) **********************************************************/ int -copy_plasma (x1, x2) - PlasmaPtr x1, x2; +copy_plasma (PlasmaPtr x1, PlasmaPtr x2) { int i; @@ -518,8 +506,7 @@ copy_plasma (x1, x2) **********************************************************/ int -dealloc_copied_plasma (xcopy) - PlasmaPtr xcopy; +dealloc_copied_plasma (PlasmaPtr xcopy) { free (xcopy->state.density); free (xcopy->state.partition); @@ -546,19 +533,13 @@ dealloc_copied_plasma (xcopy) **********************************************************/ int -depcoef_overview_specific (version, nconfig, w, rootname, ochoice) - int version; - int nconfig; - WindPtr w; - char rootname[]; - int ochoice; +depcoef_overview_specific (int version, int nconfig, WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH], lname[LINELENGTH]; ConfigPtr p; PlasmaPtr xplasma, xdummy; double xden, lteden, ion_density; - int copy_plasma (); plasma_dummy pdum; @@ -649,11 +630,7 @@ depcoef_overview_specific (version, nconfig, w, rootname, ochoice) **********************************************************/ int -level_popsoverview (nplasma, w, rootname, ochoice) - int nplasma; - WindPtr w; - char rootname[]; - int ochoice; +level_popsoverview (int nplasma, WindPtr w, char rootname[], int ochoice) { int i; PlasmaPtr xplasma, xdummy; @@ -661,7 +638,6 @@ level_popsoverview (nplasma, w, rootname, ochoice) char filename[LINELENGTH]; char lname[LINELENGTH]; double xden, lteden; - int copy_plasma (); strcpy (filename, rootname); strcpy (filename, rootname); @@ -733,11 +709,7 @@ level_popsoverview (nplasma, w, rootname, ochoice) **********************************************************/ int -level_emissoverview (nlev, w, rootname, ochoice) - int nlev; - WindPtr w; - char rootname[]; - int ochoice; +level_emissoverview (int nlev, WindPtr w, char rootname[], int ochoice) { int n, nplasma; char name[LINELENGTH], lname[LINELENGTH]; @@ -813,11 +785,7 @@ level_emissoverview (nlev, w, rootname, ochoice) **********************************************************/ int -level_escapeoverview (nlev, w, rootname, ochoice) - int nlev; - WindPtr w; - char rootname[]; - int ochoice; +level_escapeoverview (int nlev, WindPtr w, char rootname[], int ochoice) { PlasmaPtr xplasma; int n, nplasma, nline, found; @@ -905,11 +873,7 @@ level_escapeoverview (nlev, w, rootname, ochoice) **********************************************************/ int -level_tauoverview (nlev, w, rootname, ochoice) - int nlev; - WindPtr w; - char rootname[]; - int ochoice; +level_tauoverview (int nlev, WindPtr w, char rootname[], int ochoice) { PlasmaPtr xplasma; WindPtr one; diff --git a/source/swind_sub.c b/source/swind_sub.c index 3be6d9724..090465813 100644 --- a/source/swind_sub.c +++ b/source/swind_sub.c @@ -63,8 +63,7 @@ ************************************************************************/ int -zoom (direction) - int direction; +zoom (int direction) { int center; int ndim; @@ -131,9 +130,7 @@ zoom (direction) ************************************************************************/ int -overview (w, rootname) - WindPtr w; - char rootname[]; +overview (WindPtr w, char rootname[]) { int n; double heating, lines, ff, photo; @@ -180,8 +177,7 @@ overview (w, rootname) ************************************************************************/ int -position_summary (w) - WindPtr w; +position_summary (WindPtr w) { double x[3], v[3]; struct photon p; @@ -258,10 +254,7 @@ a:Log ("Input x=0,y=0,z=0 to return to main routine\n"); ************************************************************************/ int -abs_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +abs_summary (WindPtr w, char rootname[], int ochoice) { int n; double x, xtot; @@ -396,14 +389,10 @@ abs_summary (w, rootname, ochoice) ************************************************************************/ int -shock_heating_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +shock_heating_summary (WindPtr w, char rootname[], int ochoice) { int n; double tot; - double shock_heating (); char filename[LINELENGTH]; @@ -462,14 +451,10 @@ shock_heating_summary (w, rootname, ochoice) ************************************************************************/ int -adiabatic_cooling_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +adiabatic_cooling_summary (WindPtr w, char rootname[], int ochoice) { int n; double tot; - double adiabatic_cooling (); char filename[LINELENGTH]; double t_e; @@ -534,10 +519,7 @@ adiabatic_cooling_summary (w, rootname, ochoice) ************************************************************************/ int -lum_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +lum_summary (WindPtr w, char rootname[], int ochoice) { int n; double x, xtot; @@ -680,10 +662,7 @@ lum_summary (w, rootname, ochoice) ************************************************************************/ int -photo_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +photo_summary (WindPtr w, char rootname[], int ochoice) { int n, ion; char filename[LINELENGTH]; @@ -739,10 +718,7 @@ photo_summary (w, rootname, ochoice) ************************************************************************/ int -recomb_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +recomb_summary (WindPtr w, char rootname[], int ochoice) { int n; int ion; @@ -803,10 +779,7 @@ recomb_summary (w, rootname, ochoice) ************************************************************************/ int -electron_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +electron_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -858,10 +831,7 @@ A summary of rho ************************************************************************/ int -rho_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +rho_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -917,10 +887,7 @@ rho_summary (w, rootname, ochoice) ************************************************************************/ int -plasma_cell (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +plasma_cell (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -972,10 +939,7 @@ plasma_cell (w, rootname, ochoice) ************************************************************************/ int -freq_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +freq_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -1028,10 +992,7 @@ freq_summary (w, rootname, ochoice) ************************************************************************/ int -nphot_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +nphot_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -1130,10 +1091,7 @@ nphot_summary (w, rootname, ochoice) ************************************************************************/ int -temp_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +temp_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -1180,10 +1138,7 @@ temp_summary (w, rootname, ochoice) ************************************************************************/ int -temp_rad (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +temp_rad (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -1231,10 +1186,7 @@ temp_rad (w, rootname, ochoice) ************************************************************************/ int -weight_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +weight_summary (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -1285,10 +1237,7 @@ weight_summary (w, rootname, ochoice) ************************************************************************/ int -velocity_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +velocity_summary (WindPtr w, char rootname[], int ochoice) { int n; double x; @@ -1386,10 +1335,7 @@ velocity_summary (w, rootname, ochoice) ************************************************************************/ int -mo_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +mo_summary (WindPtr w, char rootname[], int ochoice) { int n; int ichoice; @@ -1497,10 +1443,7 @@ mo_summary (w, rootname, ochoice) ************************************************************************/ int -vol_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +vol_summary (WindPtr w, char rootname[], int ochoice) { int n; @@ -1555,8 +1498,7 @@ vol_summary (w, rootname, ochoice) **************************************************************/ int -wind_element (w) - WindPtr w; +wind_element (WindPtr w) { PlasmaPtr xplasma; int m, n, i, j, nn, mm; @@ -1733,10 +1675,7 @@ b:return (0); ************************************************************************/ int -tau_h_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +tau_h_summary (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -1779,10 +1718,7 @@ tau_h_summary (w, rootname, ochoice) ************************************************************************/ int -coolheat_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +coolheat_summary (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -1842,10 +1778,7 @@ coolheat_summary (w, rootname, ochoice) int -complete_file_summary (w, root, ochoice) - WindPtr w; - char root[]; - int ochoice; +complete_file_summary (WindPtr w, char root[], int ochoice) { temp_summary (w, root, ochoice); temp_rad (w, root, ochoice); @@ -1916,10 +1849,7 @@ complete_file_summary (w, root, ochoice) /* A summary of the regions in the wind */ int -wind_reg_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +wind_reg_summary (WindPtr w, char rootname[], int ochoice) { int n; @@ -1943,10 +1873,7 @@ wind_reg_summary (w, rootname, ochoice) /* A summary of the dvds_ave */ int -dvds_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +dvds_summary (WindPtr w, char rootname[], int ochoice) { char filename[LINELENGTH], suffix[LINELENGTH]; int n, ichoice; @@ -2018,10 +1945,7 @@ dvds_summary (w, rootname, ochoice) /* A summary of inner shell ionization */ /* NSH - this code removed May 18 int -inner_shell_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +inner_shell_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -2052,10 +1976,7 @@ inner_shell_summary (w, rootname, ochoice) /* A summary of the Ionization parameter - might not always be present */ int -IP_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +IP_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -2158,10 +2079,7 @@ IP_summary (w, rootname, ochoice) */ int -alpha_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +alpha_summary (WindPtr w, char rootname[], int ochoice) { int n, m; char filename[LINELENGTH]; @@ -2353,10 +2271,7 @@ alpha_summary (w, rootname, ochoice) */ int -J_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +J_summary (WindPtr w, char rootname[], int ochoice) { int i, n; char filename[LINELENGTH]; @@ -2456,10 +2371,7 @@ J_summary (w, rootname, ochoice) int -J_scat_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +J_scat_summary (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -2533,10 +2445,7 @@ J_scat_summary (w, rootname, ochoice) //Split of photons from different sources in the cell. int -phot_split (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +phot_split (WindPtr w, char rootname[], int ochoice) { int n; char filename[LINELENGTH]; @@ -2619,10 +2528,7 @@ phot_split (w, rootname, ochoice) } int -thompson (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +thompson (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -2655,10 +2561,7 @@ thompson (w, rootname, ochoice) int -nscat_split (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +nscat_split (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -2703,10 +2606,7 @@ nscat_split (w, rootname, ochoice) } int -convergence_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +convergence_summary (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -2742,10 +2642,7 @@ convergence_summary (w, rootname, ochoice) */ int -convergence_all (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +convergence_all (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -2836,10 +2733,7 @@ convergence_all (w, rootname, ochoice) */ int -model_bands (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +model_bands (WindPtr w, char rootname[], int ochoice) { int n, m; int nplasma; @@ -2966,10 +2860,7 @@ model_bands (w, rootname, ochoice) /* A summary of adiabatic cooling */ int -heatcool_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +heatcool_summary (WindPtr w, char rootname[], int ochoice) { int n; int nplasma; @@ -3282,10 +3173,7 @@ heatcool_summary (w, rootname, ochoice) ************************************************************************/ int -complete_physical_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +complete_physical_summary (WindPtr w, char rootname[], int ochoice) { int n, np; char filename[LINELENGTH]; @@ -3295,7 +3183,7 @@ complete_physical_summary (w, rootname, ochoice) int frac_choice; int ii, jj; double vtot; - FILE *fptr, *fopen (); + FILE *fptr; PlasmaPtr xplasma; int ndom; @@ -3427,11 +3315,7 @@ ionH1\tionH2\tionHe1\tionHe2\tionHe3\tionC3\tionC4\tionC5\tionN5\tionO6\tionSi4\ int -complete_ion_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; - +complete_ion_summary (WindPtr w, char rootname[], int ochoice) { char cell[5]; PlasmaPtr xplasma; @@ -3511,11 +3395,7 @@ b:return (0); double -get_density_or_frac (xplasma, element, istate, frac_choice) - PlasmaPtr xplasma; - int element; - int istate; - int frac_choice; +get_density_or_frac (PlasmaPtr xplasma, int element, int istate, int frac_choice) { int nion, nelem; double nh, density; @@ -3553,9 +3433,7 @@ get_density_or_frac (xplasma, element, istate, frac_choice) int -find_ion (element, istate) - int element; - int istate; +find_ion (int element, int istate) { int nion; @@ -3581,8 +3459,7 @@ find_ion (element, istate) int -find_element (element) - int element; +find_element (int element) { int n; @@ -3609,10 +3486,7 @@ find_element (element) ************************************************************************/ int -get_los_dvds (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +get_los_dvds (WindPtr w, char rootname[], int ochoice) { struct photon p; struct photon ptest; @@ -3758,7 +3632,7 @@ int grid_summary (WindPtr w, char rootname[], int ochoice) { char filename[LINELENGTH], suffix[LINELENGTH]; - FILE *fopen (), *fptr; + FILE *fptr; int i, j; printf ("Outputting grid boundaries to file.\n"); @@ -3795,15 +3669,12 @@ grid_summary (WindPtr w, char rootname[], int ochoice) int -flux_summary (w, rootname, ochoice) - WindPtr w; - char rootname[]; - int ochoice; +flux_summary (WindPtr w, char rootname[], int ochoice) { int n, np; char filename[LINELENGTH]; int ii, jj; - FILE *fptr, *fopen (); + FILE *fptr = NULL; //OLD PlasmaPtr xplasma; int ndom, m; diff --git a/source/swind_write.c b/source/swind_write.c index a8590de66..17bb7db8d 100644 --- a/source/swind_write.c +++ b/source/swind_write.c @@ -49,19 +49,16 @@ float aout[ODIM][ODIM]; **********************************************************/ int -write_array (filename, choice) - char filename[]; - int choice; +write_array (char filename[], int choice) { //Dynamical allocation is allowed, although I generally avoid it -- 05apr ksl float r, z; float rmin, rmax, zmin, zmax; int ii, jj; - FILE *fopen (), *fptr; + FILE *fptr; char outfile[LINELENGTH]; char extra[LINELENGTH]; - double length (); double xx[3]; int i; int nn, nnn[4], nelem; @@ -253,8 +250,7 @@ are linear, and x otherwise. This is not particularly transparent ?? ksl */ **********************************************************/ int -display (name) - char name[]; +display (char name[]) { int i, j, n; //OLD int ndom, ndim, mdim, nstart; diff --git a/source/synonyms.c b/source/synonyms.c index 95855a2fd..c8e82c83a 100644 --- a/source/synonyms.c +++ b/source/synonyms.c @@ -131,8 +131,7 @@ int synonyms_validated = 0; * and answer strings e.g. "xyz(cm/s) 10.7e3" **********************************************************/ int -get_question_name_length (question) - char question[]; +get_question_name_length (char question[]) { char *found_location; @@ -233,9 +232,7 @@ are_synonym_lists_valid () **********************************************************/ int -is_input_line_synonym_for_question (question, input_line) - char question[]; - char input_line[]; +is_input_line_synonym_for_question (char question[], char input_line[]) { int synonym_index; int question_name_length = get_question_name_length (question); diff --git a/source/test_cooling.c b/source/test_cooling.c index 57a92dc65..ae9334c1b 100644 --- a/source/test_cooling.c +++ b/source/test_cooling.c @@ -34,7 +34,6 @@ int model_flag, ksl_flag, cmf2obs_flag, obs2cmf_flag; double line_matom_lum_single (double lum[], PlasmaPtr xplasma, int uplvl); int line_matom_lum (int uplvl); -int create_matom_level_map (); /**********************************************************/ /** @@ -57,14 +56,11 @@ int create_matom_level_map (); **********************************************************/ int -xparse_command_line (argc, argv) - int argc; - char *argv[]; +xparse_command_line (int argc, char *argv[]) { int j = 0; int i; char dummy[LINELENGTH]; - int mkdir (); char *fgets_rc; @@ -261,16 +257,13 @@ xcalc_te (PlasmaPtr xplasma, double tmin, double tmax) int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { char infile[LINELENGTH], outfile[LINELENGTH]; int n, i; - FILE *fptr, *fopen (); + FILE *fptr; int ii, jj, ndom, nnwind; - int mkdir (); xparse_command_line (argc, argv); diff --git a/source/time.c b/source/time.c index 268367537..392290818 100644 --- a/source/time.c +++ b/source/time.c @@ -86,8 +86,7 @@ timer () **********************************************************/ int -get_time (curtime) - char curtime[]; +get_time (char curtime[]) { time_t tloc; time (&tloc); diff --git a/source/unit_test.c b/source/unit_test.c index 273bf09ea..21f56e122 100644 --- a/source/unit_test.c +++ b/source/unit_test.c @@ -29,9 +29,7 @@ char inroot[LINELENGTH]; #define LUM_TEST 0 int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { // FILE *fptr, *fopen (); @@ -203,7 +201,6 @@ main (argc, argv) char infile[LINELENGTH]; double lum_one; - int zparse (); double f1 = 1e12; double f2 = 1e18; @@ -235,7 +232,6 @@ main (argc, argv) - double par_wind_luminosity (); xsignal ("unit_test", "%-20s before new wind luminosity %s\n", "NOK", "unit_test"); @@ -258,9 +254,7 @@ main (argc, argv) int -zparse (argc, argv) - int argc; - char *argv[]; +zparse (int argc, char *argv[]) { char dummy[LINELENGTH]; @@ -283,9 +277,7 @@ zparse (argc, argv) double -par_wind_luminosity (f1, f2, mode) - double f1, f2; - int mode; +par_wind_luminosity (double f1, double f2, int mode) { double lum, lum_lines, lum_rr, lum_ff, factor; int nplasma; diff --git a/source/vvector.c b/source/vvector.c index 4144ede94..07c9e21e6 100644 --- a/source/vvector.c +++ b/source/vvector.c @@ -75,8 +75,7 @@ **********************************************************/ double -dot (a, b) - double a[], b[]; +dot (double a[], double b[]) { double x; @@ -105,11 +104,9 @@ dot (a, b) **********************************************************/ double -length (a) - double a[]; +length (double a[]) { double x, y; - double sqrt (); y = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); if (sane_check (y)) Error ("length:sane_check of y: a %f %f %f \n", a[0], a[1], a[2]); @@ -137,8 +134,7 @@ length (a) **********************************************************/ int -renorm (a, scalar) - double a[], scalar; +renorm (double a[], double scalar) { double x; @@ -176,8 +172,7 @@ renorm (a, scalar) **********************************************************/ int -rescale (a, scalar, b) - double a[], scalar, b[]; +rescale (double a[], double scalar, double b[]) { b[0] = a[0] * scalar; @@ -203,8 +198,7 @@ rescale (a, scalar, b) **********************************************************/ int -cross (a, b, c) - double a[], b[], c[]; +cross (double a[], double b[], double c[]) { c[0] = a[1] * b[2] - a[2] * b[1]; c[1] = a[2] * b[0] - a[0] * b[2]; @@ -235,8 +229,7 @@ cross (a, b, c) **********************************************************/ int -vmove (u, lmn, s, result) - double u[], lmn[], s, result[]; +vmove (double u[], double lmn[], double s, double result[]) { result[0] = lmn[0] * s + u[0]; result[1] = lmn[1] * s + u[1]; @@ -261,8 +254,7 @@ vmove (u, lmn, s, result) **********************************************************/ int -vsub (u, v, result) - double u[], v[], result[]; +vsub (double u[], double v[], double result[]) { result[0] = u[0] - v[0]; result[1] = u[1] - v[1]; @@ -288,8 +280,7 @@ vsub (u, v, result) **********************************************************/ int -vadd (u, v, result) - double u[], v[], result[]; +vadd (double u[], double v[], double result[]) { result[0] = u[0] + v[0]; result[1] = u[1] + v[1]; @@ -315,8 +306,7 @@ vadd (u, v, result) **********************************************************/ int -stuff_v (vin, vout) - double vin[], vout[]; +stuff_v (double vin[], double vout[]) { vout[0] = vin[0]; vout[1] = vin[1]; @@ -350,10 +340,8 @@ stuff_v (vin, vout) **********************************************************/ double -dot_tensor_vec (tensor, vin, vout) - double tensor[3][3], vin[3], vout[3]; +dot_tensor_vec (double tensor[3][3], double vin[3], double vout[3]) { - double dot (); vout[0] = dot (tensor[0], vin); vout[1] = dot (tensor[1], vin); vout[2] = dot (tensor[2], vin); @@ -382,8 +370,7 @@ dot_tensor_vec (tensor, vin, vout) **********************************************************/ int -project_from_xyz_cyl (a, b, result) - double a[], b[], result[]; +project_from_xyz_cyl (double a[], double b[], double result[]) { double n_rho[3], n_phi[3], n_z[3]; @@ -440,8 +427,7 @@ project_from_xyz_cyl (a, b, result) **********************************************************/ int -project_from_cyl_xyz (a, b, result) - double a[], b[], result[]; +project_from_cyl_xyz (double a[], double b[], double result[]) { double x, ctheta, stheta; @@ -487,14 +473,11 @@ project_from_cyl_xyz (a, b, result) **********************************************************/ int -create_basis (u, v, basis_new) - double u[], v[]; - struct basis *basis_new; +create_basis (double u[], double v[], struct basis *basis_new) { int i; double x[3], y[3], z[3]; double mu_x; - double dot (); for (i = 0; i < 3; i++) { @@ -648,9 +631,7 @@ project_to (basis_from, v_in, v_out) **********************************************************/ int -reorient (basis_from, basis_to, v_from, v_to) - struct basis *basis_from, *basis_to; - double v_from[], v_to[]; +reorient (struct basis *basis_from, struct basis *basis_to, double v_from[], double v_to[]) { double a[3][3]; int i, j, k; diff --git a/source/walls.c b/source/walls.c index cc48e7561..531abe2e6 100644 --- a/source/walls.c +++ b/source/walls.c @@ -82,9 +82,7 @@ double xsouth[] = { * **********************************************************/ int -walls (p, pold, normal) - PhotPtr p, pold; - double *normal; +walls (PhotPtr p, PhotPtr pold, double *normal) { double r, rho, rho_sq; double r_hit_disk; diff --git a/source/wind.c b/source/wind.c index 072613fe0..a867419a8 100644 --- a/source/wind.c +++ b/source/wind.c @@ -75,9 +75,7 @@ **********************************************************/ int -where_in_wind (x, ndomain) - double x[]; - int *ndomain; +where_in_wind (double x[], int *ndomain) { double rho, rad, z; int ireturn; @@ -230,9 +228,7 @@ where_in_wind (x, ndomain) **********************************************************/ double -model_velocity (ndom, x, v) - double x[], v[]; - int ndom; +model_velocity (int ndom, double x[], double v[]) { double speed = 0; @@ -317,9 +313,7 @@ model_velocity (ndom, x, v) **********************************************************/ int -model_vgrad (ndom, x, v_grad) - double x[], v_grad[][3]; - int ndom; +model_vgrad (int ndom, double x[], double v_grad[][3]) { double v[3], v_forward[3], v_reverse[3]; @@ -415,9 +409,7 @@ model_vgrad (ndom, x, v_grad) **********************************************************/ double -get_div_v_in_cmf_frame (ndom, x) - int ndom; - double *x; +get_div_v_in_cmf_frame (int ndom, double *x) { int i; double v[3][3]; @@ -456,9 +448,7 @@ get_div_v_in_cmf_frame (ndom, x) **********************************************************/ double -model_rho (ndom, x) - int ndom; - double x[]; +model_rho (int ndom, double x[]) { double rho = 0; int n = 0; @@ -544,9 +534,7 @@ model_rho (ndom, x) **********************************************************/ int -wind_check (www, n) - WindPtr www; - int n; +wind_check (WindPtr www, int n) { int i, j, k, istart, istop; int ierr = 0; diff --git a/source/wind2d.c b/source/wind2d.c index 0f5d13ac2..d30d51730 100644 --- a/source/wind2d.c +++ b/source/wind2d.c @@ -56,9 +56,7 @@ double wig_x, wig_y, wig_z; **********************************************************/ int -where_in_grid (ndom, x) - int ndom; - double x[]; +where_in_grid (int ndom, double x[]) { int n; double fx, fz; @@ -160,10 +158,7 @@ struct vwind } xvwind[NVWIND]; int -vwind_xyz (ndom, p, v) - int ndom; - PhotPtr p; - double v[]; +vwind_xyz (int ndom, PhotPtr p, double v[]) { int i; double rho, r; @@ -321,9 +316,7 @@ wind_div_v (int ndom, WindPtr cell) **********************************************************/ double -rho (w, x) - WindPtr w; - double x[]; +rho (WindPtr w, double x[]) { int n; double dd; @@ -399,9 +392,9 @@ mdot_wind (w, z, rmax) struct photon p; double r, dr, rmin; double theta, dtheta; - double den, rho (); + double den; double mdot, mplane, msphere; - double x[3], v[3], q[3], dot (); + double x[3], v[3], q[3]; int ndom; ndom = 0; @@ -569,8 +562,7 @@ zero_scatters () **********************************************************/ int -check_corners_inwind (n) - int n; +check_corners_inwind (int n) { int n_inwind; int i, j; diff --git a/source/wind_sum.c b/source/wind_sum.c index 60c2d829b..3ab0a7638 100644 --- a/source/wind_sum.c +++ b/source/wind_sum.c @@ -54,8 +54,7 @@ **********************************************************/ int -xtemp_rad (w) - WindPtr w; +xtemp_rad (WindPtr w) { int i, j, n; double x; diff --git a/source/wind_util.c b/source/wind_util.c index b131c36ca..e0e2f2adc 100644 --- a/source/wind_util.c +++ b/source/wind_util.c @@ -80,13 +80,7 @@ int ierr_coord_fraction = 0; **********************************************************/ int -coord_fraction (ndom, ichoice, x, ii, frac, nelem) - int ndom; - int ichoice; - double x[]; - int ii[]; - double frac[]; - int *nelem; +coord_fraction (int ndom, int ichoice, double x[], int ii[], double frac[], int *nelem) { double r, z; double *xx, *zz; @@ -342,8 +336,7 @@ where_in_2dcell (ichoice, x, n, fx, fz) **********************************************************/ int -wind_n_to_ij (ndom, n, i, j) - int n, *i, *j, ndom; +wind_n_to_ij (int ndom, int n, int *i, int *j) { int n_use; if (zdom[ndom].coord_type == SPHERICAL) @@ -383,8 +376,7 @@ wind_n_to_ij (ndom, n, i, j) **********************************************************/ int -wind_ij_to_n (ndom, i, j, n) - int *n, i, j, ndom; +wind_ij_to_n (int ndom, int i, int j, int *n) { int ierror = 0; int ii, jj; diff --git a/source/windsave.c b/source/windsave.c index cfb074713..d0f9e3aec 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -51,8 +51,7 @@ **********************************************************/ int -wind_save (filename) - char filename[]; +wind_save (char filename[]) { FILE *fptr; char header[LINELENGTH]; @@ -192,8 +191,7 @@ in the plasma structure */ **********************************************************/ int -wind_read (filename) - char filename[]; +wind_read (char filename[]) { FILE *fptr; int ndom; @@ -416,8 +414,7 @@ wind_complete () **********************************************************/ int -spec_save (filename) - char filename[]; +spec_save (char filename[]) { FILE *fptr; @@ -474,8 +471,7 @@ spec_save (filename) **********************************************************/ int -spec_read (filename) - char filename[]; +spec_read (char filename[]) { FILE *fptr; int nhead, nwave_ioniz_check; diff --git a/source/windsave2fits.c b/source/windsave2fits.c index e3a462de9..aa00c3e01 100644 --- a/source/windsave2fits.c +++ b/source/windsave2fits.c @@ -36,7 +36,6 @@ int model_flag, ksl_flag, cmf2obs_flag, obs2cmf_flag; double line_matom_lum_single (double lum[], PlasmaPtr xplasma, int uplvl); int line_matom_lum (int uplvl); -int create_matom_level_map (); // Define a structure to hold spectral data typedef struct @@ -403,8 +402,7 @@ write_spectra_model_table (fitsfile *fptr) int -make_spec (inroot) - char *inroot; +make_spec (char *inroot) { fitsfile *fptr; // Pointer to the FITS file @@ -558,14 +556,11 @@ make_spec (inroot) **********************************************************/ int -xparse_command_line (argc, argv) - int argc; - char *argv[]; +xparse_command_line (int argc, char *argv[]) { int j = 0; int i; char dummy[LINELENGTH]; - int mkdir (); char *fgets_rc; @@ -678,14 +673,10 @@ xparse_command_line (argc, argv) int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { char infile[LINELENGTH], outfile[LINELENGTH]; - FILE *fopen (); - int mkdir (); xparse_command_line (argc, argv); diff --git a/source/windsave2table.c b/source/windsave2table.c index 42440e801..a7addbf3a 100644 --- a/source/windsave2table.c +++ b/source/windsave2table.c @@ -231,9 +231,7 @@ parse_arguments (int argc, char *argv[], char root[], int *ion_switch, int *spec **********************************************************/ int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { char root[LINELENGTH], xroot[LINELENGTH]; char outputfile[LINELENGTH]; diff --git a/source/windsave2table_sub.c b/source/windsave2table_sub.c index 599e774b1..5f9234929 100644 --- a/source/windsave2table_sub.c +++ b/source/windsave2table_sub.c @@ -49,10 +49,7 @@ int xedge = FALSE; **********************************************************/ int -do_windsave2table (root, ion_switch, edge_switch) - char *root; - int ion_switch; - int edge_switch; +do_windsave2table (char *root, int ion_switch, int edge_switch) { int ndom, i; char rootname[LINELENGTH]; @@ -148,9 +145,7 @@ do_windsave2table (root, ion_switch, edge_switch) **********************************************************/ int -create_master_table (ndom, rootname) - int ndom; - char rootname[]; +create_master_table (int ndom, char rootname[]) { char filename[132]; double *c[51], *converge; @@ -413,9 +408,7 @@ create_master_table (ndom, rootname) **********************************************************/ int -create_heat_table (ndom, rootname) - int ndom; - char rootname[]; +create_heat_table (int ndom, char rootname[]) { char filename[132]; double *c[50], *converge; @@ -649,9 +642,7 @@ create_heat_table (ndom, rootname) **********************************************************/ int -create_convergence_table (ndom, rootname) - int ndom; - char rootname[]; +create_convergence_table (int ndom, char rootname[]) { char filename[132]; double *c[50], *converge; @@ -849,9 +840,7 @@ create_convergence_table (ndom, rootname) **********************************************************/ int -create_velocity_gradient_table (ndom, rootname) - int ndom; - char rootname[]; +create_velocity_gradient_table (int ndom, char rootname[]) { char filename[132]; double *c[50], *converge; @@ -1031,11 +1020,7 @@ create_velocity_gradient_table (ndom, rootname) **********************************************************/ int -create_ion_table (ndom, rootname, iz, ion_switch) - int ndom; - char rootname[]; - int iz; - int ion_switch; +create_ion_table (int ndom, char rootname[], int iz, int ion_switch) { char filename[132]; double *c[100]; @@ -1197,9 +1182,7 @@ create_ion_table (ndom, rootname, iz, ion_switch) **********************************************************/ double * -get_ion (ndom, element, istate, iswitch, name) - int ndom, element, istate, iswitch; - char *name; +get_ion (int ndom, int element, int istate, int iswitch, char *name) { int nion, nelem; int n; @@ -1329,9 +1312,7 @@ get_ion (ndom, element, istate, iswitch, name) **********************************************************/ double * -get_one (ndom, variable_name) - int ndom; - char variable_name[]; +get_one (int ndom, char variable_name[]) { int n; int nplasma; @@ -1664,11 +1645,7 @@ get_one (ndom, variable_name) **********************************************************/ int -get_one_array_element (ndom, variable_name, array_dim, xval) - int ndom; - char variable_name[]; - int array_dim; - double xval[]; +get_one_array_element (int ndom, char variable_name[], int array_dim, double xval[]) { int j, n; int nplasma; @@ -1799,9 +1776,7 @@ get_one_array_element (ndom, variable_name, array_dim, xval) **********************************************************/ int -create_spec_table (ndom, rootname) - int ndom; - char rootname[]; +create_spec_table (int ndom, char rootname[]) { char filename[132]; double *c[50], *converge; @@ -2044,9 +2019,7 @@ create_spec_table (ndom, rootname) **********************************************************/ int -create_detailed_cell_spec_table (ncell, rootname) - int ncell; - char rootname[]; +create_detailed_cell_spec_table (int ncell, char rootname[]) { FILE *fptr; char filename[132]; @@ -2120,9 +2093,7 @@ create_detailed_cell_spec_table (ncell, rootname) **********************************************************/ int -create_big_detailed_spec_table (ndom, rootname) - int ndom; - char *rootname; +create_big_detailed_spec_table (int ndom, char *rootname) { char column_name[MAX_COLUMNS][20]; int nplasma[MAX_COLUMNS], ii, jj, ncols; diff --git a/source/xlog.c b/source/xlog.c index d2b15f1b4..99e197a77 100644 --- a/source/xlog.c +++ b/source/xlog.c @@ -146,8 +146,7 @@ int log_verbosity = 5; // A parameter which can be used to suppress wha **********************************************************/ int -Log_init (filename) - char *filename; +Log_init (char *filename) { if ((diagptr = fopen (filename, "w")) == NULL) { @@ -189,8 +188,7 @@ Log_init (filename) **********************************************************/ int -Log_append (filename) - char *filename; +Log_append (char *filename) { if ((diagptr = fopen (filename, "a")) == NULL) { @@ -263,8 +261,7 @@ Log_close () **********************************************************/ int -Log_set_verbosity (vlevel) - int vlevel; +Log_set_verbosity (int vlevel) { log_verbosity = vlevel; rdpar_set_verbose (vlevel); @@ -293,8 +290,7 @@ Log_set_verbosity (vlevel) **********************************************************/ int -Log_print_max (print_max) - int print_max; +Log_print_max (int print_max) { log_print_max = print_max; return (0); @@ -321,8 +317,7 @@ Log_print_max (print_max) **********************************************************/ int -Log_quit_after_n_errors (n) - int n; +Log_quit_after_n_errors (int n) { max_errors = n; return (0); @@ -549,8 +544,7 @@ Shout (char *format, ...) **********************************************************/ int -sane_check (x) - double x; +sane_check (double x) { int i; if ((i = isfinite (x)) == 0) @@ -651,8 +645,7 @@ error_count (char *format) **********************************************************/ int -error_summary (message) - char *message; +error_summary (char *message) { int n; @@ -756,8 +749,7 @@ Log_flush () **********************************************************/ int -Log_set_mpi_rank (rank, n_mpi) - int rank, n_mpi; +Log_set_mpi_rank (int rank, int n_mpi) { my_rank = rank; n_mpi_procs = n_mpi; diff --git a/source/xtest.c b/source/xtest.c index f02b88ca3..cc97bc89d 100644 --- a/source/xtest.c +++ b/source/xtest.c @@ -64,7 +64,7 @@ xtest () double x, xmin, xmax; double y, z, delta; double rzero, theta, vel[3]; - FILE *fopen (), *fptr; + FILE *fptr; modes.run_xtest_diagnostics = TRUE; double v_escape; diff --git a/source/zeta.c b/source/zeta.c index 1e5380ce5..37b67175b 100644 --- a/source/zeta.c +++ b/source/zeta.c @@ -60,9 +60,7 @@ **********************************************************/ double -compute_zeta (temp, nion, mode) - double temp; - int mode, nion; +compute_zeta (double temp, int nion, int mode) { double zeta, interpfrac, dummy; int ihi, ilow; From 78d50ada5cc5738e2ba38a562d190b09ed3cf2c0 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 20 Mar 2026 09:30:26 -0500 Subject: [PATCH 03/33] Update developer docs to describe plasma/macro sub-struct memory model Document the three-way split of plasma_dummy and macro_dummy into state/est/derived sub-structures in programmer_notes.rst and mpi_comms.rst, including field access patterns, communication function mappings, and guidance for adding new variables. Co-Authored-By: Claude Opus 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 69 +++++++++++++- .../source/developer/programmer_notes.rst | 91 +++++++++++++++++-- 2 files changed, 150 insertions(+), 10 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index c455f4bc9..cd5743159 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -6,7 +6,7 @@ between ranks and should serve as a basic set of instructions for extending or m routines. In general, all calls to MPI are isolated from the rest of SIROCCO. Most, if not all, of the MPI code is contained -within give source files, which deal entirely with parallelisation or communication. Currently these files are: +within five source files, which deal entirely with parallelisation or communication. Currently these files are: - :code:`communicate_macro.c` - :code:`communicate_plasma.c` @@ -153,3 +153,70 @@ Adding a new variable to an existing communication there as an example. - In the block where :code:`rank != rank_global`, add a new call to :code:`MPI_Unpack` using the code which is already there as an example. + +Relationship between sub-structures and communication patterns +============================================================== + +The ``plasma_dummy`` and ``macro_dummy`` structures are each divided into three +sub-structures that correspond directly to different MPI communication patterns. +This makes it straightforward to determine which communication function to modify +when adding a new variable: + +.. list-table:: Plasma sub-structures and their communication + :header-rows: 1 + :widths: 20 30 25 25 + + * - Sub-structure + - Contents + - Communication + - Key functions + * - ``state`` + - Thermodynamic state (``ne``, ``t_e``, ``t_r``, ``w``, ``rho``, ``vol``), ion populations (``density``, ``partition``, ``levden``), spectral model parameters, bound-free data + - Broadcast after wind updates + - ``broadcast_updated_plasma_properties()``, ``broadcast_plasma_grid()`` + * - ``est`` + - Radiation field estimators (``j``, ``ave_freq``), heating rates (``heat_tot``, ``heat_lines``, etc.), photon counters, flux estimators, cell spectra, ionization estimators + - Reduced (summed) across ranks after photon transport + - ``reduce_simple_estimators()`` + * - ``derived`` + - Cooling rates, luminosities, convergence diagnostics, scatter counts, persistent flux averages, ionization parameter (``xi``) + - Broadcast after wind updates + - ``broadcast_updated_plasma_properties()``, ``broadcast_wind_luminosity()``, ``broadcast_wind_cooling()`` + +.. list-table:: Macro-atom sub-structures and their communication + :header-rows: 1 + :widths: 20 30 25 25 + + * - Sub-structure + - Contents + - Communication + - Key functions + * - ``state`` + - Normalized rate coefficients (``jbar_old``, ``gamma_old``, ``alpha_st_old``, etc.), mode flags + - Broadcast after wind updates + - ``broadcast_updated_macro_atom_properties()`` + * - ``est`` + - Raw Sobolev mean intensities (``jbar``), photoionization rates (``gamma``), stimulated recombination rates (``alpha_st``), macro-atom absorption, cooling stores + - Reduced (summed) across ranks after transport + - ``reduce_macro_atom_estimators()`` + * - ``derived`` + - Macro-atom emissivities (``matom_emiss``), k-packet rate flags, transition probability matrix + - Broadcast after computation + - ``broadcast_macro_atom_emissivities()`` + +When adding a new variable, place it in the appropriate sub-structure and update +the corresponding communication function. For ``est`` fields, update the reduction +function. For ``state`` or ``derived`` fields, update the broadcast function. +In both cases, remember to update the buffer size calculation (the integer and double +counts) to account for the new variable. + +Future shared-memory model +-------------------------- + +The sub-structure split is designed to enable a future MPI-3 shared memory optimization. +The idea is that ranks on the same node can share a single copy of the ``state`` and +``derived`` sub-structures (which are read-only during transport) via ``MPI_Win_allocate_shared``, +while each rank maintains its own private copy of the ``est`` sub-structure for accumulating +estimators. After transport, a two-level reduction would sum the estimators: first within +each node (intra-node), then across nodes (inter-node). This would significantly reduce +memory usage for large models run on multi-core nodes. diff --git a/docs/sphinx/source/developer/programmer_notes.rst b/docs/sphinx/source/developer/programmer_notes.rst index 96c053dc4..945e13780 100644 --- a/docs/sphinx/source/developer/programmer_notes.rst +++ b/docs/sphinx/source/developer/programmer_notes.rst @@ -33,6 +33,76 @@ The main header files are: * sirocco.h - This contains the structures and other data that comprise the wind as well as the parameters of the model. (This is fairly well-documented, or should be) +Plasma and macro-atom sub-structures +------------------------------------- + +The two largest data structures, ``plasma_dummy`` (accessed via ``PlasmaPtr``) and +``macro_dummy`` (accessed via ``MacroPtr``), are each split into three sub-structures +that categorize fields by their role during a simulation cycle. This split makes the +MPI communication patterns self-documenting and lays the groundwork for a future +shared-memory optimization where read-only data can be shared between ranks on the +same node while private estimator data remains per-rank. + +The top-level ``plasma_dummy`` struct is: + +.. code:: c + + typedef struct plasma { + int nwind; /* cross-reference to wind cell */ + int nplasma; /* self-reference index */ + struct plasma_state state; /* read-only during transport */ + struct plasma_estimators est; /* accumulated during transport */ + struct plasma_derived derived; /* computed during wind updates */ + } plasma_dummy, *PlasmaPtr; + +The three sub-structures are: + +* **plasma_state** -- Thermodynamic state, ion/level populations, spectral model + parameters, and bound-free process data. These fields are set during initialization + or the wind update phase. During photon transport, all ranks read them but none + write them. Fields are accessed as ``xplasma->state.ne``, ``xplasma->state.t_e``, + ``xplasma->state.density[n]``, etc. + +* **plasma_estimators** -- Radiation field estimators (mean intensity, heating rates, + ionization rates, flux estimators, photon counters, cell spectra). Every rank + accumulates these independently during photon transport via ``+=``. After transport, + ``reduce_simple_estimators()`` sums them across ranks using ``MPI_Allreduce``. + Fields are accessed as ``xplasma->est.j``, ``xplasma->est.heat_tot``, + ``xplasma->est.ioniz[n]``, etc. + +* **plasma_derived** -- Cooling rates, luminosities, convergence diagnostics, + per-ion recombination/scattering counts, persistent flux averages, and the + ionization parameter. These are computed from the estimators during the wind + update phase. Each rank computes its assigned partition of cells, then broadcasts + to all ranks via ``broadcast_updated_plasma_properties()``. + Fields are accessed as ``xplasma->derived.lum_tot``, ``xplasma->derived.cool_comp``, + ``xplasma->derived.xi``, etc. + +The ``macro_dummy`` struct follows the same pattern: + +.. code:: c + + typedef struct macro { + struct macro_state state; /* normalized rates, read-only during transport */ + struct macro_estimators est; /* raw estimators, accumulated during transport */ + struct macro_derived derived; /* computed quantities, broadcast after wind updates */ + } macro_dummy, *MacroPtr; + +* **macro_state** -- Normalized rate coefficients (``jbar_old``, ``gamma_old``, etc.) + and mode flags. Set before transport, read-only during it. +* **macro_estimators** -- Raw Sobolev mean intensities, photoionization rates, + stimulated recombination rates, and macro-atom cooling stores. Accumulated during + transport and reduced across ranks. +* **macro_derived** -- Macro-atom emissivities, k-packet rate flags, and the + transition probability matrix. Computed during wind updates and broadcast. + +When adding a new field to the plasma or macro-atom grid, place it in the +appropriate sub-structure based on when it is read and written: + +* If it is set during initialization/wind updates and only read during transport → ``state`` +* If it is accumulated (``+=``) during transport and reduced across ranks → ``est`` +* If it is computed from estimators during wind updates and then broadcast → ``derived`` + Program Flow ============ @@ -67,20 +137,22 @@ Parallel Operation SIROCCO uses MPI to parallelize the most compute intensive portions of the routine. It has been run on large machines with 100s of cores without problem. -The portions of the routine that are parallelize are: +The portions of the routine that are parallelized are: -* Photon generation and transfer: When run in multiprocesser mode, each thread creates only a +* Photon generation and transfer: When run in multiprocessor mode, each thread creates only a fraction of the total number of photons. The weight of the photons in each thread is such that the sum of the weights is the total energy expected to be produced in one observer frame second. - These photons are propagated through the wind, and estimators based on these photons are accumulated. - At the end of photon transfer by all threads, the various quantities, including the spectra, that - have been accumulated in the separate threads are gathered together and averaged or summed as - appropriate. For ionization cycles, this means that all of the data needed to calculate the + These photons are propagated through the wind, and estimators based on these photons are accumulated + in the ``est`` sub-structures of ``plasmamain`` and ``macromain``. + At the end of photon transfer by all threads, the estimators + are reduced (summed) across ranks via ``reduce_simple_estimators()`` and + ``reduce_macro_atom_estimators()``, so that all of the data needed to calculate the ionization in any cell is available on each of the threads. * Ionization calculation: Although all of the threads have all of the data needed to calculate the ionization in any cell, in practice what happens is that the program assigns a different set of cells to each thread to calculate the ionization. After the thread calculates the new ionization - state for its assigned cells, the ionization states are then gathered back and broadcast to all + state for its assigned cells, the results (stored in the ``state`` and ``derived`` sub-structures) + are then gathered back and broadcast to all of the threads, in preparation for the next cycle. * Preparation for detailed radiative transfer in the macro-atom mode. When photons go through the grid in the simple-atom mode, photon frequencies do not change a great deal, however in macro-atom @@ -94,9 +166,10 @@ The portions of the routine that are parallelize are: the radiative transfer step in the detailed spectrum phase. -MPI requires intialization. For SIROCCO this is carried out in sirocco.c. Various subroutines make +MPI requires initialization. For SIROCCO this is carried out in sirocco.c. Various subroutines make use of MPI, and as a result, programmers need to be aware of this fact when they write auxiliary -routines that use the various subroutines called by SIROCCO. +routines that use the various subroutines called by SIROCCO. See :doc:`mpi_comms` for details +on the communication patterns and how they relate to the plasma and macro-atom sub-structures. Input naming conventions ======================== From 96cc54c3c7e4022e872d246c6b09c60bb8215e9d Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 20 Mar 2026 21:56:19 -0500 Subject: [PATCH 04/33] Implement MPI-3 shared memory for plasma/macro dynamic arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements Phase 2 of the shared-memory optimization for SIROCCO. When running with multiple MPI ranks on the same node, variable-length plasma and macro-atom arrays now use MPI-3 shared memory windows (MPI_Win_allocate_shared) so that only one physical copy exists per node, rather than one per rank. This significantly reduces memory consumption for large models on multi-core nodes. Phase 2a — contiguous block allocation: All dynamic plasma arrays (density, partition, levden, ioniz, etc.) are now allocated as single contiguous blocks in calloc_dyn_plasma() and calloc_estimators(), with each cell's pointer set to the correct offset within the block. This replaces the previous pattern of separate calloc() calls per cell and is a prerequisite for shared memory, which requires contiguous regions. Block base pointers and MPI_Win handles are tracked in new global structs plasma_block_ptrs (type plasma_blocks) and macro_block_ptrs (type macro_blocks), declared in sirocco.h. Phase 2b — MPI-3 shared memory windows: A node-local communicator (node_comm) is created during MPI init via MPI_Comm_split_type(MPI_COMM_TYPE_SHARED). The helper functions alloc_block_double() and alloc_block_int() accept a use_shared flag: when TRUE and np_mpi_global > 1, only the node leader (node_rank==0) allocates memory via MPI_Win_allocate_shared; other ranks obtain a pointer to the same physical memory via MPI_Win_shared_query. The allocation strategy follows the sub-structure split: - State arrays (density, partition, levden, recomb_simple, etc.) are shared — read-only during photon transport. - Estimator arrays (ioniz, heat_ion, heat_inner_ion, inner_ioniz) are always private — each rank accumulates independently. - Derived arrays (recomb, cool_rr_ion, lum_rr_ion, cool_dr_ion, inner_recomb) are shared — computed during wind updates. - scatters and xscatters are private despite being derived, because they are incremented during photon transport. The same pattern applies to macro-atom arrays in calloc_estimators(). Race condition fix in sobolev(): The sobolev() function in resonate.c previously modified xplasma->state.density[nion] temporarily during photon transport to pass an interpolated density to two_level_atom(). With shared memory, this created a race condition where other ranks could read the temporarily corrupted value. Fixed by adding a density_override parameter to two_level_atom(): when >= 0, it overrides the density read from xplasma->state.density, eliminating the need to modify shared state. All callers pass -1.0 for normal behaviour. Cleanup and synchronisation: MPI_Barrier(node_comm) is called after every broadcast that writes to shared dynamic arrays, ensuring visibility to all node-local ranks. Cleanup at program exit in janitor.c frees contiguous blocks via the block pointer structs; shared blocks are simply NULLed (the MPI runtime frees them at MPI_Finalize), while private blocks are freed with free(). Documentation: Updated mpi_comms.rst to replace the "Future shared-memory model" placeholder with a complete description of the implementation. Updated programmer_notes.rst to reflect the current shared-memory model and document thread-safety constraints on state arrays. Updated doxygen headers for two_level_atom(), sobolev(), and calloc_dyn_plasma(). Files modified: source/sirocco.c — node_comm setup via MPI_Comm_split_type source/sirocco.h — plasma_blocks/macro_blocks structs, MPI_Win handles source/sirocco_extern_init.c — node_comm, node_rank, node_size globals source/gridwind.c — contiguous block allocation with shared memory source/janitor.c — block-aware cleanup for shared/private memory source/lines.c — density_override parameter for two_level_atom() source/resonate.c — sobolev() no longer modifies shared state source/templates.h — updated two_level_atom() prototype source/communicate_plasma.c — MPI_Barrier(node_comm) after broadcasts source/communicate_macro.c — MPI_Barrier(node_comm) after broadcasts source/estimators_macro.c — updated two_level_atom() call source/macro_accelerate.c — updated two_level_atom() call source/swind_ion.c — updated two_level_atom() call source/wind_updates2d.c — removed debug log message docs/sphinx/source/developer/mpi_comms.rst — full shared-memory docs docs/sphinx/source/developer/programmer_notes.rst — thread-safety notes Co-Authored-By: Claude Opus 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 131 ++++- .../source/developer/programmer_notes.rst | 15 +- source/communicate_macro.c | 16 + source/communicate_plasma.c | 14 + source/estimators_macro.c | 2 +- source/gridwind.c | 542 +++++++++++------- source/janitor.c | 139 +++-- source/lines.c | 13 +- source/macro_accelerate.c | 2 +- source/resonate.c | 25 +- source/sirocco.c | 21 + source/sirocco.h | 96 ++++ source/sirocco_extern_init.c | 11 + source/swind_ion.c | 2 +- source/templates.h | 2 +- source/wind_updates2d.c | 1 - 16 files changed, 754 insertions(+), 278 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index cd5743159..96139588a 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -210,13 +210,124 @@ function. For ``state`` or ``derived`` fields, update the broadcast function. In both cases, remember to update the buffer size calculation (the integer and double counts) to account for the new variable. -Future shared-memory model --------------------------- - -The sub-structure split is designed to enable a future MPI-3 shared memory optimization. -The idea is that ranks on the same node can share a single copy of the ``state`` and -``derived`` sub-structures (which are read-only during transport) via ``MPI_Win_allocate_shared``, -while each rank maintains its own private copy of the ``est`` sub-structure for accumulating -estimators. After transport, a two-level reduction would sum the estimators: first within -each node (intra-node), then across nodes (inter-node). This would significantly reduce -memory usage for large models run on multi-core nodes. +MPI-3 shared memory model +------------------------- + +When running with more than one MPI rank, SIROCCO uses MPI-3 shared memory windows +to reduce per-node memory consumption. The key idea is that ranks on the same +physical node share a single copy of data that is read-only during photon transport, +rather than duplicating it across every rank. + +During MPI initialisation (in ``sirocco.c``), a *node-local communicator* +is created with ``MPI_Comm_split_type(MPI_COMM_TYPE_SHARED, ...)``. Three global +variables track the node topology: + +- ``node_comm`` — communicator for ranks sharing the same node +- ``node_rank`` — rank index within the node (0 = node leader) +- ``node_size`` — number of ranks on the node + +Contiguous block allocation +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All variable-length plasma arrays (density, partition, ioniz, etc.) are allocated +as contiguous blocks in ``calloc_dyn_plasma()`` (in ``gridwind.c``), with each +cell's pointer set to the appropriate offset within the block. This replaces the +earlier pattern of separate ``calloc`` calls per cell and is a prerequisite for +shared memory, since ``MPI_Win_allocate_shared`` requires contiguous regions. + +The allocation is performed by two helper functions, ``alloc_block_double()`` and +``alloc_block_int()``, which accept a ``use_shared`` flag: + +- When ``use_shared`` is TRUE and ``np_mpi_global > 1``, only the node leader + (``node_rank == 0``) allocates memory via ``MPI_Win_allocate_shared``; other + ranks on the same node obtain a pointer to the same physical memory via + ``MPI_Win_shared_query``. +- When ``use_shared`` is FALSE, each rank allocates its own private block with + regular ``calloc``. + +The same contiguous block layout is used in non-MPI builds and with a single MPI +rank; the only difference is that ``calloc`` is used unconditionally. + +Which arrays are shared +^^^^^^^^^^^^^^^^^^^^^^^ + +The allocation strategy mirrors the three sub-structures: + +.. list-table:: + :header-rows: 1 + :widths: 15 55 15 15 + + * - Category + - Arrays + - Allocation + - Reason + * - **State** + - ``density``, ``partition``, ``levden``, ``recomb_simple``, ``recomb_simple_upweight``, ``kbf_use`` + - Shared + - Read-only during photon transport + * - **Estimators** + - ``ioniz``, ``heat_ion``, ``heat_inner_ion``, ``inner_ioniz`` + - Private + - Each rank accumulates independently + * - **Derived** + - ``recomb``, ``cool_rr_ion``, ``lum_rr_ion``, ``cool_dr_ion``, ``inner_recomb`` + - Shared + - Computed during wind updates, then broadcast + * - **Derived (exceptions)** + - ``scatters``, ``xscatters`` + - Private + - Incremented during photon transport (would race in shared memory) + +The same shared/private split applies to macro-atom dynamic arrays in +``calloc_estimators()`` (also in ``gridwind.c``). State and derived arrays +(``jbar_old``, ``gamma_old``, ``matom_emiss``, etc.) are shared, while +estimator arrays (``jbar``, ``gamma``, ``cooling_bf``, etc.) are private. + +Block pointer management +^^^^^^^^^^^^^^^^^^^^^^^^ + +Base pointers for all contiguous blocks are stored in global structs +``plasma_block_ptrs`` (type ``plasma_blocks``) and ``macro_block_ptrs`` +(type ``macro_blocks``), declared in ``sirocco.h``. These structs also hold +the ``MPI_Win`` handles needed to free shared windows and a +``shared_memory_active`` flag that records whether the current allocation +used shared memory. + +Synchronisation +^^^^^^^^^^^^^^^ + +After any broadcast that writes to shared dynamic arrays, an +``MPI_Barrier(node_comm)`` ensures all node-local ranks see the new data +before proceeding. These barriers appear at the end of: + +- ``broadcast_updated_plasma_properties()`` +- ``broadcast_plasma_grid()`` +- ``broadcast_wind_luminosity()`` +- ``broadcast_wind_cooling()`` +- ``broadcast_updated_macro_atom_properties()`` +- ``broadcast_macro_atom_emissivities()`` +- ``reduce_macro_atom_estimators()`` + +During photon transport, state arrays are read-only so no synchronisation +is required. The ``sobolev()`` function in ``resonate.c`` previously +modified ``state.density`` temporarily during transport; it now passes a +density override to ``two_level_atom()`` instead, avoiding a race condition +on shared memory. + +Cleanup +^^^^^^^ + +At program exit, ``free_plasma_grid()`` and ``free_macro_grid()`` in +``janitor.c`` free the contiguous blocks. For shared blocks the memory is +owned by the MPI window, so the pointer is simply NULLed (the MPI runtime +frees it at ``MPI_Finalize``). Private blocks are freed with ``free()`` +as usual. + +Memory savings +^^^^^^^^^^^^^^ + +For a model with *N* plasma cells, *I* ions, and *R* ranks on one node, +the dominant dynamic arrays total roughly ``N * I * 14 * 8`` bytes per rank. +With shared memory the state and derived arrays exist only once per node, +reducing the per-node footprint by approximately ``(R-1)/R`` of the shared +portion. Estimator arrays remain duplicated across ranks. diff --git a/docs/sphinx/source/developer/programmer_notes.rst b/docs/sphinx/source/developer/programmer_notes.rst index 945e13780..fda4288e3 100644 --- a/docs/sphinx/source/developer/programmer_notes.rst +++ b/docs/sphinx/source/developer/programmer_notes.rst @@ -39,9 +39,9 @@ Plasma and macro-atom sub-structures The two largest data structures, ``plasma_dummy`` (accessed via ``PlasmaPtr``) and ``macro_dummy`` (accessed via ``MacroPtr``), are each split into three sub-structures that categorize fields by their role during a simulation cycle. This split makes the -MPI communication patterns self-documenting and lays the groundwork for a future -shared-memory optimization where read-only data can be shared between ranks on the -same node while private estimator data remains per-rank. +MPI communication patterns self-documenting and enables the MPI-3 shared-memory model +(see :doc:`mpi_comms`) where read-only data is shared between ranks on the same node +while private estimator data remains per-rank. The top-level ``plasma_dummy`` struct is: @@ -60,7 +60,11 @@ The three sub-structures are: * **plasma_state** -- Thermodynamic state, ion/level populations, spectral model parameters, and bound-free process data. These fields are set during initialization or the wind update phase. During photon transport, all ranks read them but none - write them. Fields are accessed as ``xplasma->state.ne``, ``xplasma->state.t_e``, + write them. In the MPI shared-memory model the dynamic state arrays (``density``, + ``partition``, ``levden``, etc.) reside in shared memory, so it is critical that + transport code never modifies them — use local variables or function parameters + (e.g. the ``density_override`` argument to ``two_level_atom()``) instead. + Fields are accessed as ``xplasma->state.ne``, ``xplasma->state.t_e``, ``xplasma->state.density[n]``, etc. * **plasma_estimators** -- Radiation field estimators (mean intensity, heating rates, @@ -75,6 +79,9 @@ The three sub-structures are: ionization parameter. These are computed from the estimators during the wind update phase. Each rank computes its assigned partition of cells, then broadcasts to all ranks via ``broadcast_updated_plasma_properties()``. + Most derived dynamic arrays reside in shared memory, but ``scatters`` and + ``xscatters`` are kept private per rank because they are incremented during + photon transport. Fields are accessed as ``xplasma->derived.lum_tot``, ``xplasma->derived.cool_comp``, ``xplasma->derived.xi``, etc. diff --git a/source/communicate_macro.c b/source/communicate_macro.c index 23d2b0045..3ad85ec7b 100644 --- a/source/communicate_macro.c +++ b/source/communicate_macro.c @@ -89,6 +89,10 @@ broadcast_macro_atom_emissivities (const int n_start, const int n_stop, const in } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished macro atom emissivity communication\n", "OK"); #endif } @@ -190,6 +194,10 @@ broadcast_macro_atom_recomb (const int n_start, const int n_stop, const int n_ce } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished macro atom recombination communication\n", "OK"); #endif } @@ -289,6 +297,10 @@ broadcast_updated_macro_atom_properties (const int n_start, const int n_stop, co } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished macro atom updated properties communication\n", "OK"); #endif return EXIT_SUCCESS; @@ -374,6 +386,10 @@ broadcast_macro_atom_state_matrix (int n_start, int n_stop, int n_cells_rank) } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished macro atom state matrix communication\n", "OK"); #endif return (0); diff --git a/source/communicate_plasma.c b/source/communicate_plasma.c index 6ad940c1f..adc9d78d5 100644 --- a/source/communicate_plasma.c +++ b/source/communicate_plasma.c @@ -401,6 +401,10 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished communicating plasma grid\n", "OK"); #endif } @@ -488,6 +492,9 @@ broadcast_wind_luminosity (const int n_start, const int n_stop, const int n_cell } } + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished communicating wind luminosity\n", "OK"); free (comm_buffer); #endif @@ -585,6 +592,9 @@ broadcast_wind_cooling (const int n_start, const int n_stop, const int n_cells_r } } + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished communicating wind cooling\n", "OK"); free (comm_buffer); #endif @@ -1025,6 +1035,10 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra } free (comm_buffer); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished communicating updated plasma properties\n", "OK"); #endif return EXIT_SUCCESS; diff --git a/source/estimators_macro.c b/source/estimators_macro.c index 64dab65f8..caf714f3d 100644 --- a/source/estimators_macro.c +++ b/source/estimators_macro.c @@ -680,7 +680,7 @@ total_bb_cooling (PlasmaPtr xplasma, double t_e) //The cooling rate is computed using the scattering probability formalism in KSL's notes on Sirocco. - two_level_atom (line_ptr, xplasma, &lower_density, &upper_density); + two_level_atom (line_ptr, xplasma, &lower_density, &upper_density, -1.0); coll_rate = q21 (line_ptr, t_e) * xplasma->state.ne * (1. - exp (-H_OVER_K * line_ptr->freq / t_e)); cool_contribution = diff --git a/source/gridwind.c b/source/gridwind.c index a675c787a..85dc2e930 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -47,12 +47,179 @@ #include #include +#include #include #include "atomic.h" #include "sirocco.h" +/* Convenience macros to pass MPI_Win addresses or NULL depending on MPI mode */ +#ifdef MPI_ON +#define PLASMA_WIN(field) plasma_block_ptrs.field +#define MACRO_WIN(field) macro_block_ptrs.field +#else +/* Use a dummy variable to satisfy the void* parameter when MPI is off */ +static int _dummy_win; +#define PLASMA_WIN(field) _dummy_win +#define MACRO_WIN(field) _dummy_win +#endif + + +/**********************************************************/ +/** + * @brief Allocate a contiguous block, using MPI shared memory when available. + * + * @param [in] count Number of elements to allocate + * @param [in] elem_size Size of each element in bytes + * @param [out] ptr Pointer set to the allocated block (shared or private) + * @param [out] win MPI_Win handle (set only when MPI shared memory is used) + * @param [in] use_shared If TRUE, use MPI_Win_allocate_shared (state/derived); + * if FALSE, use regular calloc (est arrays) + * @return 0 on success, exits on failure + * + * @details + * When MPI-3 shared memory is available and use_shared is TRUE, only the + * node leader (node_rank == 0) allocates memory; other ranks on the same + * node query the leader's pointer via MPI_Win_shared_query. This means + * one physical copy per node for read-only (state) and broadcast (derived) + * data. + * + * For estimator arrays (use_shared == FALSE), each rank gets its own + * private allocation via regular calloc, since estimators are accumulated + * independently per rank. + * + * In non-MPI builds, always uses calloc. + **********************************************************/ + +static int +alloc_block_double (long count, double **ptr, void *win_ptr, int use_shared) +{ +#ifdef MPI_ON + if (use_shared && np_mpi_global > 1) + { + MPI_Win *win = (MPI_Win *) win_ptr; + MPI_Aint block_size = (node_rank == 0) ? count * (MPI_Aint) sizeof (double) : 0; + MPI_Win_allocate_shared (block_size, sizeof (double), MPI_INFO_NULL, node_comm, ptr, win); + + if (node_rank != 0) + { + MPI_Aint sz; + int disp; + MPI_Win_shared_query (*win, 0, &sz, &disp, ptr); + } + + /* Zero-initialize the shared block (only leader needs to, but barrier ensures visibility) */ + if (node_rank == 0) + { + memset (*ptr, 0, count * sizeof (double)); + } + MPI_Barrier (node_comm); + + if (*ptr == NULL) + { + Error ("alloc_block_double: MPI_Win_allocate_shared returned NULL\n"); + Exit (0); + } + return (0); + } +#endif + + (void) win_ptr; + (void) use_shared; + *ptr = calloc (count, sizeof (double)); + if (*ptr == NULL) + { + Error ("alloc_block_double: calloc failed for %ld doubles\n", count); + Exit (0); + } + return (0); +} + + +/**********************************************************/ +/** + * @brief Allocate a contiguous int block, using MPI shared memory when available. + * + * @details Same as alloc_block_double but for int arrays. + **********************************************************/ + +static int +alloc_block_int (long count, int **ptr, void *win_ptr, int use_shared) +{ +#ifdef MPI_ON + if (use_shared && np_mpi_global > 1) + { + MPI_Win *win = (MPI_Win *) win_ptr; + MPI_Aint block_size = (node_rank == 0) ? count * (MPI_Aint) sizeof (int) : 0; + MPI_Win_allocate_shared (block_size, sizeof (int), MPI_INFO_NULL, node_comm, ptr, win); + + if (node_rank != 0) + { + MPI_Aint sz; + int disp; + MPI_Win_shared_query (*win, 0, &sz, &disp, ptr); + } + + if (node_rank == 0) + { + memset (*ptr, 0, count * sizeof (int)); + } + MPI_Barrier (node_comm); + + if (*ptr == NULL) + { + Error ("alloc_block_int: MPI_Win_allocate_shared returned NULL\n"); + Exit (0); + } + return (0); + } +#endif + + (void) win_ptr; + (void) use_shared; + *ptr = calloc (count, sizeof (int)); + if (*ptr == NULL) + { + Error ("alloc_block_int: calloc failed for %ld ints\n", count); + Exit (0); + } + return (0); +} + + +/**********************************************************/ +/** + * @brief Free a block, using MPI_Win_free for shared blocks or free() for private. + * + * @param [in,out] ptr Pointer to set to NULL after freeing + * @param [in] win_ptr MPI_Win handle (or NULL for non-shared) + * @param [in] is_shared TRUE if block was allocated with MPI shared memory + **********************************************************/ + +static void +free_block (void **ptr, void *win_ptr, int is_shared) +{ + if (*ptr == NULL) + return; + +#ifdef MPI_ON + if (is_shared && np_mpi_global > 1) + { + MPI_Win *win = (MPI_Win *) win_ptr; + MPI_Win_free (win); + *ptr = NULL; + return; + } +#endif + + (void) win_ptr; + (void) is_shared; + free (*ptr); + *ptr = NULL; +} + + /**********************************************************/ /** * @brief Create a map between wind and plasma cells @@ -426,109 +593,64 @@ calloc_estimators (int nelem) Log ("calloc_estimators: size_Jbar_est %d size_gamma_est %d size_alpha_est %d\n", size_Jbar_est, size_gamma_est, size_alpha_est); + /* Allocate contiguous blocks for all macro atom dynamic arrays. + * State and derived arrays use MPI shared memory (one copy per node). + * Estimator arrays are always private (each rank accumulates independently). */ + + int use_shared = FALSE; +#ifdef MPI_ON + use_shared = (np_mpi_global > 1) ? TRUE : FALSE; +#endif + + /* state arrays — shared across node-local ranks */ + alloc_block_double ((long) nelem * size_Jbar_est, ¯o_block_ptrs.jbar_old_block, &MACRO_WIN (win_jbar_old), use_shared); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.gamma_old_block, &MACRO_WIN (win_gamma_old), use_shared); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.gamma_e_old_block, &MACRO_WIN (win_gamma_e_old), use_shared); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.alpha_st_old_block, &MACRO_WIN (win_alpha_st_old), use_shared); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.alpha_st_e_old_block, &MACRO_WIN (win_alpha_st_e_old), use_shared); + + /* est arrays — always private per rank */ + alloc_block_double ((long) nelem * size_Jbar_est, ¯o_block_ptrs.jbar_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.gamma_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.gamma_e_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.alpha_st_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_gamma_est, ¯o_block_ptrs.alpha_st_e_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_alpha_est, ¯o_block_ptrs.recomb_sp_block, NULL, FALSE); + alloc_block_double ((long) nelem * size_alpha_est, ¯o_block_ptrs.recomb_sp_e_block, NULL, FALSE); + alloc_block_double ((long) nelem * nlevels_macro, ¯o_block_ptrs.matom_abs_block, NULL, FALSE); + alloc_block_double ((long) nelem * nphot_total, ¯o_block_ptrs.cooling_bf_block, NULL, FALSE); + alloc_block_double ((long) nelem * nphot_total, ¯o_block_ptrs.cooling_bf_col_block, NULL, FALSE); + alloc_block_double ((long) nelem * nlines, ¯o_block_ptrs.cooling_bb_block, NULL, FALSE); + + /* derived arrays — shared across node-local ranks */ + alloc_block_double ((long) nelem * nlevels_macro, ¯o_block_ptrs.matom_emiss_block, &MACRO_WIN (win_matom_emiss), use_shared); + +#ifdef MPI_ON + macro_block_ptrs.shared_memory_active = use_shared; +#endif + + /* Point each cell's pointers into the contiguous blocks */ for (n = 0; n < nelem; n++) { - if ((macromain[n].est.jbar = calloc (sizeof (double), size_Jbar_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].state.jbar_old = calloc (sizeof (double), size_Jbar_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.gamma = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].state.gamma_old = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.gamma_e = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].state.gamma_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.alpha_st = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].state.alpha_st_old = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.alpha_st_e = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].state.alpha_st_e_old = calloc (sizeof (double), size_gamma_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.recomb_sp = calloc (sizeof (double), size_alpha_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.recomb_sp_e = calloc (sizeof (double), size_alpha_est)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].derived.matom_emiss = calloc (sizeof (double), nlevels_macro)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.matom_abs = calloc (sizeof (double), nlevels_macro)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.cooling_bf = calloc (sizeof (double), nphot_total)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.cooling_bf_col = calloc (sizeof (double), nphot_total)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } - - if ((macromain[n].est.cooling_bb = calloc (sizeof (double), nlines)) == NULL) - { - Error ("calloc_estimators: Error in allocating memory for MA estimators\n"); - Exit (0); - } + macromain[n].state.jbar_old = macro_block_ptrs.jbar_old_block + n * size_Jbar_est; + macromain[n].state.gamma_old = macro_block_ptrs.gamma_old_block + n * size_gamma_est; + macromain[n].state.gamma_e_old = macro_block_ptrs.gamma_e_old_block + n * size_gamma_est; + macromain[n].state.alpha_st_old = macro_block_ptrs.alpha_st_old_block + n * size_gamma_est; + macromain[n].state.alpha_st_e_old = macro_block_ptrs.alpha_st_e_old_block + n * size_gamma_est; + + macromain[n].est.jbar = macro_block_ptrs.jbar_block + n * size_Jbar_est; + macromain[n].est.gamma = macro_block_ptrs.gamma_block + n * size_gamma_est; + macromain[n].est.gamma_e = macro_block_ptrs.gamma_e_block + n * size_gamma_est; + macromain[n].est.alpha_st = macro_block_ptrs.alpha_st_block + n * size_gamma_est; + macromain[n].est.alpha_st_e = macro_block_ptrs.alpha_st_e_block + n * size_gamma_est; + macromain[n].est.recomb_sp = macro_block_ptrs.recomb_sp_block + n * size_alpha_est; + macromain[n].est.recomb_sp_e = macro_block_ptrs.recomb_sp_e_block + n * size_alpha_est; + macromain[n].est.matom_abs = macro_block_ptrs.matom_abs_block + n * nlevels_macro; + macromain[n].est.cooling_bf = macro_block_ptrs.cooling_bf_block + n * nphot_total; + macromain[n].est.cooling_bf_col = macro_block_ptrs.cooling_bf_col_block + n * nphot_total; + macromain[n].est.cooling_bb = macro_block_ptrs.cooling_bb_block + n * nlines; + + macromain[n].derived.matom_emiss = macro_block_ptrs.matom_emiss_block + n * nlevels_macro; } @@ -552,22 +674,36 @@ calloc_estimators (int nelem) /**********************************************************/ -/** - * @brief This subroutine allocates space for dynamic arrays in the plasma - * structure +/** + * @brief Allocate contiguous blocks for all dynamic plasma arrays. * - * @param [in] int nelem the number of plasma cells (actually NPLASMA+1) - * to allow for empty cell + * @param [in] int nelem the number of plasma cells (NPLASMA; one extra + * element is added internally for the empty/dummy cell) * @return Returns 0, unless the memory cannot be allocated in which case - * the proram exits + * the program exits * * @details - * This subroutine allocates space for variable length arrays in the plasma structure. + * Allocates contiguous blocks for variable-length arrays in the plasma structure, + * then points each cell's sub-struct pointers into the blocks at the correct offset. + * + * In MPI builds with np_mpi_global > 1, blocks are allocated using MPI-3 + * shared memory so that only one physical copy exists per node: + * + * - **State arrays** (density, partition, levden, recomb_simple, etc.) — + * shared across node-local ranks (read-only during photon transport). + * - **Estimator arrays** (ioniz, heat_ion, heat_inner_ion, inner_ioniz) — + * always private per rank (each rank accumulates independently). + * - **Derived arrays** (recomb, cool_rr_ion, lum_rr_ion, cool_dr_ion, + * inner_recomb) — shared across node-local ranks. + * - **scatters, xscatters** — always private per rank despite being + * derived quantities, because they are incremented during photon + * transport and would otherwise create a race condition in shared memory. + * + * In non-MPI builds or with a single MPI rank, all blocks use regular calloc. * * ### Notes ### * Arrays sized to the number of ions are largest, - * and dominate the size of nplasma, so these were first to be - * dynamically allocated. + * and dominate the memory footprint of the plasma grid. * **********************************************************/ @@ -575,109 +711,101 @@ int calloc_dyn_plasma (int nelem) { int n; - -/* Loop over all elements in the plasma array, adding one for an empty cell - * used for extrapolations. - */ - - for (n = 0; n < nelem + 1; n++) + int nelem_alloc = nelem + 1; /* One extra element for the empty/dummy cell */ + long nalloc_ions = (long) nelem_alloc * nions; + long nalloc_nlte = (long) nelem_alloc * nlte_levels; + long nalloc_phot = (long) nelem_alloc * nphot_total; + long nalloc_inner = (long) nelem_alloc * n_inner_tot; + int use_shared = FALSE; + int was_shared = FALSE; + +#ifdef MPI_ON + use_shared = (np_mpi_global > 1) ? TRUE : FALSE; + was_shared = plasma_block_ptrs.shared_memory_active; +#endif + + /* Free any previously allocated blocks */ + if (plasma_block_ptrs.density_block != NULL) { - if ((plasmamain[n].state.density = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for density\n"); - Exit (0); - } - if ((plasmamain[n].state.partition = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for partition\n"); - Exit (0); - } - if ((plasmamain[n].est.ioniz = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for ioniz\n"); - Exit (0); - } - if ((plasmamain[n].derived.recomb = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for recomb\n"); - Exit (0); - } - if ((plasmamain[n].derived.scatters = calloc (sizeof (int), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for scatters\n"); - Exit (0); - } - if ((plasmamain[n].derived.xscatters = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for xscatters\n"); - Exit (0); - } - if ((plasmamain[n].est.heat_ion = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for heat_ion\n"); - Exit (0); - } - if ((plasmamain[n].est.heat_inner_ion = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for heat_ion\n"); - Exit (0); - } - if ((plasmamain[n].derived.cool_rr_ion = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for cool_rr_ion\n"); - Exit (0); - } - if ((plasmamain[n].derived.lum_rr_ion = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for lum_rr_ion\n"); - Exit (0); - } - if ((plasmamain[n].derived.inner_recomb = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for inner_recomb\n"); - Exit (0); - } - if ((plasmamain[n].est.inner_ioniz = calloc (sizeof (double), n_inner_tot)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for inner_ioniz\n"); - Exit (0); - } - if ((plasmamain[n].derived.cool_dr_ion = calloc (sizeof (double), nions)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for lum_inner_recomb\n"); - Exit (0); - } - - - if ((plasmamain[n].state.levden = calloc (sizeof (double), nlte_levels)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for levden\n"); - Exit (0); - } - - if ((plasmamain[n].state.recomb_simple = calloc (sizeof (double), nphot_total)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for recomb_simple\n"); - Exit (0); - } - - if ((plasmamain[n].state.recomb_simple_upweight = calloc (sizeof (double), nphot_total)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for recomb_simple_upweight\n"); - Exit (0); - } - + free_block ((void **) &plasma_block_ptrs.density_block, &PLASMA_WIN (win_density), was_shared); + free_block ((void **) &plasma_block_ptrs.partition_block, &PLASMA_WIN (win_partition), was_shared); + free_block ((void **) &plasma_block_ptrs.levden_block, &PLASMA_WIN (win_levden), was_shared); + free_block ((void **) &plasma_block_ptrs.recomb_simple_block, &PLASMA_WIN (win_recomb_simple), was_shared); + free_block ((void **) &plasma_block_ptrs.recomb_simple_upweight_block, &PLASMA_WIN (win_recomb_simple_upweight), was_shared); + free_block ((void **) &plasma_block_ptrs.kbf_use_block, &PLASMA_WIN (win_kbf_use), was_shared); + free_block ((void **) &plasma_block_ptrs.ioniz_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.heat_ion_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.heat_inner_ion_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.inner_ioniz_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.recomb_block, &PLASMA_WIN (win_recomb), was_shared); + free_block ((void **) &plasma_block_ptrs.scatters_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.xscatters_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.cool_rr_ion_block, &PLASMA_WIN (win_cool_rr_ion), was_shared); + free_block ((void **) &plasma_block_ptrs.lum_rr_ion_block, &PLASMA_WIN (win_lum_rr_ion), was_shared); + free_block ((void **) &plasma_block_ptrs.cool_dr_ion_block, &PLASMA_WIN (win_cool_dr_ion), was_shared); + free_block ((void **) &plasma_block_ptrs.inner_recomb_block, &PLASMA_WIN (win_inner_recomb), was_shared); + } - if ((plasmamain[n].state.kbf_use = calloc (sizeof (double), nphot_total)) == NULL) - { - Error ("calloc_dyn_plasma: Error in allocating memory for kbf_use\n"); - Exit (0); - } + /* Allocate contiguous blocks for all dynamic plasma arrays. + * State and derived arrays use MPI shared memory (one copy per node). + * Estimator arrays are always private (each rank accumulates independently). */ + + /* state arrays — shared across node-local ranks */ + alloc_block_double (nalloc_ions, &plasma_block_ptrs.density_block, &PLASMA_WIN (win_density), use_shared); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.partition_block, &PLASMA_WIN (win_partition), use_shared); + alloc_block_double (nalloc_nlte, &plasma_block_ptrs.levden_block, &PLASMA_WIN (win_levden), use_shared); + alloc_block_double (nalloc_phot, &plasma_block_ptrs.recomb_simple_block, &PLASMA_WIN (win_recomb_simple), use_shared); + alloc_block_double (nalloc_phot, &plasma_block_ptrs.recomb_simple_upweight_block, &PLASMA_WIN (win_recomb_simple_upweight), use_shared); + /* kbf_use is int* but historically allocated/written as doubles for binary compat */ + alloc_block_double (nalloc_phot, &plasma_block_ptrs.kbf_use_block, &PLASMA_WIN (win_kbf_use), use_shared); + + /* est arrays — always private per rank */ + alloc_block_double (nalloc_ions, &plasma_block_ptrs.ioniz_block, NULL, FALSE); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.heat_ion_block, NULL, FALSE); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.heat_inner_ion_block, NULL, FALSE); + alloc_block_double (nalloc_inner, &plasma_block_ptrs.inner_ioniz_block, NULL, FALSE); + + /* derived arrays — shared across node-local ranks (except scatters/xscatters + * which are written during photon transport and must be private per rank) */ + alloc_block_double (nalloc_ions, &plasma_block_ptrs.recomb_block, &PLASMA_WIN (win_recomb), use_shared); + alloc_block_int (nalloc_ions, &plasma_block_ptrs.scatters_block, NULL, FALSE); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.xscatters_block, NULL, FALSE); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.cool_rr_ion_block, &PLASMA_WIN (win_cool_rr_ion), use_shared); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.lum_rr_ion_block, &PLASMA_WIN (win_lum_rr_ion), use_shared); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.cool_dr_ion_block, &PLASMA_WIN (win_cool_dr_ion), use_shared); + alloc_block_double (nalloc_ions, &plasma_block_ptrs.inner_recomb_block, &PLASMA_WIN (win_inner_recomb), use_shared); + +#ifdef MPI_ON + plasma_block_ptrs.shared_memory_active = use_shared; +#endif + + /* Point each cell's pointers into the contiguous blocks at the right offset */ + for (n = 0; n < nelem_alloc; n++) + { + plasmamain[n].state.density = plasma_block_ptrs.density_block + n * nions; + plasmamain[n].state.partition = plasma_block_ptrs.partition_block + n * nions; + plasmamain[n].state.levden = plasma_block_ptrs.levden_block + n * nlte_levels; + plasmamain[n].state.recomb_simple = plasma_block_ptrs.recomb_simple_block + n * nphot_total; + plasmamain[n].state.recomb_simple_upweight = plasma_block_ptrs.recomb_simple_upweight_block + n * nphot_total; + plasmamain[n].state.kbf_use = (int *) (plasma_block_ptrs.kbf_use_block + n * nphot_total); + + plasmamain[n].est.ioniz = plasma_block_ptrs.ioniz_block + n * nions; + plasmamain[n].est.heat_ion = plasma_block_ptrs.heat_ion_block + n * nions; + plasmamain[n].est.heat_inner_ion = plasma_block_ptrs.heat_inner_ion_block + n * nions; + plasmamain[n].est.inner_ioniz = plasma_block_ptrs.inner_ioniz_block + n * n_inner_tot; + + plasmamain[n].derived.recomb = plasma_block_ptrs.recomb_block + n * nions; + plasmamain[n].derived.scatters = plasma_block_ptrs.scatters_block + n * nions; + plasmamain[n].derived.xscatters = plasma_block_ptrs.xscatters_block + n * nions; + plasmamain[n].derived.cool_rr_ion = plasma_block_ptrs.cool_rr_ion_block + n * nions; + plasmamain[n].derived.lum_rr_ion = plasma_block_ptrs.lum_rr_ion_block + n * nions; + plasmamain[n].derived.cool_dr_ion = plasma_block_ptrs.cool_dr_ion_block + n * nions; + plasmamain[n].derived.inner_recomb = plasma_block_ptrs.inner_recomb_block + n * nions; } Log ("Allocated %10d bytes for each of %5d elements variable length plasma arrays totaling %10.1f Mb \n", - sizeof (double) * nions * 14, (nelem + 1), 1.e-6 * (nelem + 1) * sizeof (double) * (nions * 14 + nlte_levels + nphot_total * 2)); + sizeof (double) * nions * 14, nelem_alloc, 1.e-6 * nelem_alloc * sizeof (double) * (nions * 14 + nlte_levels + nphot_total * 2)); return (0); } diff --git a/source/janitor.c b/source/janitor.c index baded8488..94acb2eb4 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -14,6 +14,45 @@ #include "atomic.h" #include "sirocco.h" + +/**********************************************************/ +/** + * @brief Free a contiguous block, using MPI_Win_free for shared blocks. + * + * @param [in,out] ptr Address of the block pointer (set to NULL after freeing) + * @param [in] is_shared TRUE if the block was allocated with MPI shared memory + * + * @details + * This is the counterpart to alloc_block_double/alloc_block_int in gridwind.c. + * For shared blocks, we cannot call free() since the memory was allocated by + * MPI_Win_allocate_shared; instead we would need MPI_Win_free on the corresponding + * window. However, at program exit the MPI runtime handles cleanup, so for + * shared blocks we simply NULL the pointer without calling free. + * For private (non-shared) blocks, we call free() as normal. + **********************************************************/ + +static void +free_plasma_block (void **ptr, int is_shared) +{ + if (*ptr == NULL) + return; + +#ifdef MPI_ON + if (is_shared && np_mpi_global > 1) + { + /* Shared memory is freed via MPI_Win_free, which is handled + * by the cleanup in calloc_dyn_plasma/calloc_estimators when + * re-allocating, or by MPI_Finalize at exit. */ + *ptr = NULL; + return; + } +#endif + + (void) is_shared; + free (*ptr); + *ptr = NULL; +} + /**********************************************************/ /** * @brief Free memory associated with the domains @@ -83,27 +122,39 @@ free_wind_grid (void) void free_plasma_grid (void) { - int n_plasma; + /* Free contiguous blocks instead of per-cell pointers, since all cell + * pointers now index into contiguous blocks managed by plasma_block_ptrs. + * For MPI shared memory blocks, use MPI_Win_free instead of free. */ - for (n_plasma = 0; n_plasma < NPLASMA + 1; ++n_plasma) + int is_shared = FALSE; +#ifdef MPI_ON + is_shared = plasma_block_ptrs.shared_memory_active; +#endif + + /* state blocks (shared in MPI mode) */ + if (plasma_block_ptrs.density_block != NULL) { - free (plasmamain[n_plasma].state.density); - free (plasmamain[n_plasma].state.partition); - free (plasmamain[n_plasma].est.ioniz); - free (plasmamain[n_plasma].derived.recomb); - free (plasmamain[n_plasma].derived.scatters); - free (plasmamain[n_plasma].derived.xscatters); - free (plasmamain[n_plasma].est.heat_ion); - free (plasmamain[n_plasma].est.heat_inner_ion); - free (plasmamain[n_plasma].derived.cool_rr_ion); - free (plasmamain[n_plasma].derived.lum_rr_ion); - free (plasmamain[n_plasma].derived.inner_recomb); - free (plasmamain[n_plasma].est.inner_ioniz); - free (plasmamain[n_plasma].derived.cool_dr_ion); - free (plasmamain[n_plasma].state.levden); - free (plasmamain[n_plasma].state.recomb_simple); - free (plasmamain[n_plasma].state.recomb_simple_upweight); - free (plasmamain[n_plasma].state.kbf_use); + free_plasma_block ((void **) &plasma_block_ptrs.density_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.partition_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.levden_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.recomb_simple_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.recomb_simple_upweight_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.kbf_use_block, is_shared); + + /* est blocks (always private) */ + free_plasma_block ((void **) &plasma_block_ptrs.ioniz_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.heat_ion_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.heat_inner_ion_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.inner_ioniz_block, FALSE); + + /* derived blocks (shared in MPI mode, except scatters/xscatters which are private) */ + free_plasma_block ((void **) &plasma_block_ptrs.recomb_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.scatters_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.xscatters_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.cool_rr_ion_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.lum_rr_ion_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.cool_dr_ion_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.inner_recomb_block, is_shared); } free (plasmamain); @@ -122,25 +173,41 @@ free_macro_grid (void) { int n_plasma; + /* Free contiguous blocks instead of per-cell pointers */ + int is_shared = FALSE; +#ifdef MPI_ON + is_shared = macro_block_ptrs.shared_memory_active; +#endif + + if (macro_block_ptrs.jbar_block != NULL) + { + /* state blocks (shared in MPI mode) */ + free_plasma_block ((void **) ¯o_block_ptrs.jbar_old_block, is_shared); + free_plasma_block ((void **) ¯o_block_ptrs.gamma_old_block, is_shared); + free_plasma_block ((void **) ¯o_block_ptrs.gamma_e_old_block, is_shared); + free_plasma_block ((void **) ¯o_block_ptrs.alpha_st_old_block, is_shared); + free_plasma_block ((void **) ¯o_block_ptrs.alpha_st_e_old_block, is_shared); + + /* est blocks (always private) */ + free_plasma_block ((void **) ¯o_block_ptrs.jbar_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.gamma_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.gamma_e_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.alpha_st_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.alpha_st_e_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.recomb_sp_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.recomb_sp_e_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.matom_abs_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.cooling_bf_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.cooling_bf_col_block, FALSE); + free_plasma_block ((void **) ¯o_block_ptrs.cooling_bb_block, FALSE); + + /* derived blocks (shared in MPI mode) */ + free_plasma_block ((void **) ¯o_block_ptrs.matom_emiss_block, is_shared); + } + + /* matom_matrix is still allocated per-cell (not part of contiguous blocks) */ for (n_plasma = 0; n_plasma < NPLASMA + 1; n_plasma++) { - free (macromain[n_plasma].est.jbar); - free (macromain[n_plasma].state.jbar_old); - free (macromain[n_plasma].est.gamma); - free (macromain[n_plasma].state.gamma_old); - free (macromain[n_plasma].est.gamma_e); - free (macromain[n_plasma].state.gamma_e_old); - free (macromain[n_plasma].est.alpha_st); - free (macromain[n_plasma].state.alpha_st_old); - free (macromain[n_plasma].est.alpha_st_e); - free (macromain[n_plasma].state.alpha_st_e_old); - free (macromain[n_plasma].est.recomb_sp); - free (macromain[n_plasma].est.recomb_sp_e); - free (macromain[n_plasma].derived.matom_emiss); - free (macromain[n_plasma].est.matom_abs); - free (macromain[n_plasma].est.cooling_bf); - free (macromain[n_plasma].est.cooling_bf_col); - free (macromain[n_plasma].est.cooling_bb); if (macromain[n_plasma].state.store_matom_matrix == TRUE) { free (macromain[n_plasma].derived.matom_matrix[0]); diff --git a/source/lines.c b/source/lines.c index 367498a86..f66140d34 100644 --- a/source/lines.c +++ b/source/lines.c @@ -121,7 +121,7 @@ lum_lines (xplasma, nmin, nmax) if (dd > LDEN_MIN) { /* potentially dangerous step to avoid lines with no power */ - two_level_atom (lin_ptr[n], xplasma, &d1, &d2); + two_level_atom (lin_ptr[n], xplasma, &d1, &d2, -1.0); x = foo1 = lin_ptr[n]->gu / lin_ptr[n]->gl * d1 - d2; z = exp (-H_OVER_K * lin_ptr[n]->freq / t_e); @@ -177,7 +177,10 @@ double old_d1, old_d2, old_n2_over_n1; * @param [in] struct lines * line_ptr The line of interest * @param [in] PlasmaPtr xplasma The plasma cell of interest * @param [out] double * d1 The calculated density of the lower level for the line of interest - * @param [out] double * d2 The calculated density of the upper levl + * @param [out] double * d2 The calculated density of the upper level + * @param [in] double density_override If >= 0, use this ion density instead of + * reading from xplasma->state.density. Pass -1.0 for normal behaviour. + * This avoids modifying shared memory in the MPI shared-memory model. * @return The density ratio d2/d1 * * @details @@ -200,7 +203,7 @@ double old_d1, old_d2, old_n2_over_n1; double -two_level_atom (struct lines *line_ptr, PlasmaPtr xplasma, double *d1, double *d2) +two_level_atom (struct lines *line_ptr, PlasmaPtr xplasma, double *d1, double *d2, double density_override) { double a; double q, c12, c21; @@ -230,7 +233,7 @@ two_level_atom (struct lines *line_ptr, PlasmaPtr xplasma, double *d1, double *d tr = xplasma->state.t_r; w = xplasma->state.w; nion = line_ptr->nion; - dd = xplasma->state.density[nion]; + dd = (density_override >= 0) ? density_override : xplasma->state.density[nion]; /* Calculate the number density of the lower level for the transition using the partition function */ ; @@ -360,7 +363,7 @@ line_nsigma (struct lines *line_ptr, PlasmaPtr xplasma) { double d1, d2, x; - two_level_atom (line_ptr, xplasma, &d1, &d2); + two_level_atom (line_ptr, xplasma, &d1, &d2, -1.0); x = (d1 - line_ptr->gl / line_ptr->gu * d2); x *= PI_E2_OVER_MC * line_ptr->f; diff --git a/source/macro_accelerate.c b/source/macro_accelerate.c index e1d62b0cb..f58bb40c6 100644 --- a/source/macro_accelerate.c +++ b/source/macro_accelerate.c @@ -481,7 +481,7 @@ fill_kpkt_rates (PlasmaPtr xplasma, int *escape, PhotPtr p) } else { - two_level_atom (line_ptr, xplasma, &lower_density, &upper_density); + two_level_atom (line_ptr, xplasma, &lower_density, &upper_density, -1.0); coll_rate = q21 (line_ptr, electron_temperature) * (1. - exp (-H_OVER_K * line_ptr->freq / electron_temperature)); diff --git a/source/resonate.c b/source/resonate.c index 57ade4c0b..535c70e75 100644 --- a/source/resonate.c +++ b/source/resonate.c @@ -672,14 +672,16 @@ int sobolev_error_counter = 0; * @brief calculates tau in the sobolev approximation for a resonance, given the * conditions in the wind and the direction of the photon. * - * It does not modify any of the variables that are passed to it, including for example - * the photon. + * This routine does not modify any shared plasma state. When a density + * override is needed (den_ion >= 0 or forced recalculation), the desired + * density is passed to two_level_atom via its density_override parameter + * rather than temporarily modifying the shared state.density array. * * @param [in] WindPtr one A single wind cell * @param [in] double x[] A position * @param [in] double den_ion The density of the ion. If less than 0, the routine calculates - * the density at x - * @param [in] struct lines * lptr A pointer to a particular ion + * the density at x using get_ion_density + * @param [in] struct lines * lptr A pointer to a particular line transition * @param [in] double dvds the velocity gradient in the direction of travel of the photon * @return The optical depth associated with a transition * @@ -700,7 +702,6 @@ sobolev (WindPtr one, double x[], double den_ion, struct lines *lptr, double dvd double tau, xden_ion, tau_x_dvds, levden_upper; double d1, d2; int nion; - double d_hold; int nplasma; int ndom; PlasmaPtr xplasma; @@ -738,18 +739,20 @@ ion which was done above in calculate ds. It was made necessary by a change in calls to two_level atom */ - d_hold = xplasma->state.density[nion]; // Store the density of this ion in the cell - + /* Use a density override to avoid modifying the shared state.density + * array, which would create a race condition with MPI shared memory. + * The density override is passed to two_level_atom so it uses this + * value instead of reading from xplasma->state.density[nion]. */ + double den_override; if (den_ion < 0) { - xplasma->state.density[nion] = get_ion_density (ndom, x, lptr->nion); // Forced calculation of density + den_override = get_ion_density (ndom, x, lptr->nion); // Forced calculation of density } else { - xplasma->state.density[nion] = den_ion; // Put den_ion into the density array + den_override = den_ion; // Use the interpolated density } - two_level_atom (lptr, xplasma, &d1, &d2); // Calculate d1 & d2 - xplasma->state.density[nion] = d_hold; // Restore w + two_level_atom (lptr, xplasma, &d1, &d2, den_override); // Calculate d1 & d2 levden_upper = d2 / xplasma->state.density[nion]; } diff --git a/source/sirocco.c b/source/sirocco.c index 53884be00..333108d45 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -91,6 +91,23 @@ main (int argc, char *argv[]) } MPI_Comm_rank (MPI_COMM_WORLD, &my_rank); MPI_Comm_size (MPI_COMM_WORLD, &np_mpi); + + /* Create node-local communicator for MPI-3 shared memory */ + MPI_Comm_split_type (MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, my_rank, MPI_INFO_NULL, &node_comm); + MPI_Comm_rank (node_comm, &node_rank); + MPI_Comm_size (node_comm, &node_size); + + /* Create inter-node leader communicator (one leader per node) */ + MPI_Comm_split (MPI_COMM_WORLD, (node_rank == 0) ? 0 : MPI_UNDEFINED, my_rank, &leader_comm); + + /* Determine total number of nodes */ + num_nodes = 0; + if (leader_comm != MPI_COMM_NULL) + { + MPI_Comm_size (leader_comm, &num_nodes); + } + MPI_Bcast (&num_nodes, 1, MPI_INT, 0, MPI_COMM_WORLD); + #else my_rank = 0; np_mpi = 1; @@ -112,6 +129,10 @@ main (int argc, char *argv[]) rank_global = my_rank; // Global variable which holds the rank of the active MPI process Log_set_mpi_rank (my_rank, np_mpi); // communicates my_rank to kpar +#ifdef MPI_ON + Log ("MPI topology: %d ranks across %d node(s), %d ranks on this node (node_rank %d)\n", np_mpi, num_nodes, node_size, node_rank); +#endif + /* This completes the initialisation of mpi */ opar_stat = 0; /* Initialize opar_stat to indicate that if we do not open a rdpar file, diff --git a/source/sirocco.h b/source/sirocco.h index d87395aa9..185c18cb7 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -15,6 +15,14 @@ extern int np_mpi_global; /**< Global variable which holds the number of MP extern int rank_global; /** Date: Sat, 21 Mar 2026 13:40:00 -0500 Subject: [PATCH 05/33] Move fixed-size plasma arrays to shared contiguous blocks Convert 18 fixed-size arrays in plasma_state (spectral model parameters) and plasma_derived (persistent radiation field averages) from inline arrays to pointers into shared contiguous blocks, reducing sizeof(plasma_dummy) by ~2.3 KB/cell. State arrays moved: f1, f2, spec_mod_type, pl_alpha, pl_log_w, exp_temp, exp_w, fmin_mod, fmax_mod (4 combined blocks). Derived arrays moved: F_vis_persistent, F_UV_persistent, F_Xray_persistent, rad_force_*_persist, F_UV_ang_*_persist. Also fixes a pre-existing bug in broadcast_plasma_cell() where spec_mod_type was packed with &cell->state.spec_mod_type (address of array/pointer) and count 1, instead of cell->state.spec_mod_type with count NXBANDS. The buffer size calculation is updated to match. Co-Authored-By: Claude Opus 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 23 ++++- .../source/developer/programmer_notes.rst | 16 ++-- source/communicate_plasma.c | 6 +- source/gridwind.c | 89 +++++++++++++++++-- source/janitor.c | 6 ++ source/sirocco.h | 51 ++++++----- source/windsave.c | 40 +++++++++ 7 files changed, 194 insertions(+), 37 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index 96139588a..812808b04 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -261,18 +261,26 @@ The allocation strategy mirrors the three sub-structures: - Arrays - Allocation - Reason - * - **State** + * - **State (dynamic)** - ``density``, ``partition``, ``levden``, ``recomb_simple``, ``recomb_simple_upweight``, ``kbf_use`` - Shared - Read-only during photon transport + * - **State (fixed-size)** + - ``f1``, ``f2``, ``spec_mod_type``, ``pl_alpha``, ``pl_log_w``, ``exp_temp``, ``exp_w``, ``fmin_mod``, ``fmax_mod`` + - Shared + - Spectral model parameters, read-only during transport * - **Estimators** - ``ioniz``, ``heat_ion``, ``heat_inner_ion``, ``inner_ioniz`` - Private - Each rank accumulates independently - * - **Derived** + * - **Derived (dynamic)** - ``recomb``, ``cool_rr_ion``, ``lum_rr_ion``, ``cool_dr_ion``, ``inner_recomb`` - Shared - Computed during wind updates, then broadcast + * - **Derived (fixed-size)** + - ``F_vis_persistent``, ``F_UV_persistent``, ``F_Xray_persistent``, ``rad_force_es_persist``, ``rad_force_ff_persist``, ``rad_force_bf_persist``, ``F_UV_ang_theta_persist``, ``F_UV_ang_phi_persist``, ``F_UV_ang_r_persist`` + - Shared + - Persistent radiation field averages, read-only during transport * - **Derived (exceptions)** - ``scatters``, ``xscatters`` - Private @@ -331,3 +339,14 @@ the dominant dynamic arrays total roughly ``N * I * 14 * 8`` bytes per rank. With shared memory the state and derived arrays exist only once per node, reducing the per-node footprint by approximately ``(R-1)/R`` of the shared portion. Estimator arrays remain duplicated across ranks. + +In addition to the variable-length dynamic arrays, fixed-size arrays that +were previously embedded in the ``plasma_state`` and ``plasma_derived`` +sub-structures (spectral model parameters, persistent flux averages) have +been moved to shared contiguous blocks. These arrays are declared as +pointers in the struct and point into combined blocks allocated in +``calloc_dyn_plasma()``. This reduces ``sizeof(plasma_dummy)`` by +approximately 2.3 KB per cell, yielding additional PSS savings of +roughly ``2.3 * N * (R-1)/R`` KB. The savings scale linearly with +NPLASMA: for a model with 80K cells and 29 ranks, this adds approximately +177 MB of per-rank savings. diff --git a/docs/sphinx/source/developer/programmer_notes.rst b/docs/sphinx/source/developer/programmer_notes.rst index fda4288e3..d1dbca65c 100644 --- a/docs/sphinx/source/developer/programmer_notes.rst +++ b/docs/sphinx/source/developer/programmer_notes.rst @@ -60,12 +60,14 @@ The three sub-structures are: * **plasma_state** -- Thermodynamic state, ion/level populations, spectral model parameters, and bound-free process data. These fields are set during initialization or the wind update phase. During photon transport, all ranks read them but none - write them. In the MPI shared-memory model the dynamic state arrays (``density``, - ``partition``, ``levden``, etc.) reside in shared memory, so it is critical that - transport code never modifies them — use local variables or function parameters - (e.g. the ``density_override`` argument to ``two_level_atom()``) instead. + write them. In the MPI shared-memory model, both the variable-length dynamic arrays + (``density``, ``partition``, ``levden``, etc.) and the fixed-size spectral model + arrays (``f1``, ``f2``, ``spec_mod_type``, ``pl_alpha``, ``pl_log_w``, ``exp_temp``, + ``exp_w``, ``fmin_mod``, ``fmax_mod``) reside in shared contiguous blocks, so it is + critical that transport code never modifies them — use local variables or function + parameters (e.g. the ``density_override`` argument to ``two_level_atom()``) instead. Fields are accessed as ``xplasma->state.ne``, ``xplasma->state.t_e``, - ``xplasma->state.density[n]``, etc. + ``xplasma->state.density[n]``, ``xplasma->state.pl_alpha[band]``, etc. * **plasma_estimators** -- Radiation field estimators (mean intensity, heating rates, ionization rates, flux estimators, photon counters, cell spectra). Every rank @@ -81,7 +83,9 @@ The three sub-structures are: to all ranks via ``broadcast_updated_plasma_properties()``. Most derived dynamic arrays reside in shared memory, but ``scatters`` and ``xscatters`` are kept private per rank because they are incremented during - photon transport. + photon transport. The persistent radiation field arrays (``F_vis_persistent``, + ``F_UV_persistent``, ``F_Xray_persistent``, ``rad_force_*_persist``, + ``F_UV_ang_*_persist``) also reside in shared contiguous blocks. Fields are accessed as ``xplasma->derived.lum_tot``, ``xplasma->derived.cool_comp``, ``xplasma->derived.xi``, etc. diff --git a/source/communicate_plasma.c b/source/communicate_plasma.c index adc9d78d5..c6735f601 100644 --- a/source/communicate_plasma.c +++ b/source/communicate_plasma.c @@ -57,7 +57,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra d_xsignal (files.root, "%-20s Begin communicating plasma grid\n", "NOK"); const int n_cells_max = get_max_cells_per_rank (NPLASMA); - const int num_ints = 1 + n_cells_max * (1 + N_BASIC_INTS + nphot_total + nions + NXBANDS + 2 * N_PHOT_PROC); + const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + nions + 2 * NXBANDS + 2 * N_PHOT_PROC); const int num_doubles = n_cells_max * (N_BASIC_DOUBLES + 11 * nions + nlte_levels + 2 * nphot_total + n_inner_tot + 11 * NXBANDS + NBINS_IN_CELL_SPEC + 6 * NFLUX_ANGLES + N_DMO_DT_DIRECTIONS + 12 * NFORCE_DIRECTIONS); @@ -157,7 +157,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Pack (cell->state.fmax_mod, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.xsd_freq, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.nxtot, NXBANDS, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (&cell->state.spec_mod_type, 1, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->state.spec_mod_type, NXBANDS, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->state.pl_alpha, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->state.exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); @@ -319,7 +319,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.fmax_mod, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.xsd_freq, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.nxtot, NXBANDS, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->state.spec_mod_type, 1, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.spec_mod_type, NXBANDS, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.pl_alpha, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); diff --git a/source/gridwind.c b/source/gridwind.c index 85dc2e930..b859f2543 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -657,9 +657,12 @@ calloc_estimators (int nelem) if (nlevels_macro > 0 || geo.nmacro > 0) { + double macro_shared_bytes = (double) nelem * sizeof (double) * (size_Jbar_est + 4.0 * size_gamma_est + nlevels_macro); + double macro_private_bytes = (double) nelem * sizeof (double) * + (size_Jbar_est + 4.0 * size_gamma_est + 2.0 * size_alpha_est + nlevels_macro + 2.0 * nphot_total + nlines); Log - ("Allocated %10.1f Mb for MA estimators \n", - 1.e-6 * (nelem + 1) * (2. * nlevels_macro + 2. * size_alpha_est + 8. * size_gamma_est + 2. * size_Jbar_est) * sizeof (double)); + ("Macro-atom memory per rank: dynamic shared %.1f MB (one copy/node), dynamic private %.1f MB (per rank)\n", + 1.e-6 * macro_shared_bytes, 1.e-6 * macro_private_bytes); } else @@ -744,6 +747,10 @@ calloc_dyn_plasma (int nelem) free_block ((void **) &plasma_block_ptrs.lum_rr_ion_block, &PLASMA_WIN (win_lum_rr_ion), was_shared); free_block ((void **) &plasma_block_ptrs.cool_dr_ion_block, &PLASMA_WIN (win_cool_dr_ion), was_shared); free_block ((void **) &plasma_block_ptrs.inner_recomb_block, &PLASMA_WIN (win_inner_recomb), was_shared); + free_block ((void **) &plasma_block_ptrs.state_xbands_dblock, &PLASMA_WIN (win_state_xbands_d), was_shared); + free_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, &PLASMA_WIN (win_state_spec_mod_type), was_shared); + free_block ((void **) &plasma_block_ptrs.derived_persist_force_block, &PLASMA_WIN (win_derived_persist_force), was_shared); + free_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, &PLASMA_WIN (win_derived_persist_angle), was_shared); } /* Allocate contiguous blocks for all dynamic plasma arrays. @@ -775,6 +782,21 @@ calloc_dyn_plasma (int nelem) alloc_block_double (nalloc_ions, &plasma_block_ptrs.cool_dr_ion_block, &PLASMA_WIN (win_cool_dr_ion), use_shared); alloc_block_double (nalloc_ions, &plasma_block_ptrs.inner_recomb_block, &PLASMA_WIN (win_inner_recomb), use_shared); + /* state fixed-size arrays — combined contiguous blocks (shared) */ + { + int state_xbands_stride = 6 * NXBANDS + 2 * (NXBANDS + 1); + alloc_block_double ((long) nelem_alloc * state_xbands_stride, &plasma_block_ptrs.state_xbands_dblock, + &PLASMA_WIN (win_state_xbands_d), use_shared); + } + alloc_block_int ((long) nelem_alloc * NXBANDS, &plasma_block_ptrs.state_spec_mod_type_block, + &PLASMA_WIN (win_state_spec_mod_type), use_shared); + + /* derived fixed-size arrays — combined contiguous blocks (shared) */ + alloc_block_double ((long) nelem_alloc * 6 * NFORCE_DIRECTIONS, &plasma_block_ptrs.derived_persist_force_block, + &PLASMA_WIN (win_derived_persist_force), use_shared); + alloc_block_double ((long) nelem_alloc * 3 * NFLUX_ANGLES, &plasma_block_ptrs.derived_persist_angle_block, + &PLASMA_WIN (win_derived_persist_angle), use_shared); + #ifdef MPI_ON plasma_block_ptrs.shared_memory_active = use_shared; #endif @@ -801,11 +823,68 @@ calloc_dyn_plasma (int nelem) plasmamain[n].derived.lum_rr_ion = plasma_block_ptrs.lum_rr_ion_block + n * nions; plasmamain[n].derived.cool_dr_ion = plasma_block_ptrs.cool_dr_ion_block + n * nions; plasmamain[n].derived.inner_recomb = plasma_block_ptrs.inner_recomb_block + n * nions; + + /* State spectral block: stride = 6*NXBANDS + 2*(NXBANDS+1) = 162 */ + { + int state_xbands_stride = 6 * NXBANDS + 2 * (NXBANDS + 1); + double *sbase = plasma_block_ptrs.state_xbands_dblock + n * state_xbands_stride; + plasmamain[n].state.f1 = sbase; + plasmamain[n].state.f2 = sbase + (NXBANDS + 1); + plasmamain[n].state.pl_alpha = sbase + 2 * (NXBANDS + 1); + plasmamain[n].state.pl_log_w = sbase + 2 * (NXBANDS + 1) + NXBANDS; + plasmamain[n].state.exp_temp = sbase + 2 * (NXBANDS + 1) + 2 * NXBANDS; + plasmamain[n].state.exp_w = sbase + 2 * (NXBANDS + 1) + 3 * NXBANDS; + plasmamain[n].state.fmin_mod = sbase + 2 * (NXBANDS + 1) + 4 * NXBANDS; + plasmamain[n].state.fmax_mod = sbase + 2 * (NXBANDS + 1) + 5 * NXBANDS; + } + plasmamain[n].state.spec_mod_type = (enum spec_mod_type_enum *) (plasma_block_ptrs.state_spec_mod_type_block + n * NXBANDS); + + /* Derived persistent force block: stride = 6 * NFORCE_DIRECTIONS */ + { + double *dbase = plasma_block_ptrs.derived_persist_force_block + n * 6 * NFORCE_DIRECTIONS; + plasmamain[n].derived.F_vis_persistent = dbase; + plasmamain[n].derived.F_UV_persistent = dbase + NFORCE_DIRECTIONS; + plasmamain[n].derived.F_Xray_persistent = dbase + 2 * NFORCE_DIRECTIONS; + plasmamain[n].derived.rad_force_es_persist = dbase + 3 * NFORCE_DIRECTIONS; + plasmamain[n].derived.rad_force_ff_persist = dbase + 4 * NFORCE_DIRECTIONS; + plasmamain[n].derived.rad_force_bf_persist = dbase + 5 * NFORCE_DIRECTIONS; + } + + /* Derived persistent angle block: stride = 3 * NFLUX_ANGLES */ + { + double *dbase = plasma_block_ptrs.derived_persist_angle_block + n * 3 * NFLUX_ANGLES; + plasmamain[n].derived.F_UV_ang_theta_persist = dbase; + plasmamain[n].derived.F_UV_ang_phi_persist = dbase + NFLUX_ANGLES; + plasmamain[n].derived.F_UV_ang_r_persist = dbase + 2 * NFLUX_ANGLES; + } } - Log - ("Allocated %10d bytes for each of %5d elements variable length plasma arrays totaling %10.1f Mb \n", - sizeof (double) * nions * 14, nelem_alloc, 1.e-6 * nelem_alloc * sizeof (double) * (nions * 14 + nlte_levels + nphot_total * 2)); + /* Report memory breakdown: shared (one copy per node) vs private (per rank) vs base struct */ + { + double shared_bytes = + (double) nelem_alloc * sizeof (double) * (2.0 * nions + nlte_levels + 3.0 * nphot_total + 5.0 * nions + n_inner_tot); + double private_bytes = (double) nelem_alloc * sizeof (double) * (3.0 * nions + n_inner_tot) + (double) nelem_alloc * sizeof (int) * nions; /* scatters(int) + xscatters(double) already in shared_bytes above... */ + + /* Recalculate properly: + * Shared state: density(nions) + partition(nions) + levden(nlte) + recomb_simple(nphot) + recomb_simple_upweight(nphot) + kbf_use(nphot) = 2*nions + nlte + 3*nphot + * + state_xbands_d(6*NXBANDS + 2*(NXBANDS+1)) + spec_mod_type(NXBANDS ints) + * Shared derived: recomb(nions) + cool_rr_ion(nions) + lum_rr_ion(nions) + cool_dr_ion(nions) + inner_recomb(nions) = 5*nions + * + persist_force(6*NFORCE_DIRECTIONS) + persist_angle(3*NFLUX_ANGLES) + * Private est: ioniz(nions) + heat_ion(nions) + heat_inner_ion(nions) + inner_ioniz(n_inner) = 3*nions + n_inner + * Private derived: scatters(nions, int) + xscatters(nions, double) = nions*(4+8) */ + shared_bytes = (double) nelem_alloc *(sizeof (double) * (2.0 * nions + nlte_levels + 3.0 * nphot_total + 5.0 * nions + + 6.0 * NXBANDS + 2.0 * (NXBANDS + 1) + + 6.0 * NFORCE_DIRECTIONS + 3.0 * NFLUX_ANGLES) + sizeof (int) * NXBANDS); + private_bytes = (double) nelem_alloc *(sizeof (double) * (3.0 * nions + n_inner_tot + nions) + sizeof (int) * nions); + double base_struct_bytes = (double) nelem_alloc * sizeof (plasma_dummy); + + Log + ("Plasma memory per rank: base struct %.1f MB, dynamic shared %.1f MB (one copy/node), dynamic private %.1f MB (per rank)\n", + 1.e-6 * base_struct_bytes, 1.e-6 * shared_bytes, 1.e-6 * private_bytes); + Log + (" nions=%d, nlte_levels=%d, nphot_total=%d, n_inner_tot=%d, nelem=%d\n", + nions, nlte_levels, nphot_total, n_inner_tot, nelem_alloc - 1); + } return (0); } diff --git a/source/janitor.c b/source/janitor.c index 94acb2eb4..3078a24fb 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -155,6 +155,12 @@ free_plasma_grid (void) free_plasma_block ((void **) &plasma_block_ptrs.lum_rr_ion_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.cool_dr_ion_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.inner_recomb_block, is_shared); + + /* Fixed-size array blocks (shared in MPI mode) */ + free_plasma_block ((void **) &plasma_block_ptrs.state_xbands_dblock, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_force_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, is_shared); } free (plasmamain); diff --git a/source/sirocco.h b/source/sirocco.h index 185c18cb7..d6e2071c8 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -947,18 +947,17 @@ typedef struct plasma_state /* Spectral model parameters (set during wind update) */ int nbands; /* The number of spectral bands for this cell */ - double f1[NXBANDS + 1]; /* Spectral band boundaries for this cell */ - double f2[NXBANDS + 1]; /* Spectral band boundaries for this cell */ - enum spec_mod_type_enum spec_mod_type[NXBANDS]; /**< A switch to say which type of representation we are using for this band in this cell. - Negative means we have no useful representation, 0 means power law, 1 means exponential */ - double pl_alpha[NXBANDS]; /**< Computed spectral index for a power law spectrum representing this cell */ - double pl_log_w[NXBANDS]; /**< This is the log version of the power law weight. It is in an attempt to allow very large - values of alpha to work with the PL spectral model to avoide NAN problems. - The pl_w version can be deleted once testing is complete */ - double exp_temp[NXBANDS]; /**< The effective temperature of an exponential representation of the radiation field in a cell */ - double exp_w[NXBANDS]; /**< The prefactor of an exponential representation of the radiation field in a cell */ - double fmin_mod[NXBANDS]; /**< Minimum frequency of the band-limited model */ - double fmax_mod[NXBANDS]; /**< Maximum frequency of the band-limited model */ + double *f1; /* Spectral band boundaries for this cell (NXBANDS+1, contiguous block) */ + double *f2; /* Spectral band boundaries for this cell (NXBANDS+1, contiguous block) */ + enum spec_mod_type_enum *spec_mod_type; /**< A switch to say which type of representation we are using for this band in this cell. + Negative means we have no useful representation, 0 means power law, 1 means exponential + (NXBANDS, contiguous block) */ + double *pl_alpha; /**< Computed spectral index for a power law spectrum representing this cell (NXBANDS, contiguous block) */ + double *pl_log_w; /**< This is the log version of the power law weight (NXBANDS, contiguous block) */ + double *exp_temp; /**< The effective temperature of an exponential representation of the radiation field in a cell (NXBANDS, contiguous block) */ + double *exp_w; /**< The prefactor of an exponential representation of the radiation field in a cell (NXBANDS, contiguous block) */ + double *fmin_mod; /**< Minimum frequency of the band-limited model (NXBANDS, contiguous block) */ + double *fmax_mod; /**< Maximum frequency of the band-limited model (NXBANDS, contiguous block) */ } plasma_state; /** @@ -1094,15 +1093,15 @@ typedef struct plasma_derived double *inner_recomb; /* Persistent/averaged radiation field */ - double F_vis_persistent[NFORCE_DIRECTIONS]; - double F_UV_persistent[NFORCE_DIRECTIONS]; - double F_Xray_persistent[NFORCE_DIRECTIONS]; - double rad_force_es_persist[NFORCE_DIRECTIONS]; - double rad_force_ff_persist[NFORCE_DIRECTIONS]; - double rad_force_bf_persist[NFORCE_DIRECTIONS]; - double F_UV_ang_theta_persist[NFLUX_ANGLES]; - double F_UV_ang_phi_persist[NFLUX_ANGLES]; - double F_UV_ang_r_persist[NFLUX_ANGLES]; + double *F_vis_persistent; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *F_UV_persistent; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *F_Xray_persistent; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *rad_force_es_persist; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *rad_force_ff_persist; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *rad_force_bf_persist; /**< (NFORCE_DIRECTIONS, contiguous block) */ + double *F_UV_ang_theta_persist; /**< (NFLUX_ANGLES, contiguous block) */ + double *F_UV_ang_phi_persist; /**< (NFLUX_ANGLES, contiguous block) */ + double *F_UV_ang_r_persist; /**< (NFLUX_ANGLES, contiguous block) */ /* Momentum/force */ double dmo_dt[N_DMO_DT_DIRECTIONS]; /**< Radiative force of wind */ @@ -1288,6 +1287,10 @@ typedef struct plasma_blocks double *heat_inner_ion_block; /**< NPLASMA * nions */ double *inner_ioniz_block; /**< NPLASMA * n_inner_tot */ + /* state fixed-size arrays moved to contiguous blocks (shared in MPI-3 mode) */ + double *state_xbands_dblock; /**< NPLASMA * (6*NXBANDS + 2*(NXBANDS+1)) doubles: f1,f2,pl_alpha,pl_log_w,exp_temp,exp_w,fmin_mod,fmax_mod */ + int *state_spec_mod_type_block; /**< NPLASMA * NXBANDS ints: spec_mod_type */ + /* derived arrays (shared in MPI-3 mode) */ double *recomb_block; /**< NPLASMA * nions */ int *scatters_block; /**< NPLASMA * nions */ @@ -1297,13 +1300,19 @@ typedef struct plasma_blocks double *cool_dr_ion_block; /**< NPLASMA * nions */ double *inner_recomb_block; /**< NPLASMA * nions */ + /* derived fixed-size arrays moved to contiguous blocks (shared in MPI-3 mode) */ + double *derived_persist_force_block; /**< NPLASMA * 6 * NFORCE_DIRECTIONS doubles */ + double *derived_persist_angle_block; /**< NPLASMA * 3 * NFLUX_ANGLES doubles */ + #ifdef MPI_ON /* MPI shared memory windows for state/derived blocks */ MPI_Win win_density, win_partition, win_levden; MPI_Win win_recomb_simple, win_recomb_simple_upweight, win_kbf_use; + MPI_Win win_state_xbands_d, win_state_spec_mod_type; MPI_Win win_recomb; /* win_scatters and win_xscatters removed: these are always private (written during transport) */ MPI_Win win_cool_rr_ion, win_lum_rr_ion, win_cool_dr_ion, win_inner_recomb; + MPI_Win win_derived_persist_force, win_derived_persist_angle; int shared_memory_active; /**< TRUE if using MPI shared memory for this allocation */ #endif } plasma_blocks; diff --git a/source/windsave.c b/source/windsave.c index d0f9e3aec..1b4a41864 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -116,6 +116,26 @@ in the plasma structure */ n += fwrite (plasmamain[m].state.recomb_simple, sizeof (double), nphot_total, fptr); n += fwrite (plasmamain[m].state.recomb_simple_upweight, sizeof (double), nphot_total, fptr); n += fwrite (plasmamain[m].state.kbf_use, sizeof (double), nphot_total, fptr); + + /* Fixed-size arrays now in contiguous blocks */ + n += fwrite (plasmamain[m].state.f1, sizeof (double), NXBANDS + 1, fptr); + n += fwrite (plasmamain[m].state.f2, sizeof (double), NXBANDS + 1, fptr); + n += fwrite (plasmamain[m].state.spec_mod_type, sizeof (int), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.pl_alpha, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.pl_log_w, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.exp_temp, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.exp_w, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.fmin_mod, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].state.fmax_mod, sizeof (double), NXBANDS, fptr); + n += fwrite (plasmamain[m].derived.F_vis_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.F_UV_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.F_Xray_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.rad_force_es_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.rad_force_ff_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.rad_force_bf_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fwrite (plasmamain[m].derived.F_UV_ang_theta_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fwrite (plasmamain[m].derived.F_UV_ang_phi_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fwrite (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); } /* Now write out the macro atom info */ @@ -290,6 +310,26 @@ wind_read (char filename[]) n += fread (plasmamain[m].state.recomb_simple, sizeof (double), nphot_total, fptr); n += fread (plasmamain[m].state.recomb_simple_upweight, sizeof (double), nphot_total, fptr); n += fread (plasmamain[m].state.kbf_use, sizeof (double), nphot_total, fptr); + + /* Fixed-size arrays now in contiguous blocks */ + n += fread (plasmamain[m].state.f1, sizeof (double), NXBANDS + 1, fptr); + n += fread (plasmamain[m].state.f2, sizeof (double), NXBANDS + 1, fptr); + n += fread (plasmamain[m].state.spec_mod_type, sizeof (int), NXBANDS, fptr); + n += fread (plasmamain[m].state.pl_alpha, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].state.pl_log_w, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].state.exp_temp, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].state.exp_w, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].state.fmin_mod, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].state.fmax_mod, sizeof (double), NXBANDS, fptr); + n += fread (plasmamain[m].derived.F_vis_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.F_UV_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.F_Xray_persistent, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.rad_force_es_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.rad_force_ff_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.rad_force_bf_persist, sizeof (double), NFORCE_DIRECTIONS, fptr); + n += fread (plasmamain[m].derived.F_UV_ang_theta_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fread (plasmamain[m].derived.F_UV_ang_phi_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fread (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); } From a6d5c65058c40ba37d2dc6be0a2adb7034bd4e46 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 21 Mar 2026 15:57:27 -0500 Subject: [PATCH 06/33] Dynamically size n_bf_in/n_bf_out to nphot_total instead of N_PHOT_PROC=500 Remove the compile-time N_PHOT_PROC=500 upper bound and allocate n_bf_in/n_bf_out as private contiguous blocks sized to nphot_total (e.g. 290 for the standard macro-atom dataset). This saves ~1680 bytes/cell (~20 MB/rank for 12K cells). Co-Authored-By: Claude Opus 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 4 ++-- source/communicate_plasma.c | 23 +++++++++++----------- source/gridwind.c | 14 +++++++++++-- source/janitor.c | 2 ++ source/sirocco.h | 8 ++++++-- source/windsave.c | 4 ++++ 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index 812808b04..b5f547827 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -282,9 +282,9 @@ The allocation strategy mirrors the three sub-structures: - Shared - Persistent radiation field averages, read-only during transport * - **Derived (exceptions)** - - ``scatters``, ``xscatters`` + - ``scatters``, ``xscatters``, ``n_bf_in``, ``n_bf_out`` - Private - - Incremented during photon transport (would race in shared memory) + - Incremented during photon transport (would race in shared memory). ``n_bf_in``/``n_bf_out`` are dynamically sized to ``nphot_total`` (formerly fixed at ``N_PHOT_PROC=500``). The same shared/private split applies to macro-atom dynamic arrays in ``calloc_estimators()`` (also in ``gridwind.c``). State and derived arrays diff --git a/source/communicate_plasma.c b/source/communicate_plasma.c index c6735f601..bf73d0d7d 100644 --- a/source/communicate_plasma.c +++ b/source/communicate_plasma.c @@ -57,7 +57,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra d_xsignal (files.root, "%-20s Begin communicating plasma grid\n", "NOK"); const int n_cells_max = get_max_cells_per_rank (NPLASMA); - const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + nions + 2 * NXBANDS + 2 * N_PHOT_PROC); + const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + nions + 2 * NXBANDS + 2 * nphot_total); const int num_doubles = n_cells_max * (N_BASIC_DOUBLES + 11 * nions + nlte_levels + 2 * nphot_total + n_inner_tot + 11 * NXBANDS + NBINS_IN_CELL_SPEC + 6 * NFLUX_ANGLES + N_DMO_DT_DIRECTIONS + 12 * NFORCE_DIRECTIONS); @@ -207,8 +207,8 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Pack (&cell->derived.heat_shock, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (&cell->derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (&cell->derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->derived.n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->derived.n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.n_bf_in, nphot_total, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->derived.n_bf_out, nphot_total, MPI_INT, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (&cell->derived.comp_nujnu, 1, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); @@ -372,8 +372,8 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.heat_shock, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.bf_simple_ionpool_in, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_in, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_out, N_PHOT_PROC, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_in, nphot_total, MPI_INT, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.n_bf_out, nphot_total, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, &cell->derived.comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.rad_force_es, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); @@ -631,8 +631,8 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra d_xsignal (files.root, "%-20s Begin communicating updated plasma properties\n", "NOK"); const int n_cells_max = get_max_cells_per_rank (NPLASMA); - //OLD const int num_ints = 1 + n_cells_max * (20 + nphot_total + 2 * NXBANDS + 2 * N_PHOT_PROC + nions); - const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + 2 * NXBANDS + 2 * N_PHOT_PROC + nions); + //OLD const int num_ints = 1 + n_cells_max * (20 + nphot_total + 2 * NXBANDS + 2 * nphot_total + nions); + const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + 2 * NXBANDS + 2 * nphot_total + nions); const int num_doubles = n_cells_max * (N_BASIC_DOUBLES + 1 * 3 + 9 * 4 + 6 * NFLUX_ANGLES + 3 * NFORCE_DIRECTIONS + 9 * nions + 1 * nlte_levels + 3 * nphot_total + 1 * n_inner_tot + 9 * NXBANDS + 1 * NBINS_IN_CELL_SPEC); @@ -799,9 +799,8 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_COMM_WORLD); MPI_Pack (&plasmamain[n_plasma].derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].derived.n_bf_in, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (&plasmamain[n_plasma].derived.n_bf_out, N_PHOT_PROC, MPI_INT, comm_buffer, size_of_comm_buffer, &position, - MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.n_bf_in, nphot_total, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); + MPI_Pack (plasmamain[n_plasma].derived.n_bf_out, nphot_total, MPI_INT, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (&plasmamain[n_plasma].derived.comp_nujnu, 1, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (plasmamain[n_plasma].derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); @@ -1000,9 +999,9 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.bf_simple_ionpool_out, 1, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.n_bf_in, N_PHOT_PROC, MPI_INT, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.n_bf_in, nphot_total, MPI_INT, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.n_bf_out, N_PHOT_PROC, MPI_INT, + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.n_bf_out, nphot_total, MPI_INT, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, &plasmamain[n_plasma].derived.comp_nujnu, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].derived.dmo_dt, N_DMO_DT_DIRECTIONS, MPI_DOUBLE, diff --git a/source/gridwind.c b/source/gridwind.c index b859f2543..085183b62 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -751,6 +751,8 @@ calloc_dyn_plasma (int nelem) free_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, &PLASMA_WIN (win_state_spec_mod_type), was_shared); free_block ((void **) &plasma_block_ptrs.derived_persist_force_block, &PLASMA_WIN (win_derived_persist_force), was_shared); free_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, &PLASMA_WIN (win_derived_persist_angle), was_shared); + free_block ((void **) &plasma_block_ptrs.n_bf_in_block, NULL, FALSE); + free_block ((void **) &plasma_block_ptrs.n_bf_out_block, NULL, FALSE); } /* Allocate contiguous blocks for all dynamic plasma arrays. @@ -797,6 +799,10 @@ calloc_dyn_plasma (int nelem) alloc_block_double ((long) nelem_alloc * 3 * NFLUX_ANGLES, &plasma_block_ptrs.derived_persist_angle_block, &PLASMA_WIN (win_derived_persist_angle), use_shared); + /* derived n_bf diagnostic counters — private (incremented during transport) */ + alloc_block_int (nalloc_phot, &plasma_block_ptrs.n_bf_in_block, NULL, FALSE); + alloc_block_int (nalloc_phot, &plasma_block_ptrs.n_bf_out_block, NULL, FALSE); + #ifdef MPI_ON plasma_block_ptrs.shared_memory_active = use_shared; #endif @@ -857,6 +863,9 @@ calloc_dyn_plasma (int nelem) plasmamain[n].derived.F_UV_ang_phi_persist = dbase + NFLUX_ANGLES; plasmamain[n].derived.F_UV_ang_r_persist = dbase + 2 * NFLUX_ANGLES; } + + plasmamain[n].derived.n_bf_in = plasma_block_ptrs.n_bf_in_block + n * nphot_total; + plasmamain[n].derived.n_bf_out = plasma_block_ptrs.n_bf_out_block + n * nphot_total; } /* Report memory breakdown: shared (one copy per node) vs private (per rank) vs base struct */ @@ -871,11 +880,12 @@ calloc_dyn_plasma (int nelem) * Shared derived: recomb(nions) + cool_rr_ion(nions) + lum_rr_ion(nions) + cool_dr_ion(nions) + inner_recomb(nions) = 5*nions * + persist_force(6*NFORCE_DIRECTIONS) + persist_angle(3*NFLUX_ANGLES) * Private est: ioniz(nions) + heat_ion(nions) + heat_inner_ion(nions) + inner_ioniz(n_inner) = 3*nions + n_inner - * Private derived: scatters(nions, int) + xscatters(nions, double) = nions*(4+8) */ + * Private derived: scatters(nions, int) + xscatters(nions, double) + n_bf_in(nphot, int) + n_bf_out(nphot, int) */ shared_bytes = (double) nelem_alloc *(sizeof (double) * (2.0 * nions + nlte_levels + 3.0 * nphot_total + 5.0 * nions + 6.0 * NXBANDS + 2.0 * (NXBANDS + 1) + 6.0 * NFORCE_DIRECTIONS + 3.0 * NFLUX_ANGLES) + sizeof (int) * NXBANDS); - private_bytes = (double) nelem_alloc *(sizeof (double) * (3.0 * nions + n_inner_tot + nions) + sizeof (int) * nions); + private_bytes = + (double) nelem_alloc *(sizeof (double) * (3.0 * nions + n_inner_tot + nions) + sizeof (int) * (nions + 2.0 * nphot_total)); double base_struct_bytes = (double) nelem_alloc * sizeof (plasma_dummy); Log diff --git a/source/janitor.c b/source/janitor.c index 3078a24fb..a72df34ba 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -161,6 +161,8 @@ free_plasma_grid (void) free_plasma_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_force_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.n_bf_in_block, FALSE); + free_plasma_block ((void **) &plasma_block_ptrs.n_bf_out_block, FALSE); } free (plasmamain); diff --git a/source/sirocco.h b/source/sirocco.h index d6e2071c8..f57597747 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -895,7 +895,7 @@ extern WindPtr wmain; /* Constants used in plasma sub-structs (moved out of the struct body) */ #define NFLUX_ANGLES 36 /**< The number of bins into which the directional flux is calculated */ -#define N_PHOT_PROC 500 +/* N_PHOT_PROC removed: n_bf_in/n_bf_out are now dynamically sized to nphot_total */ #define N_DMO_DT_DIRECTIONS 3 #define NFORCE_DIRECTIONS 4 @@ -1108,7 +1108,7 @@ typedef struct plasma_derived /* BF diagnostics */ double bf_simple_ionpool_in, bf_simple_ionpool_out; /**< Track net flow of energy into/from ionization pool */ - int n_bf_in[N_PHOT_PROC], n_bf_out[N_PHOT_PROC]; /**< Counters for bf excitations and de-excitations */ + int *n_bf_in, *n_bf_out; /**< Counters for bf excitations and de-excitations (nphot_total, contiguous block) */ /* Compton integral */ double comp_nujnu; /**< The integral of alpha(nu)nuj(nu) used to @@ -1304,6 +1304,10 @@ typedef struct plasma_blocks double *derived_persist_force_block; /**< NPLASMA * 6 * NFORCE_DIRECTIONS doubles */ double *derived_persist_angle_block; /**< NPLASMA * 3 * NFLUX_ANGLES doubles */ + /* derived n_bf diagnostic counters (private — written during transport) */ + int *n_bf_in_block; /**< NPLASMA * nphot_total ints */ + int *n_bf_out_block; /**< NPLASMA * nphot_total ints */ + #ifdef MPI_ON /* MPI shared memory windows for state/derived blocks */ MPI_Win win_density, win_partition, win_levden; diff --git a/source/windsave.c b/source/windsave.c index 1b4a41864..808608de5 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -136,6 +136,8 @@ in the plasma structure */ n += fwrite (plasmamain[m].derived.F_UV_ang_theta_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fwrite (plasmamain[m].derived.F_UV_ang_phi_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fwrite (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fwrite (plasmamain[m].derived.n_bf_in, sizeof (int), nphot_total, fptr); + n += fwrite (plasmamain[m].derived.n_bf_out, sizeof (int), nphot_total, fptr); } /* Now write out the macro atom info */ @@ -330,6 +332,8 @@ wind_read (char filename[]) n += fread (plasmamain[m].derived.F_UV_ang_theta_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fread (plasmamain[m].derived.F_UV_ang_phi_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fread (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); + n += fread (plasmamain[m].derived.n_bf_in, sizeof (int), nphot_total, fptr); + n += fread (plasmamain[m].derived.n_bf_out, sizeof (int), nphot_total, fptr); } From 5819f9d0b85c64ae3a455a279230829fa834f051 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 21 Mar 2026 16:19:15 -0500 Subject: [PATCH 07/33] Share wind struct (wmain) via MPI-3 shared memory Move wmain allocation to MPI_Win_allocate_shared so all ranks on the same node share a single copy of the wind geometry array (~25 MB savings/rank for a 300x300 grid). The reverb path-tracking fields (paths, line_paths) are moved out of wind_dummy into a separate per-rank wind_paths_main array since they are written during photon transport. Co-Authored-By: Claude Opus 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 19 ++++ source/gridwind.c | 55 +++++++++- source/janitor.c | 18 +++- source/paths.c | 119 +++++++++++---------- source/sirocco.h | 18 +++- source/sirocco_extern_init.c | 4 + source/tests/unit_test_model.c | 4 +- source/windsave.c | 20 +++- 8 files changed, 189 insertions(+), 68 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index b5f547827..bc3053293 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -350,3 +350,22 @@ approximately 2.3 KB per cell, yielding additional PSS savings of roughly ``2.3 * N * (R-1)/R`` KB. The savings scale linearly with NPLASMA: for a model with 80K cells and 29 ranks, this adds approximately 177 MB of per-rank savings. + +Shared wind structure +^^^^^^^^^^^^^^^^^^^^^ + +The wind geometry array ``wmain`` (type ``wind_dummy``, indexed by NDIM2) is +allocated via ``MPI_Win_allocate_shared`` in ``calloc_wind()`` so that all +ranks on the same node share a single copy. This is safe because ``wmain`` +is populated during initialization and is strictly read-only during photon +transport. + +The reverb path-tracking data (``paths`` and ``line_paths``) was moved out +of ``wind_dummy`` into a separate per-rank array ``wind_paths_main`` (type +``wind_paths_store``), because path histograms are accumulated during photon +transport and must remain private per rank. Code in ``paths.c`` accesses +these via ``wind_paths_main[cell_index]`` instead of ``wmain[cell_index]``. + +For a 300x300 grid (NDIM2 = 90,000, ``sizeof(wind_dummy)`` = 288 bytes), +this saves approximately ``90000 * 288 * (R-1)/R`` bytes, or about 25 MB +per rank with 29 ranks. diff --git a/source/gridwind.c b/source/gridwind.c index 085183b62..48ef866de 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -316,13 +316,42 @@ create_wind_and_plasma_cell_maps () int calloc_wind (int nelem) { + long alloc_size = (long) (nelem + 1) * sizeof (wind_dummy); +#ifdef MPI_ON if (wmain != NULL) { - free (wmain); + MPI_Win_free (&wmain_win); + wmain = NULL; } - wmain = (WindPtr) calloc (nelem + 1, sizeof (wind_dummy)); + if (np_mpi_global > 1) + { + MPI_Aint win_size; + int disp_unit; + void *base; + + if (node_rank == 0) + { + MPI_Win_allocate_shared (alloc_size, 1, MPI_INFO_NULL, node_comm, &base, &wmain_win); + memset (base, 0, alloc_size); + } + else + { + MPI_Win_allocate_shared (0, 1, MPI_INFO_NULL, node_comm, &base, &wmain_win); + MPI_Win_shared_query (wmain_win, 0, &win_size, &disp_unit, &base); + } + wmain = (WindPtr) base; + } + else +#endif + { + if (wmain != NULL) + { + free (wmain); + } + wmain = (WindPtr) calloc (nelem + 1, sizeof (wind_dummy)); + } if (wmain == NULL) { @@ -332,8 +361,26 @@ calloc_wind (int nelem) else { Log - ("Allocated %10d bytes for each of %5d elements of totaling %10.1f Mb\n", - sizeof (wind_dummy), nelem + 1, 1.e-6 * (nelem + 1) * sizeof (wind_dummy)); + ("Allocated %10d bytes for each of %5d elements of wind totaling %10.1f Mb (%s)\n", + sizeof (wind_dummy), nelem + 1, 1.e-6 * alloc_size, +#ifdef MPI_ON + (np_mpi_global > 1) ? "shared" : "private" +#else + "private" +#endif + ); + } + + /* Allocate per-rank wind paths storage (always private) */ + if (wind_paths_main != NULL) + { + free (wind_paths_main); + } + wind_paths_main = (wind_paths_store *) calloc (nelem + 1, sizeof (wind_paths_store)); + if (wind_paths_main == NULL) + { + Error ("There is a problem in allocating memory for wind_paths_main\n"); + Exit (0); } return (0); diff --git a/source/janitor.c b/source/janitor.c index a72df34ba..6f0be8fb4 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -104,11 +104,23 @@ free_wind_grid (void) for (n_wind = 0; n_wind < NDIM2; ++n_wind) { - free (wmain[n_wind].paths); - free (wmain[n_wind].line_paths); + free (wind_paths_main[n_wind].paths); + free (wind_paths_main[n_wind].line_paths); } + free (wind_paths_main); + wind_paths_main = NULL; - free (wmain); +#ifdef MPI_ON + if (np_mpi_global > 1) + { + MPI_Win_free (&wmain_win); + wmain = NULL; + } + else +#endif + { + free (wmain); + } } /**********************************************************/ diff --git a/source/paths.c b/source/paths.c index 7d6578805..7e3bbaf16 100644 --- a/source/paths.c +++ b/source/paths.c @@ -186,11 +186,11 @@ wind_paths_init (WindPtr wind) for (i = 0; i < geo.ndim2; i++) { //For each entry in the wind array - wind[i].paths = (Wind_Paths_Ptr) wind_paths_constructor (&wind[i]); - wind[i].line_paths = (Wind_Paths_Ptr *) calloc (sizeof (Wind_Paths_Ptr), geo.reverb_lines); + wind_paths_main[i].paths = (Wind_Paths_Ptr) wind_paths_constructor (&wind[i]); + wind_paths_main[i].line_paths = (Wind_Paths_Ptr *) calloc (sizeof (Wind_Paths_Ptr), geo.reverb_lines); for (j = 0; j < geo.reverb_lines; j++) { //For each line tracked on each cell - wind[i].line_paths[j] = (Wind_Paths_Ptr) wind_paths_constructor (&wind[i]); + wind_paths_main[i].line_paths[j] = (Wind_Paths_Ptr) wind_paths_constructor (&wind[i]); } } return (0); @@ -216,6 +216,7 @@ int line_paths_add_phot (WindPtr wind, PhotPtr pp, int *nres) { int i, j; + wind_paths_store *wpaths = &wind_paths_main[wind - wmain]; if (geo.reverb_disk == REV_DISK_IGNORE && pp->origin_orig == PTYPE_DISK) return (0); @@ -231,23 +232,23 @@ line_paths_add_phot (WindPtr wind, PhotPtr pp, int *nres) if (pp->path >= reverb_path_bin[j] && pp->path <= reverb_path_bin[j + 1]) { //If the photon's path lies in this bin's bounds, record it //printf("DEBUG: Added to line %d in cell %d - path %g weight %g\n",geo.reverb_line[i], wind->nwind, pp->path, pp->w); - wind->line_paths[i]->ad_path_flux[j] += pp->w; - wind->line_paths[i]->ai_path_num[j]++; + wpaths->line_paths[i]->ad_path_flux[j] += pp->w; + wpaths->line_paths[i]->ai_path_num[j]++; switch (pp->origin) { case PTYPE_STAR: case PTYPE_AGN: case PTYPE_BL: - wind->line_paths[i]->ad_path_flux_cent[j] += pp->w; - wind->line_paths[i]->ai_path_num_cent[j]++; + wpaths->line_paths[i]->ad_path_flux_cent[j] += pp->w; + wpaths->line_paths[i]->ai_path_num_cent[j]++; break; case PTYPE_DISK: - wind->line_paths[i]->ad_path_flux_disk[j] += pp->w; - wind->line_paths[i]->ai_path_num_disk[j]++; + wpaths->line_paths[i]->ad_path_flux_disk[j] += pp->w; + wpaths->line_paths[i]->ai_path_num_disk[j]++; break; default: - wind->line_paths[i]->ad_path_flux_wind[j] += pp->w; - wind->line_paths[i]->ai_path_num_wind[j]++; + wpaths->line_paths[i]->ad_path_flux_wind[j] += pp->w; + wpaths->line_paths[i]->ai_path_num_wind[j]++; break; } //Exit out of this loop @@ -277,6 +278,7 @@ int wind_paths_add_phot (WindPtr wind, PhotPtr pp) { int i; + wind_paths_store *wpaths = &wind_paths_main[wind - wmain]; if (geo.reverb_disk == REV_DISK_IGNORE && pp->origin_orig == PTYPE_DISK) return (0); @@ -284,24 +286,24 @@ wind_paths_add_phot (WindPtr wind, PhotPtr pp) { //For each bin if (pp->path >= reverb_path_bin[i] && pp->path <= reverb_path_bin[i + 1]) { //If the path falls within its bounds, add photon weight - wind->paths->ad_path_flux[i] += pp->w; - wind->paths->ai_path_num[i]++; + wpaths->paths->ad_path_flux[i] += pp->w; + wpaths->paths->ai_path_num[i]++; switch (pp->origin) { case PTYPE_STAR: case PTYPE_AGN: case PTYPE_BL: - wind->paths->ad_path_flux_cent[i] += pp->w; - wind->paths->ai_path_num_cent[i]++; + wpaths->paths->ad_path_flux_cent[i] += pp->w; + wpaths->paths->ai_path_num_cent[i]++; break; case PTYPE_DISK: - wind->paths->ad_path_flux_disk[i] += pp->w; - wind->paths->ai_path_num_disk[i]++; + wpaths->paths->ad_path_flux_disk[i] += pp->w; + wpaths->paths->ai_path_num_disk[i]++; break; default: - wind->paths->ad_path_flux_wind[i] += pp->w; - wind->paths->ai_path_num_wind[i]++; + wpaths->paths->ad_path_flux_wind[i] += pp->w; + wpaths->paths->ai_path_num_wind[i]++; break; } return (0); @@ -395,11 +397,12 @@ r_draw_from_path_histogram (Wind_Paths_Ptr PathPtr) int wind_paths_gen_phot (WindPtr wind, PhotPtr pp) { + wind_paths_store *wpaths = &wind_paths_main[wind - wmain]; if (geo.ioniz_or_extract == CYCLE_IONIZ) { simple_paths_gen_phot (pp); } - else if (wind->paths->i_num == 0) + else if (wpaths->paths->i_num == 0) { //If there's no path data registered in this cell, default to simple Error ("wind_paths_gen_phot: No path data in cell %d at r=%g, z=%g\n", wind->nwind, sqrt (wind->x[0] * wind->x[0] + wind->x[1] * wind->x[1]), wind->x[2]); @@ -407,7 +410,7 @@ wind_paths_gen_phot (WindPtr wind, PhotPtr pp) } else { //Otherwise, draw a path for the photon from the cell's histogram - pp->path = r_draw_from_path_histogram (wind->paths); + pp->path = r_draw_from_path_histogram (wpaths->paths); } return (0); } @@ -435,11 +438,12 @@ int line_paths_gen_phot (WindPtr wind, PhotPtr pp, int nres) { int i; + wind_paths_store *wpaths = &wind_paths_main[wind - wmain]; if (geo.ioniz_or_extract == CYCLE_IONIZ) { simple_paths_gen_phot (pp); } - else if (wind->paths->i_num == 0) + else if (wpaths->paths->i_num == 0) { //If there's no path data registered in this cell, default to simple //Error ("line_paths_gen_phot: No path data in cell %d at r=%g, z=%g\n", // wind->nwind, sqrt(wind->x[0]*wind->x[0] + wind->x[1]*wind->x[1]), wind->x[2]); @@ -447,7 +451,7 @@ line_paths_gen_phot (WindPtr wind, PhotPtr pp, int nres) } else if (nres < 0 || nres >= nlines || lin_ptr[nres]->macro_info == FALSE) { //If this line is invalid, continuum or non-matom then default to wind - pp->path = r_draw_from_path_histogram (wind->paths); + pp->path = r_draw_from_path_histogram (wpaths->paths); } else { //Iterate over array to see if this line is tracked. If so, use that @@ -457,22 +461,22 @@ line_paths_gen_phot (WindPtr wind, PhotPtr pp, int nres) { if (lin_ptr[nres]->where_in_list == geo.reverb_line[i]) { //Line identified using its position in nres as unique ID - if (wind->line_paths[i]->i_num > 0) + if (wpaths->line_paths[i]->i_num > 0) { //If there photons recorded in this histogram - pp->path = r_draw_from_path_histogram (wind->line_paths[i]); + pp->path = r_draw_from_path_histogram (wpaths->line_paths[i]); } else { //If there are no photons in this histogram, log and default //to using the wind path histogram. //Error("line_paths_gen_phot: No path data for line %d in cell %d at r=%g, z=%g\n", // wind->nwind, nres, sqrt(wind->x[0]*wind->x[0] + wind->x[1]*wind->x[1]), wind->x[2]); - pp->path = r_draw_from_path_histogram (wind->paths); + pp->path = r_draw_from_path_histogram (wpaths->paths); } return (0); } } //If the line isn't being tracked, default to wind - pp->path = r_draw_from_path_histogram (wind->paths); + pp->path = r_draw_from_path_histogram (wpaths->paths); } return (0); } @@ -546,10 +550,10 @@ wind_paths_evaluate (WindPtr wind) { //For each cell in the wind if (wind[i].inwind >= 0) { //If this is a wind cel;, evaluate each of the path histograms - wind_paths_evaluate_single (wind[i].paths); + wind_paths_evaluate_single (wind_paths_main[i].paths); for (j = 0; j < geo.reverb_lines; j++) { - wind_paths_evaluate_single (wind[i].line_paths[j]); + wind_paths_evaluate_single (wind_paths_main[i].line_paths[j]); } } } @@ -593,6 +597,7 @@ wind_paths_dump (WindPtr wind, int rank_global) FILE *fptr; char c_file[LINELENGTH]; int j, k; + wind_paths_store *wpaths = &wind_paths_main[wind - wmain]; //Setup file name and open the file sprintf (c_file, "%.100s.wind_paths_%d.%d.csv", files.root, wind->nwind, rank_global); @@ -614,15 +619,15 @@ wind_paths_dump (WindPtr wind, int rank_global) for (k = 0; k < geo.reverb_path_bins; k++) { //For each path bin, print the 'wind' weight fprintf (fptr, "%g, %g, %g, %g, %g", reverb_path_bin[k], - wind->paths->ad_path_flux[k], - wind->paths->ad_path_flux_cent[k], wind->paths->ad_path_flux_disk[k], wind->paths->ad_path_flux_wind[k]); + wpaths->paths->ad_path_flux[k], + wpaths->paths->ad_path_flux_cent[k], wpaths->paths->ad_path_flux_disk[k], wpaths->paths->ad_path_flux_wind[k]); for (j = 0; j < geo.reverb_lines; j++) { //For each tracked line, print the weight in this bin fprintf (fptr, ", %g, %g, %g, %g", - wind->line_paths[j]->ad_path_flux[k], - wind->line_paths[j]->ad_path_flux_cent[k], - wind->line_paths[j]->ad_path_flux_disk[k], wind->line_paths[j]->ad_path_flux_wind[k]); + wpaths->line_paths[j]->ad_path_flux[k], + wpaths->line_paths[j]->ad_path_flux_cent[k], + wpaths->line_paths[j]->ad_path_flux_disk[k], wpaths->line_paths[j]->ad_path_flux_wind[k]); } fprintf (fptr, "\n"); } @@ -897,7 +902,7 @@ wind_paths_output_vtk (WindPtr wind, int ndom) { for (k = 0; k < geo.reverb_angle_bins; k++) { - fprintf (fptr, "%d\n", wind[n].paths->i_num); + fprintf (fptr, "%d\n", wind_paths_main[n].paths->i_num); } } } @@ -911,8 +916,8 @@ wind_paths_output_vtk (WindPtr wind, int ndom) wind_ij_to_n (ndom, i, j, &n); for (k = 0; k < geo.reverb_angle_bins; k++) { - fprintf (fptr, "%d\n", wind[n].paths->i_num); - fprintf (fptr, "%d\n", wind[n].paths->i_num); + fprintf (fptr, "%d\n", wind_paths_main[n].paths->i_num); + fprintf (fptr, "%d\n", wind_paths_main[n].paths->i_num); } } } @@ -930,9 +935,9 @@ wind_paths_output_vtk (WindPtr wind, int ndom) { for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { - r_err = sqrt ((double) wind[n].paths->i_num) / (double) wind[n].paths->i_num; + r_err = sqrt ((double) wind_paths_main[n].paths->i_num) / (double) wind_paths_main[n].paths->i_num; fprintf (fptr, "%g\n", r_err); } else @@ -952,9 +957,9 @@ wind_paths_output_vtk (WindPtr wind, int ndom) wind_ij_to_n (ndom, i, j, &n); for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { - r_err = sqrt ((double) wind[n].paths->i_num) / (double) wind[n].paths->i_num; + r_err = sqrt ((double) wind_paths_main[n].paths->i_num) / (double) wind_paths_main[n].paths->i_num; fprintf (fptr, "%g\n", r_err); fprintf (fptr, "%g\n", r_err); } @@ -980,14 +985,14 @@ wind_paths_output_vtk (WindPtr wind, int ndom) { for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { double f_diff; - f_diff = wind[n].paths->d_path; + f_diff = wind_paths_main[n].paths->d_path; f_diff -= (sqrt (wind[n].xcen[0] * wind[n].xcen[0] + wind[n].xcen[1] * wind[n].xcen[1] + wind[n].xcen[2] * wind[n].xcen[2]) - geo.rstar); f_diff = fabs (f_diff); - f_diff /= wind[n].paths->d_path; + f_diff /= wind_paths_main[n].paths->d_path; fprintf (fptr, "%g\n", f_diff); } @@ -1008,14 +1013,14 @@ wind_paths_output_vtk (WindPtr wind, int ndom) wind_ij_to_n (ndom, i, j, &n); for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { double f_diff; - f_diff = wind[n].paths->d_path; + f_diff = wind_paths_main[n].paths->d_path; f_diff -= (sqrt (wind[n].xcen[0] * wind[n].xcen[0] + wind[n].xcen[1] * wind[n].xcen[1] + wind[n].xcen[2] * wind[n].xcen[2]) - geo.rstar); f_diff = fabs (f_diff); - f_diff /= wind[n].paths->d_path; + f_diff /= wind_paths_main[n].paths->d_path; fprintf (fptr, "%g\n", f_diff); fprintf (fptr, "%g\n", f_diff); @@ -1041,9 +1046,9 @@ wind_paths_output_vtk (WindPtr wind, int ndom) { for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { - fprintf (fptr, "%g\n", wind[n].paths->d_path); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path); } else { @@ -1062,10 +1067,10 @@ wind_paths_output_vtk (WindPtr wind, int ndom) wind_ij_to_n (ndom, i, j, &n); for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { - fprintf (fptr, "%g\n", wind[n].paths->d_path); - fprintf (fptr, "%g\n", wind[n].paths->d_path); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path); } else { @@ -1095,13 +1100,13 @@ wind_paths_output_vtk (WindPtr wind, int ndom) for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { r_azi = ((double) k + 0.5) * (PI / (double) geo.reverb_angle_bins); p_test->x[0] = wind[n].xcen[0] * sin (r_inc) * cos (r_azi); p_test->x[1] = wind[n].xcen[0] * sin (r_inc) * sin (r_azi); p_test->x[2] = wind[n].xcen[0] * cos (r_inc); - fprintf (fptr, "%g\n", wind[n].paths->d_path + delay_to_observer (p_test)); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path + delay_to_observer (p_test)); } else { @@ -1120,15 +1125,15 @@ wind_paths_output_vtk (WindPtr wind, int ndom) wind_ij_to_n (ndom, i, j, &n); for (k = 0; k < geo.reverb_angle_bins; k++) { - if (wind[n].paths->i_num > 0) + if (wind_paths_main[n].paths->i_num > 0) { r_azi = ((double) k + 0.5) * (PI / (double) geo.reverb_angle_bins); p_test->x[0] = wind[n].xcen[0] * cos (r_azi); p_test->x[1] = wind[n].xcen[0] * sin (r_azi); p_test->x[2] = wind[n].xcen[2]; - fprintf (fptr, "%g\n", wind[n].paths->d_path + delay_to_observer (p_test)); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path + delay_to_observer (p_test)); p_test->x[2] = -wind[n].xcen[2]; - fprintf (fptr, "%g\n", wind[n].paths->d_path + delay_to_observer (p_test)); + fprintf (fptr, "%g\n", wind_paths_main[n].paths->d_path + delay_to_observer (p_test)); } else { diff --git a/source/sirocco.h b/source/sirocco.h index f57597747..662bc36b0 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -869,12 +869,28 @@ typedef struct wind { W_IN_DISK = -5, W_IN_STAR = -4, W_IGNORE = -2, W_NOT_INWIND = -1, W_ALL_INWIND = 0, W_PART_INWIND = 1, W_NOT_ASSIGNED = -999 } inwind; /**< Basic information on the nature of a particular cell. */ - Wind_Paths_Ptr paths, *line_paths; /**< Path data struct for each cell */ } wind_dummy, *WindPtr; extern WindPtr wmain; +#ifdef MPI_ON +extern MPI_Win wmain_win; /**< MPI shared memory window for wmain */ +#endif + +/** + * Per-cell reverb path data, stored separately from wind_dummy so that + * wmain can be placed in MPI-3 shared memory (paths are written during + * transport and must remain private per rank). + */ +typedef struct wind_paths_store +{ + Wind_Paths_Ptr paths; /**< Continuum path histogram */ + Wind_Paths_Ptr *line_paths; /**< Per-line path histograms */ +} wind_paths_store; + +extern wind_paths_store *wind_paths_main; + /*****************************PLASMA STRUCTURE**************************/ /** Plasma is a structure that contains information about the properties of the * plasma in regions of the geometry that are actually included in the wind. diff --git a/source/sirocco_extern_init.c b/source/sirocco_extern_init.c index b4dcbf425..8c417c268 100644 --- a/source/sirocco_extern_init.c +++ b/source/sirocco_extern_init.c @@ -78,6 +78,10 @@ struct xdisk disk, qdisk; /**< disk defines zones in the disk which in a speci struct blmodel blmod; WindPtr wmain; +#ifdef MPI_ON +MPI_Win wmain_win; +#endif +wind_paths_store *wind_paths_main; PlasmaPtr plasmamain; diff --git a/source/tests/unit_test_model.c b/source/tests/unit_test_model.c index 1174e21a9..e086f80d2 100644 --- a/source/tests/unit_test_model.c +++ b/source/tests/unit_test_model.c @@ -126,8 +126,8 @@ cleanup_model (const char *root_name) for (int n_wind = 0; n_wind < NDIM2; ++n_wind) { - free_and_null ((void **) &wmain[n_wind].paths); - free_and_null ((void **) &wmain[n_wind].line_paths); + free_and_null ((void **) &wind_paths_main[n_wind].paths); + free_and_null ((void **) &wind_paths_main[n_wind].line_paths); } free_and_null ((void **) &wmain); diff --git a/source/windsave.c b/source/windsave.c index 808608de5..c82034566 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -273,7 +273,25 @@ wind_read (char filename[]) } calloc_wind (NDIM2); - n += fread (wmain, sizeof (wind_dummy), NDIM2, fptr); +#ifdef MPI_ON + if (np_mpi_global > 1) + { + if (node_rank == 0) + { + n += fread (wmain, sizeof (wind_dummy), NDIM2, fptr); + } + else + { + /* Skip past the wind data in the file without reading into shared memory */ + fseek (fptr, (long) NDIM2 * sizeof (wind_dummy), SEEK_CUR); + } + MPI_Barrier (node_comm); + } + else +#endif + { + n += fread (wmain, sizeof (wind_dummy), NDIM2, fptr); + } /* Read the disk and qdisk structures */ From 9362f1f32e71e0de319cd4bcb4adbb454891324c Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 21 Mar 2026 18:33:03 -0500 Subject: [PATCH 08/33] Dynamically size cell_spec_flux with -cell_spec_dim flag cell_spec_flux was a fixed 1000-element array in plasma_estimators, consuming ~98 MB/rank for the big model (12,271 cells). Convert to a dynamically allocated pointer with runtime sizing via geo.nbins_in_cell_spec (default 100, max 1000). Users can restore original behavior with -cell_spec_dim 1000 on the command line. geo.cell_freq (frequency bin boundaries) also converted from fixed array to dynamic allocation in bands_init(). Both are properly freed on exit. cell_spec_flux uses a private contiguous block (cell_spec_flux_block) since it is an estimator accumulated during transport. Backward compatibility: geo.cell_freq pointer nulled after fread in wind_read(); nbins_in_cell_spec validated after reading old windsave files. Command-line -cell_spec_dim overrides windsave values on restart. Saves ~88 MB/rank at default (100 bins) for 12K-cell models. Co-Authored-By: Claude Opus 4.6 --- source/bands.c | 8 ++++++-- source/communicate_plasma.c | 20 ++++++++++---------- source/estimators_simple.c | 10 +++++----- source/gridwind.c | 9 ++++++++- source/janitor.c | 6 ++++++ source/parse.c | 16 ++++++++++++++++ source/setup.c | 1 + source/sirocco.c | 25 +++++++++++++++++++++++++ source/sirocco.h | 10 +++++++--- source/wind_updates2d.c | 2 +- source/windsave.c | 5 +++++ source/windsave2fits.c | 18 +++++++++--------- source/windsave2table_sub.c | 33 +++++++++------------------------ 13 files changed, 108 insertions(+), 55 deletions(-) diff --git a/source/bands.c b/source/bands.c index 55f7f3d58..cb0c0bdfb 100644 --- a/source/bands.c +++ b/source/bands.c @@ -607,9 +607,13 @@ bands_init (imode, band) /* Now define the freqquency boundaries for the cell spectra */ geo.cell_log_freq_min = log10 (band->f1[0]); geo.cell_log_freq_max = log10 (band->f2[band->nbands - 1]); - geo.cell_delta_lfreq = (geo.cell_log_freq_max - geo.cell_log_freq_min) / NBINS_IN_CELL_SPEC; + geo.cell_delta_lfreq = (geo.cell_log_freq_max - geo.cell_log_freq_min) / geo.nbins_in_cell_spec; - for (ii = 0; ii <= NBINS_IN_CELL_SPEC; ii++) + if (geo.cell_freq != NULL) + free (geo.cell_freq); + geo.cell_freq = calloc (geo.nbins_in_cell_spec + 1, sizeof (double)); + + for (ii = 0; ii <= geo.nbins_in_cell_spec; ii++) { geo.cell_freq[ii] = pow (10., (geo.cell_log_freq_min + ii * geo.cell_delta_lfreq)); } diff --git a/source/communicate_plasma.c b/source/communicate_plasma.c index bf73d0d7d..7a311f7c6 100644 --- a/source/communicate_plasma.c +++ b/source/communicate_plasma.c @@ -59,7 +59,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + nions + 2 * NXBANDS + 2 * nphot_total); const int num_doubles = n_cells_max * (N_BASIC_DOUBLES + 11 * nions + nlte_levels + 2 * nphot_total + n_inner_tot + - 11 * NXBANDS + NBINS_IN_CELL_SPEC + 6 * NFLUX_ANGLES + + 11 * NXBANDS + geo.nbins_in_cell_spec + 6 * NFLUX_ANGLES + N_DMO_DT_DIRECTIONS + 12 * NFORCE_DIRECTIONS); @@ -162,7 +162,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Pack (cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->state.exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->state.exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); - MPI_Pack (cell->est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); + MPI_Pack (cell->est.cell_spec_flux, geo.nbins_in_cell_spec, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); MPI_Pack (cell->est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, comm_buffer_size, &position, MPI_COMM_WORLD); @@ -324,7 +324,7 @@ broadcast_plasma_grid (const int n_start, const int n_stop, const int n_cells_ra MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->state.exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.cell_spec_flux, geo.nbins_in_cell_spec, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, comm_buffer_size, &position, cell->est.F_Xray, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); @@ -635,7 +635,7 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra const int num_ints = 1 + n_cells_max * (N_BASIC_INTS + nphot_total + 2 * NXBANDS + 2 * nphot_total + nions); const int num_doubles = n_cells_max * (N_BASIC_DOUBLES + 1 * 3 + 9 * 4 + 6 * NFLUX_ANGLES + 3 * NFORCE_DIRECTIONS + 9 * nions + 1 * nlte_levels + - 3 * nphot_total + 1 * n_inner_tot + 9 * NXBANDS + 1 * NBINS_IN_CELL_SPEC); + 3 * nphot_total + 1 * n_inner_tot + 9 * NXBANDS + 1 * geo.nbins_in_cell_spec); const int size_of_comm_buffer = calculate_comm_buffer_size (num_ints, num_doubles); char *const comm_buffer = malloc (size_of_comm_buffer); @@ -735,7 +735,7 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_Pack (plasmamain[n_plasma].state.pl_log_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (plasmamain[n_plasma].state.exp_temp, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (plasmamain[n_plasma].state.exp_w, NXBANDS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); - MPI_Pack (plasmamain[n_plasma].est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, + MPI_Pack (plasmamain[n_plasma].est.cell_spec_flux, geo.nbins_in_cell_spec, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); MPI_Pack (plasmamain[n_plasma].est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, comm_buffer, size_of_comm_buffer, &position, MPI_COMM_WORLD); @@ -927,8 +927,8 @@ broadcast_updated_plasma_properties (const int n_start_rank, const int n_stop_ra MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.pl_log_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.exp_temp, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].state.exp_w, NXBANDS, MPI_DOUBLE, MPI_COMM_WORLD); - MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.cell_spec_flux, NBINS_IN_CELL_SPEC, MPI_DOUBLE, - MPI_COMM_WORLD); + MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.cell_spec_flux, geo.nbins_in_cell_spec, + MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_vis, NFORCE_DIRECTIONS, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Unpack (comm_buffer, size_of_comm_buffer, &position, plasmamain[n_plasma].est.F_UV, NFORCE_DIRECTIONS, MPI_DOUBLE, @@ -1368,12 +1368,12 @@ reduce_simple_estimators (void) if (geo.ioniz_or_extract == CYCLE_IONIZ) { - size_of_commbuffer = NPLASMA * NBINS_IN_CELL_SPEC; + size_of_commbuffer = NPLASMA * geo.nbins_in_cell_spec; redhelper = calloc (sizeof (double), size_of_commbuffer); redhelper2 = calloc (sizeof (double), size_of_commbuffer); - for (mpi_i = 0; mpi_i < NBINS_IN_CELL_SPEC; mpi_i++) + for (mpi_i = 0; mpi_i < geo.nbins_in_cell_spec; mpi_i++) { for (mpi_j = 0; mpi_j < NPLASMA; mpi_j++) { @@ -1384,7 +1384,7 @@ reduce_simple_estimators (void) MPI_Allreduce (redhelper, redhelper2, size_of_commbuffer, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for (mpi_i = 0; mpi_i < NBINS_IN_CELL_SPEC; mpi_i++) + for (mpi_i = 0; mpi_i < geo.nbins_in_cell_spec; mpi_i++) { for (mpi_j = 0; mpi_j < NPLASMA; mpi_j++) { diff --git a/source/estimators_simple.c b/source/estimators_simple.c index 362f7937d..5783b853c 100644 --- a/source/estimators_simple.c +++ b/source/estimators_simple.c @@ -148,9 +148,9 @@ update_banded_estimators (PlasmaPtr xplasma, PhotPtr p, double ds, double w_ave, i = (log_freq - geo.cell_log_freq_min) / geo.cell_delta_lfreq; if (i < 0) i = 0; - if (i > NBINS_IN_CELL_SPEC - 1) + if (i > geo.nbins_in_cell_spec - 1) { - i = NBINS_IN_CELL_SPEC - 1; + i = geo.nbins_in_cell_spec - 1; } xplasma->est.cell_spec_flux[i] += w_ave * ds; @@ -647,10 +647,10 @@ normalise_simple_estimators (PlasmaPtr xplasma) xplasma->est.xsd_freq[i] = 0; xplasma->est.xj[i] = 0; xplasma->est.nxtot[i] = 0; - xplasma->est.fmin[i] = geo.cell_freq[NBINS_IN_CELL_SPEC]; + xplasma->est.fmin[i] = geo.cell_freq[geo.nbins_in_cell_spec]; xplasma->est.fmax[i] = geo.cell_freq[0]; - while (geo.cell_freq[j] < xplasma->state.f2[i] && j < NBINS_IN_CELL_SPEC) + while (geo.cell_freq[j] < xplasma->state.f2[i] && j < geo.nbins_in_cell_spec) { double ave_freq; if (xplasma->est.cell_spec_flux[j] > 0) @@ -704,7 +704,7 @@ normalise_simple_estimators (PlasmaPtr xplasma) /* Normalize the cell spectra to J_nu - erg/s/cm^3/Sr/Hz */ - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) + for (i = 0; i < geo.nbins_in_cell_spec; i++) { freq_min = geo.cell_log_freq_min + (i) * geo.cell_delta_lfreq; freq_max = freq_min + geo.cell_delta_lfreq; diff --git a/source/gridwind.c b/source/gridwind.c index 48ef866de..2d2dab08c 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -798,6 +798,7 @@ calloc_dyn_plasma (int nelem) free_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, &PLASMA_WIN (win_state_spec_mod_type), was_shared); free_block ((void **) &plasma_block_ptrs.derived_persist_force_block, &PLASMA_WIN (win_derived_persist_force), was_shared); free_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, &PLASMA_WIN (win_derived_persist_angle), was_shared); + free_block ((void **) &plasma_block_ptrs.cell_spec_flux_block, NULL, FALSE); free_block ((void **) &plasma_block_ptrs.n_bf_in_block, NULL, FALSE); free_block ((void **) &plasma_block_ptrs.n_bf_out_block, NULL, FALSE); } @@ -846,6 +847,9 @@ calloc_dyn_plasma (int nelem) alloc_block_double ((long) nelem_alloc * 3 * NFLUX_ANGLES, &plasma_block_ptrs.derived_persist_angle_block, &PLASMA_WIN (win_derived_persist_angle), use_shared); + /* est cell_spec_flux — private (accumulated during transport) */ + alloc_block_double ((long) nelem_alloc * geo.nbins_in_cell_spec, &plasma_block_ptrs.cell_spec_flux_block, NULL, FALSE); + /* derived n_bf diagnostic counters — private (incremented during transport) */ alloc_block_int (nalloc_phot, &plasma_block_ptrs.n_bf_in_block, NULL, FALSE); alloc_block_int (nalloc_phot, &plasma_block_ptrs.n_bf_out_block, NULL, FALSE); @@ -911,6 +915,8 @@ calloc_dyn_plasma (int nelem) plasmamain[n].derived.F_UV_ang_r_persist = dbase + 2 * NFLUX_ANGLES; } + plasmamain[n].est.cell_spec_flux = plasma_block_ptrs.cell_spec_flux_block + n * geo.nbins_in_cell_spec; + plasmamain[n].derived.n_bf_in = plasma_block_ptrs.n_bf_in_block + n * nphot_total; plasmamain[n].derived.n_bf_out = plasma_block_ptrs.n_bf_out_block + n * nphot_total; } @@ -932,7 +938,8 @@ calloc_dyn_plasma (int nelem) + 6.0 * NXBANDS + 2.0 * (NXBANDS + 1) + 6.0 * NFORCE_DIRECTIONS + 3.0 * NFLUX_ANGLES) + sizeof (int) * NXBANDS); private_bytes = - (double) nelem_alloc *(sizeof (double) * (3.0 * nions + n_inner_tot + nions) + sizeof (int) * (nions + 2.0 * nphot_total)); + (double) nelem_alloc *(sizeof (double) * (3.0 * nions + n_inner_tot + nions + geo.nbins_in_cell_spec) + + sizeof (int) * (nions + 2.0 * nphot_total)); double base_struct_bytes = (double) nelem_alloc * sizeof (plasma_dummy); Log diff --git a/source/janitor.c b/source/janitor.c index 6f0be8fb4..a4d222776 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -173,6 +173,7 @@ free_plasma_grid (void) free_plasma_block ((void **) &plasma_block_ptrs.state_spec_mod_type_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_force_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.derived_persist_angle_block, is_shared); + free_plasma_block ((void **) &plasma_block_ptrs.cell_spec_flux_block, FALSE); free_plasma_block ((void **) &plasma_block_ptrs.n_bf_in_block, FALSE); free_plasma_block ((void **) &plasma_block_ptrs.n_bf_out_block, FALSE); } @@ -328,4 +329,9 @@ clean_on_exit (void) free_photons (); free_spectra (); free_atomic_data (); + if (geo.cell_freq != NULL) + { + free (geo.cell_freq); + geo.cell_freq = NULL; + } } diff --git a/source/parse.c b/source/parse.c index 4876e8027..eb04ade40 100644 --- a/source/parse.c +++ b/source/parse.c @@ -237,6 +237,22 @@ parse_command_line (int argc, char *argv[]) modes.quit_after_inputs = 1; j = i; } + else if (strcmp (argv[i], "-cell_spec_dim") == 0) + { + if (sscanf (argv[i + 1], "%d", &geo.nbins_in_cell_spec) != 1) + { + Error ("parse_command_line: could not parse cell_spec_dim\n"); + exit (1); + } + if (geo.nbins_in_cell_spec < 1 || geo.nbins_in_cell_spec > NBINS_IN_CELL_SPEC) + { + Error ("parse_command_line: cell_spec_dim must be 1-%d\n", NBINS_IN_CELL_SPEC); + exit (1); + } + Log ("parse_command_line: setting cell_spec_dim to %d\n", geo.nbins_in_cell_spec); + i++; + j = i; + } else if (strcmp (argv[i], "-p") == 0) { Log ("Logarithmic photon stepping enabled\n"); diff --git a/source/setup.c b/source/setup.c index 5b142f085..7e5f9cf24 100644 --- a/source/setup.c +++ b/source/setup.c @@ -93,6 +93,7 @@ init_geo () geo.run_type = 0; // Not a restart of a previous run + geo.nbins_in_cell_spec = 100; // Default number of bins for cell spectra (max NBINS_IN_CELL_SPEC) geo.star_ion_spectype = geo.star_spectype = geo.disk_ion_spectype = geo.disk_spectype = geo.bl_ion_spectype = geo.bl_spectype = SPECTYPE_BB; diff --git a/source/sirocco.c b/source/sirocco.c index 333108d45..ec6bdba41 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -164,6 +164,9 @@ main (int argc, char *argv[]) restart_stat = parse_command_line (argc, argv); + /* Save the command-line cell_spec_dim setting (if specified) so it survives wind_read overwriting geo */ + int cmd_nbins_in_cell_spec = geo.nbins_in_cell_spec; + /* If the restart flag has been set, we check to see if a windsave file exists. If it doues we will we will restart from that point. If the windsave file does not exist we will start from scratch */ @@ -218,6 +221,17 @@ main (int argc, char *argv[]) } //OLD w = wmain; + /* Restore command-line cell_spec_dim or validate the value read from windsave */ + if (cmd_nbins_in_cell_spec > 0) + { + geo.nbins_in_cell_spec = cmd_nbins_in_cell_spec; + } + if (geo.nbins_in_cell_spec < 1 || geo.nbins_in_cell_spec > NBINS_IN_CELL_SPEC) + { + Log ("Windsave had invalid nbins_in_cell_spec=%d, resetting to 100\n", geo.nbins_in_cell_spec); + geo.nbins_in_cell_spec = 100; + } + geo.run_type = RUN_TYPE_RESTART; xsignal (files.root, "%-20s Read %s\n", "COMMENT", files.old_windsave); @@ -283,6 +297,17 @@ main (int argc, char *argv[]) Exit (0); } + /* Restore command-line cell_spec_dim or validate the value read from windsave */ + if (cmd_nbins_in_cell_spec > 0) + { + geo.nbins_in_cell_spec = cmd_nbins_in_cell_spec; + } + if (geo.nbins_in_cell_spec < 1 || geo.nbins_in_cell_spec > NBINS_IN_CELL_SPEC) + { + Log ("Windsave had invalid nbins_in_cell_spec=%d, resetting to 100\n", geo.nbins_in_cell_spec); + geo.nbins_in_cell_spec = 100; + } + geo.run_type = RUN_TYPE_PREVIOUS; //OLD w = wmain; diff --git a/source/sirocco.h b/source/sirocco.h index 662bc36b0..51ef4af48 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -578,11 +578,12 @@ struct geometry int nxfreq; /**< the number of frequency intervals actually used */ double xfreq[NXBANDS + 1]; /**< the frequency boundaries for the coarse spectra */ -#define NBINS_IN_CELL_SPEC 1000 /**< The number of bins in the cell spectra */ +#define NBINS_IN_CELL_SPEC 1000 /**< The maximum number of bins in the cell spectra */ + int nbins_in_cell_spec; /**< Runtime number of bins in cell spectra (default 100, max NBINS_IN_CELL_SPEC) */ double cell_log_freq_min, cell_log_freq_max, cell_delta_lfreq; /**< Parameters defining freqency intervals for cell spectra. These are defined as logarithmic frequency intervals */ - double cell_freq[NBINS_IN_CELL_SPEC +1]; + double *cell_freq; /**< Frequency bin boundaries for cell spectra (nbins_in_cell_spec+1 elements) */ /* The next set pf variables assign a SPECTYPE (see above) for @@ -1041,7 +1042,7 @@ typedef struct plasma_estimators double F_UV_ang_r[NFLUX_ANGLES]; /* Cell spectrum (accumulated during ionization cycles) */ - double cell_spec_flux[NBINS_IN_CELL_SPEC]; /**< The array where the cell spectra are accumulated. */ + double *cell_spec_flux; /**< The array where the cell spectra are accumulated (nbins_in_cell_spec elements). */ /* Ionization estimators (dynamically allocated) */ double *ioniz; /**< Number of ionizations for each ion */ @@ -1320,6 +1321,9 @@ typedef struct plasma_blocks double *derived_persist_force_block; /**< NPLASMA * 6 * NFORCE_DIRECTIONS doubles */ double *derived_persist_angle_block; /**< NPLASMA * 3 * NFLUX_ANGLES doubles */ + /* est cell_spec_flux block (private — accumulated during transport) */ + double *cell_spec_flux_block; /**< NPLASMA * nbins_in_cell_spec doubles */ + /* derived n_bf diagnostic counters (private — written during transport) */ int *n_bf_in_block; /**< NPLASMA * nphot_total ints */ int *n_bf_out_block; /**< NPLASMA * nphot_total ints */ diff --git a/source/wind_updates2d.c b/source/wind_updates2d.c index 892edde8c..5dbbac2a3 100644 --- a/source/wind_updates2d.c +++ b/source/wind_updates2d.c @@ -654,7 +654,7 @@ init_plasma_rad_properties (void) plasmamain[i].est.fmin[j] = 0.0; plasmamain[i].est.fmax[j] = 0.0; } - for (j = 0; j < NBINS_IN_CELL_SPEC; ++j) + for (j = 0; j < geo.nbins_in_cell_spec; ++j) { plasmamain[i].est.cell_spec_flux[j] = 0.0; } diff --git a/source/windsave.c b/source/windsave.c index c82034566..96db525f7 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -235,6 +235,11 @@ wind_read (char filename[]) n += fread (&geo, sizeof (geo), 1, fptr); + /* Null out pointer fields that were serialized as raw bytes — they will be + * re-allocated when bands_init() runs. Without this, the stale pointer + * from the previous process could cause a double-free or corruption. */ + geo.cell_freq = NULL; + /* Read the atomic data file. This is necessary to do here in order to establish the * values for the dimensionality of some of the variable length structures, associated * with macro atoms, especially but likely to be a good idea ovrall diff --git a/source/windsave2fits.c b/source/windsave2fits.c index aa00c3e01..3b6bc7a8c 100644 --- a/source/windsave2fits.c +++ b/source/windsave2fits.c @@ -433,12 +433,12 @@ make_spec (char *inroot) printf ("Hello World %s \n", inroot); printf ("Plasma %d \n", NPLASMA); - printf ("NBINS in spec %d \n", NBINS_IN_CELL_SPEC); + printf ("NBINS in spec %d \n", geo.nbins_in_cell_spec); Spectra spectra; spectra.num_spectra = NPLASMA; - spectra.num_wavelengths = NBINS_IN_CELL_SPEC; + spectra.num_wavelengths = geo.nbins_in_cell_spec; spectra.data = calloc (spectra.num_spectra, sizeof (float *)); for (int i = 0; i < spectra.num_spectra; i++) @@ -471,30 +471,30 @@ make_spec (char *inroot) Spectra freq; freq.num_spectra = 1; - freq.num_wavelengths = NBINS_IN_CELL_SPEC; + freq.num_wavelengths = geo.nbins_in_cell_spec; freq.data = calloc (freq.num_spectra, sizeof (float *)); freq.data[0] = calloc (freq.num_wavelengths, sizeof (float)); - for (int i = 0; i < NBINS_IN_CELL_SPEC; i++) + for (int i = 0; i < geo.nbins_in_cell_spec; i++) { freq.data[0][i] = (float) pow (10., geo.cell_log_freq_min + i * geo.cell_delta_lfreq); } - float *image_data2 = prepare_image_data (freq.data, NBINS_IN_CELL_SPEC, 1); + float *image_data2 = prepare_image_data (freq.data, geo.nbins_in_cell_spec, 1); /* double freq[2000][1]; int i; - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) + for (i = 0; i < geo.nbins_in_cell_spec; i++) { freq[i][0] = (float) pow (10., geo.cell_log_freq_min + i * geo.cell_delta_lfreq); } - float *image_data2 = prepare_image_data (freq, NBINS_IN_CELL_SPEC, 1); + float *image_data2 = prepare_image_data (freq, geo.nbins_in_cell_spec, 1); */ - // status = write_image_extension (fptr, image_data2, NBINS_IN_CELL_SPEC, 1, "nu"); - status = write_1d_image_extension (fptr, image_data2, NBINS_IN_CELL_SPEC, "nu"); + // status = write_image_extension (fptr, image_data2, geo.nbins_in_cell_spec, 1, "nu"); + status = write_1d_image_extension (fptr, image_data2, geo.nbins_in_cell_spec, "nu"); /* Elimainate this for now diff --git a/source/windsave2table_sub.c b/source/windsave2table_sub.c index 5f9234929..a3aa67267 100644 --- a/source/windsave2table_sub.c +++ b/source/windsave2table_sub.c @@ -2024,34 +2024,22 @@ create_detailed_cell_spec_table (int ncell, char rootname[]) FILE *fptr; char filename[132]; - double freq[NBINS_IN_CELL_SPEC]; - double flux[NBINS_IN_CELL_SPEC]; int i, nplasma; printf ("%e %e\n", geo.cell_log_freq_min, geo.cell_delta_lfreq); sprintf (filename, "%s.xspec.%d.txt", rootname, ncell); - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) - { - freq[i] = pow (10., geo.cell_log_freq_min + i * geo.cell_delta_lfreq); - } - nplasma = wmain[ncell].nplasma; - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) - { - flux[i] = plasmamain[nplasma].est.cell_spec_flux[i]; - } - - fptr = fopen (filename, "w"); fprintf (fptr, "Freq. Flux\n"); - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) + for (i = 0; i < geo.nbins_in_cell_spec; i++) { - fprintf (fptr, "%10.3e %10.3e\n", freq[i], flux[i]); + double freq = pow (10., geo.cell_log_freq_min + i * geo.cell_delta_lfreq); + fprintf (fptr, "%10.3e %10.3e\n", freq, plasmamain[nplasma].est.cell_spec_flux[i]); } @@ -2101,7 +2089,7 @@ create_big_detailed_spec_table (int ndom, char *rootname) FILE *fptr; char filename[132]; - double freq[NBINS_IN_CELL_SPEC]; + double *freq; int nstart, nstop; /* Identify the range of wind cells for this domain */ @@ -2144,7 +2132,8 @@ create_big_detailed_spec_table (int ndom, char *rootname) /* Calculate the frequencies */ - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) + freq = calloc (geo.nbins_in_cell_spec, sizeof (double)); + for (i = 0; i < geo.nbins_in_cell_spec; i++) { freq[i] = pow (10., geo.cell_log_freq_min + i * geo.cell_delta_lfreq); } @@ -2176,7 +2165,7 @@ create_big_detailed_spec_table (int ndom, char *rootname) } fprintf (fptr, "\n"); - for (i = 0; i < NBINS_IN_CELL_SPEC; i++) + for (i = 0; i < geo.nbins_in_cell_spec; i++) { fprintf (fptr, "%10.3e ", freq[i]); @@ -2195,11 +2184,7 @@ create_big_detailed_spec_table (int ndom, char *rootname) nstop = nstart + MAX_IN_TABLE; } - return (0); - - - - - + free (freq); + return (0); } From c1f4f6cfcdd16a0df073e4a280084ed9c206b1d2 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sun, 22 Mar 2026 15:23:37 -0500 Subject: [PATCH 09/33] Share matom_matrix via MPI-3 shared memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The transition probability matrix (matom_matrix, nrows×nrows doubles per plasma cell) was previously allocated per-cell with separate calloc calls, leaving each MPI rank holding a full independent copy. Since the matrix is written only during wind updates (each rank fills its own slice in calc_all_matom_matrices) and is strictly read-only during photon transport, it is a natural fit for MPI-3 shared memory. Changes: - calloc_matom_matrix() now allocates a single contiguous shared block (macro_block_ptrs.matom_matrix_block) via alloc_block_double with use_shared=TRUE, replacing the per-cell allocate_macro_matrix() loop. A private per-rank row-pointer array (matom_matrix_rowptrs) preserves the double** interface without duplicating the data. - broadcast_macro_atom_state_matrix() required no changes: it already packs/unpacks via matom_matrix[0] which now points into the shared block, and the existing MPI_Barrier(node_comm) ensures visibility to all node-local ranks. - janitor.c: replaced per-cell free loop with free_plasma_block on the shared block plus free() of the row-pointer array. - unit_test_model.c: replaced free_and_null(matom_matrix) with a NULL assignment since the data is now owned by the block. - Memory reporting updated: matom_matrix_block included in shared total. - mpi_comms.rst updated to document the new layout and savings. For the h20_hetop_standard80 dataset (85 macro levels) on a 300×300 grid (~12,270 plasma cells) with 24 ranks on one node, this eliminates 23 × 726 MB ≈ 16.7 GB of duplicated physical memory. Co-Authored-By: Claude Sonnet 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 35 +++++++++++--- source/gridwind.c | 53 +++++++++++++++++----- source/janitor.c | 14 ++---- source/sirocco.h | 7 +++ source/tests/unit_test_model.c | 6 +-- 5 files changed, 85 insertions(+), 30 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index bc3053293..872419072 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -200,9 +200,9 @@ when adding a new variable: - Reduced (summed) across ranks after transport - ``reduce_macro_atom_estimators()`` * - ``derived`` - - Macro-atom emissivities (``matom_emiss``), k-packet rate flags, transition probability matrix - - Broadcast after computation - - ``broadcast_macro_atom_emissivities()`` + - Macro-atom emissivities (``matom_emiss``), k-packet rate flags, transition probability matrix (``matom_matrix``) + - Broadcast after computation; matrix placed in shared memory + - ``broadcast_macro_atom_emissivities()``, ``broadcast_macro_atom_state_matrix()`` When adding a new variable, place it in the appropriate sub-structure and update the corresponding communication function. For ``est`` fields, update the reduction @@ -287,9 +287,23 @@ The allocation strategy mirrors the three sub-structures: - Incremented during photon transport (would race in shared memory). ``n_bf_in``/``n_bf_out`` are dynamically sized to ``nphot_total`` (formerly fixed at ``N_PHOT_PROC=500``). The same shared/private split applies to macro-atom dynamic arrays in -``calloc_estimators()`` (also in ``gridwind.c``). State and derived arrays -(``jbar_old``, ``gamma_old``, ``matom_emiss``, etc.) are shared, while -estimator arrays (``jbar``, ``gamma``, ``cooling_bf``, etc.) are private. +``calloc_estimators()`` and ``calloc_matom_matrix()`` (both in ``gridwind.c``). +State and derived arrays (``jbar_old``, ``gamma_old``, ``matom_emiss``, and the +transition probability matrix ``matom_matrix``) are shared, while estimator arrays +(``jbar``, ``gamma``, ``cooling_bf``, ``cooling_bb``, etc.) are private. + +The ``matom_matrix`` (an *nrows × nrows* transition probability matrix per cell, +where *nrows = nlevels_macro + 1*) is allocated as a single contiguous shared +block in ``calloc_matom_matrix()``. The flat data (``NPLASMA × nrows × nrows`` +doubles) lives in ``macro_block_ptrs.matom_matrix_block`` (shared), while a +private per-rank array of row-pointers (``matom_matrix_rowptrs``) points into +the shared block to preserve the ``double **`` interface used throughout the code. +The matrix is computed during wind updates — each rank fills its own cell slice — +then broadcast via ``broadcast_macro_atom_state_matrix()`` so all nodes obtain +a complete copy. The ``MPI_Barrier(node_comm)`` at the end of that function +ensures node-local ranks see the written data before transport begins. Because +the matrix is strictly read-only during photon transport, no further +synchronisation is required. Block pointer management ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,6 +365,15 @@ roughly ``2.3 * N * (R-1)/R`` KB. The savings scale linearly with NPLASMA: for a model with 80K cells and 29 ranks, this adds approximately 177 MB of per-rank savings. +The transition probability matrix ``matom_matrix`` (``nrows × nrows`` doubles +per cell, allocated by ``calloc_matom_matrix()``) is also placed in shared +memory. For the ``h20_hetop_standard80`` atomic dataset (85 macro-atom levels, +*nrows* = 86) and a 300×300 grid with ~12,000 active plasma cells, this matrix +totals approximately 726 MB. Without shared memory each of the *R* ranks holds +its own copy; with shared memory there is one copy per node. On a 24-rank +single-node run this saves roughly ``726 × 23 ≈ 16.7 GB`` of physical memory, +making it the single largest shared-memory saving in the code. + Shared wind structure ^^^^^^^^^^^^^^^^^^^^^ diff --git a/source/gridwind.c b/source/gridwind.c index 2d2dab08c..d901e3218 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -704,7 +704,8 @@ calloc_estimators (int nelem) if (nlevels_macro > 0 || geo.nmacro > 0) { - double macro_shared_bytes = (double) nelem * sizeof (double) * (size_Jbar_est + 4.0 * size_gamma_est + nlevels_macro); + double nrows = nlevels_macro + 1; + double macro_shared_bytes = (double) nelem * sizeof (double) * (size_Jbar_est + 4.0 * size_gamma_est + nlevels_macro + nrows * nrows); double macro_private_bytes = (double) nelem * sizeof (double) * (size_Jbar_est + 4.0 * size_gamma_est + 2.0 * size_alpha_est + nlevels_macro + 2.0 * nphot_total + nlines); Log @@ -973,8 +974,10 @@ int calloc_matom_matrix (int nelem) { int nrows = nlevels_macro + 1; - int n; - int nmatrices_allocated = 0; + int n, row; + int use_shared = FALSE; + int was_shared = FALSE; + if (nlevels_macro == 0 && geo.nmacro == 0) { geo.nmacro = 0; @@ -982,20 +985,48 @@ calloc_matom_matrix (int nelem) return (0); } - for (n = 0; n < nelem; n++) + /* Free any previously allocated blocks */ + if (macro_block_ptrs.matom_matrix_block != NULL) { - if (macromain[n].state.store_matom_matrix == TRUE) - { - allocate_macro_matrix (¯omain[n].derived.matom_matrix, nrows); - nmatrices_allocated += 1; - } +#ifdef MPI_ON + was_shared = macro_block_ptrs.shared_memory_active; +#endif + free_block ((void **) ¯o_block_ptrs.matom_matrix_block, &MACRO_WIN (win_matom_matrix), was_shared); + free (macro_block_ptrs.matom_matrix_rowptrs); + macro_block_ptrs.matom_matrix_rowptrs = NULL; } - if (nlevels_macro > 0 && nmatrices_allocated > 0) +#ifdef MPI_ON + use_shared = (np_mpi_global > 1) ? TRUE : FALSE; +#endif + + /* Allocate one contiguous shared block for all cell data: NPLASMA * nrows * nrows doubles */ + alloc_block_double ((long) nelem * nrows * nrows, ¯o_block_ptrs.matom_matrix_block, &MACRO_WIN (win_matom_matrix), use_shared); + + /* Allocate private per-rank row-pointer arrays: NPLASMA * nrows double* */ + macro_block_ptrs.matom_matrix_rowptrs = calloc ((long) nelem * nrows, sizeof (double *)); + if (macro_block_ptrs.matom_matrix_rowptrs == NULL) + { + Error ("calloc_matom_matrix: failed to allocate matom_matrix_rowptrs\n"); + Exit (EXIT_FAILURE); + } + + /* Point each cell's matom_matrix into the shared block */ + for (n = 0; n < nelem; n++) { - Log ("Allocated %10.1f Mb for MA matrix \n", 1.e-6 * (nmatrices_allocated + 1) * (nrows * nrows) * sizeof (double)); + if (macromain[n].state.store_matom_matrix == FALSE) + continue; + + double *flat = macro_block_ptrs.matom_matrix_block + (long) n * nrows * nrows; + double **rowptrs = macro_block_ptrs.matom_matrix_rowptrs + (long) n * nrows; + for (row = 0; row < nrows; row++) + rowptrs[row] = flat + row * nrows; + macromain[n].derived.matom_matrix = rowptrs; } + Log ("Allocated %10.1f Mb for MA matrix (%s)\n", + 1.e-6 * (long) nelem * nrows * nrows * sizeof (double), use_shared ? "shared" : "private"); + return (0); } diff --git a/source/janitor.c b/source/janitor.c index a4d222776..c7a2c8366 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -192,8 +192,6 @@ free_plasma_grid (void) void free_macro_grid (void) { - int n_plasma; - /* Free contiguous blocks instead of per-cell pointers */ int is_shared = FALSE; #ifdef MPI_ON @@ -226,14 +224,12 @@ free_macro_grid (void) free_plasma_block ((void **) ¯o_block_ptrs.matom_emiss_block, is_shared); } - /* matom_matrix is still allocated per-cell (not part of contiguous blocks) */ - for (n_plasma = 0; n_plasma < NPLASMA + 1; n_plasma++) + /* matom_matrix flat data block (shared in MPI mode) */ + if (macro_block_ptrs.matom_matrix_block != NULL) { - if (macromain[n_plasma].state.store_matom_matrix == TRUE) - { - free (macromain[n_plasma].derived.matom_matrix[0]); - free (macromain[n_plasma].derived.matom_matrix); - } + free_plasma_block ((void **) ¯o_block_ptrs.matom_matrix_block, is_shared); + free (macro_block_ptrs.matom_matrix_rowptrs); + macro_block_ptrs.matom_matrix_rowptrs = NULL; } free (macromain); diff --git a/source/sirocco.h b/source/sirocco.h index 51ef4af48..52eaa1309 100644 --- a/source/sirocco.h +++ b/source/sirocco.h @@ -1372,11 +1372,18 @@ typedef struct macro_blocks /* derived arrays (shared in MPI-3 mode) */ double *matom_emiss_block; /**< NPLASMA * nlevels_macro */ + /* matom_matrix flat data (shared in MPI-3 mode when store_matom_matrix is TRUE) */ + double *matom_matrix_block; /**< NPLASMA * nrows * nrows, nrows = nlevels_macro + 1 */ + + /* per-rank row-pointer arrays for matom_matrix (always private calloc) */ + double **matom_matrix_rowptrs; /**< NPLASMA * nrows double* pointers into matom_matrix_block */ + #ifdef MPI_ON /* MPI shared memory windows for state/derived blocks */ MPI_Win win_jbar_old, win_gamma_old, win_gamma_e_old; MPI_Win win_alpha_st_old, win_alpha_st_e_old; MPI_Win win_matom_emiss; + MPI_Win win_matom_matrix; int shared_memory_active; /**< TRUE if using MPI shared memory for this allocation */ #endif } macro_blocks; diff --git a/source/tests/unit_test_model.c b/source/tests/unit_test_model.c index e086f80d2..d22e3f419 100644 --- a/source/tests/unit_test_model.c +++ b/source/tests/unit_test_model.c @@ -182,10 +182,8 @@ cleanup_model (const char *root_name) free (macro_cell->est.cooling_bf_col); free (macro_cell->est.cooling_bb); - if (macro_cell->state.store_matom_matrix == TRUE) - { - free_and_null ((void **) ¯o_cell->derived.matom_matrix); - } + /* matom_matrix points into macro_block_ptrs.matom_matrix_block — freed via free_macro_grid */ + macro_cell->derived.matom_matrix = NULL; } free_and_null ((void **) ¯omain); From 641647a14bf186928899d1415534135e6d24db9d Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sun, 22 Mar 2026 15:47:08 -0500 Subject: [PATCH 10/33] Reduce peak transient memory in macro-atom communication Two low-complexity optimisations in communicate_macro.c: 1. Skip broadcast_macro_atom_state_matrix for single-node runs. matom_matrix lives in MPI-3 shared memory, so a MPI_Barrier is sufficient when all ranks share the same node (num_nodes==1). This avoids the pack/Bcast/unpack cycle and its comm buffer. 2. Replace the monolithic 2x NPLASMA*nlines cooling_bb Allreduce (2x585 MB for big.pf) with a chunked MPI_IN_PLACE Allreduce targeting ~50 MB per chunk (~13 calls for big.pf). Peak transient memory drops from ~1.17 GB to ~50 MB per rank. Documentation updated in docs/sphinx/source/developer/mpi_comms.rst. Co-Authored-By: Claude Sonnet 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 34 +++++++++++ source/communicate_macro.c | 66 +++++++++++++++++----- 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index 872419072..65d108df4 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -392,3 +392,37 @@ these via ``wind_paths_main[cell_index]`` instead of ``wmain[cell_index]``. For a 300x300 grid (NDIM2 = 90,000, ``sizeof(wind_dummy)`` = 288 bytes), this saves approximately ``90000 * 288 * (R-1)/R`` bytes, or about 25 MB per rank with 29 ranks. + +Single-node optimisation for matom_matrix broadcast +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``broadcast_macro_atom_state_matrix()`` in ``communicate_macro.c`` normally +packs the full transition-probability matrix for each rank's cell range into a +comm buffer and broadcasts it to all other ranks. When ``matom_matrix`` lives +in shared memory (the normal MPI build) and all ranks are on the same node +(``num_nodes == 1``), this broadcast is unnecessary: the writing rank's data +is already visible to all node-local ranks through shared memory. The function +therefore returns early with a ``MPI_Barrier(node_comm)`` to ensure coherence, +skipping the pack/Bcast/unpack cycle entirely. On a single-node run this +avoids allocating the comm buffer (~100 KB) and removes latency proportional +to the number of ranks. + +Chunked Allreduce for cooling_bb +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``reduce_macro_atom_estimators()`` in ``communicate_macro.c`` uses +``MPI_Allreduce`` to sum the per-rank ``cooling_bb`` estimator across all +ranks. The naive approach allocates two temporary buffers of size +``NPLASMA × nlines`` doubles each. For big.pf (12270 cells, 5964 lines) +this is approximately 2 × 585 MB = 1.17 GB of transient peak memory per +rank. + +The function instead processes cells in chunks, targeting a peak buffer size +of ~50 MB. For each chunk of cells the data is packed into a single +``chunk_cells × nlines`` buffer, reduced in place with +``MPI_Allreduce(MPI_IN_PLACE, ...)``, and unpacked back to ``macromain``. +The chunk size is computed at runtime as +``chunk_size = 50 MB / (nlines × sizeof(double))``, giving approximately +1000 cells per chunk and 13 Allreduce calls instead of one for big.pf. +Peak transient memory is reduced from ~1.17 GB to ~50 MB at the cost of +a small increase in Allreduce call overhead. diff --git a/source/communicate_macro.c b/source/communicate_macro.c index 3ad85ec7b..0026607d9 100644 --- a/source/communicate_macro.c +++ b/source/communicate_macro.c @@ -333,6 +333,17 @@ broadcast_macro_atom_state_matrix (int n_start, int n_stop, int n_cells_rank) int n, position; d_xsignal (files.root, "%-20s Begin macro atom state matrix communication\n", "NOK"); + + /* matom_matrix lives in shared memory on each node, so for a single-node run + * the writing rank's data is already visible to all node-local ranks. + * A barrier is sufficient; no cross-rank data transfer is needed. */ + if (num_nodes == 1) + { + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished macro atom state matrix communication\n", "OK"); + return (0); + } + const int matrix_size = nlevels_macro + 1; const int n_cells_max = get_max_cells_per_rank (NPLASMA); const int comm_buffer_size = calculate_comm_buffer_size (1 + n_cells_max, n_cells_max * (matrix_size * matrix_size)); @@ -417,8 +428,8 @@ reduce_macro_atom_estimators (void) double *level_helper, *cell_helper, *jbar_helper; double *gamma_helper2, *alpha_helper2; double *level_helper2, *cell_helper2, *jbar_helper2; - double *cooling_bf_helper, *cooling_bb_helper; - double *cooling_bf_helper2, *cooling_bb_helper2; + double *cooling_bf_helper; + double *cooling_bf_helper2; d_xsignal (files.root, "%-20s Begin reduction of macro atom estimators\n", "NOK"); @@ -440,7 +451,6 @@ reduce_macro_atom_estimators (void) level_helper = calloc (sizeof (double), NPLASMA * nlevels_macro); cell_helper = calloc (sizeof (double), 8 * NPLASMA); cooling_bf_helper = calloc (sizeof (double), NPLASMA * 2 * nphot_total); - cooling_bb_helper = calloc (sizeof (double), NPLASMA * nlines); jbar_helper2 = calloc (sizeof (double), NPLASMA * size_Jbar_est); gamma_helper2 = calloc (sizeof (double), NPLASMA * 4 * size_gamma_est); @@ -448,7 +458,6 @@ reduce_macro_atom_estimators (void) level_helper2 = calloc (sizeof (double), NPLASMA * nlevels_macro); cell_helper2 = calloc (sizeof (double), 8 * NPLASMA); cooling_bf_helper2 = calloc (sizeof (double), NPLASMA * 2 * nphot_total); - cooling_bb_helper2 = calloc (sizeof (double), NPLASMA * nlines); /* now we loop through each cell and copy the values of our variables into our helper arrays */ @@ -498,10 +507,6 @@ reduce_macro_atom_estimators (void) cooling_bf_helper[mpi_i + ((n + nphot_total) * NPLASMA)] = macromain[mpi_i].est.cooling_bf_col[n] / np_mpi_global; } - for (n = 0; n < nlines; n++) - { - cooling_bb_helper[mpi_i + (n * NPLASMA)] = macromain[mpi_i].est.cooling_bb[n] / np_mpi_global; - } } /* because in the above loop we have already divided by number of processes, we can now do a sum @@ -512,7 +517,44 @@ reduce_macro_atom_estimators (void) MPI_Allreduce (gamma_helper, gamma_helper2, NPLASMA * 4 * size_gamma_est, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce (alpha_helper, alpha_helper2, NPLASMA * 2 * size_alpha_est, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce (cooling_bf_helper, cooling_bf_helper2, NPLASMA * 2 * nphot_total, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce (cooling_bb_helper, cooling_bb_helper2, NPLASMA * nlines, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + + /* cooling_bb: chunked MPI_IN_PLACE Allreduce to avoid a 2x peak allocation of + * NPLASMA*nlines doubles (~2x585 MB for big.pf). Target ~50 MB per chunk. */ + { + int chunk_size = (int) ((long) 50 * 1024 * 1024 / ((long) nlines * sizeof (double))); + if (chunk_size < 1) + chunk_size = 1; + double *cooling_bb_chunk = malloc ((long) chunk_size * nlines * sizeof (double)); + if (cooling_bb_chunk == NULL) + { + Error ("reduce_macro_atom_estimators: Error allocating cooling_bb_chunk\n"); + Exit (EXIT_FAILURE); + } + int chunk_start, chunk_end, chunk_cells, ci; + for (chunk_start = 0; chunk_start < NPLASMA; chunk_start += chunk_size) + { + chunk_end = chunk_start + chunk_size; + if (chunk_end > NPLASMA) + chunk_end = NPLASMA; + chunk_cells = chunk_end - chunk_start; + for (ci = 0; ci < chunk_cells; ci++) + { + for (n = 0; n < nlines; n++) + { + cooling_bb_chunk[ci + (long) n * chunk_cells] = macromain[chunk_start + ci].est.cooling_bb[n] / np_mpi_global; + } + } + MPI_Allreduce (MPI_IN_PLACE, cooling_bb_chunk, chunk_cells * nlines, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + for (ci = 0; ci < chunk_cells; ci++) + { + for (n = 0; n < nlines; n++) + { + macromain[chunk_start + ci].est.cooling_bb[n] = cooling_bb_chunk[ci + (long) n * chunk_cells]; + } + } + } + free (cooling_bb_chunk); + } /* We now need to copy these reduced variables to the plasma structure in each thread */ @@ -562,10 +604,6 @@ reduce_macro_atom_estimators (void) macromain[mpi_i].est.cooling_bf_col[n] = cooling_bf_helper2[mpi_i + ((n + nphot_total) * NPLASMA)]; } - for (n = 0; n < nlines; n++) - { - macromain[mpi_i].est.cooling_bb[n] = cooling_bb_helper2[mpi_i + (n * NPLASMA)]; - } } free (cell_helper); @@ -574,7 +612,6 @@ reduce_macro_atom_estimators (void) free (gamma_helper); free (alpha_helper); free (cooling_bf_helper); - free (cooling_bb_helper); free (cell_helper2); free (level_helper2); @@ -582,7 +619,6 @@ reduce_macro_atom_estimators (void) free (gamma_helper2); free (alpha_helper2); free (cooling_bf_helper2); - free (cooling_bb_helper2); d_xsignal (files.root, "%-20s Finished reduction of macro atom estimators\n", "OK"); #endif From 7595621a54000a8866a32585508790e1b333fa89 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Tue, 31 Mar 2026 19:19:14 -0400 Subject: [PATCH 11/33] Work around macOS MPI-3 shared-memory SEGV_ACCERR for wmain On macOS with OpenMPI 5.0.9, MPI_Win_allocate_shared maps the shared window with invalid (read-only) permissions for non-allocating ranks, causing a SEGV_ACCERR (signal code 2) the first time any non-rank-0 process writes to wmain. Additionally, kern.sysv.shmmax is only 4 MB on macOS, far too small for a full wind grid. Fix: add #ifdef __APPLE__ guards in calloc_wind() (gridwind.c) and free_wind_grid() (janitor.c) so that macOS always uses private calloc instead of MPI_Win_allocate_shared. The Linux shared-memory path is unchanged. broadcast_wind_grid() already synchronises wmain across ranks, so correctness is preserved on macOS. Co-Authored-By: Claude Sonnet 4.6 --- source/gridwind.c | 18 ++++++++++++++++++ source/janitor.c | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/source/gridwind.c b/source/gridwind.c index d901e3218..9c8b14331 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -321,12 +321,20 @@ calloc_wind (int nelem) #ifdef MPI_ON if (wmain != NULL) { +#ifdef __APPLE__ + /* On macOS wmain is always calloc'd (see below) */ + free (wmain); +#else MPI_Win_free (&wmain_win); +#endif wmain = NULL; } if (np_mpi_global > 1) { +#ifndef __APPLE__ + /* Linux: use MPI-3 shared memory so all ranks on a node share one copy + * of wmain, avoiding per-rank duplication of large wind grids. */ MPI_Aint win_size; int disp_unit; void *base; @@ -342,6 +350,12 @@ calloc_wind (int nelem) MPI_Win_shared_query (wmain_win, 0, &win_size, &disp_unit, &base); } wmain = (WindPtr) base; +#else + /* macOS: MPI-3 shared memory windows are mapped with invalid permissions + * for non-allocating ranks, causing SEGV_ACCERR. Use private calloc on + * every rank instead; broadcast_wind_grid() keeps copies in sync. */ + wmain = (WindPtr) calloc (nelem + 1, sizeof (wind_dummy)); +#endif } else #endif @@ -364,7 +378,11 @@ calloc_wind (int nelem) ("Allocated %10d bytes for each of %5d elements of wind totaling %10.1f Mb (%s)\n", sizeof (wind_dummy), nelem + 1, 1.e-6 * alloc_size, #ifdef MPI_ON +#ifndef __APPLE__ (np_mpi_global > 1) ? "shared" : "private" +#else + "private" +#endif #else "private" #endif diff --git a/source/janitor.c b/source/janitor.c index c7a2c8366..a3fd573ff 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -113,7 +113,11 @@ free_wind_grid (void) #ifdef MPI_ON if (np_mpi_global > 1) { +#ifndef __APPLE__ MPI_Win_free (&wmain_win); +#else + free (wmain); +#endif wmain = NULL; } else From bf727a17ace7a132821d8f62f9ff212a4325eda9 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 1 Apr 2026 03:25:33 -0400 Subject: [PATCH 12/33] Convert K&R function definitions to modern prototypes Fix all 44 -Wdeprecated-non-prototype warnings on macOS (Apple clang). All affected functions used old-style K&R parameter declarations; these have been converted to standard C prototypes. No logic changes. Also update the local get_models() forward declarations in sirocco.c and setup.c from empty-parameter style to full prototypes, eliminating the two remaining "passing arguments without prototype" warnings. Build is now warning-clean on macOS with Apple clang. Co-Authored-By: Claude Sonnet 4.6 --- source/agn.c | 8 +------- source/bands.c | 5 +---- source/charge_exchange.c | 5 +---- source/compton.c | 14 ++++---------- source/cooling.c | 5 +---- source/cylind_var.c | 4 +--- source/cylindrical.c | 3 +-- source/dielectronic.c | 4 +--- source/emission.c | 4 +--- source/get_models.c | 7 +------ source/hydro_import.c | 6 +----- source/lines.c | 8 ++------ source/phot_util.c | 5 +---- source/photon2d.c | 13 ++----------- source/photon_gen.c | 26 +++----------------------- source/recipes.c | 14 ++------------ source/recomb.c | 23 ++++------------------- source/rtheta.c | 7 ++----- source/saha.c | 5 +---- source/setup.c | 2 +- source/sirocco.c | 2 +- source/spectral_estimators.c | 18 ++++-------------- source/spherical.c | 4 +--- source/sv.c | 4 +--- source/vvector.c | 10 ++-------- source/wind2d.c | 9 ++------- source/wind_util.c | 6 +----- 27 files changed, 44 insertions(+), 177 deletions(-) diff --git a/source/agn.c b/source/agn.c index 45a5ac346..d0180db3c 100644 --- a/source/agn.c +++ b/source/agn.c @@ -343,13 +343,7 @@ emittance_bpow (double freqmin, double freqmax, double alpha) **********************************************************/ int -photo_gen_agn (p, r, alpha, weight, f1, f2, spectype, istart, nphot) - PhotPtr p; - double r, alpha, weight; - double f1, f2; /* The freqency mininimum and maximum if a uniform distribution is selected */ - int spectype; /*The spectrum type to generate: 0 is bb, 1 (or in fact anything but 0) - is uniform in frequency space */ - int istart, nphot; /* Respecitively the starting point in p and the number of photons to generate */ +photo_gen_agn (PhotPtr p, double r, double alpha, double weight, double f1, double f2, int spectype, int istart, int nphot) { double freqmin, freqmax, t; int i, iend; diff --git a/source/bands.c b/source/bands.c index cb0c0bdfb..3710813bd 100644 --- a/source/bands.c +++ b/source/bands.c @@ -129,10 +129,7 @@ xband; **********************************************************/ int -bands_init (imode, band) - int imode; // A switch used for determining how the bands are to be populated - struct xbands *band; - +bands_init (int imode, struct xbands *band) { int mode; int nband; diff --git a/source/charge_exchange.c b/source/charge_exchange.c index 819cd876b..2027c3e22 100644 --- a/source/charge_exchange.c +++ b/source/charge_exchange.c @@ -121,10 +121,7 @@ compute_ch_ex_coeffs (double T) **********************************************************/ double -ch_ex_heat (one, t_e) - WindPtr one; // Pointer to the current wind cell - we need the cell volume, this is not in the plasma structure - double t_e; //Current electron temperature of the cell - +ch_ex_heat (WindPtr one, double t_e) { double x; //The returned variable int nplasma; //The cell number in the plasma array diff --git a/source/compton.c b/source/compton.c index 659d91504..96aee46ac 100644 --- a/source/compton.c +++ b/source/compton.c @@ -36,8 +36,7 @@ PlasmaPtr xplasma; /// Pointer to current plasma cell int -compton_scatter (p) - PhotPtr p; // Pointer to the current photon +compton_scatter (PhotPtr p) { double t_e; double vel[3]; @@ -344,8 +343,7 @@ total_comp (WindPtr one, double t_e) **********************************************************/ double -klein_nishina (nu) - double nu; //The frequency of the photon packet +klein_nishina (double nu) { double x; //h nu / kt double x1, x2, x3, x4; //variables to store intermediate results. @@ -445,9 +443,7 @@ set_comp_func_values (double rand_cs, double max_cs, double energy_ratio) **********************************************************/ int -compton_dir (p) - PhotPtr p; // Pointer to the current photon - +compton_dir (PhotPtr p) { double f_min, f_max, f; //Fractional energy changes - E_old/E_new - minimum possible, maximum possible, actual as implied by random cross section double n, l, m, phi, len; //The direction cosines of the new photon direction in the frame of reference with q along the photon path @@ -643,9 +639,7 @@ compton_func (double f, void *params) **********************************************************/ double -sigma_compton_partial (f, x) - double f; //This is the fractional energy change, nu/nu' - double x; //h nu/mec**2 - the energy of the photon divided by the rest energy of an electron +sigma_compton_partial (double f, double x) { double term1, term2, term3, tot; diff --git a/source/cooling.c b/source/cooling.c index 227276008..2e557452c 100644 --- a/source/cooling.c +++ b/source/cooling.c @@ -120,10 +120,7 @@ cooling (PlasmaPtr xplasma, double t) **********************************************************/ double -xtotal_emission (one, f1, f2) - WindPtr one; /* WindPtr to a specific cell in the wind */ - double f1, f2; /* The minimum and maximum frequency over which the emission is - integrated */ +xtotal_emission (WindPtr one, double f1, double f2) { double t_e; int nplasma; diff --git a/source/cylind_var.c b/source/cylind_var.c index 2caec5090..de6f7b943 100644 --- a/source/cylind_var.c +++ b/source/cylind_var.c @@ -654,9 +654,7 @@ cylvar_where_in_grid (int ndom, double x[], int ichoice, double *fx, double *fz) **********************************************************/ int -cylvar_get_random_location (n, x) - int n; // Cell in which to create position - double x[]; // Returned position +cylvar_get_random_location (int n, double x[]) { int i, j; int inwind, incell; diff --git a/source/cylindrical.c b/source/cylindrical.c index e15017a36..adcbcc1cb 100644 --- a/source/cylindrical.c +++ b/source/cylindrical.c @@ -702,8 +702,7 @@ Note that it simply calls where_in_wind multiple times. **********************************************************/ int -cylind_is_cell_in_wind (n) - int n; // cell number +cylind_is_cell_in_wind (int n) { int i, j; double r, z, dr, dz; diff --git a/source/dielectronic.c b/source/dielectronic.c index fc51dab0d..03bb1c64b 100644 --- a/source/dielectronic.c +++ b/source/dielectronic.c @@ -102,9 +102,7 @@ compute_dr_coeffs (double temp) **********************************************************/ double -total_dr (one, t_e) - WindPtr one; // Pointer to the current wind cell - we need the cell volume, this is not in the plasma structure - double t_e; //Current electron temperature of the cell +total_dr (WindPtr one, double t_e) { double x; //The returned variable //OLD double meanv, meanke; //The mean velocity and kinetic energy of electrons in the cell diff --git a/source/emission.c b/source/emission.c index 6a3d9d4f4..c9612163d 100644 --- a/source/emission.c +++ b/source/emission.c @@ -731,9 +731,7 @@ double one_ff_f1, one_ff_f2, one_ff_te; **********************************************************/ double -one_ff (xplasma, f1, f2) - PlasmaPtr xplasma; /* a single cell */ - double f1, f2; /* freqmin and freqmax */ +one_ff (PlasmaPtr xplasma, double f1, double f2) { double freq, dfreq; int n; diff --git a/source/get_models.c b/source/get_models.c index fd660c4af..a05a14e23 100644 --- a/source/get_models.c +++ b/source/get_models.c @@ -159,12 +159,7 @@ calloc_models (int nmods) **********************************************************/ int -get_models (modellist, npars, spectype) - char modellist[]; // filename containing location and associated parameters of models - int npars; // Number of parameters which vary for these models - int *spectype; // The returned spectrum type - - +get_models (char modellist[], int npars, int *spectype) { FILE *mptr; char dummy[LINELENGTH]; diff --git a/source/hydro_import.c b/source/hydro_import.c index 324adce29..cce565593 100644 --- a/source/hydro_import.c +++ b/source/hydro_import.c @@ -769,11 +769,7 @@ hydro_frac (double coord, double coord_array[], int imax, int *cell1, int *cell2 double -hydro_interp_value (array, im, ii, jm, jj, f1, f2) - double array[]; - int im, ii; //the two cells surrounding the cell in the first dim (r) - int jm, jj; //the two cells surrounding the cell in the second dim (theta) - double f1, f2; //the fraction between the two values in first and second dim +hydro_interp_value (double array[], int im, int ii, int jm, int jj, double f1, double f2) { double value; double d1, d2; diff --git a/source/lines.c b/source/lines.c index f66140d34..bc678ad2a 100644 --- a/source/lines.c +++ b/source/lines.c @@ -51,9 +51,7 @@ **********************************************************/ double -total_line_emission (xplasma, f1, f2) - PlasmaPtr xplasma; /* WindPtr to a specific cell in the wind */ - double f1, f2; /* Minimum and maximum frequency */ +total_line_emission (PlasmaPtr xplasma, double f1, double f2) { double lum; @@ -103,9 +101,7 @@ total_line_emission (xplasma, f1, f2) **********************************************************/ double -lum_lines (xplasma, nmin, nmax) - PlasmaPtr xplasma; - int nmin, nmax; /* The min and max index in lptr array for which the power is to be calculated */ +lum_lines (PlasmaPtr xplasma, int nmin, int nmax) { int n; double lum, x, z; diff --git a/source/phot_util.c b/source/phot_util.c index 2d70736ca..2e249ba1f 100644 --- a/source/phot_util.c +++ b/source/phot_util.c @@ -502,10 +502,7 @@ ds_to_plane (struct plane *pl, struct photon *p, int force_positive_z) **********************************************************/ double -ds_to_closest_approach (x, p, impact_parameter) - double x[]; /* point for which impact parameter is calculated */ - struct photon *p; /* Photon ptr of interest */ - double *impact_parameter; /* distance of ray to point a closest approach */ +ds_to_closest_approach (double x[], struct photon *p, double *impact_parameter) { double diff[3], s, result[3]; diff --git a/source/photon2d.c b/source/photon2d.c index e9e774b02..8fe033607 100644 --- a/source/photon2d.c +++ b/source/photon2d.c @@ -77,12 +77,7 @@ **********************************************************/ int -translate (w, pp, tau_scat, tau, nres) - WindPtr w; //w here refers to entire wind, not a single element - PhotPtr pp; - double tau_scat; - double *tau; - int *nres; +translate (WindPtr w, PhotPtr pp, double tau_scat, double *tau, int *nres) { int istat; int ndomain; @@ -429,11 +424,7 @@ ds_to_wind (PhotPtr pp, int *ndom_current) * **********************************************************/ int -translate_in_wind (w, p, tau_scat, tau, nres) - WindPtr w; //w here refers to entire wind, not a single element - PhotPtr p; - double tau_scat, *tau; - int *nres; +translate_in_wind (WindPtr w, PhotPtr p, double tau_scat, double *tau, int *nres) { int n; double smax, ds_current, ds_cmf; diff --git a/source/photon_gen.c b/source/photon_gen.c index 21ba8e027..f30457c90 100644 --- a/source/photon_gen.c +++ b/source/photon_gen.c @@ -72,14 +72,7 @@ int iwind_old = 0; **********************************************************/ int -define_phot (p, f1, f2, nphot_tot, ioniz_or_extract, iwind, freq_sampling) - PhotPtr p; - double f1, f2; - long nphot_tot; - int ioniz_or_extract; - int iwind; - int freq_sampling; // 0 --> old uniform approach, 1 --> minimum fractions ins various bins - +define_phot (PhotPtr p, double f1, double f2, long nphot_tot, int ioniz_or_extract, int iwind, int freq_sampling) { double natural_weight, weight; double ftot; @@ -541,14 +534,7 @@ phot_status () **********************************************************/ int -xmake_phot (p, f1, f2, ioniz_or_extract, iwind, weight, iphot_start, nphotons) - PhotPtr p; - double f1, f2; - int ioniz_or_extract; - int iwind; - double weight; - int iphot_start; //The place to begin putting photons in the photon structure in this call - int nphotons; //The total number of photons to generate in this call +xmake_phot (PhotPtr p, double f1, double f2, int ioniz_or_extract, int iwind, double weight, int iphot_start, int nphotons) { int nphot, nn; @@ -881,13 +867,7 @@ star_init (double freqmin, double freqmax, int ioniz_or_extract, double *f) **********************************************************/ int -photo_gen_star (p, r, t, weight, f1, f2, spectype, istart, nphot) - PhotPtr p; - double r, t, weight; - double f1, f2; /* The freqency mininimum and maximum if a uniform distribution is selected */ - int spectype; /*The spectrum type to generate: 0 is bb, 1 (or in fact anything but 0) - is uniform in frequency space */ - int istart, nphot; /* Respecitively the starting point in p and the number of photons to generate */ +photo_gen_star (PhotPtr p, double r, double t, double weight, double f1, double f2, int spectype, int istart, int nphot) { double freqmin, freqmax; int i, iend; diff --git a/source/recipes.c b/source/recipes.c index 259f13ac5..0b0d39cb8 100644 --- a/source/recipes.c +++ b/source/recipes.c @@ -354,12 +354,7 @@ find_function_minimum (double a, double m, double b, double (*func) (double, voi **********************************************************/ int -fraction (value, array, npts, ival, f, mode) - double array[]; // The array in we want to search - int npts, *ival; // ival is the lower point - double value; // The value we want to index - double *f; // The fractional "distance" to the next point in the array - int mode; // 0 = compute in linear space, 1=compute in log space +fraction (double value, double array[], int npts, int *ival, double *f, int mode) { int imin, imax, ihalf; @@ -462,12 +457,7 @@ to reflect the behavior of the search routine in where_in_grid. */ **********************************************************/ int -linterp (x, xarray, yarray, xdim, y, mode) - double x; // The value that we wish to index i - double xarray[], yarray[]; - int xdim; - double *y; - int mode; //0 = linear, 1 = log +linterp (double x, double xarray[], double yarray[], int xdim, double *y, int mode) { int nelem = 0; double frac; diff --git a/source/recomb.c b/source/recomb.c index 9e8b8f61f..125f6123a 100644 --- a/source/recomb.c +++ b/source/recomb.c @@ -288,12 +288,7 @@ fb_topbase_partial2 (double freq, void *params) **********************************************************/ double -integ_fb (t, f1, f2, nion, fb_choice, mode) - double t; // The temperature at which to calculate the emissivity - double f1, f2; // The frequencies over which to integrate the emissivity - int nion; // The ion for which the "specific emissivity" is calculateed - int fb_choice; // 0=full, 1=reduced, 2= rate - int mode; // 1- outer shell 2-inner shell +integ_fb (double t, double f1, double f2, int nion, int fb_choice, int mode) { double fnu; int n; @@ -538,9 +533,7 @@ double one_fb_f1, one_fb_f2, one_fb_te; /* Old values */ **********************************************************/ double -one_fb (xplasma, f1, f2) - PlasmaPtr xplasma; /* a single cell */ - double f1, f2; /* freqmin and freqmax */ +one_fb (PlasmaPtr xplasma, double f1, double f2) { double freq, tt, delta; int n, nn, nnn; @@ -1170,11 +1163,7 @@ get_fb (double t, int nion, int narray, int fb_choice, int mode) **********************************************************/ double -xinteg_fb (t, f1, f2, nion, fb_choice) - double t; // The temperature at which to calculate the emissivity - double f1, f2; // The frequencies overwhich to integrate the emissivity - int nion; // The ion for which the "specific emissivity is calculateed - int fb_choice; // 0=full, otherwise reduced +xinteg_fb (double t, double f1, double f2, int nion, int fb_choice) { int n; double fnu; @@ -1299,11 +1288,7 @@ xinteg_fb (t, f1, f2, nion, fb_choice) **********************************************************/ double -xinteg_inner_fb (t, f1, f2, nion, fb_choice) - double t; // The temperature at which to calculate the emissivity - double f1, f2; // The frequencies overwhich to integrate the emissivity - int nion; // The ion for which the "specific emissivity is calculateed - int fb_choice; // 0=full, otherwise reduced +xinteg_inner_fb (double t, double f1, double f2, int nion, int fb_choice) { int n, nn; double fnu; diff --git a/source/rtheta.c b/source/rtheta.c index 0edc2ffff..28ef5f072 100644 --- a/source/rtheta.c +++ b/source/rtheta.c @@ -560,9 +560,7 @@ rtheta_where_in_grid (int ndom, double x[]) **********************************************************/ int -rtheta_get_random_location (n, x) - int n; // Wind cell in which to create position - double x[]; // Returned position +rtheta_get_random_location (int n, double x[]) { int i, j; int inwind; @@ -723,8 +721,7 @@ rtheta_extend_density (int ndom, WindPtr w) **********************************************************/ int -rtheta_is_cell_in_wind (n) - int n; /* The wind cell number */ +rtheta_is_cell_in_wind (int n) { int i, j; double r, theta; diff --git a/source/saha.c b/source/saha.c index 698c5262e..5e8ce8a2e 100644 --- a/source/saha.c +++ b/source/saha.c @@ -712,10 +712,7 @@ int nforce; **********************************************************/ int -fix_concentrations (xplasma, mode) - PlasmaPtr xplasma; - int mode; // 0=saha using tr, 1=saha using te, 2= Lucy & Mazzali - +fix_concentrations (PlasmaPtr xplasma, int mode) { int nelem, nion; int n; diff --git a/source/setup.c b/source/setup.c index 7e5f9cf24..6a1ba043b 100644 --- a/source/setup.c +++ b/source/setup.c @@ -192,7 +192,7 @@ get_spectype (int yesno, char *question, int *spectype) char model_list[LINELENGTH]; char one_choice[LINELENGTH]; char choices[LINELENGTH]; - int get_models (); // Note: Needed because get_models cannot be included in templates.h + int get_models (char modellist[], int npars, int *spectype); int i; diff --git a/source/sirocco.c b/source/sirocco.c index ec6bdba41..ad10eb45d 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -71,7 +71,7 @@ main (int argc, char *argv[]) double freqmin, freqmax; int n; char values[LINELENGTH], answer[LINELENGTH]; - int get_models (); // Note: Needed because get_models cannot be included in templates.h + int get_models (char modellist[], int npars, int *spectype); int dummy_spectype; int opar_stat, restart_stat; double time_max; diff --git a/source/spectral_estimators.c b/source/spectral_estimators.c index 77f55f9ab..9d85a5055 100644 --- a/source/spectral_estimators.c +++ b/source/spectral_estimators.c @@ -449,10 +449,7 @@ pl_logmean (double alpha, double lnumin, double lnumax) **********************************************************/ double -pl_log_w (j, alpha, lnumin, lnumax) - double j; //the band limited spectral density - double alpha; //Computed spectral index for the cell - double lnumin, lnumax; //Range of frequencies we are considering +pl_log_w (double j, double alpha, double lnumin, double lnumax) { double logw; //the answer double logk; //scaling prefactor to permit huge numbers to be dealt with @@ -487,9 +484,7 @@ pl_log_w (j, alpha, lnumin, lnumax) **********************************************************/ double -pl_log_stddev (alpha, lnumin, lnumax) - double alpha; //Computed spectral index for the cell - double lnumin, lnumax; //Range of frequencies we are considering +pl_log_stddev (double alpha, double lnumin, double lnumax) { double answer; //the answer @@ -618,10 +613,7 @@ exp_mean (double exp_temp, double numin, double numax) **********************************************************/ double -exp_w (j, exp_temp, numin, numax) - double j; //the band limited spectral density - double exp_temp; //Computed effective temperature for the cell - double numin, numax; //Range of frequencies we are considering +exp_w (double j, double exp_temp, double numin, double numax) { double w; //the answer @@ -660,9 +652,7 @@ exp_w (j, exp_temp, numin, numax) **********************************************************/ double -exp_stddev (exp_temp, numin, numax) - double exp_temp; //Computed spectral index for the cell - double numin, numax; //Range of frequencies we are considering +exp_stddev (double exp_temp, double numin, double numax) { double answer; //the answer double exp1; /* We supply a temperature, but actually we expect the correct function to be of the form e^-hnu/kt, so this will hold -1*h/kt */ diff --git a/source/spherical.c b/source/spherical.c index a22702476..2811fd585 100644 --- a/source/spherical.c +++ b/source/spherical.c @@ -405,9 +405,7 @@ spherical_where_in_grid (int ndom, double x[]) **********************************************************/ int -spherical_get_random_location (n, x) - int n; // Cell in which to create position - double x[]; // Returned position +spherical_get_random_location (int n, double x[]) { int i, j; int inwind; diff --git a/source/sv.c b/source/sv.c index f865486b4..819578436 100644 --- a/source/sv.c +++ b/source/sv.c @@ -368,9 +368,7 @@ sv_rho (int ndom, double x[]) **********************************************************/ double -sv_find_wind_rzero (ndom, p) - int ndom; - double p[]; /* Note that p is a 3 vector and not a photon structure */ +sv_find_wind_rzero (int ndom, double p[]) { double x, z; double rho_min, rho_max, rho; diff --git a/source/vvector.c b/source/vvector.c index 07c9e21e6..e1edb2511 100644 --- a/source/vvector.c +++ b/source/vvector.c @@ -555,10 +555,7 @@ create_basis (double u[], double v[], struct basis *basis_new) **********************************************************/ int -project_from (basis_from, v_in, v_out) - struct basis *basis_from; /* direction cosines to go from rotated to unrotated frame */ - double v_in[], v_out[]; /*v_in here is in rotated frame, v_out in unrotated frame */ - +project_from (struct basis *basis_from, double v_in[], double v_out[]) { int i, j; for (i = 0; i < 3; i++) @@ -590,10 +587,7 @@ project_from (basis_from, v_in, v_out) **********************************************************/ int -project_to (basis_from, v_in, v_out) - struct basis *basis_from; /* direction cosines to go from rotated to unrotated frame */ - double v_in[], v_out[]; /*v_in here is in unrotated frame, v_out in rotated frame */ - +project_to (struct basis *basis_from, double v_in[], double v_out[]) { int i, j; for (i = 0; i < 3; i++) diff --git a/source/wind2d.c b/source/wind2d.c index d30d51730..1c6198c57 100644 --- a/source/wind2d.c +++ b/source/wind2d.c @@ -384,10 +384,7 @@ rho (WindPtr w, double x[]) **********************************************************/ int -mdot_wind (w, z, rmax) - WindPtr w; - double z; // The height (usually small) above the disk at which mdot will be calculated - double rmax; // The radius at which mdot will be calculated +mdot_wind (WindPtr w, double z, double rmax) { struct photon p; double r, dr, rmin; @@ -468,9 +465,7 @@ mdot_wind (w, z, rmax) **********************************************************/ int -get_random_location (n, x) - int n; // Cell in which to create position - double x[]; // Returned position +get_random_location (int n, double x[]) { int ndom; diff --git a/source/wind_util.c b/source/wind_util.c index e0e2f2adc..7cd08477a 100644 --- a/source/wind_util.c +++ b/source/wind_util.c @@ -240,11 +240,7 @@ int ierr_where_in_2dcell = 0; **********************************************************/ int -where_in_2dcell (ichoice, x, n, fx, fz) - int ichoice; - double x[]; - int n; // A known wind cell - double *fx, *fz; +where_in_2dcell (int ichoice, double x[], int n, double *fx, double *fz) { double *x00, *x01, *x10, *x11; double z[3]; From dc217a8d0118b111c4237c2db1dcfd12bfc1209a Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 1 Apr 2026 03:30:07 -0400 Subject: [PATCH 13/33] Fix remaining warnings in make all (MPI build) - communicate_wind.c: replace VLA block_offsets[count] with fixed size block_offsets[2]; remove now-unused 'count' variable. Apple clang warns on VLAs with const-int size under -Wgnu-folding-constant. - swind_sub.c, swind_ion.c, rad_hydro_files.c: remove old-style FILE *fopen() forward declarations. fopen() is already declared by ; the empty-parameter declaration conflicts with the system prototype under -Wdeprecated-non-prototype. Build is now warning-clean on macOS for both make sirocco and make all. Co-Authored-By: Claude Sonnet 4.6 --- source/communicate_wind.c | 5 ++--- source/rad_hydro_files.c | 2 +- source/swind_ion.c | 2 +- source/swind_sub.c | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/communicate_wind.c b/source/communicate_wind.c index 4bf9a4b7f..a4e948137 100644 --- a/source/communicate_wind.c +++ b/source/communicate_wind.c @@ -55,14 +55,13 @@ broadcast_wind_grid (const int n_start, const int n_stop, const int n_cells_rank * more efficiently. Although, it may just as easy and quick to communicate * each field one by one... but this is the right way to do it */ MPI_Datatype wcone_derived_type; - const int count = 2; const int block_lengths[] = { 1, 1 }; const MPI_Datatype block_types[] = { MPI_DOUBLE, MPI_DOUBLE }; /* We need to find the memory displacements. We'll use the wcone struct in * the first cell for this. Each struct should have the same amount of * alignment for the fields, so this should be OK */ MPI_Aint base_address; - MPI_Aint block_offsets[count]; + MPI_Aint block_offsets[2]; MPI_Get_address (&wmain[0].wcone, &base_address); MPI_Get_address (&wmain[0].wcone.z, &block_offsets[0]); MPI_Get_address (&wmain[0].wcone.dzdr, &block_offsets[1]); @@ -70,7 +69,7 @@ broadcast_wind_grid (const int n_start, const int n_stop, const int n_cells_rank { block_offsets[i] = MPI_Aint_diff (block_offsets[i], base_address); } - MPI_Type_create_struct (count, block_lengths, block_offsets, block_types, &wcone_derived_type); + MPI_Type_create_struct (2, block_lengths, block_offsets, block_types, &wcone_derived_type); MPI_Type_commit (&wcone_derived_type); /* Calculate the size of the communication buffer */ diff --git a/source/rad_hydro_files.c b/source/rad_hydro_files.c index 5cdac32d2..5e9ab2b32 100644 --- a/source/rad_hydro_files.c +++ b/source/rad_hydro_files.c @@ -143,7 +143,7 @@ main (int argc, char *argv[]) struct photon ptest; //We need a test photon structure in order to compute t - FILE *fptr_hc, *fptr_drive, *fptr_ion, *fptr_spec, *fptr_pcon, *fptr_debug, *fptr_flux, *fptr_flux_theta, *fptr_flux_phi, *fptr_flux_r, *fopen (); /*This is the file to communicate with zeus */ + FILE *fptr_hc, *fptr_drive, *fptr_ion, *fptr_spec, *fptr_pcon, *fptr_debug, *fptr_flux, *fptr_flux_theta, *fptr_flux_phi, *fptr_flux_r; /*This is the file to communicate with zeus */ domain = geo.hydro_domain_number; /* Initialize MPI, which is needed because some of the routines are MPI enabled */ diff --git a/source/swind_ion.c b/source/swind_ion.c index 1f99f5e29..ff004d714 100644 --- a/source/swind_ion.c +++ b/source/swind_ion.c @@ -757,7 +757,7 @@ collision_summary (WindPtr w, char rootname[], int ochoice) int nline, int_te; double t_e, qup, qdown, A, wavelength; char filename[LINELENGTH], suffix[LINELENGTH]; - FILE *fopen (), *fptr = NULL; + FILE *fptr = NULL; t_e = 10000.0; diff --git a/source/swind_sub.c b/source/swind_sub.c index 090465813..9387ea961 100644 --- a/source/swind_sub.c +++ b/source/swind_sub.c @@ -3319,7 +3319,7 @@ complete_ion_summary (WindPtr w, char rootname[], int ochoice) { char cell[5]; PlasmaPtr xplasma; - FILE *fptr = NULL, *fopen (); + FILE *fptr = NULL; char filename[LINELENGTH]; From b070ade35f64ffcc8c6c62d656e5f81b7c7bd27a Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 8 Apr 2026 10:07:42 -0400 Subject: [PATCH 14/33] Add a big disk to regress3d --- examples/regress3d/agn_cyl_big.pf | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 examples/regress3d/agn_cyl_big.pf diff --git a/examples/regress3d/agn_cyl_big.pf b/examples/regress3d/agn_cyl_big.pf new file mode 100644 index 000000000..a03ac8761 --- /dev/null +++ b/examples/regress3d/agn_cyl_big.pf @@ -0,0 +1,78 @@ +System_type(star,cv,bh,agn,previous) agn + +### Parameters for the Central Object +Central_object.mass(msol) 1e9 +Central_object.radius(cm) 8.85667e+14 + +### Parameters for the Disk (if there is one) +Disk.type(none,flat,vertically.extended,rmin>central.obj.rad) flat +Disk.radiation(yes,no) no +Disk.temperature.profile(standard,readin) standard +Disk.mdot(msol/yr) 5 +Disk.radmax(cm) 1e19 + +### Parameters for Boundary Layer or the compact object in an X-ray Binary or AGN +Central_object.radiation(yes,no) yes +Central_object.rad_type_to_make_wind(bb,models,power,cloudy,brems,mono) power +Central_object.luminosity(ergs/s) 1e43 +Central_object.power_law_index -0.9 +Central_object.geometry_for_source(sphere,lamp_post,bubble,iso) sphere + +### Parameters describing the various winds or coronae in the system +Wind.number_of_components 1 +Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) sv +Wind.coord_system(spherical,cylindrical,polar,cyl_var) cylindrical +Wind.dim.in.x_or_r.direction 30 +Wind.dim.in.z_or_theta.direction 30 + +### Parameters associated with photon number, cycles,ionization and radiative transfer options +Photons_per_cycle 2000000 +Ionization_cycles 3 +Spectrum_cycles 2 +Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) matrix_pow +Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) escape_prob +Wind.radiation(yes,no) yes +Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb +Wind_heating.extra_processes(none,adiabatic,nonthermal,both) adiabatic +Atomic_data data/standard80.dat + +### Parameters for Domain 0 +Wind.mdot(msol/yr) 5 +SV.diskmin(units_of_rstar) 50 +SV.diskmax(units_of_rstar) 100 +SV.thetamin(deg) 20 +SV.thetamax(deg) 82 +SV.mdot_r_exponent 0 +SV.v_infinity(in_units_of_vescape 1 +SV.acceleration_length(cm) 1e18 +SV.acceleration_exponent 1.0 +SV.gamma(streamline_skew;1=usually) 1 +SV.v_zero_mode(fixed,sound_speed) fixed +SV.v_zero(cm/s) 6e5 +Wind.radmax(cm) 1e19 +Wind.t.init 1e5 +Wind.filling_factor(1=smooth,<1=clumped) 1 + +### Parameters defining the spectra seen by observers + +Central_object.rad_type_in_final_spectrum(bb,models,power,cloudy,brems,mono) power + +### The minimum and maximum wavelengths in the final spectra and the number of wavelength bins +Spectrum.nwave 10000 +Spectrum.wavemin(Angstroms) 200 +Spectrum.wavemax(Angstroms) 2600 + +### The observers and their location relative to the system +Spectrum.no_observers 4 +Spectrum.angle(0=pole) 20 +Spectrum.angle(0=pole) 80 +Spectrum.angle(0=pole) 100 +Spectrum.angle(0=pole) 160 +Spectrum.live_or_die(live.or.die,extract) extract +Spectrum.type(flambda,fnu,basic) flambda + +### Parameters for Reverberation Modeling (if needed) +Reverb.type(none,photon,wind,matom) none + +### Other parameters +Photon_sampling.approach(T_star,cv,yso,AGN,tde_bb,min_max_freq,user_bands,cloudy_test,wide,logarithmic) agn From 839087e9e681ce2f79bfed655c2ae3e5593811c2 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Thu, 16 Apr 2026 14:26:44 -0500 Subject: [PATCH 15/33] Fix unit tests for memory branch restructuring - Update test_define_wind.c to access plasma fields via ->state sub-struct (rho, ne, t_e, t_r, density) following the plasma struct refactor - Fix cleanup_model to use free_domains/free_wind_grid/free_plasma_grid/ free_macro_grid instead of per-cell frees, since arrays are now offsets into contiguous blocks managed by plasma_block_ptrs - Fix free() calls on non-heap CYLVAR pointers in unit_test_model.c - Initialize node_comm/leader_comm in unit_test_main.c to match sirocco.c, fixing MPI_ERR_COMM crashes on MPI_Barrier(node_comm) - Add missing NULL assignments after free() in janitor.c for zdom, wmain, plasmamain and macromain, preventing double-free on successive test runs - Update .pf test parameter files to include new ionization modes (LTE_iterate, matrix_multishot) and geometry option (iso) added on this branch Co-Authored-By: Claude Sonnet 4.6 --- source/janitor.c | 4 + .../tests/test_data/define_wind/agn_macro.pf | 4 +- source/tests/test_data/define_wind/cv.pf | 2 +- source/tests/test_data/define_wind/shell.pf | 2 +- source/tests/test_data/define_wind/star.pf | 2 +- source/tests/tests/test_define_wind.c | 54 +++++------ source/tests/unit_test_main.c | 9 ++ source/tests/unit_test_model.c | 92 +------------------ 8 files changed, 50 insertions(+), 119 deletions(-) diff --git a/source/janitor.c b/source/janitor.c index a3fd573ff..9060f82df 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -87,6 +87,7 @@ free_domains (void) } free (zdom); + zdom = NULL; } /**********************************************************/ @@ -124,6 +125,7 @@ free_wind_grid (void) #endif { free (wmain); + wmain = NULL; } } @@ -183,6 +185,7 @@ free_plasma_grid (void) } free (plasmamain); + plasmamain = NULL; } /**********************************************************/ @@ -237,6 +240,7 @@ free_macro_grid (void) } free (macromain); + macromain = NULL; } /**********************************************************/ diff --git a/source/tests/test_data/define_wind/agn_macro.pf b/source/tests/test_data/define_wind/agn_macro.pf index 74a3b4ecb..8170458e6 100644 --- a/source/tests/test_data/define_wind/agn_macro.pf +++ b/source/tests/test_data/define_wind/agn_macro.pf @@ -17,13 +17,13 @@ Central_object.radiation(yes,no) yes Central_object.rad_type_to_make_wind(bb,models,power,cloudy,brems,mono) power Central_object.luminosity(ergs/s) 1e43 Central_object.power_law_index -0.9 -Central_object.geometry_for_source(sphere,lamp_post,bubble) sphere +Central_object.geometry_for_source(sphere,lamp_post,bubble,iso) sphere Wind.number_of_components 1 Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) sv Wind.coord_system(spherical,cylindrical,polar,cyl_var) cylindrical Wind.dim.in.x_or_r.direction 30 Wind.dim.in.z_or_theta.direction 30 -Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,fixed,matrix_bb,matrix_pow,matrix_est) matrix_pow +Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) matrix_pow Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) macro_atoms_thermal_trapping Matom_transition_mode(mc_jumps,matrix) mc_jumps Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb diff --git a/source/tests/test_data/define_wind/cv.pf b/source/tests/test_data/define_wind/cv.pf index 5c1b98181..19bc1251d 100644 --- a/source/tests/test_data/define_wind/cv.pf +++ b/source/tests/test_data/define_wind/cv.pf @@ -24,7 +24,7 @@ Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) Wind.coord_system(spherical,cylindrical,polar,cyl_var) cylindrical Wind.dim.in.x_or_r.direction 30 Wind.dim.in.z_or_theta.direction 30 -Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,fixed,matrix_bb,matrix_pow,matrix_est) matrix_bb +Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) matrix_bb Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) thermal_trapping Wind.radiation(yes,no) yes Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb diff --git a/source/tests/test_data/define_wind/shell.pf b/source/tests/test_data/define_wind/shell.pf index f80db347e..2ede892a5 100644 --- a/source/tests/test_data/define_wind/shell.pf +++ b/source/tests/test_data/define_wind/shell.pf @@ -14,7 +14,7 @@ Disk.type(none,flat,vertically.extended,rmin>central.obj.rad) no Boundary_layer.radiation(yes,no) no Wind.number_of_components 1 Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) shell -Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,fixed,matrix_bb,matrix_pow,matrix_est) ml93 +Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) ml93 Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) macro_atoms_thermal_trapping Matom_transition_mode(mc_jumps,matrix) matrix Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb diff --git a/source/tests/test_data/define_wind/star.pf b/source/tests/test_data/define_wind/star.pf index 1099db36d..502c93413 100644 --- a/source/tests/test_data/define_wind/star.pf +++ b/source/tests/test_data/define_wind/star.pf @@ -16,7 +16,7 @@ Wind.number_of_components 1 Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) star Wind.coord_system(spherical,cylindrical,polar,cyl_var) spherical Wind.dim.in.x_or_r.direction 30 -Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,fixed,matrix_bb,matrix_pow,matrix_est) ml93 +Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) ml93 Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) escape_prob Wind.radiation(yes,no) yes Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb diff --git a/source/tests/tests/test_define_wind.c b/source/tests/tests/test_define_wind.c index 1bd6e5383..0d195334e 100644 --- a/source/tests/tests/test_define_wind.c +++ b/source/tests/tests/test_define_wind.c @@ -144,16 +144,16 @@ test_sv_agn_macro_wind (void) CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (wind_cell->xgamma, gamma, TEST_TOLERANCE); /* Some things (plasma properties) are stored in plasma cells */ - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->rho, rho, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->ne, ne, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_e, t_e, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_r, t_r, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.rho, rho, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.ne, ne, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_e, t_e, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_r, t_r, TEST_TOLERANCE); /* Ion abundances are tested in their number density relative to Hydrogen. * This is the default output option in windsave2table */ - const double n_h = rho2nh * plasma_cell->rho; - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); + const double n_h = rho2nh * plasma_cell->state.rho; + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); } fclose (fp); @@ -276,16 +276,16 @@ test_sv_cv_wind (void) CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (wind_cell->xgamma, gamma, TEST_TOLERANCE); /* Some things (plasma properties) are stored in plasma cells */ - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->rho, rho, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->ne, ne, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_e, t_e, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_r, t_r, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.rho, rho, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.ne, ne, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_e, t_e, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_r, t_r, TEST_TOLERANCE); /* Ion abundances are tested in their number density relative to Hydrogen. * This is the default output option in windsave2table */ - const double n_h = rho2nh * plasma_cell->rho; - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); + const double n_h = rho2nh * plasma_cell->state.rho; + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); } /* For the CV model, we want to save the wind_save to use in another test */ @@ -410,15 +410,15 @@ test_shell_wind (void) CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (wind_cell->xgamma, gamma, TEST_TOLERANCE); /* Some things (plasma properties) are stored in plasma cells */ - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->rho, rho, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->ne, ne, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_e, t_e, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_r, t_r, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.rho, rho, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.ne, ne, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_e, t_e, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_r, t_r, TEST_TOLERANCE); /* Ion abundances are tested in their number density relative to Hydrogen. * This is the default output option in windsave2table */ - const double n_h = rho2nh * plasma_cell->rho; - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); + const double n_h = rho2nh * plasma_cell->state.rho; + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); } fclose (fp); @@ -534,16 +534,16 @@ test_spherical_star_wind (void) CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (wind_cell->xgamma, gamma, TEST_TOLERANCE); /* Some things (plasma properties) are stored in plasma cells */ - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->rho, rho, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->ne, ne, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_e, t_e, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->t_r, t_r, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.rho, rho, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.ne, ne, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_e, t_e, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.t_r, t_r, TEST_TOLERANCE); /* Ion abundances are tested in their number density relative to Hydrogen. * This is the default output option in windsave2table */ - const double n_h = rho2nh * plasma_cell->rho; - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); - CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); + const double n_h = rho2nh * plasma_cell->state.rho; + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[0] / (n_h * ele[0].abun), h1, TEST_TOLERANCE); + CU_ASSERT_DOUBLE_FRACTIONAL_EQUAL_FATAL (plasma_cell->state.density[8] / (n_h * ele[2].abun), c4, TEST_TOLERANCE); } fclose (fp); diff --git a/source/tests/unit_test_main.c b/source/tests/unit_test_main.c index e7aff91c1..978050968 100644 --- a/source/tests/unit_test_main.c +++ b/source/tests/unit_test_main.c @@ -45,6 +45,12 @@ main (int argc, char **argv) } MPI_Comm_rank (MPI_COMM_WORLD, &rank_global); MPI_Comm_size (MPI_COMM_WORLD, &np_mpi_global); + + MPI_Comm_split_type (MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, rank_global, MPI_INFO_NULL, &node_comm); + MPI_Comm_rank (node_comm, &node_rank); + MPI_Comm_size (node_comm, &node_size); + MPI_Comm_split (MPI_COMM_WORLD, (node_rank == 0) ? 0 : MPI_UNDEFINED, rank_global, &leader_comm); + num_nodes = 1; #else rank_global = 0; np_mpi_global = 1; @@ -101,6 +107,9 @@ main (int argc, char **argv) Log_close (); #ifdef MPI_ON + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); MPI_Finalize (); #endif diff --git a/source/tests/unit_test_model.c b/source/tests/unit_test_model.c index d22e3f419..3c5092007 100644 --- a/source/tests/unit_test_model.c +++ b/source/tests/unit_test_model.c @@ -78,13 +78,9 @@ free_and_null (void **ptr) int cleanup_model (const char *root_name) { - int n_plasma; char *SIROCCO_ENV; char parameter_filepath[LINELENGTH]; - PlasmaPtr plasma_cell; - MacroPtr macro_cell; - (void) root_name; SIROCCO_ENV = getenv ("SIROCCO"); @@ -100,93 +96,15 @@ cleanup_model (const char *root_name) return EXIT_FAILURE; } - /* free domains */ - for (int n_dom = 0; n_dom < geo.ndomain; ++n_dom) - { - free_and_null ((void **) &zdom[n_dom].wind_x); - free_and_null ((void **) &zdom[n_dom].wind_midx); - free_and_null ((void **) &zdom[n_dom].wind_z); - free_and_null ((void **) &zdom[n_dom].wind_midz); - - if (zdom[n_dom].coord_type == RTHETA) - { - free_and_null ((void **) &zdom[n_dom].cones_rtheta); - } - else if (zdom[n_dom].coord_type == CYLVAR) - { - free ((void **) &zdom[n_dom].wind_z_var[0]); - free ((void **) &zdom[n_dom].wind_z_var); - free ((void **) &zdom[n_dom].wind_midz_var[0]); - free ((void **) &zdom[n_dom].wind_midz_var); - } - } - free_and_null ((void **) &zdom); - - /* free dynamic grid properties */ - - for (int n_wind = 0; n_wind < NDIM2; ++n_wind) - { - free_and_null ((void **) &wind_paths_main[n_wind].paths); - free_and_null ((void **) &wind_paths_main[n_wind].line_paths); - } - - free_and_null ((void **) &wmain); - - /* NPLASMA + 1 is the dummy plasma cell */ - for (n_plasma = 0; n_plasma < NPLASMA + 1; ++n_plasma) - { - plasma_cell = &plasmamain[n_plasma]; - free (plasma_cell->state.density); - free (plasma_cell->state.partition); - free (plasma_cell->est.ioniz); - free (plasma_cell->derived.recomb); - free (plasma_cell->derived.scatters); - free (plasma_cell->derived.xscatters); - free (plasma_cell->est.heat_ion); - free (plasma_cell->est.heat_inner_ion); - free (plasma_cell->derived.cool_rr_ion); - free (plasma_cell->derived.lum_rr_ion); - free (plasma_cell->derived.inner_recomb); - free (plasma_cell->est.inner_ioniz); - free (plasma_cell->derived.cool_dr_ion); - free (plasma_cell->state.levden); - free (plasma_cell->state.recomb_simple); - free (plasma_cell->state.recomb_simple_upweight); - free (plasma_cell->state.kbf_use); - } - - free_and_null ((void **) &plasmamain); + free_domains (); + free_wind_grid (); + free_plasma_grid (); free_and_null ((void **) &photstoremain); - free_and_null ((void **) &matomphotstoremain); /* This one doesn't care about if macro atoms are used or not */ + free_and_null ((void **) &matomphotstoremain); if (nlevels_macro > 0) { - for (n_plasma = 0; n_plasma < NPLASMA + 1; n_plasma++) - { - macro_cell = ¯omain[n_plasma]; - free (macro_cell->est.jbar); - free (macro_cell->state.jbar_old); - free (macro_cell->est.gamma); - free (macro_cell->state.gamma_old); - free (macro_cell->est.gamma_e); - free (macro_cell->state.gamma_e_old); - free (macro_cell->est.alpha_st); - free (macro_cell->state.alpha_st_old); - free (macro_cell->est.alpha_st_e); - free (macro_cell->state.alpha_st_e_old); - free (macro_cell->est.recomb_sp); - free (macro_cell->est.recomb_sp_e); - free (macro_cell->derived.matom_emiss); - free (macro_cell->est.matom_abs); - free (macro_cell->est.cooling_bf); - free (macro_cell->est.cooling_bf_col); - free (macro_cell->est.cooling_bb); - - /* matom_matrix points into macro_block_ptrs.matom_matrix_block — freed via free_macro_grid */ - macro_cell->derived.matom_matrix = NULL; - } - - free_and_null ((void **) ¯omain); + free_macro_grid (); } NDIM2 = 0; From d03642797797fec2bff64de9fc88b7a064100097 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 17 Apr 2026 05:52:07 -0500 Subject: [PATCH 16/33] Remove agn_cyl_big.pf from memory (belongs on xmem3d branch) Co-Authored-By: Claude Sonnet 4.6 --- examples/regress3d/agn_cyl_big.pf | 78 ------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 examples/regress3d/agn_cyl_big.pf diff --git a/examples/regress3d/agn_cyl_big.pf b/examples/regress3d/agn_cyl_big.pf deleted file mode 100644 index a03ac8761..000000000 --- a/examples/regress3d/agn_cyl_big.pf +++ /dev/null @@ -1,78 +0,0 @@ -System_type(star,cv,bh,agn,previous) agn - -### Parameters for the Central Object -Central_object.mass(msol) 1e9 -Central_object.radius(cm) 8.85667e+14 - -### Parameters for the Disk (if there is one) -Disk.type(none,flat,vertically.extended,rmin>central.obj.rad) flat -Disk.radiation(yes,no) no -Disk.temperature.profile(standard,readin) standard -Disk.mdot(msol/yr) 5 -Disk.radmax(cm) 1e19 - -### Parameters for Boundary Layer or the compact object in an X-ray Binary or AGN -Central_object.radiation(yes,no) yes -Central_object.rad_type_to_make_wind(bb,models,power,cloudy,brems,mono) power -Central_object.luminosity(ergs/s) 1e43 -Central_object.power_law_index -0.9 -Central_object.geometry_for_source(sphere,lamp_post,bubble,iso) sphere - -### Parameters describing the various winds or coronae in the system -Wind.number_of_components 1 -Wind.type(SV,star,hydro,corona,kwd,homologous,shell,imported) sv -Wind.coord_system(spherical,cylindrical,polar,cyl_var) cylindrical -Wind.dim.in.x_or_r.direction 30 -Wind.dim.in.z_or_theta.direction 30 - -### Parameters associated with photon number, cycles,ionization and radiative transfer options -Photons_per_cycle 2000000 -Ionization_cycles 3 -Spectrum_cycles 2 -Wind.ionization(on.the.spot,ML93,LTE_tr,LTE_te,LTE_iterate,fixed,matrix_bb,matrix_pow,matrix_est,matrix_multishot) matrix_pow -Line_transfer(pure_abs,pure_scat,sing_scat,escape_prob,thermal_trapping,macro_atoms_escape_prob,macro_atoms_thermal_trapping) escape_prob -Wind.radiation(yes,no) yes -Surface.reflection.or.absorption(reflect,absorb,thermalized.rerad) absorb -Wind_heating.extra_processes(none,adiabatic,nonthermal,both) adiabatic -Atomic_data data/standard80.dat - -### Parameters for Domain 0 -Wind.mdot(msol/yr) 5 -SV.diskmin(units_of_rstar) 50 -SV.diskmax(units_of_rstar) 100 -SV.thetamin(deg) 20 -SV.thetamax(deg) 82 -SV.mdot_r_exponent 0 -SV.v_infinity(in_units_of_vescape 1 -SV.acceleration_length(cm) 1e18 -SV.acceleration_exponent 1.0 -SV.gamma(streamline_skew;1=usually) 1 -SV.v_zero_mode(fixed,sound_speed) fixed -SV.v_zero(cm/s) 6e5 -Wind.radmax(cm) 1e19 -Wind.t.init 1e5 -Wind.filling_factor(1=smooth,<1=clumped) 1 - -### Parameters defining the spectra seen by observers - -Central_object.rad_type_in_final_spectrum(bb,models,power,cloudy,brems,mono) power - -### The minimum and maximum wavelengths in the final spectra and the number of wavelength bins -Spectrum.nwave 10000 -Spectrum.wavemin(Angstroms) 200 -Spectrum.wavemax(Angstroms) 2600 - -### The observers and their location relative to the system -Spectrum.no_observers 4 -Spectrum.angle(0=pole) 20 -Spectrum.angle(0=pole) 80 -Spectrum.angle(0=pole) 100 -Spectrum.angle(0=pole) 160 -Spectrum.live_or_die(live.or.die,extract) extract -Spectrum.type(flambda,fnu,basic) flambda - -### Parameters for Reverberation Modeling (if needed) -Reverb.type(none,photon,wind,matom) none - -### Other parameters -Photon_sampling.approach(T_star,cv,yso,AGN,tde_bb,min_max_freq,user_bands,cloudy_test,wide,logarithmic) agn From 3e579f024e5667a81e6ecfe831ed42aeb7c08ca2 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 17 Apr 2026 17:33:07 -0500 Subject: [PATCH 17/33] Fix MPI shared-memory race conditions and clean up unit test warnings Race conditions (Linux MPI multi-rank runs): - sirocco.c: Move MPI_Finalize() to after clean_on_exit() and Log_close(). free_wind_grid() calls MPI_Win_free(&wmain_win), which must run before MPI_Finalize(); the previous ordering caused SEGV_MAPERR at exit when running agn_macro.pf with multiple MPI ranks. - gridwind.c (calloc_wind): Add MPI_Barrier(node_comm) after the node leader's memset of the shared wmain block, so all node-local ranks see the zeroed memory before any rank begins writing wind-cell fields. - communicate_wind.c (broadcast_wind_grid): Add MPI_Barrier(node_comm) at the end of the broadcast, matching the pattern used in all plasma broadcast functions. Without this, a fast rank could proceed to read stale zero-initialised wmain cells (e.g. producing "zero volume but flagged inwind" errors in 1d_sn.pf). - define_wind.c (create_wind_grid): Add two MPI_Barrier(node_comm) calls bracketing make_coordinate_grid() and wind_complete(). The first prevents a fast rank from writing import-derived inwind values to shared wmain while a slow rank's init loop is still writing W_NOT_ASSIGNED to the same cells (triggered cv_standard_import.pf failure). The second ensures all ranks have finished coordinate grid setup before entering the parallel volume/velocity loop. Documentation: - docs/sphinx/source/developer/mpi_comms.rst: Document the new barriers and add a new section "Platform differences: macOS vs Linux" explaining why these races are invisible on macOS (wmain uses private calloc per rank via #ifdef __APPLE__) but fatal on Linux (genuinely shared pages). Includes a rule of thumb for when Linux testing is required. Unit test warning fixes: - source/tests/Makefile: Make -Wno-deprecated-non-prototype Darwin-only (Linux GCC does not recognise the flag); add -Wno-unused-result since test utility functions intentionally ignore fscanf return values on known-good test data files. - source/tests/tests/test_matrix.c: Initialise matrix/inverse/vector pointers and size variables to NULL/0 to silence -Wmaybe-uninitialized. - source/tests/tests/test_define_wind.c, source/tests/unit_test_model.c: Widen path buffers from LINELENGTH to 2*LINELENGTH and update snprintf size arguments accordingly, eliminating -Wformat-truncation warnings. All regression tests pass with mpirun -n 4 and all 11 unit tests pass with make check. Co-Authored-By: Claude Sonnet 4.6 --- docs/sphinx/source/developer/mpi_comms.rst | 84 ++++++++++++++++++++++ source/communicate_wind.c | 4 ++ source/define_wind.c | 16 +++++ source/gridwind.c | 2 + source/sirocco.c | 24 ++++--- source/tests/Makefile | 6 +- source/tests/tests/test_define_wind.c | 8 +-- source/tests/tests/test_matrix.c | 14 ++-- source/tests/unit_test_model.c | 8 +-- 9 files changed, 140 insertions(+), 26 deletions(-) diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst index 65d108df4..dc94fbe4f 100644 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ b/docs/sphinx/source/developer/mpi_comms.rst @@ -322,6 +322,7 @@ After any broadcast that writes to shared dynamic arrays, an ``MPI_Barrier(node_comm)`` ensures all node-local ranks see the new data before proceeding. These barriers appear at the end of: +- ``broadcast_wind_grid()`` - ``broadcast_updated_plasma_properties()`` - ``broadcast_plasma_grid()`` - ``broadcast_wind_luminosity()`` @@ -330,6 +331,25 @@ before proceeding. These barriers appear at the end of: - ``broadcast_macro_atom_emissivities()`` - ``reduce_macro_atom_estimators()`` +A barrier is also placed in ``calloc_wind()`` (``gridwind.c``) immediately after +the node leader's ``memset`` that zero-initialises the shared ``wmain`` block, +ensuring the zeroed memory is visible to all node-local ranks before any rank +begins writing wind-cell fields. + +Two additional barriers appear in ``create_wind_grid()`` (``define_wind.c``): + +- Before ``make_coordinate_grid()`` — ensures all ranks have completed the + serial ``wmain`` field initialisation loop (which writes ``inwind = + W_NOT_ASSIGNED``) before any rank enters ``make_coordinate_grid()``, which + for imported models overwrites ``inwind`` with values from the import file. + Without this, a fast rank's import writes can be overwritten by a slow rank's + init-loop writes, leaving cells with ``inwind = W_NOT_ASSIGNED``. +- After ``wind_complete()`` — ensures all ranks have finished + ``make_coordinate_grid()`` and ``wind_complete()`` before any rank enters + the parallel volume/velocity loop. Without this, a fast rank can read a + cell's ``inwind`` value before a slow rank has finished writing it from the + coordinate grid setup. + During photon transport, state arrays are read-only so no synchronisation is required. The ``sobolev()`` function in ``resonate.c`` previously modified ``state.density`` temporarily during transport; it now passes a @@ -426,3 +446,67 @@ The chunk size is computed at runtime as 1000 cells per chunk and 13 Allreduce calls instead of one for big.pf. Peak transient memory is reduced from ~1.17 GB to ~50 MB at the cost of a small increase in Allreduce call overhead. + +Platform differences: macOS vs Linux +===================================== + +The shared-memory code paths behave differently on macOS and Linux. Because of +this, certain classes of bug are only visible on Linux, and **any change to the +shared-memory allocation or synchronisation logic must be tested on both +platforms** before merging. + +macOS behaviour +--------------- + +On macOS with OpenMPI 5.x, ``MPI_Win_allocate_shared`` has two known +limitations: + +1. **Permission fault (SEGV_ACCERR).** Non-allocating ranks receive a window + pointer that is mapped read-only, so the first write from any rank other than + the node leader causes a ``SEGV_ACCERR`` (signal code 2, "address has wrong + permissions"). + +2. **Tiny shared-memory limit.** The ``kern.sysv.shmmax`` kernel parameter + defaults to 4 MB on macOS, far smaller than a typical wind grid. + +As a result, the ``wmain`` wind array uses a **private** ``calloc`` per rank on +macOS (guarded by ``#ifdef __APPLE__`` in ``calloc_wind()`` and +``free_wind_grid()``). Each rank holds its own independent copy, kept in sync +by ``broadcast_wind_grid()``. + +The plasma and macro-atom dynamic arrays (allocated by ``calloc_dyn_plasma()`` +and ``calloc_estimators()``) still use ``MPI_Win_allocate_shared`` on macOS via +``alloc_block_double()`` / ``alloc_block_int()``. Whether these work correctly +on macOS under all OpenMPI versions has not been fully audited; if macOS +``SEGV_ACCERR`` faults re-emerge for plasma arrays, the same ``#ifdef __APPLE__`` +fallback pattern should be applied. + +Linux behaviour +--------------- + +On Linux, ``MPI_Win_allocate_shared`` works as specified: all node-local ranks +receive a pointer to the same physical pages. Both ``wmain`` and the plasma/macro +dynamic arrays are therefore genuinely shared in memory — one physical copy per +node, not per rank. + +Consequences for testing and debugging +--------------------------------------- + +Because macOS uses a private copy of ``wmain`` per rank, **race conditions in +the shared wind-grid code path are invisible on macOS**. Specifically: + +- Missing ``MPI_Barrier(node_comm)`` calls after shared writes to ``wmain`` + (e.g. the barriers in ``calloc_wind()`` and ``broadcast_wind_grid()``) have + no effect on macOS but are essential on Linux. Without them, a rank can + proceed past a broadcast and read stale zero-initialised memory, producing + errors such as *"wind cell has zero volume but flagged inwind"* or silent + wrong results. + +- Similarly, any new code that allocates or writes to a shared MPI window must + include a ``MPI_Barrier(node_comm)`` before any rank reads from that window. + This requirement will not be caught by macOS testing alone. + +**Rule of thumb:** whenever you add, remove, or reorder a ``MPI_Barrier``, +``MPI_Win_allocate_shared``, ``MPI_Win_shared_query``, or ``memset`` on a shared +block, run the full regression suite on Linux before merging. Mac testing is +sufficient for everything else in the MPI layer. diff --git a/source/communicate_wind.c b/source/communicate_wind.c index a4e948137..46862067d 100644 --- a/source/communicate_wind.c +++ b/source/communicate_wind.c @@ -161,6 +161,10 @@ broadcast_wind_grid (const int n_start, const int n_stop, const int n_cells_rank free (comm_buffer); MPI_Type_free (&wcone_derived_type); + + /* Barrier to ensure shared memory writes are visible to all node-local ranks */ + MPI_Barrier (node_comm); + d_xsignal (files.root, "%-20s Finished communication of wind grid\n", "NOK"); #endif } diff --git a/source/define_wind.c b/source/define_wind.c index e420a0837..4b8b6f1c5 100644 --- a/source/define_wind.c +++ b/source/define_wind.c @@ -635,6 +635,14 @@ create_wind_grid (void) offset += zdom[ndom].ndim; } + /* Barrier: ensure all ranks have finished initialising wmain fields above + * before any rank enters make_coordinate_grid. With shared wmain, a fast + * rank could otherwise start writing import-derived inwind values while a + * slow rank's init loop is still writing W_NOT_ASSIGNED to the same cells. */ +#ifdef MPI_ON + MPI_Barrier (node_comm); +#endif + /* The first thing we need to do is to create the coordinate grid. We'll do * this in serial, as it's very difficult to untangle this process into * something done in parallel due to data dependencies and how certain/special @@ -649,6 +657,14 @@ create_wind_grid (void) * As above, it is impractical and not worthwhile to parallelise this step */ wind_complete (); + /* Barrier: ensure all ranks have completed make_coordinate_grid and + * wind_complete before any rank enters the parallel volume/velocity loop. + * Without this, a fast rank could read a cell's inwind value before a slow + * rank has finished writing it from make_coordinate_grid. */ +#ifdef MPI_ON + MPI_Barrier (node_comm); +#endif + #ifdef MPI_ON n_cells_rank = get_parallel_nrange (rank_global, NDIM2, np_mpi_global, &n_start, &n_stop); #else diff --git a/source/gridwind.c b/source/gridwind.c index 9c8b14331..8a6bfcfcc 100644 --- a/source/gridwind.c +++ b/source/gridwind.c @@ -350,6 +350,8 @@ calloc_wind (int nelem) MPI_Win_shared_query (wmain_win, 0, &win_size, &disp_unit, &base); } wmain = (WindPtr) base; + /* Barrier to ensure node leader's memset is visible before any rank uses wmain */ + MPI_Barrier (node_comm); #else /* macOS: MPI-3 shared memory windows are mapped with invalid permissions * for non-allocating ranks, causing SEGV_ACCERR. Use private calloc on diff --git a/source/sirocco.c b/source/sirocco.c index ad10eb45d..e49997cd6 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -792,16 +792,6 @@ main (int argc, char *argv[]) /* Finally done */ -#ifdef MPI_ON - char dummy[LINELENGTH]; - sprintf (dummy, "End of program, Thread %d only", rank_global); // added so we make clear these are just errors for thread ngit status - error_summary (dummy); // Summarize the errors that were recorded by the program - Log ("Run py_error.py for full error report.\n"); - MPI_Finalize (); -#else - error_summary ("End of program"); // Summarize the errors that were recorded by the program -#endif - #ifdef CUDA_ON cusolver_destroy (); #endif @@ -830,12 +820,26 @@ main (int argc, char *argv[]) Log ("Information about luminosities and apparent fluxes due to various portions of the system:\n"); phot_status (); +#ifdef MPI_ON + { + char dummy[LINELENGTH]; + sprintf (dummy, "End of program, Thread %d only", rank_global); + error_summary (dummy); + Log ("Run py_error.py for full error report.\n"); + } +#else + error_summary ("End of program"); +#endif + /* clean_on_exit calls free_wind_grid which calls MPI_Win_free — must happen before MPI_Finalize */ clean_on_exit (); print_memory_usage ("After program is complete"); Log_close (); +#ifdef MPI_ON + MPI_Finalize (); +#endif return (0); } diff --git a/source/tests/Makefile b/source/tests/Makefile index 1587e73f5..0f85b73d4 100644 --- a/source/tests/Makefile +++ b/source/tests/Makefile @@ -15,7 +15,11 @@ TARGET = sirocco_unit_test I_FLAGS = -I$(SIROCCO)/include L_FLAGS = -L$(SIROCCO)/lib -C_FLAGS = -O3 -Wall -Wno-deprecated-non-prototype -DMATOM_VER=$(MATOM_VER) +C_FLAGS = -O3 -Wall -Wno-unused-result -DMATOM_VER=$(MATOM_VER) +UNAME := $(shell uname) +ifeq ($(UNAME), Darwin) + C_FLAGS += -Wno-deprecated-non-prototype +endif CU_FLAGS = -O3 INCLUDES = diff --git a/source/tests/tests/test_define_wind.c b/source/tests/tests/test_define_wind.c index 0d195334e..51293f576 100644 --- a/source/tests/tests/test_define_wind.c +++ b/source/tests/tests/test_define_wind.c @@ -26,9 +26,9 @@ char *SIROCCO_ENV; char TEST_CWD[LINELENGTH]; char ATOMIC_DATA_TARGET[LINELENGTH]; -char ATOMIC_DATA_DEST[LINELENGTH]; +char ATOMIC_DATA_DEST[2 * LINELENGTH]; char ATOMIC_DATA_TARGET_DEVELOPER[LINELENGTH]; -char ATOMIC_DATA_DEST_DEVELOPER[LINELENGTH]; +char ATOMIC_DATA_DEST_DEVELOPER[2 * LINELENGTH]; #define TEST_DATA_LENGTH 2056 @@ -616,7 +616,7 @@ suite_init (void) return EXIT_FAILURE; } - snprintf (ATOMIC_DATA_DEST, LINELENGTH, "%s/data", TEST_CWD); + snprintf (ATOMIC_DATA_DEST, 2 * LINELENGTH, "%s/data", TEST_CWD); if (symlink (ATOMIC_DATA_TARGET, ATOMIC_DATA_DEST) != EXIT_SUCCESS) { /* If the symlink exists, we'll try not worry about it as if something is @@ -636,7 +636,7 @@ suite_init (void) return EXIT_FAILURE; } - snprintf (ATOMIC_DATA_DEST_DEVELOPER, LINELENGTH, "%s/zdata", TEST_CWD); + snprintf (ATOMIC_DATA_DEST_DEVELOPER, 2 * LINELENGTH, "%s/zdata", TEST_CWD); if (symlink (ATOMIC_DATA_TARGET_DEVELOPER, ATOMIC_DATA_DEST_DEVELOPER) != EXIT_SUCCESS) { /* If the symlink exists, we'll try not worry about it as if something is diff --git a/source/tests/tests/test_matrix.c b/source/tests/tests/test_matrix.c index 9bba4ad11..6c376e915 100644 --- a/source/tests/tests/test_matrix.c +++ b/source/tests/tests/test_matrix.c @@ -173,15 +173,15 @@ call_invert_matrix (const char *test_name) CU_FAIL_FATAL ("$SIROCCO has not been set"); } - double *matrix; - double *inverse; + double *matrix = NULL; + double *inverse = NULL; char matrix_filepath[BUFFER_LENGTH]; char inverse_filepath[BUFFER_LENGTH]; sprintf (matrix_filepath, "%s/source/tests/test_data/matrix/%s/matrix.txt", sirocco_path, test_name); sprintf (inverse_filepath, "%s/source/tests/test_data/matrix/%s/inverse.txt", sirocco_path, test_name); - int matrix_size; + int matrix_size = 0; const int get_err = get_invert_matrix_test_data (matrix_filepath, inverse_filepath, &matrix, &inverse, &matrix_size); if (get_err) { @@ -227,9 +227,9 @@ call_solve_matrix (const char *test_name) CU_FAIL_FATAL ("$SIROCCO has not been set"); } - double *matrix_a; - double *vector_b; - double *vector_x; + double *matrix_a = NULL; + double *vector_b = NULL; + double *vector_x = NULL; char matrix_a_filepath[BUFFER_LENGTH]; char vector_b_filepath[BUFFER_LENGTH]; char vector_x_filepath[BUFFER_LENGTH]; @@ -238,7 +238,7 @@ call_solve_matrix (const char *test_name) sprintf (vector_b_filepath, "%s/source/tests/test_data/matrix/%s/b.txt", sirocco_path, test_name); sprintf (vector_x_filepath, "%s/source/tests/test_data/matrix/%s/x.txt", sirocco_path, test_name); - int vector_size; + int vector_size = 0; const int get_err = get_solve_matrix_test_data (matrix_a_filepath, vector_b_filepath, vector_x_filepath, &matrix_a, &vector_b, &vector_x, &vector_size); if (get_err) diff --git a/source/tests/unit_test_model.c b/source/tests/unit_test_model.c index 3c5092007..3f2b02144 100644 --- a/source/tests/unit_test_model.c +++ b/source/tests/unit_test_model.c @@ -79,7 +79,7 @@ int cleanup_model (const char *root_name) { char *SIROCCO_ENV; - char parameter_filepath[LINELENGTH]; + char parameter_filepath[2 * LINELENGTH]; (void) root_name; @@ -90,7 +90,7 @@ cleanup_model (const char *root_name) return EXIT_FAILURE; } - snprintf (parameter_filepath, LINELENGTH, "%s/source/tests/test_data/define_wind/%s.pf", SIROCCO_ENV, files.root); + snprintf (parameter_filepath, 2 * LINELENGTH, "%s/source/tests/test_data/define_wind/%s.pf", SIROCCO_ENV, files.root); if (cpar (parameter_filepath) != 1) /* cpar returns 1 when something is "normal" */ { return EXIT_FAILURE; @@ -203,7 +203,7 @@ setup_model_grid (const char *root_name, const char *atomic_data_location) char *SIROCCO_ENV; char rdchoice_answer[LINELENGTH]; char rdchoice_choices[LINELENGTH]; - char parameter_filepath[LINELENGTH]; + char parameter_filepath[2 * LINELENGTH]; SIROCCO_ENV = getenv ("SIROCCO"); if (SIROCCO_ENV == NULL) @@ -217,7 +217,7 @@ setup_model_grid (const char *root_name, const char *atomic_data_location) /* Set up parameter file, that way we can get all the parameters from that * instead of defining them manually */ strcpy (files.root, root_name); - snprintf (parameter_filepath, LINELENGTH, "%s/source/tests/test_data/define_wind/%s.pf", SIROCCO_ENV, files.root); + snprintf (parameter_filepath, 2 * LINELENGTH, "%s/source/tests/test_data/define_wind/%s.pf", SIROCCO_ENV, files.root); if (opar (parameter_filepath) != 2) /* opar returns 2 when reading for the parameter file */ { fprintf (stderr, "Unable to read from parameter file %s.pf", files.root); From 7d7056d22d881066a75684afa186a02c9ccb9d67 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 17 Apr 2026 22:00:05 -0500 Subject: [PATCH 18/33] Rename mpi_comms.rst to mixed_memory_model.rst and restructure Replaces the old MPI communication page with a new page that leads with an explanation of the v2.0 mixed memory model, contrasting it with the pure-MPI approach of v1.2. Adds explicit descriptions of both communication modes (broadcast for state/derived, reduce for estimators), a decision guide for adding new variables, and coverage of spectra accumulation via communicate_spectra.c. Co-Authored-By: Claude Sonnet 4.6 --- docs/sphinx/source/developer.rst | 2 +- .../source/developer/mixed_memory_model.rst | 692 ++++++++++++++++++ docs/sphinx/source/developer/mpi_comms.rst | 512 ------------- .../source/developer/programmer_notes.rst | 4 +- 4 files changed, 695 insertions(+), 515 deletions(-) create mode 100644 docs/sphinx/source/developer/mixed_memory_model.rst delete mode 100644 docs/sphinx/source/developer/mpi_comms.rst diff --git a/docs/sphinx/source/developer.rst b/docs/sphinx/source/developer.rst index 818e273a8..60b6ad38e 100644 --- a/docs/sphinx/source/developer.rst +++ b/docs/sphinx/source/developer.rst @@ -7,6 +7,6 @@ This page contains documentation intended for developers. :glob: developer/programmer_notes - developer/mpi_comms + developer/mixed_memory_model developer/cuda developer/tests diff --git a/docs/sphinx/source/developer/mixed_memory_model.rst b/docs/sphinx/source/developer/mixed_memory_model.rst new file mode 100644 index 000000000..6f66637e3 --- /dev/null +++ b/docs/sphinx/source/developer/mixed_memory_model.rst @@ -0,0 +1,692 @@ +Mixed Memory Model and MPI Communication +######################################### + +Overview +======== + +Version 2.0 of SIROCCO introduced a **mixed memory model** that significantly +reduces per-rank memory consumption on multi-core nodes. Understanding this +model is essential for any developer working on parallelisation, data +communication, or memory allocation. + +SIROCCO uses MPI to run across multiple ranks (independent processes, each +with their own address space). There are two distinct inter-rank communication +patterns, applied at different points in the simulation cycle: + +**Broadcast** (one rank → all ranks) + Used *after* each ionization or spectral cycle, once a rank has updated + its share of the wind or plasma grid. Each rank in turn packs its updated + cells into a buffer and calls ``MPI_Bcast`` so every other rank receives + the result. This is how ``state`` and ``derived`` sub-structure fields are + kept consistent across ranks. + +**Reduce** (all ranks → one combined result) + Used *after* photon transport, to combine the partial radiation-field + estimators that each rank accumulated independently while transporting its + subset of photons. All ranks call ``MPI_Allreduce`` (or an equivalent + loop) to sum their per-rank tallies into a single global value. This is + how ``est`` sub-structure fields are aggregated. + +Which pattern applies to a given variable is determined entirely by which +sub-structure it belongs to — ``state`` and ``derived`` fields are broadcast; +``est`` fields are reduced. See `Choosing the right communication pattern`_ +for a decision guide before diving into the implementation details. + +Memory model: version 1.2 vs version 2.0 +====================================================== + +Version 1.2: pure MPI, all data duplicated +--------------------------------------------------------- + +In version 1.2 every MPI rank held its **own independent, complete copy** of +all data structures — the plasma grid (``plasmamain``), the macro-atom grid +(``macromain``), and the wind geometry array (``wmain``). Data was shared +between ranks exclusively through explicit MPI message-passing calls +(``MPI_Pack`` / ``MPI_Bcast`` / ``MPI_Unpack``). + +This meant that on a node with *R* ranks, the same read-only state data (ion +populations, spectral-model parameters, transition-probability matrices, etc.) +was stored *R* times in physical memory. For large models with macro-atom +atomic data this could amount to tens of gigabytes of duplicated memory per +node. + +Version 2.0 : mixed shared + private memory +----------------------------------------------------------- + +Version 2.0 replaces the duplicated-copy model with a **mixed memory model**: + +- **Shared memory (one copy per node)** — data that is read-only during + photon transport is allocated using MPI-3 ``MPI_Win_allocate_shared``. + All ranks on the same physical node map their pointers to the *same* + physical pages. There is therefore only one copy per node regardless of + how many ranks that node hosts. + +- **Private memory (one copy per rank)** — data that each rank writes + independently during photon transport (radiation-field estimators, photon + counters, scatter tallies) is allocated with ordinary ``calloc``. Each + rank has its own copy so writes never race. + +- **MPI message passing (unchanged)** — after each ionization or spectral + cycle the results from all ranks are combined via the same ``MPI_Pack`` / + ``MPI_Bcast`` / ``MPI_Unpack`` pattern used in v1.2. The broadcasts now + write into the shared memory regions and are followed by + ``MPI_Barrier(node_comm)`` calls to ensure coherence before transport + resumes. + +The split between shared and private follows the three sub-structure +decomposition of ``plasma_dummy`` and ``macro_dummy``: + +.. list-table:: + :header-rows: 1 + :widths: 20 35 15 30 + + * - Sub-structure + - Typical contents + - Memory in v2.0 + - Memory in v1.2 + * - ``state`` + - Ion populations, spectral model params + - **Shared** + - Private (duplicated) + * - ``est`` (estimators) + - Radiation field estimators, heating rates + - **Private** + - Private + * - ``derived`` + - Cooling rates, luminosities, transition matrix + - **Shared** + - Private (duplicated) + +The net effect is that for a model with *N* plasma cells, *I* ions, and *R* +ranks on one node, the dominant variable-length state and derived arrays +(roughly ``N × I × 14 × 8`` bytes) exist only once per node instead of *R* +times. See `Memory savings`_ below for worked examples. + +MPI communication files +======================= + +All calls to MPI are isolated from the rest of SIROCCO. Most, if not all, of +the MPI code is contained within five source files: + +- :code:`communicate_macro.c` +- :code:`communicate_plasma.c` +- :code:`communicate_spectra.c` +- :code:`communicate_wind.c` +- :code:`para_update.c` + +If you need to extend or implement a new function for MPI, please place it +either in one of the above files or create a new file using an appropriately +similar name. Any parallel code should be wrapped by :code:`#ifdef MPI_ON` +and :code:`#endif` as shown below: + +.. code:: c + + void communication_function(void) + { + #ifdef MPI_ON + /* MPI communication code should go between the #ifdef's here */ + #endif + } + +Don't forget to update the Makefile and :code:`templates.h` if you add a new +file or function. + +Choosing the right communication pattern +========================================= + +The ``plasma_dummy`` and ``macro_dummy`` structures are each divided into three +sub-structures. The sub-structure a variable belongs to determines which +communication pattern applies — and therefore which function to modify when +adding or removing a variable. + +**The rule is simple:** + +- ``est`` (estimator) fields are **reduced** — each rank accumulates + partial results during photon transport; ``MPI_Allreduce`` sums them across + all ranks. Any variable that is incremented or accumulated as photons pass + through the grid belongs here and must be handled via a reduce. +- ``state`` and ``derived`` fields are **broadcast** — one rank computes + updated values during the wind update phase; ``MPI_Bcast`` distributes them + to all ranks. Any variable that is not written during photon transport + belongs here and is placed in shared memory. + +.. list-table:: Plasma sub-structures and their communication + :header-rows: 1 + :widths: 20 30 20 30 + + * - Sub-structure + - Contents + - Pattern + - Key functions + * - ``state`` + - Thermodynamic state (``ne``, ``t_e``, ``t_r``, ``w``, ``rho``, ``vol``), ion populations (``density``, ``partition``, ``levden``), spectral model parameters, bound-free data + - **Broadcast** + - ``broadcast_updated_plasma_properties()``, ``broadcast_plasma_grid()`` + * - ``est`` + - Radiation field estimators (``j``, ``ave_freq``), heating rates (``heat_tot``, ``heat_lines``, etc.), photon counters, flux estimators, cell spectra, ionization estimators + - **Reduce** + - ``reduce_simple_estimators()`` + * - ``derived`` + - Cooling rates, luminosities, convergence diagnostics, scatter counts, persistent flux averages, ionization parameter (``xi``) + - **Broadcast** + - ``broadcast_updated_plasma_properties()``, ``broadcast_wind_luminosity()``, ``broadcast_wind_cooling()`` + +.. list-table:: Macro-atom sub-structures and their communication + :header-rows: 1 + :widths: 20 30 20 30 + + * - Sub-structure + - Contents + - Pattern + - Key functions + * - ``state`` + - Normalized rate coefficients (``jbar_old``, ``gamma_old``, ``alpha_st_old``, etc.), mode flags + - **Broadcast** + - ``broadcast_updated_macro_atom_properties()`` + * - ``est`` + - Raw Sobolev mean intensities (``jbar``), photoionization rates (``gamma``), stimulated recombination rates (``alpha_st``), macro-atom absorption, cooling stores + - **Reduce** + - ``reduce_macro_atom_estimators()`` + * - ``derived`` + - Macro-atom emissivities (``matom_emiss``), k-packet rate flags, transition probability matrix (``matom_matrix``) + - **Broadcast** + - ``broadcast_macro_atom_emissivities()``, ``broadcast_macro_atom_state_matrix()`` + +The sections below describe how each pattern is implemented and give step-by-step +instructions for adding or removing a variable from each. + +Mode 1: Broadcast (state and derived variables) +================================================ + +Broadcast is used to distribute updated ``state`` and ``derived`` fields after +the wind update phase of each ionization cycle. One rank at a time acts as +root: it packs its updated cell range into a buffer and calls ``MPI_Bcast`` so +every other rank receives the result. The full loop ensures each rank +eventually sends its cell subset to all others. + +As the data structures in SIROCCO are fairly complex and use +pointers/dynamic memory allocation, data must be manually packed and unpacked +into a contiguous communication buffer — a fairly manual (and error-prone) +process. + +Calculating the broadcast buffer size +-------------------------------------- + +The size of the communication buffer has to be calculated manually, by +counting the number of variables being copied into it and converting this to +the appropriate number of bytes. This is done by the +:code:`calculate_comm_buffer_size` function which takes two arguments: 1) the +number of :code:`int`'s and 2) the number of :code:`double`'s. We have to +*manually* count the number of :code:`int` and :code:`double` variables being +communicated. Due to the manual nature of this, great care has to be taken to +ensure the correct number are counted otherwise MPI will cause a crash during +communication. + +When counting variables, one needs to count the number of *single* variables +of a certain type as well as the number of elements in an array of that same +type. Consider the example below, + +.. code:: c + + int my_int; + int *my_int_arr = malloc(10 * sizeof(int)); + int num_ints = 11; + +In this case there are 11 integer variables which will want to be communicated. +In practise, calculating the communication buffer is usually done as in the +code example below: + +.. code:: c + + /* We need to ensure the buffer is large enough, as some ranks may be sending a smaller + communicating buffer. When communicating the plasma grid for example, some ranks may send + 10 cells whilst others may send 9. Therefore we need the buffer to be big enough to receive + 10 cells of data */ + int n_cells_max = get_max_cells_per_rank(NDIM2); + + /* Count the number of integers which will be copied to the communication buffer. In this + example (20 + 2 * nphot_total + 1) is the number of ints being sent PER CELL; + 20 corresponds to 20 ints, 2 * nphot_total corresponds to 2 arrays with nphot_total elements + and the + 1 is an extra int to send the cell number. The extra + 1 at the end is used to + communicate the size of the buffer in bytes */ + int num_ints = n_cells_max * (20 + nphot_total + 1) + 1; + + /* Count the number of doubles to send, following the same arguments as above */ + int num_doubles = n_cells_max * (71 + 2 * NXBANDS + 6 * nphot_total); + + /* Using the data above, we can calculate the buffer size in bytes and then allocate memory*/ + int comm_buffer_size = calculate_comm_buffer_size(num_ints, num_doubles); + char * comm_buffer = malloc(comm_buffer_size); + +Broadcast implementation +------------------------- + +The general pattern for packing data into a communication buffer and then +broadcasting it between ranks is as follows: + +- Loop over all the MPI ranks (in MPI_COMM_WORLD). +- If the loop variable is equal to a rank's ID, that rank will broadcast its + subset of data to the other ranks. This rank uses :code:`MPI_Pack` to copy + its data into the communication buffer. +- All ranks call :code:`MPI_Bcast`, which sends data from the root rank (this + is the rank which has just put its data into the communication buffer) and + receives it into all non-root ranks. +- Non-root ranks use :code:`MPI_Unpack` to copy data from the communication + buffer into the appropriate location. +- This is repeated until all MPI ranks have sent their data as root, and have + therefore received data from all other ranks. + +In code, this looks something like this: + +.. code:: c + + char *comm_buffer = malloc(comm_buffer_size); + + /* loop over all mpi ranks */ + for (int rank = 0 ; rank < np_mpi_global; ++rank) + { + /* if rank == your rank id, then pack data into comm_buffer. This is the root rank */ + if (rank_global == rank) + { + /* communicates the number of cells the other ranks have to unpack. n_cells_rank + is usually provided via a function argument */ + MPI_Pack(&n_cells_rank, 1, MPI_INT, comm_buffer, ...); + /* start and stop refer to the first cell and last cell for the subset + of cells which this rank has updated or is broadcasting. stop and start + usually are provided via function arguments */ + for (int n_plasma = start; n_plasma < stop; ++n_plasma) + { + MPI_Pack(&plasmamain[n_plasma]->nwind, 1, MPI_INT, comm_buffer, ...); + } + } + + /* every rank calls MPI_Bcast: the root rank will send data and non-root ranks + will receive data */ + MPI_Bcast(comm_buffer, comm_buffer_size, ...); + + /* if you aren't the root rank, then unpack data from the comm buffer */ + if (rank_global != rank) + { + /* unpack the number of cells communicated, so we know how many cells of data, + for example, we need to unpack */ + MPI_Unpack(comm_buffer, 1, MPI_INT, ..., &n_cells_communicated, ...); + /* now we can unpack back into the appropriate data structure */ + for (int n_plasma = 0; n_plasma < n_cells_communicated; ++n_plasma) + { + MPI_Unpack(comm_buffer, 1, MPI_INT, ..., &plasmamain[n_plasma]->nwind, ...); + } + } + } + +This is the standard method for communicating data in SIROCCO, given the +complexity of the data structures. Unfortunately there are not many structures +or situations where using a derived data type is viable because none of the +structures are contiguous in memory. + +Adding a variable to a broadcast +---------------------------------- + +1. Identify the correct broadcast function from the table above (e.g. + ``broadcast_updated_plasma_properties()`` for plasma ``state``/``derived`` + fields). +2. Increment the appropriate variable count in the call to + :code:`calculate_comm_buffer_size`. For example, if the new variable is an + :code:`int` in the plasma grid, update + :code:`n_cells_max * (20 + 2 * n_phot_total + 1)` to + :code:`n_cells_max * (21 + 2 * n_phot_total + 1)`. +3. In the block where :code:`rank == rank_global`, add a new call to + :code:`MPI_Pack` following the existing pattern. +4. In the block where :code:`rank != rank_global`, add a matching call to + :code:`MPI_Unpack`. +5. If the variable lives in a shared-memory region, ensure an + ``MPI_Barrier(node_comm)`` follows the broadcast so all node-local ranks + see the updated value before transport resumes (see `Synchronisation`_). + +Mode 2: Reduce (estimator variables) +====================================== + +Reduce is used to combine the ``est`` (estimator) fields that each rank has +accumulated independently during photon transport. Because every rank +transports a different subset of photons, its estimators represent only a +partial contribution to the total radiation field. After transport, all ranks +call ``MPI_Allreduce`` to sum their partial values into a single consistent +result that is then available on every rank. + +The reduce step is simpler to implement than the broadcast because the +operation is a straightforward element-wise sum rather than a +rank-by-rank pack/unpack cycle. The key functions are: + +- ``reduce_simple_estimators()`` in ``communicate_plasma.c`` — sums plasma + ``est`` fields (``j``, ``ave_freq``, ``heat_tot``, etc.) across all ranks + using ``MPI_Allreduce``. +- ``reduce_macro_atom_estimators()`` in ``communicate_macro.c`` — sums + macro-atom ``est`` fields (``jbar``, ``gamma``, ``cooling_bf``, etc.), + with a chunked ``MPI_Allreduce`` for the large ``cooling_bb`` array (see + `Chunked Allreduce for cooling_bb`_). +- ``communicate_spectra.c`` — handles the output spectra, which are also + accumulated independently per rank during spectral cycles. Each rank + records photon contributions to the extracted spectra (``xxspec``) for + its own subset of photons; after transport the partial spectra are summed + across all ranks so that every rank holds the complete spectrum. The + same reduce logic applies: spectra are private during transport and + combined afterwards. + +Adding a variable to a reduction +---------------------------------- + +1. Confirm the variable belongs to an ``est`` sub-structure (it is written + during photon transport and must be summed across ranks). +2. In the appropriate reduce function, add the variable to the existing + ``MPI_Allreduce`` call, or add a new ``MPI_Allreduce`` call following the + existing pattern. +3. Ensure the variable is zeroed (reset) at the start of each transport cycle + so partial sums from the previous cycle do not accumulate. +4. Because estimator arrays are always **private** (one copy per rank), no + shared-memory or barrier changes are needed. + +MPI-3 shared memory implementation +=================================== + +When running with more than one MPI rank, SIROCCO uses MPI-3 shared memory +windows to reduce per-node memory consumption. The key idea is that ranks on +the same physical node share a single copy of data that is read-only during +photon transport, rather than duplicating it across every rank. + +During MPI initialisation (in ``sirocco.c``), a *node-local communicator* is +created with ``MPI_Comm_split_type(MPI_COMM_TYPE_SHARED, ...)``. Three global +variables track the node topology: + +- ``node_comm`` — communicator for ranks sharing the same node +- ``node_rank`` — rank index within the node (0 = node leader) +- ``node_size`` — number of ranks on the node + +Contiguous block allocation +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All variable-length plasma arrays (density, partition, ioniz, etc.) are +allocated as contiguous blocks in ``calloc_dyn_plasma()`` (in +``gridwind.c``), with each cell's pointer set to the appropriate offset +within the block. This replaces the earlier pattern of separate ``calloc`` +calls per cell and is a prerequisite for shared memory, since +``MPI_Win_allocate_shared`` requires contiguous regions. + +The allocation is performed by two helper functions, ``alloc_block_double()`` +and ``alloc_block_int()``, which accept a ``use_shared`` flag: + +- When ``use_shared`` is TRUE and ``np_mpi_global > 1``, only the node leader + (``node_rank == 0``) allocates memory via ``MPI_Win_allocate_shared``; other + ranks on the same node obtain a pointer to the same physical memory via + ``MPI_Win_shared_query``. +- When ``use_shared`` is FALSE, each rank allocates its own private block with + regular ``calloc``. + +The same contiguous block layout is used in non-MPI builds and with a single +MPI rank; the only difference is that ``calloc`` is used unconditionally. + +Which arrays are shared +^^^^^^^^^^^^^^^^^^^^^^^ + +The allocation strategy mirrors the three sub-structures: + +.. list-table:: + :header-rows: 1 + :widths: 15 55 15 15 + + * - Category + - Arrays + - Allocation + - Reason + * - **State (dynamic)** + - ``density``, ``partition``, ``levden``, ``recomb_simple``, ``recomb_simple_upweight``, ``kbf_use`` + - Shared + - Read-only during photon transport + * - **State (fixed-size)** + - ``f1``, ``f2``, ``spec_mod_type``, ``pl_alpha``, ``pl_log_w``, ``exp_temp``, ``exp_w``, ``fmin_mod``, ``fmax_mod`` + - Shared + - Spectral model parameters, read-only during transport + * - **Estimators** + - ``ioniz``, ``heat_ion``, ``heat_inner_ion``, ``inner_ioniz`` + - Private + - Each rank accumulates independently + * - **Derived (dynamic)** + - ``recomb``, ``cool_rr_ion``, ``lum_rr_ion``, ``cool_dr_ion``, ``inner_recomb`` + - Shared + - Computed during wind updates, then broadcast + * - **Derived (fixed-size)** + - ``F_vis_persistent``, ``F_UV_persistent``, ``F_Xray_persistent``, ``rad_force_es_persist``, ``rad_force_ff_persist``, ``rad_force_bf_persist``, ``F_UV_ang_theta_persist``, ``F_UV_ang_phi_persist``, ``F_UV_ang_r_persist`` + - Shared + - Persistent radiation field averages, read-only during transport + * - **Derived (exceptions)** + - ``scatters``, ``xscatters``, ``n_bf_in``, ``n_bf_out`` + - Private + - Incremented during photon transport (would race in shared memory). ``n_bf_in``/``n_bf_out`` are dynamically sized to ``nphot_total`` (formerly fixed at ``N_PHOT_PROC=500``). + +The same shared/private split applies to macro-atom dynamic arrays in +``calloc_estimators()`` and ``calloc_matom_matrix()`` (both in +``gridwind.c``). State and derived arrays (``jbar_old``, ``gamma_old``, +``matom_emiss``, and the transition probability matrix ``matom_matrix``) are +shared, while estimator arrays (``jbar``, ``gamma``, ``cooling_bf``, +``cooling_bb``, etc.) are private. + +The ``matom_matrix`` (an *nrows × nrows* transition probability matrix per +cell, where *nrows = nlevels_macro + 1*) is allocated as a single contiguous +shared block in ``calloc_matom_matrix()``. The flat data +(``NPLASMA × nrows × nrows`` doubles) lives in +``macro_block_ptrs.matom_matrix_block`` (shared), while a private per-rank +array of row-pointers (``matom_matrix_rowptrs``) points into the shared block +to preserve the ``double **`` interface used throughout the code. The matrix +is computed during wind updates — each rank fills its own cell slice — then +broadcast via ``broadcast_macro_atom_state_matrix()`` so all nodes obtain a +complete copy. The ``MPI_Barrier(node_comm)`` at the end of that function +ensures node-local ranks see the written data before transport begins. +Because the matrix is strictly read-only during photon transport, no further +synchronisation is required. + +Block pointer management +^^^^^^^^^^^^^^^^^^^^^^^^ + +Base pointers for all contiguous blocks are stored in global structs +``plasma_block_ptrs`` (type ``plasma_blocks``) and ``macro_block_ptrs`` +(type ``macro_blocks``), declared in ``sirocco.h``. These structs also hold +the ``MPI_Win`` handles needed to free shared windows and a +``shared_memory_active`` flag that records whether the current allocation +used shared memory. + +Synchronisation +^^^^^^^^^^^^^^^ + +After any broadcast that writes to shared dynamic arrays, an +``MPI_Barrier(node_comm)`` ensures all node-local ranks see the new data +before proceeding. These barriers appear at the end of: + +- ``broadcast_wind_grid()`` +- ``broadcast_updated_plasma_properties()`` +- ``broadcast_plasma_grid()`` +- ``broadcast_wind_luminosity()`` +- ``broadcast_wind_cooling()`` +- ``broadcast_updated_macro_atom_properties()`` +- ``broadcast_macro_atom_emissivities()`` +- ``reduce_macro_atom_estimators()`` + +A barrier is also placed in ``calloc_wind()`` (``gridwind.c``) immediately +after the node leader's ``memset`` that zero-initialises the shared ``wmain`` +block, ensuring the zeroed memory is visible to all node-local ranks before +any rank begins writing wind-cell fields. + +Two additional barriers appear in ``create_wind_grid()`` +(``define_wind.c``): + +- Before ``make_coordinate_grid()`` — ensures all ranks have completed the + serial ``wmain`` field initialisation loop (which writes ``inwind = + W_NOT_ASSIGNED``) before any rank enters ``make_coordinate_grid()``, which + for imported models overwrites ``inwind`` with values from the import file. + Without this, a fast rank's import writes can be overwritten by a slow + rank's init-loop writes, leaving cells with ``inwind = W_NOT_ASSIGNED``. +- After ``wind_complete()`` — ensures all ranks have finished + ``make_coordinate_grid()`` and ``wind_complete()`` before any rank enters + the parallel volume/velocity loop. Without this, a fast rank can read a + cell's ``inwind`` value before a slow rank has finished writing it from the + coordinate grid setup. + +During photon transport, state arrays are read-only so no synchronisation is +required. The ``sobolev()`` function in ``resonate.c`` previously modified +``state.density`` temporarily during transport; it now passes a density +override to ``two_level_atom()`` instead, avoiding a race condition on shared +memory. + +Cleanup +^^^^^^^ + +At program exit, ``free_plasma_grid()`` and ``free_macro_grid()`` in +``janitor.c`` free the contiguous blocks. For shared blocks the memory is +owned by the MPI window, so the pointer is simply NULLed (the MPI runtime +frees it at ``MPI_Finalize``). Private blocks are freed with ``free()`` as +usual. + +Memory savings +^^^^^^^^^^^^^^ + +For a model with *N* plasma cells, *I* ions, and *R* ranks on one node, the +dominant dynamic arrays total roughly ``N * I * 14 * 8`` bytes per rank. +With shared memory the state and derived arrays exist only once per node, +reducing the per-node footprint by approximately ``(R-1)/R`` of the shared +portion. Estimator arrays remain duplicated across ranks. + +In addition to the variable-length dynamic arrays, fixed-size arrays that +were previously embedded in the ``plasma_state`` and ``plasma_derived`` +sub-structures (spectral model parameters, persistent flux averages) have +been moved to shared contiguous blocks. These arrays are declared as +pointers in the struct and point into combined blocks allocated in +``calloc_dyn_plasma()``. This reduces ``sizeof(plasma_dummy)`` by +approximately 2.3 KB per cell, yielding additional PSS savings of roughly +``2.3 * N * (R-1)/R`` KB. The savings scale linearly with NPLASMA: for a +model with 80K cells and 29 ranks, this adds approximately 177 MB of +per-rank savings. + +The transition probability matrix ``matom_matrix`` (``nrows × nrows`` doubles +per cell, allocated by ``calloc_matom_matrix()``) is also placed in shared +memory. For the ``h20_hetop_standard80`` atomic dataset (85 macro-atom +levels, *nrows* = 86) and a 300×300 grid with ~12,000 active plasma cells, +this matrix totals approximately 726 MB. Without shared memory each of the +*R* ranks holds its own copy; with shared memory there is one copy per node. +On a 24-rank single-node run this saves roughly ``726 × 23 ≈ 16.7 GB`` of +physical memory, making it the single largest shared-memory saving in the +code. + +Shared wind structure +^^^^^^^^^^^^^^^^^^^^^ + +The wind geometry array ``wmain`` (type ``wind_dummy``, indexed by NDIM2) is +allocated via ``MPI_Win_allocate_shared`` in ``calloc_wind()`` so that all +ranks on the same node share a single copy. This is safe because ``wmain`` +is populated during initialization and is strictly read-only during photon +transport. + +The reverb path-tracking data (``paths`` and ``line_paths``) was moved out of +``wind_dummy`` into a separate per-rank array ``wind_paths_main`` (type +``wind_paths_store``), because path histograms are accumulated during photon +transport and must remain private per rank. Code in ``paths.c`` accesses +these via ``wind_paths_main[cell_index]`` instead of +``wmain[cell_index]``. + +For a 300x300 grid (NDIM2 = 90,000, ``sizeof(wind_dummy)`` = 288 bytes), +this saves approximately ``90000 * 288 * (R-1)/R`` bytes, or about 25 MB per +rank with 29 ranks. + +Single-node optimisation for matom_matrix broadcast +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``broadcast_macro_atom_state_matrix()`` in ``communicate_macro.c`` normally +packs the full transition-probability matrix for each rank's cell range into a +comm buffer and broadcasts it to all other ranks. When ``matom_matrix`` lives +in shared memory (the normal MPI build) and all ranks are on the same node +(``num_nodes == 1``), this broadcast is unnecessary: the writing rank's data +is already visible to all node-local ranks through shared memory. The +function therefore returns early with a ``MPI_Barrier(node_comm)`` to ensure +coherence, skipping the pack/Bcast/unpack cycle entirely. On a single-node +run this avoids allocating the comm buffer (~100 KB) and removes latency +proportional to the number of ranks. + +Chunked Allreduce for cooling_bb +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``reduce_macro_atom_estimators()`` in ``communicate_macro.c`` uses +``MPI_Allreduce`` to sum the per-rank ``cooling_bb`` estimator across all +ranks. The naive approach allocates two temporary buffers of size +``NPLASMA × nlines`` doubles each. For big.pf (12270 cells, 5964 lines) +this is approximately 2 × 585 MB = 1.17 GB of transient peak memory per rank. + +The function instead processes cells in chunks, targeting a peak buffer size +of ~50 MB. For each chunk of cells the data is packed into a single +``chunk_cells × nlines`` buffer, reduced in place with +``MPI_Allreduce(MPI_IN_PLACE, ...)``, and unpacked back to ``macromain``. +The chunk size is computed at runtime as +``chunk_size = 50 MB / (nlines × sizeof(double))``, giving approximately +1000 cells per chunk and 13 Allreduce calls instead of one for big.pf. +Peak transient memory is reduced from ~1.17 GB to ~50 MB at the cost of a +small increase in Allreduce call overhead. + +Platform differences: macOS vs Linux +===================================== + +The shared-memory code paths behave differently on macOS and Linux. Because +of this, certain classes of bug are only visible on Linux, and **any change to +the shared-memory allocation or synchronisation logic must be tested on both +platforms** before merging. + +macOS behaviour +--------------- + +On macOS with OpenMPI 5.x, ``MPI_Win_allocate_shared`` has two known +limitations: + +1. **Permission fault (SEGV_ACCERR).** Non-allocating ranks receive a window + pointer that is mapped read-only, so the first write from any rank other + than the node leader causes a ``SEGV_ACCERR`` (signal code 2, "address has + wrong permissions"). + +2. **Tiny shared-memory limit.** The ``kern.sysv.shmmax`` kernel parameter + defaults to 4 MB on macOS, far smaller than a typical wind grid. + +As a result, the ``wmain`` wind array uses a **private** ``calloc`` per rank +on macOS (guarded by ``#ifdef __APPLE__`` in ``calloc_wind()`` and +``free_wind_grid()``). Each rank holds its own independent copy, kept in sync +by ``broadcast_wind_grid()``. + +The plasma and macro-atom dynamic arrays (allocated by +``calloc_dyn_plasma()`` and ``calloc_estimators()``) still use +``MPI_Win_allocate_shared`` on macOS via ``alloc_block_double()`` / +``alloc_block_int()``. Whether these work correctly on macOS under all +OpenMPI versions has not been fully audited; if macOS ``SEGV_ACCERR`` faults +re-emerge for plasma arrays, the same ``#ifdef __APPLE__`` fallback pattern +should be applied. + +Linux behaviour +--------------- + +On Linux, ``MPI_Win_allocate_shared`` works as specified: all node-local ranks +receive a pointer to the same physical pages. Both ``wmain`` and the +plasma/macro dynamic arrays are therefore genuinely shared in memory — one +physical copy per node, not per rank. + +Consequences for testing and debugging +--------------------------------------- + +Because macOS uses a private copy of ``wmain`` per rank, **race conditions in +the shared wind-grid code path are invisible on macOS**. Specifically: + +- Missing ``MPI_Barrier(node_comm)`` calls after shared writes to ``wmain`` + (e.g. the barriers in ``calloc_wind()`` and ``broadcast_wind_grid()``) have + no effect on macOS but are essential on Linux. Without them, a rank can + proceed past a broadcast and read stale zero-initialised memory, producing + errors such as *"wind cell has zero volume but flagged inwind"* or silent + wrong results. + +- Similarly, any new code that allocates or writes to a shared MPI window must + include a ``MPI_Barrier(node_comm)`` before any rank reads from that window. + This requirement will not be caught by macOS testing alone. + +**Rule of thumb:** whenever you add, remove, or reorder a ``MPI_Barrier``, +``MPI_Win_allocate_shared``, ``MPI_Win_shared_query``, or ``memset`` on a +shared block, run the full regression suite on Linux before merging. Mac +testing is sufficient for everything else in the MPI layer. diff --git a/docs/sphinx/source/developer/mpi_comms.rst b/docs/sphinx/source/developer/mpi_comms.rst deleted file mode 100644 index dc94fbe4f..000000000 --- a/docs/sphinx/source/developer/mpi_comms.rst +++ /dev/null @@ -1,512 +0,0 @@ -MPI Communication -################# - -SIROCCO is parallelised using the Message Passing Interface (MPI). This page contains information on how data is shared -between ranks and should serve as a basic set of instructions for extending or modifying the data communication -routines. - -In general, all calls to MPI are isolated from the rest of SIROCCO. Most, if not all, of the MPI code is contained -within five source files, which deal entirely with parallelisation or communication. Currently these files are: - -- :code:`communicate_macro.c` -- :code:`communicate_plasma.c` -- :code:`communicate_spectra.c` -- :code:`communicate_wind.c` -- :code:`para_update.c` - -Given the names of the files, it should be obvious what sort of code is contained in them. If you need to extend or -implement a new function for MPI, please place it either in one of the above files or create a new file using an -appropriately similar name. Any parallel code should be wrapped by :code:`#ifdef MPI_ON` and :code:`#endif` as shown in -the code example below: - -.. code:: c - - void communication_function(void) - { - #ifdef MPI_ON - /* MPI communication could should go between the #ifdef's here */ - #endif - } - -Don't forget to update the Makefile and :code:`templates.h` if you add a new file or function. - -Communication pattern: broadcasting data to all ranks -===================================================== - -By far the most typical communication pattern in SIROCCO (and, I think, the only pattern) is to broadcast data from one -rank to all other ranks. This is done, for example, to update and synchronise the plasma or macro atom grids in each -rank. As the data structures in SIROCCO are fairly complex and use pointers/dynamic memory allocation, we as forced to -manually pack and unpack a contiguous communication buffer which results in a fairly manual (and error prone?) process -for communicating data. - -Calculating the size of the communication buffer ------------------------------------------------- - -The size of the communication buffer has to be calculated manually, by counting the number of variables being copied -into it and converting this to the appropriate number of bytes. This is done by the :code:`calculate_comm_buffer_size` -function which takes two arguments: 1) the number of :code:`int`'s and 2) the number of :code:`double`'s. We have to -_manually_ count the number of :code:`int` and :code:`double` variables being communicated. Due to the manual nature of -this, greate care has to be taken to ensure the correct number are counted otherwise MPI will cause crash during -communication. - -When counting variables, one needs to count the number if _single_ variables of a certain type as well as the number of -elements in an array of that same type. Consider the example below, - -.. code:: c - - int my_int; - int *my_int_arr = malloc(10 * sizeof(int)); - int num_ints = 11; - -In this case there are 11 integer variables which will want to be communicated. In practise, calculating the communication -buffer is usually done as in the code example below: - -.. code:: c - - /* We need to ensure the buffer is large enough, as soon ranks may be sending a smaller - communicating buffer. When communicating the plasma grid for example, some ranks may send - 10 cells whilst others may send 9. Therefore we need the buffer to be big enough to receive - 10 cells of data */ - int n_cells_max = get_max_cells_per_rank(NDIM2); - - /* Count the number of integers which will be copied to the communication buffer. In this - example (20 + 2 * nphot_total + 1) is the number of ints being sent PER CELL; - 20 corresponds to 20 ints, 2 * nphot_total corresponds to 2 arrays with nphot_total elements - and the + 1 is an extra int to send the cell number. The extra + 1 at the end is used to - communicate the size of the buffer in bytes */ - int num_ints = n_cells_max * (20 + nphot_total + 1) + 1; - - /* Count the number of doubles to send, following the same arguments as above */ - int num_doubles = n_cells_max * (71 + 2 * NXBANDS + 6 * nphot_total); - - /* Using the data above, we can calculate the buffer size in bytes and then allocate memory*/ - int comm_buffer_size = calculate_comm_buffer_size(num_ints, num_doubles); - char * comm_buffer = malloc(comm_buffer_size); - -Communication implementation ----------------------------- - -The general pattern for packing data into a communication buffer and then sharing it between ranks is as follows, - -- Loop over all the MPI ranks (in MPI_COMM_WORLD. -- If the loop variable is equal to a rank's ID, that rank will broadcast it's subset of data to the other ranks. This - rank uses :code:`MPI_Pack` to copy its data into the communication buffer. -- All ranks call :code:`MPI_Bcast`, which sends data from the root rank (this is the rank which has just put its data - into the communication buffer) and receives it into all non-root ranks. -- Non-root ranks use :code:`MPI_Unpack` to copy data from the communication buffer into the appropriate location. -- This is repeated until all MPI ranks have sent their data root, and have therefore received data from all other ranks. - -In code, this looks something like this: - -.. code:: c - - char *comm_buffer = malloc(comm_buffer_size); - - /* loop over all mpi ranks */ - for (int rank = 0 ; rank < np_mpi_global; ++rank) - { - /* if rank == your rank id, then pack data into comm_buffer. This is the root rank */ - if (rank_global == rank) - { - /* communicates the number of cells the other ranks have to unpack. n_cells_rank - is usually provided via a function argument */ - MPI_Pack(&n_cells_rank, 1, MPI_INT, comm_buffer, ...); - /* start and stop refer to the first cell and last cell for the subset - of cells which this rank has updated or is broadcasting. stop and start - usually are provided via function arguments */ - for (int n_plasma = start; n_plasma < stop; ++n_plasma) - { - MPI_Pack(&plasmamain[n_plasma]->nwind, 1, MPI_INT, comm_buffer, ...); - } - } - - /* every rank calls MPI_Bcast: the root rank will send data and non-root ranks - will receive data */ - MPI_Bcast(comm_buffer, comm_buffer_size, ...); - - /* if you aren't the root rank, then unpack data from the comm buffer */ - if (rank_global != rank) - { - /* unpack the number of cells communicated, so we know how many cells of data, - for example, we need to unpack */ - MPI_Unpack(comm_buffer, 1, MPI_INT, ..., &n_cells_communicated, ...); - /* now we can unpack back into the appropriate data structure */ - for (int n_plasma = 0; n_plasma < n_cells_communicated; ++n_plasma) - { - MPI_Unpack(comm_buffer, 1, MPI_INT, ..., &plasmamain[n_plasma]->nwind, ...); - } - } - } - -This is likely the most best method to communicate data in SIROCCO, given the complexity of the data structures. -Unfortunately there are not many structures or situations where using a derived data type, to simplify code, is viable -due to none of the structures being contiguous in memory. - -Adding a new variable to an existing communication --------------------------------------------------- - -- Increment the appropriate variable, or function call to :code:`calculate_comm_buffer_size`, to account for and - allocate additional space in the communication buffer. For example, if the new variable is an :code:`int` in the - plasma grid then update :code:`n_cells_max * (20 + 2 * n_phot_total + 1)` to :code:`n_cells_max * (21 + 2 * - n_phot_total + 1)` -- In the block where :code:`rank == rank_global`, add a new call to :code:`MPI_Pack` using the code which is already - there as an example. -- In the block where :code:`rank != rank_global`, add a new call to :code:`MPI_Unpack` using the code which is already - there as an example. - -Relationship between sub-structures and communication patterns -============================================================== - -The ``plasma_dummy`` and ``macro_dummy`` structures are each divided into three -sub-structures that correspond directly to different MPI communication patterns. -This makes it straightforward to determine which communication function to modify -when adding a new variable: - -.. list-table:: Plasma sub-structures and their communication - :header-rows: 1 - :widths: 20 30 25 25 - - * - Sub-structure - - Contents - - Communication - - Key functions - * - ``state`` - - Thermodynamic state (``ne``, ``t_e``, ``t_r``, ``w``, ``rho``, ``vol``), ion populations (``density``, ``partition``, ``levden``), spectral model parameters, bound-free data - - Broadcast after wind updates - - ``broadcast_updated_plasma_properties()``, ``broadcast_plasma_grid()`` - * - ``est`` - - Radiation field estimators (``j``, ``ave_freq``), heating rates (``heat_tot``, ``heat_lines``, etc.), photon counters, flux estimators, cell spectra, ionization estimators - - Reduced (summed) across ranks after photon transport - - ``reduce_simple_estimators()`` - * - ``derived`` - - Cooling rates, luminosities, convergence diagnostics, scatter counts, persistent flux averages, ionization parameter (``xi``) - - Broadcast after wind updates - - ``broadcast_updated_plasma_properties()``, ``broadcast_wind_luminosity()``, ``broadcast_wind_cooling()`` - -.. list-table:: Macro-atom sub-structures and their communication - :header-rows: 1 - :widths: 20 30 25 25 - - * - Sub-structure - - Contents - - Communication - - Key functions - * - ``state`` - - Normalized rate coefficients (``jbar_old``, ``gamma_old``, ``alpha_st_old``, etc.), mode flags - - Broadcast after wind updates - - ``broadcast_updated_macro_atom_properties()`` - * - ``est`` - - Raw Sobolev mean intensities (``jbar``), photoionization rates (``gamma``), stimulated recombination rates (``alpha_st``), macro-atom absorption, cooling stores - - Reduced (summed) across ranks after transport - - ``reduce_macro_atom_estimators()`` - * - ``derived`` - - Macro-atom emissivities (``matom_emiss``), k-packet rate flags, transition probability matrix (``matom_matrix``) - - Broadcast after computation; matrix placed in shared memory - - ``broadcast_macro_atom_emissivities()``, ``broadcast_macro_atom_state_matrix()`` - -When adding a new variable, place it in the appropriate sub-structure and update -the corresponding communication function. For ``est`` fields, update the reduction -function. For ``state`` or ``derived`` fields, update the broadcast function. -In both cases, remember to update the buffer size calculation (the integer and double -counts) to account for the new variable. - -MPI-3 shared memory model -------------------------- - -When running with more than one MPI rank, SIROCCO uses MPI-3 shared memory windows -to reduce per-node memory consumption. The key idea is that ranks on the same -physical node share a single copy of data that is read-only during photon transport, -rather than duplicating it across every rank. - -During MPI initialisation (in ``sirocco.c``), a *node-local communicator* -is created with ``MPI_Comm_split_type(MPI_COMM_TYPE_SHARED, ...)``. Three global -variables track the node topology: - -- ``node_comm`` — communicator for ranks sharing the same node -- ``node_rank`` — rank index within the node (0 = node leader) -- ``node_size`` — number of ranks on the node - -Contiguous block allocation -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -All variable-length plasma arrays (density, partition, ioniz, etc.) are allocated -as contiguous blocks in ``calloc_dyn_plasma()`` (in ``gridwind.c``), with each -cell's pointer set to the appropriate offset within the block. This replaces the -earlier pattern of separate ``calloc`` calls per cell and is a prerequisite for -shared memory, since ``MPI_Win_allocate_shared`` requires contiguous regions. - -The allocation is performed by two helper functions, ``alloc_block_double()`` and -``alloc_block_int()``, which accept a ``use_shared`` flag: - -- When ``use_shared`` is TRUE and ``np_mpi_global > 1``, only the node leader - (``node_rank == 0``) allocates memory via ``MPI_Win_allocate_shared``; other - ranks on the same node obtain a pointer to the same physical memory via - ``MPI_Win_shared_query``. -- When ``use_shared`` is FALSE, each rank allocates its own private block with - regular ``calloc``. - -The same contiguous block layout is used in non-MPI builds and with a single MPI -rank; the only difference is that ``calloc`` is used unconditionally. - -Which arrays are shared -^^^^^^^^^^^^^^^^^^^^^^^ - -The allocation strategy mirrors the three sub-structures: - -.. list-table:: - :header-rows: 1 - :widths: 15 55 15 15 - - * - Category - - Arrays - - Allocation - - Reason - * - **State (dynamic)** - - ``density``, ``partition``, ``levden``, ``recomb_simple``, ``recomb_simple_upweight``, ``kbf_use`` - - Shared - - Read-only during photon transport - * - **State (fixed-size)** - - ``f1``, ``f2``, ``spec_mod_type``, ``pl_alpha``, ``pl_log_w``, ``exp_temp``, ``exp_w``, ``fmin_mod``, ``fmax_mod`` - - Shared - - Spectral model parameters, read-only during transport - * - **Estimators** - - ``ioniz``, ``heat_ion``, ``heat_inner_ion``, ``inner_ioniz`` - - Private - - Each rank accumulates independently - * - **Derived (dynamic)** - - ``recomb``, ``cool_rr_ion``, ``lum_rr_ion``, ``cool_dr_ion``, ``inner_recomb`` - - Shared - - Computed during wind updates, then broadcast - * - **Derived (fixed-size)** - - ``F_vis_persistent``, ``F_UV_persistent``, ``F_Xray_persistent``, ``rad_force_es_persist``, ``rad_force_ff_persist``, ``rad_force_bf_persist``, ``F_UV_ang_theta_persist``, ``F_UV_ang_phi_persist``, ``F_UV_ang_r_persist`` - - Shared - - Persistent radiation field averages, read-only during transport - * - **Derived (exceptions)** - - ``scatters``, ``xscatters``, ``n_bf_in``, ``n_bf_out`` - - Private - - Incremented during photon transport (would race in shared memory). ``n_bf_in``/``n_bf_out`` are dynamically sized to ``nphot_total`` (formerly fixed at ``N_PHOT_PROC=500``). - -The same shared/private split applies to macro-atom dynamic arrays in -``calloc_estimators()`` and ``calloc_matom_matrix()`` (both in ``gridwind.c``). -State and derived arrays (``jbar_old``, ``gamma_old``, ``matom_emiss``, and the -transition probability matrix ``matom_matrix``) are shared, while estimator arrays -(``jbar``, ``gamma``, ``cooling_bf``, ``cooling_bb``, etc.) are private. - -The ``matom_matrix`` (an *nrows × nrows* transition probability matrix per cell, -where *nrows = nlevels_macro + 1*) is allocated as a single contiguous shared -block in ``calloc_matom_matrix()``. The flat data (``NPLASMA × nrows × nrows`` -doubles) lives in ``macro_block_ptrs.matom_matrix_block`` (shared), while a -private per-rank array of row-pointers (``matom_matrix_rowptrs``) points into -the shared block to preserve the ``double **`` interface used throughout the code. -The matrix is computed during wind updates — each rank fills its own cell slice — -then broadcast via ``broadcast_macro_atom_state_matrix()`` so all nodes obtain -a complete copy. The ``MPI_Barrier(node_comm)`` at the end of that function -ensures node-local ranks see the written data before transport begins. Because -the matrix is strictly read-only during photon transport, no further -synchronisation is required. - -Block pointer management -^^^^^^^^^^^^^^^^^^^^^^^^ - -Base pointers for all contiguous blocks are stored in global structs -``plasma_block_ptrs`` (type ``plasma_blocks``) and ``macro_block_ptrs`` -(type ``macro_blocks``), declared in ``sirocco.h``. These structs also hold -the ``MPI_Win`` handles needed to free shared windows and a -``shared_memory_active`` flag that records whether the current allocation -used shared memory. - -Synchronisation -^^^^^^^^^^^^^^^ - -After any broadcast that writes to shared dynamic arrays, an -``MPI_Barrier(node_comm)`` ensures all node-local ranks see the new data -before proceeding. These barriers appear at the end of: - -- ``broadcast_wind_grid()`` -- ``broadcast_updated_plasma_properties()`` -- ``broadcast_plasma_grid()`` -- ``broadcast_wind_luminosity()`` -- ``broadcast_wind_cooling()`` -- ``broadcast_updated_macro_atom_properties()`` -- ``broadcast_macro_atom_emissivities()`` -- ``reduce_macro_atom_estimators()`` - -A barrier is also placed in ``calloc_wind()`` (``gridwind.c``) immediately after -the node leader's ``memset`` that zero-initialises the shared ``wmain`` block, -ensuring the zeroed memory is visible to all node-local ranks before any rank -begins writing wind-cell fields. - -Two additional barriers appear in ``create_wind_grid()`` (``define_wind.c``): - -- Before ``make_coordinate_grid()`` — ensures all ranks have completed the - serial ``wmain`` field initialisation loop (which writes ``inwind = - W_NOT_ASSIGNED``) before any rank enters ``make_coordinate_grid()``, which - for imported models overwrites ``inwind`` with values from the import file. - Without this, a fast rank's import writes can be overwritten by a slow rank's - init-loop writes, leaving cells with ``inwind = W_NOT_ASSIGNED``. -- After ``wind_complete()`` — ensures all ranks have finished - ``make_coordinate_grid()`` and ``wind_complete()`` before any rank enters - the parallel volume/velocity loop. Without this, a fast rank can read a - cell's ``inwind`` value before a slow rank has finished writing it from the - coordinate grid setup. - -During photon transport, state arrays are read-only so no synchronisation -is required. The ``sobolev()`` function in ``resonate.c`` previously -modified ``state.density`` temporarily during transport; it now passes a -density override to ``two_level_atom()`` instead, avoiding a race condition -on shared memory. - -Cleanup -^^^^^^^ - -At program exit, ``free_plasma_grid()`` and ``free_macro_grid()`` in -``janitor.c`` free the contiguous blocks. For shared blocks the memory is -owned by the MPI window, so the pointer is simply NULLed (the MPI runtime -frees it at ``MPI_Finalize``). Private blocks are freed with ``free()`` -as usual. - -Memory savings -^^^^^^^^^^^^^^ - -For a model with *N* plasma cells, *I* ions, and *R* ranks on one node, -the dominant dynamic arrays total roughly ``N * I * 14 * 8`` bytes per rank. -With shared memory the state and derived arrays exist only once per node, -reducing the per-node footprint by approximately ``(R-1)/R`` of the shared -portion. Estimator arrays remain duplicated across ranks. - -In addition to the variable-length dynamic arrays, fixed-size arrays that -were previously embedded in the ``plasma_state`` and ``plasma_derived`` -sub-structures (spectral model parameters, persistent flux averages) have -been moved to shared contiguous blocks. These arrays are declared as -pointers in the struct and point into combined blocks allocated in -``calloc_dyn_plasma()``. This reduces ``sizeof(plasma_dummy)`` by -approximately 2.3 KB per cell, yielding additional PSS savings of -roughly ``2.3 * N * (R-1)/R`` KB. The savings scale linearly with -NPLASMA: for a model with 80K cells and 29 ranks, this adds approximately -177 MB of per-rank savings. - -The transition probability matrix ``matom_matrix`` (``nrows × nrows`` doubles -per cell, allocated by ``calloc_matom_matrix()``) is also placed in shared -memory. For the ``h20_hetop_standard80`` atomic dataset (85 macro-atom levels, -*nrows* = 86) and a 300×300 grid with ~12,000 active plasma cells, this matrix -totals approximately 726 MB. Without shared memory each of the *R* ranks holds -its own copy; with shared memory there is one copy per node. On a 24-rank -single-node run this saves roughly ``726 × 23 ≈ 16.7 GB`` of physical memory, -making it the single largest shared-memory saving in the code. - -Shared wind structure -^^^^^^^^^^^^^^^^^^^^^ - -The wind geometry array ``wmain`` (type ``wind_dummy``, indexed by NDIM2) is -allocated via ``MPI_Win_allocate_shared`` in ``calloc_wind()`` so that all -ranks on the same node share a single copy. This is safe because ``wmain`` -is populated during initialization and is strictly read-only during photon -transport. - -The reverb path-tracking data (``paths`` and ``line_paths``) was moved out -of ``wind_dummy`` into a separate per-rank array ``wind_paths_main`` (type -``wind_paths_store``), because path histograms are accumulated during photon -transport and must remain private per rank. Code in ``paths.c`` accesses -these via ``wind_paths_main[cell_index]`` instead of ``wmain[cell_index]``. - -For a 300x300 grid (NDIM2 = 90,000, ``sizeof(wind_dummy)`` = 288 bytes), -this saves approximately ``90000 * 288 * (R-1)/R`` bytes, or about 25 MB -per rank with 29 ranks. - -Single-node optimisation for matom_matrix broadcast -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``broadcast_macro_atom_state_matrix()`` in ``communicate_macro.c`` normally -packs the full transition-probability matrix for each rank's cell range into a -comm buffer and broadcasts it to all other ranks. When ``matom_matrix`` lives -in shared memory (the normal MPI build) and all ranks are on the same node -(``num_nodes == 1``), this broadcast is unnecessary: the writing rank's data -is already visible to all node-local ranks through shared memory. The function -therefore returns early with a ``MPI_Barrier(node_comm)`` to ensure coherence, -skipping the pack/Bcast/unpack cycle entirely. On a single-node run this -avoids allocating the comm buffer (~100 KB) and removes latency proportional -to the number of ranks. - -Chunked Allreduce for cooling_bb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``reduce_macro_atom_estimators()`` in ``communicate_macro.c`` uses -``MPI_Allreduce`` to sum the per-rank ``cooling_bb`` estimator across all -ranks. The naive approach allocates two temporary buffers of size -``NPLASMA × nlines`` doubles each. For big.pf (12270 cells, 5964 lines) -this is approximately 2 × 585 MB = 1.17 GB of transient peak memory per -rank. - -The function instead processes cells in chunks, targeting a peak buffer size -of ~50 MB. For each chunk of cells the data is packed into a single -``chunk_cells × nlines`` buffer, reduced in place with -``MPI_Allreduce(MPI_IN_PLACE, ...)``, and unpacked back to ``macromain``. -The chunk size is computed at runtime as -``chunk_size = 50 MB / (nlines × sizeof(double))``, giving approximately -1000 cells per chunk and 13 Allreduce calls instead of one for big.pf. -Peak transient memory is reduced from ~1.17 GB to ~50 MB at the cost of -a small increase in Allreduce call overhead. - -Platform differences: macOS vs Linux -===================================== - -The shared-memory code paths behave differently on macOS and Linux. Because of -this, certain classes of bug are only visible on Linux, and **any change to the -shared-memory allocation or synchronisation logic must be tested on both -platforms** before merging. - -macOS behaviour ---------------- - -On macOS with OpenMPI 5.x, ``MPI_Win_allocate_shared`` has two known -limitations: - -1. **Permission fault (SEGV_ACCERR).** Non-allocating ranks receive a window - pointer that is mapped read-only, so the first write from any rank other than - the node leader causes a ``SEGV_ACCERR`` (signal code 2, "address has wrong - permissions"). - -2. **Tiny shared-memory limit.** The ``kern.sysv.shmmax`` kernel parameter - defaults to 4 MB on macOS, far smaller than a typical wind grid. - -As a result, the ``wmain`` wind array uses a **private** ``calloc`` per rank on -macOS (guarded by ``#ifdef __APPLE__`` in ``calloc_wind()`` and -``free_wind_grid()``). Each rank holds its own independent copy, kept in sync -by ``broadcast_wind_grid()``. - -The plasma and macro-atom dynamic arrays (allocated by ``calloc_dyn_plasma()`` -and ``calloc_estimators()``) still use ``MPI_Win_allocate_shared`` on macOS via -``alloc_block_double()`` / ``alloc_block_int()``. Whether these work correctly -on macOS under all OpenMPI versions has not been fully audited; if macOS -``SEGV_ACCERR`` faults re-emerge for plasma arrays, the same ``#ifdef __APPLE__`` -fallback pattern should be applied. - -Linux behaviour ---------------- - -On Linux, ``MPI_Win_allocate_shared`` works as specified: all node-local ranks -receive a pointer to the same physical pages. Both ``wmain`` and the plasma/macro -dynamic arrays are therefore genuinely shared in memory — one physical copy per -node, not per rank. - -Consequences for testing and debugging ---------------------------------------- - -Because macOS uses a private copy of ``wmain`` per rank, **race conditions in -the shared wind-grid code path are invisible on macOS**. Specifically: - -- Missing ``MPI_Barrier(node_comm)`` calls after shared writes to ``wmain`` - (e.g. the barriers in ``calloc_wind()`` and ``broadcast_wind_grid()``) have - no effect on macOS but are essential on Linux. Without them, a rank can - proceed past a broadcast and read stale zero-initialised memory, producing - errors such as *"wind cell has zero volume but flagged inwind"* or silent - wrong results. - -- Similarly, any new code that allocates or writes to a shared MPI window must - include a ``MPI_Barrier(node_comm)`` before any rank reads from that window. - This requirement will not be caught by macOS testing alone. - -**Rule of thumb:** whenever you add, remove, or reorder a ``MPI_Barrier``, -``MPI_Win_allocate_shared``, ``MPI_Win_shared_query``, or ``memset`` on a shared -block, run the full regression suite on Linux before merging. Mac testing is -sufficient for everything else in the MPI layer. diff --git a/docs/sphinx/source/developer/programmer_notes.rst b/docs/sphinx/source/developer/programmer_notes.rst index d1dbca65c..0beb0ce82 100644 --- a/docs/sphinx/source/developer/programmer_notes.rst +++ b/docs/sphinx/source/developer/programmer_notes.rst @@ -40,7 +40,7 @@ The two largest data structures, ``plasma_dummy`` (accessed via ``PlasmaPtr``) a ``macro_dummy`` (accessed via ``MacroPtr``), are each split into three sub-structures that categorize fields by their role during a simulation cycle. This split makes the MPI communication patterns self-documenting and enables the MPI-3 shared-memory model -(see :doc:`mpi_comms`) where read-only data is shared between ranks on the same node +(see :doc:`mixed_memory_model`) where read-only data is shared between ranks on the same node while private estimator data remains per-rank. The top-level ``plasma_dummy`` struct is: @@ -179,7 +179,7 @@ The portions of the routine that are parallelized are: MPI requires initialization. For SIROCCO this is carried out in sirocco.c. Various subroutines make use of MPI, and as a result, programmers need to be aware of this fact when they write auxiliary -routines that use the various subroutines called by SIROCCO. See :doc:`mpi_comms` for details +routines that use the various subroutines called by SIROCCO. See :doc:`mixed_memory_model` for details on the communication patterns and how they relate to the plasma and macro-atom sub-structures. Input naming conventions From 4fe09bf1a82e44e649dac7095b4f4ed1c4f471ec Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Mon, 20 Apr 2026 11:49:59 -0500 Subject: [PATCH 19/33] Fix rad_hydro_files MPI initialization for memory branch Added node communicator setup (node_comm, leader_comm, node_rank, node_size, num_nodes) after MPI_Init, matching sirocco.c, so that MPI_Win_allocate_shared in gridwind.c has a valid communicator. Also added MPI_Comm_free + MPI_Finalize before all exit() calls. Co-Authored-By: Claude Sonnet 4.6 --- source/rad_hydro_files.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/rad_hydro_files.c b/source/rad_hydro_files.c index 5e9ab2b32..726e0473a 100644 --- a/source/rad_hydro_files.c +++ b/source/rad_hydro_files.c @@ -155,6 +155,22 @@ main (int argc, char *argv[]) MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &my_rank); MPI_Comm_size (MPI_COMM_WORLD, &np_mpi); + + /* Create node-local communicator for MPI-3 shared memory */ + MPI_Comm_split_type (MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, my_rank, MPI_INFO_NULL, &node_comm); + MPI_Comm_rank (node_comm, &node_rank); + MPI_Comm_size (node_comm, &node_size); + + /* Create inter-node leader communicator (one leader per node) */ + MPI_Comm_split (MPI_COMM_WORLD, (node_rank == 0) ? 0 : MPI_UNDEFINED, my_rank, &leader_comm); + + /* Determine total number of nodes */ + num_nodes = 0; + if (leader_comm != MPI_COMM_NULL) + { + MPI_Comm_size (leader_comm, &num_nodes); + } + MPI_Bcast (&num_nodes, 1, MPI_INT, 0, MPI_COMM_WORLD); #else my_rank = 0; np_mpi = 1; @@ -192,6 +208,12 @@ main (int argc, char *argv[]) if (wind_read (windsavefile) < 0) { Error ("swind: Could not open %s", windsavefile); +#ifdef MPI_ON + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); + MPI_Finalize (); +#endif exit (0); } @@ -538,5 +560,11 @@ main (int argc, char *argv[]) fclose (fptr_flux_phi); fclose (fptr_flux_r); +#ifdef MPI_ON + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); + MPI_Finalize (); +#endif exit (0); } From 201594ed135ab308a808362615c765ec074eb9d4 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Tue, 21 Apr 2026 15:20:51 -0500 Subject: [PATCH 20/33] Fix macOS load warnings, windsave shared-memory bug, and add C executables docs - Add -fno-common to all CFLAGS variants in source/Makefile to eliminate the ld alignment warning on macOS caused by the large __DATA,__common section (~149 MB of uninitialized global arrays). - Fix windsave.c: on macOS, wmain is allocated as a private calloc per rank (not MPI shared memory), so every rank must read wmain from the wind save file independently. Guard the shared-memory read path with #ifndef __APPLE__ to match the allocation strategy in gridwind.c. Without this fix, non-rank-0 processes had zeroed wmain, causing dvds_ave=0 everywhere and 1M+ p_escape warnings that aborted MPI runs. - Add docs/sphinx/source/c_executables.rst: new page documenting all standalone C helper programs (swind, windsave2table, sirocco_optd, windsave2fits, rad_hydro_files, modify_wind, inspect_wind), including full option descriptions and output file listings for rad_hydro_files. - Wire c_executables into index.rst toctree and update output/model.rst to cross-reference the new page. - Fix RST errors in mixed_memory_model.rst: replace ^ title underlines with - so subsections of the MPI-3 shared memory section are correctly at level 3 rather than skipping from level 2 to level 4. Co-Authored-By: Claude Sonnet 4.6 --- docs/sphinx/source/c_executables.rst | 300 ++++++++++++++++++ .../source/developer/mixed_memory_model.rst | 18 +- docs/sphinx/source/index.rst | 1 + docs/sphinx/source/output/model.rst | 19 +- source/Makefile | 6 +- source/windsave.c | 7 +- 6 files changed, 327 insertions(+), 24 deletions(-) create mode 100644 docs/sphinx/source/c_executables.rst diff --git a/docs/sphinx/source/c_executables.rst b/docs/sphinx/source/c_executables.rst new file mode 100644 index 000000000..3bbd27db5 --- /dev/null +++ b/docs/sphinx/source/c_executables.rst @@ -0,0 +1,300 @@ +C Executable Programs +##################### + +In addition to the main ``sirocco`` program, the distribution includes several +standalone C executables that read a wind save file (``root.wind_save``) and +perform additional analysis or export data for use with other codes. All of +these programs are compiled and installed alongside ``sirocco`` by the standard +``make install`` build. + +.. contents:: Programs + :local: + :depth: 1 + +---- + +swind +===== + +``swind`` is an **interactive** program for inspecting the contents of a wind +save file. It is the primary tool for examining the ionization state, +temperatures, densities, velocities, and other per-cell quantities produced by +a Sirocco run. + +Usage:: + + swind [-h] [-s] [-d] [-p parameter_file] [root] + +Options: + +``-h`` + Print a brief help message and exit. + +``-s`` + Write a standard set of per-cell quantities to individual ASCII files and + exit (non-interactive). + +``-d`` + When per-cycle wind save files exist, write ASCII files for each + ionization cycle as well as for the final state (equivalent to ``-s`` when + no per-cycle saves are present). + +``-p parameter_file`` + Read the interactive choices from *parameter_file* instead of the command + line. This allows the same sequence of queries to be replayed on a + different wind save file. The commands executed interactively are saved to + ``swind.pf`` at the end of a session (if the user quits with ``q``). + +``root`` + Root name of the wind save file. If omitted, the program prompts for it. + +Running ``swind`` without ``-s`` or ``-d`` starts an interactive session in +which the user selects quantities to display from a menu. Output can +optionally be written to ASCII files. The files produced use either the +original Sirocco grid (prefix ``x.``) or a re-gridded linear array (prefix +``z.``), which is convenient for creating contour plots. + +---- + +windsave2table +============== + +``windsave2table`` writes a **standard set of ASCII tables** from a wind save +file. Unlike ``swind``, it is entirely non-interactive: the output files are +fixed and the program exits immediately after writing them. + +Usage:: + + windsave2table [-d] [-s] [-a] [-edge] [-x windcell] [-xall] + [--version] [-h] root + +Options: + +``-d`` + Report ion densities rather than ion fractions in the ion tables. + +``-s`` + Report the number of scatters per unit volume rather than ion fractions. + +``-a`` + Write additional tables with extended ion information. + +``-edge`` + Include edge (boundary) cells in the output tables. + +``-x windcell`` + In addition to the standard tables, write the detailed cell spectrum for + the wind cell numbered *windcell*. + +``-xall`` + Write detailed cell spectra for every in-wind cell to a single large file. + +``--version`` + Print version information and exit. + +``-h`` + Print this help and exit. + +Output files all begin with the root name and a domain number (e.g. +``root.0.master.txt``). Multiple domains produce separate files. Every file +starts with columns ``x``, ``z``, ``i``, ``j``, ``inwind`` so that plotting +routines can identify each cell unambiguously. The *master* file records +:math:`n_e`, velocity, :math:`\rho`, :math:`T_e`, :math:`T_r`, and ion +fractions for a set of key ions. + +---- + +sirocco_optd +============ + +``sirocco_optd`` (formerly ``py_optical_depth``) computes **optical depth +spectra and photospheric surfaces** through the Sirocco wind model. + +Usage:: + + sirocco_optd [-h] [-d ndom] [-p tau_stop] [-cion nion] + [-freq_min min] [-freq_max max] [-i i1 i2 ...] + [--nonrel] [--smax frac] [--no-es] [--version] + root + +Options: + +``-h`` + Print the full help message and exit. + +``-d ndom`` + Set the domain from which photons are launched. + +``-p tau_stop`` + Instead of tracing photons to escape, integrate outwards from the + inner boundary to find the surface of constant electron-scattering + optical depth *tau_stop* (i.e. the photosphere). + +``-cion nion`` + Extract the column density for the ion indexed *nion*. + +``-freq_min min``, ``-freq_max max`` + Frequency boundaries for the optical-depth spectrum. + +``-i i1 i2 ...`` + Calculate optical depths along the listed sight-line inclinations + (degrees from the pole). Overrides the inclinations defined in the + model. + +``--nonrel`` + Use linear frequency transforms. Use this when Sirocco was run in + non-relativistic mode. + +``--smax frac`` + Set the maximum fraction of a cell width that a photon may travel in + a single step. + +``--no-es`` + Exclude electron scattering from the opacity. + +``--version`` + Print version information and exit. + +By default the program integrates the continuum optical depth along every +observer line of sight defined in the model. If no observers were defined, +a set of default sight lines is used. + +---- + +windsave2fits +============= + +``windsave2fits`` exports selected wind-save quantities to **FITS files**. It +requires the optional ``cfitsio`` library and is the most convenient way to +export large two-dimensional data arrays (e.g. cell spectra) for analysis in +Python or other tools that read FITS. + +.. note:: + ``windsave2fits`` is built only when ``cfitsio`` is detected during + ``./configure``. If the executable is absent, ``cfitsio`` is likely not + installed. + +Usage:: + + windsave2fits [options] root + +The primary use case is exporting the per-cell spectral model data (the +spectral bands used to estimate ionization rates) in a form that can be +compared with the actual cell spectra recorded during transport. + +---- + +rad_hydro_files +=============== + +``rad_hydro_files`` is a **post-processing tool for radiation-hydrodynamics +(rad-hydro) coupling**. It reads a Sirocco wind save file and writes a +collection of ASCII files that communicate the radiative heating, cooling, +driving forces, and ionization state of the wind to a hydrodynamics code. + +The outputs are used by the `PLUTO–Sirocco +`_ coupled rad-hydro framework, +in which PLUTO advances the hydrodynamics and Sirocco provides the +radiative-transfer physics at each exchange step. + +Usage:: + + rad_hydro_files root + +where ``root`` is the root name of a Sirocco wind save file. The parameter +file is **not** read; all configuration is taken from the wind save. Because +several of the derived quantities (line cooling, recombination emissivities) +are not stored directly in the wind save, ``rad_hydro_files`` recomputes them +by calling the standard Sirocco cooling and luminosity routines before writing +the output. + +Output files +~~~~~~~~~~~~ + +All files are written to the current directory: + +``py_heatcool.dat`` + Per-cell heating and cooling rates: position, :math:`T_e`, ionisation + parameter :math:`\xi`, :math:`n_e`, X-ray photoionisation heating, + Compton heating, line heating, free–free heating, Compton cooling, line + and recombination cooling, free–free cooling, :math:`\rho`, and hydrogen + number density. + +``py_driving.dat`` + Per-cell radiation driving forces: geometry, density, electron density, + directional flux in three bands (optical, UV, X-ray), and the electron + scattering and bound-free radiation force vectors. + +``py_ion_data.dat`` + Per-cell ion density for every ion in the atomic data set. + +``py_spec_data.dat`` + Per-cell spectral model data (band boundaries and model parameters for + the spectral estimator used in the ionization calculation). + +``py_pcon_data.dat`` + Per-cell Sobolev parameter data: :math:`T_e`, :math:`\rho`, hydrogen + number density, :math:`n_e`, and dimensionless optical-depth parameters + for the optical, UV, and X-ray bands. + +``py_fluxes.dat`` + Per-cell directional flux in each of the three photometric bands. + +``directional_flux_theta.dat``, ``directional_flux_phi.dat``, ``directional_flux_r.dat`` + Per-cell UV flux decomposed into angular bins in the :math:`\theta`, + :math:`\phi`, and :math:`r` directions respectively, intended for + computing anisotropic radiation forces. + +``py_debug_data.dat`` + Diagnostic file: position, thermal velocity, velocity gradient, and + mean intensity per cell. + +MPI +~~~ + +``rad_hydro_files`` is MPI-enabled and may be run in parallel to accelerate +the cooling-rate recomputation:: + + mpirun -n 8 rad_hydro_files root + +---- + +modify_wind +=========== + +``modify_wind`` is a **developer/diagnostic tool** for modifying the contents +of a wind save file without rerunning Sirocco. Its primary current use is +overwriting ion densities in selected cells with prescribed values, making it +useful for constructing controlled test cases. + +.. note:: + ``modify_wind`` is a prototype. The modifications to be applied must be + hard-coded in the source file ``source/modify_wind.c`` before recompiling. + It is not intended for routine use. + +Usage:: + + modify_wind root + +The program reads the wind save ``root.wind_save``, applies the coded +modifications, and writes the result to a new wind save file. + +---- + +inspect_wind +============ + +``inspect_wind`` is a **diagnostic program** that prints selected internal +variables from a wind save file to ASCII files. It was originally written to +allow detailed inspection of macro-atom variables in parallel-mode runs (where +direct memory inspection is not straightforward) and is intended to be +customised in source for each diagnostic task. + +.. note:: + Like ``modify_wind``, ``inspect_wind`` requires the user to edit + ``source/inspect_wind.c`` to select which variables to output, then + recompile. + +Usage:: + + inspect_wind root diff --git a/docs/sphinx/source/developer/mixed_memory_model.rst b/docs/sphinx/source/developer/mixed_memory_model.rst index 6f66637e3..2606362df 100644 --- a/docs/sphinx/source/developer/mixed_memory_model.rst +++ b/docs/sphinx/source/developer/mixed_memory_model.rst @@ -401,7 +401,7 @@ variables track the node topology: - ``node_size`` — number of ranks on the node Contiguous block allocation -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------- All variable-length plasma arrays (density, partition, ioniz, etc.) are allocated as contiguous blocks in ``calloc_dyn_plasma()`` (in @@ -424,7 +424,7 @@ The same contiguous block layout is used in non-MPI builds and with a single MPI rank; the only difference is that ``calloc`` is used unconditionally. Which arrays are shared -^^^^^^^^^^^^^^^^^^^^^^^ +----------------------- The allocation strategy mirrors the three sub-structures: @@ -483,7 +483,7 @@ Because the matrix is strictly read-only during photon transport, no further synchronisation is required. Block pointer management -^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------ Base pointers for all contiguous blocks are stored in global structs ``plasma_block_ptrs`` (type ``plasma_blocks``) and ``macro_block_ptrs`` @@ -493,7 +493,7 @@ the ``MPI_Win`` handles needed to free shared windows and a used shared memory. Synchronisation -^^^^^^^^^^^^^^^ +--------------- After any broadcast that writes to shared dynamic arrays, an ``MPI_Barrier(node_comm)`` ensures all node-local ranks see the new data @@ -535,7 +535,7 @@ override to ``two_level_atom()`` instead, avoiding a race condition on shared memory. Cleanup -^^^^^^^ +------- At program exit, ``free_plasma_grid()`` and ``free_macro_grid()`` in ``janitor.c`` free the contiguous blocks. For shared blocks the memory is @@ -544,7 +544,7 @@ frees it at ``MPI_Finalize``). Private blocks are freed with ``free()`` as usual. Memory savings -^^^^^^^^^^^^^^ +-------------- For a model with *N* plasma cells, *I* ions, and *R* ranks on one node, the dominant dynamic arrays total roughly ``N * I * 14 * 8`` bytes per rank. @@ -574,7 +574,7 @@ physical memory, making it the single largest shared-memory saving in the code. Shared wind structure -^^^^^^^^^^^^^^^^^^^^^ +--------------------- The wind geometry array ``wmain`` (type ``wind_dummy``, indexed by NDIM2) is allocated via ``MPI_Win_allocate_shared`` in ``calloc_wind()`` so that all @@ -594,7 +594,7 @@ this saves approximately ``90000 * 288 * (R-1)/R`` bytes, or about 25 MB per rank with 29 ranks. Single-node optimisation for matom_matrix broadcast -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +---------------------------------------------------- ``broadcast_macro_atom_state_matrix()`` in ``communicate_macro.c`` normally packs the full transition-probability matrix for each rank's cell range into a @@ -608,7 +608,7 @@ run this avoids allocating the comm buffer (~100 KB) and removes latency proportional to the number of ranks. Chunked Allreduce for cooling_bb -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------------- ``reduce_macro_atom_estimators()`` in ``communicate_macro.c`` uses ``MPI_Allreduce`` to sum the per-rank ``cooling_bb`` estimator across all diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst index a1e8fa388..c42c80e92 100644 --- a/docs/sphinx/source/index.rst +++ b/docs/sphinx/source/index.rst @@ -106,6 +106,7 @@ Amin Mosallanezhad running_sirocco input output + c_executables plotting operation radiation diff --git a/docs/sphinx/source/output/model.rst b/docs/sphinx/source/output/model.rst index 6f56e8188..c30ee848a 100644 --- a/docs/sphinx/source/output/model.rst +++ b/docs/sphinx/source/output/model.rst @@ -14,20 +14,19 @@ or to add spectral cycles to get better spectra. .spec_save A binary file that contains all of the information about the spectra that have created. This file is not of interest to users directly. It is used when restarting -Two routines exist as part of the SIROCCO distribution allow the user to gain insight into the actual model +Several standalone C programs are included in the distribution for inspecting and +post-processing wind save files. See :doc:`/c_executables` for full +documentation of all programs. A brief summary of the most commonly used ones: windsave2table Executed from the command line with :code:`windsave2table rootname`. - Produces a set of standard set ascii tables that that show for each grid cell quantities such as wind velocity, - :math:`n_e`, temperatures, and densities of prominent ions. - - There are varrious options for how much data is to be printed out. A summary of these can be - obtained with code:`windsave2table -h` + Produces a standard set of ASCII tables showing per-cell quantities such as + wind velocity, :math:`n_e`, temperatures, and ion densities. Run + :code:`windsave2table -h` for a full list of options. swind - Executed from the command line with :code:`swind rootname` - - Allows the user to query for information about the model interactively. The results can be written to ascii files for future reference + Executed from the command line with :code:`swind rootname`. - Again, there are various options, and a summary can be obtained with :code:`swind -h` + Allows the user to query for information about the model interactively. + Results can be written to ASCII files. Run :code:`swind -h` for options. diff --git a/source/Makefile b/source/Makefile index 4bea384cc..46582e395 100644 --- a/source/Makefile +++ b/source/Makefile @@ -117,20 +117,20 @@ ifeq (D,$(firstword $(MAKECMDGOALS))) # use pg when you want to use gprof the profiler # to use profiler make with arguments "make D sirocco" # this can be altered to whatever is best - CFLAGS = -std=gnu99 -g -pg -O0 -Wl,-Ttext-segment=0x68000000 -Wall -Werror $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) ${CUDA_FLAG} + CFLAGS = -std=gnu99 -g -pg -O0 -Wl,-Ttext-segment=0x68000000 -Wall -Werror -fno-common $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) ${CUDA_FLAG} FFLAGS = -g -pg PRINT_VAR = DEBUGGING, -g -pg -Wl,-Ttext-segment=0x68000000 -Wall flags XDEBUG = True # Make the assumption that when using Clang the user is on MacOS, which doesn't # have (easy?) access to the GNU profiler or CUDA ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) - CFLAGS = -std=gnu99 -g -Wall $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) + CFLAGS = -std=gnu99 -g -Wall -fno-common $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) FFLAGS = -g PRINT_VAR = DEBUGGING, -g -Wall flags endif else # Use this for large runs - CFLAGS = -std=gnu99 -O3 -Wall $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) ${CUDA_FLAG} + CFLAGS = -std=gnu99 -O3 -Wall -fno-common $(EXTRA_FLAGS) -I$(INCLUDE) $(MPI_FLAG) ${CUDA_FLAG} FFLAGS = PRINT_VAR = LARGE RUNS, -03 -Wall flags endif diff --git a/source/windsave.c b/source/windsave.c index 96db525f7..98e9895e9 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -278,16 +278,17 @@ wind_read (char filename[]) } calloc_wind (NDIM2); -#ifdef MPI_ON +#if defined(MPI_ON) && !defined(__APPLE__) if (np_mpi_global > 1) { + /* Linux: wmain is in MPI shared memory; only the node leader reads from + * disk — all other ranks on the node see the same physical memory. */ if (node_rank == 0) { n += fread (wmain, sizeof (wind_dummy), NDIM2, fptr); } else { - /* Skip past the wind data in the file without reading into shared memory */ fseek (fptr, (long) NDIM2 * sizeof (wind_dummy), SEEK_CUR); } MPI_Barrier (node_comm); @@ -295,6 +296,8 @@ wind_read (char filename[]) else #endif { + /* Serial, or macOS where wmain is private per-rank: every rank reads + * its own copy directly from the file. */ n += fread (wmain, sizeof (wind_dummy), NDIM2, fptr); } From cf7ec00012e4ebfba56b30c95100c850ef851bdd Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Tue, 5 May 2026 16:25:07 -0500 Subject: [PATCH 21/33] Standardize regression_plot.py try/except to polar version Co-Authored-By: Claude Sonnet 4.6 --- py_progs/regression_plot.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/py_progs/regression_plot.py b/py_progs/regression_plot.py index b6eae04f2..3dfdc95de 100755 --- a/py_progs/regression_plot.py +++ b/py_progs/regression_plot.py @@ -601,9 +601,13 @@ def do_all(run1='py82i_181127',run2='py82i_181126',outdir=''): for one in files: word=one.split('/') model=word[1].replace(ext,'') - doit_two(run1,run2,model,outdir) + try: + doit_two(run1,run2,model,outdir) + except Exception as e: + print('Failed to plot %s' % model) + print(f"Failed with error: {e}") + - # print(fig_num) From c0c3fbb69c3a4f53a252021acac8ea1a08c82b39 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sun, 17 May 2026 12:03:56 -0500 Subject: [PATCH 22/33] Mpich (#1182) * Fix MPI_Finalize abort on MPICH by explicitly freeing shared-memory windows and communicators Shared-memory MPI_Win handles for plasma and macro blocks were not freed before MPI_Finalize, and node_comm/leader_comm were never freed at all. OpenMPI tolerates this; MPICH OFI transport aborts with OFI poll failed when it encounters unreleased resources during send-queue flushing. Fix: explicitly call MPI_Win_free on all plasma (15) and macro (6+1) shared windows in free_plasma_grid/free_macro_grid, add MPI_Comm_free for node_comm and leader_comm, and add MPI_Barrier(MPI_COMM_WORLD) before clean_on_exit to synchronize all ranks before releasing shared resources. Applied to all three MPI_Finalize sites: normal exit, grid-only early exit, and the max-time timeout path in signal.c. * Fix unit_test.c MPI cleanup: add node/leader comm init and MPI_Finalize unit_test.c called MPI_Init but never set up node_comm or leader_comm, and returned without calling MPI_Finalize. On MPICH this produces the same OFI abort seen in sirocco. Fix mirrors unit_test_main.c and sirocco.c: add MPI_Comm_split_type/MPI_Comm_split for node_comm and leader_comm after MPI_Init, MPI_Barrier + MPI_Comm_free + MPI_Finalize before return. Also replace exit(1) in zparse with Exit(1) so that if LUM_TEST is ever re-enabled, argument errors go through MPI_Abort rather than silently exiting one rank. --- source/janitor.c | 40 +++++++++++++++++++++++++++++++++++++--- source/signal.c | 4 ++++ source/sirocco.c | 12 +++++++++++- source/unit_test.c | 14 +++++++++++++- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/source/janitor.c b/source/janitor.c index 9060f82df..202ce33c7 100644 --- a/source/janitor.c +++ b/source/janitor.c @@ -40,9 +40,8 @@ free_plasma_block (void **ptr, int is_shared) #ifdef MPI_ON if (is_shared && np_mpi_global > 1) { - /* Shared memory is freed via MPI_Win_free, which is handled - * by the cleanup in calloc_dyn_plasma/calloc_estimators when - * re-allocating, or by MPI_Finalize at exit. */ + /* MPI_Win_free for shared blocks is called explicitly in free_plasma_grid / + * free_macro_grid before reaching here; just NULL the data pointer. */ *ptr = NULL; return; } @@ -152,6 +151,26 @@ free_plasma_grid (void) /* state blocks (shared in MPI mode) */ if (plasma_block_ptrs.density_block != NULL) { +#ifdef MPI_ON + if (is_shared && np_mpi_global > 1) + { + MPI_Win_free (&plasma_block_ptrs.win_density); + MPI_Win_free (&plasma_block_ptrs.win_partition); + MPI_Win_free (&plasma_block_ptrs.win_levden); + MPI_Win_free (&plasma_block_ptrs.win_recomb_simple); + MPI_Win_free (&plasma_block_ptrs.win_recomb_simple_upweight); + MPI_Win_free (&plasma_block_ptrs.win_kbf_use); + MPI_Win_free (&plasma_block_ptrs.win_recomb); + MPI_Win_free (&plasma_block_ptrs.win_cool_rr_ion); + MPI_Win_free (&plasma_block_ptrs.win_lum_rr_ion); + MPI_Win_free (&plasma_block_ptrs.win_cool_dr_ion); + MPI_Win_free (&plasma_block_ptrs.win_inner_recomb); + MPI_Win_free (&plasma_block_ptrs.win_state_xbands_d); + MPI_Win_free (&plasma_block_ptrs.win_state_spec_mod_type); + MPI_Win_free (&plasma_block_ptrs.win_derived_persist_force); + MPI_Win_free (&plasma_block_ptrs.win_derived_persist_angle); + } +#endif free_plasma_block ((void **) &plasma_block_ptrs.density_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.partition_block, is_shared); free_plasma_block ((void **) &plasma_block_ptrs.levden_block, is_shared); @@ -207,6 +226,17 @@ free_macro_grid (void) if (macro_block_ptrs.jbar_block != NULL) { +#ifdef MPI_ON + if (is_shared && np_mpi_global > 1) + { + MPI_Win_free (¯o_block_ptrs.win_jbar_old); + MPI_Win_free (¯o_block_ptrs.win_gamma_old); + MPI_Win_free (¯o_block_ptrs.win_gamma_e_old); + MPI_Win_free (¯o_block_ptrs.win_alpha_st_old); + MPI_Win_free (¯o_block_ptrs.win_alpha_st_e_old); + MPI_Win_free (¯o_block_ptrs.win_matom_emiss); + } +#endif /* state blocks (shared in MPI mode) */ free_plasma_block ((void **) ¯o_block_ptrs.jbar_old_block, is_shared); free_plasma_block ((void **) ¯o_block_ptrs.gamma_old_block, is_shared); @@ -234,6 +264,10 @@ free_macro_grid (void) /* matom_matrix flat data block (shared in MPI mode) */ if (macro_block_ptrs.matom_matrix_block != NULL) { +#ifdef MPI_ON + if (is_shared && np_mpi_global > 1) + MPI_Win_free (¯o_block_ptrs.win_matom_matrix); +#endif free_plasma_block ((void **) ¯o_block_ptrs.matom_matrix_block, is_shared); free (macro_block_ptrs.matom_matrix_rowptrs); macro_block_ptrs.matom_matrix_rowptrs = NULL; diff --git a/source/signal.c b/source/signal.c index f33e56d7c..f08a3c044 100644 --- a/source/signal.c +++ b/source/signal.c @@ -303,6 +303,10 @@ check_time (char *root) xsignal (root, "\nCOMMENT max_time %.1f seconds exceeded\n", max_time); #ifdef MPI_ON + MPI_Barrier (MPI_COMM_WORLD); + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); MPI_Finalize (); #endif diff --git a/source/sirocco.c b/source/sirocco.c index e49997cd6..637f3b717 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -710,6 +710,9 @@ main (int argc, char *argv[]) error_summary ("wind definition only (--grid-only)."); #ifdef MPI_ON MPI_Barrier (MPI_COMM_WORLD); + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); MPI_Finalize (); #endif return EXIT_SUCCESS; @@ -831,13 +834,20 @@ main (int argc, char *argv[]) error_summary ("End of program"); #endif - /* clean_on_exit calls free_wind_grid which calls MPI_Win_free — must happen before MPI_Finalize */ + /* clean_on_exit calls free_wind_grid and free_plasma_grid which call MPI_Win_free. + * The barrier ensures all ranks finish cleanup before any rank calls MPI_Finalize. */ +#ifdef MPI_ON + MPI_Barrier (MPI_COMM_WORLD); +#endif clean_on_exit (); print_memory_usage ("After program is complete"); Log_close (); #ifdef MPI_ON + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); MPI_Finalize (); #endif diff --git a/source/unit_test.c b/source/unit_test.c index 21f56e122..814447e02 100644 --- a/source/unit_test.c +++ b/source/unit_test.c @@ -43,6 +43,11 @@ main (int argc, char *argv[]) MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &my_rank); MPI_Comm_size (MPI_COMM_WORLD, &np_mpi); + MPI_Comm_split_type (MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, my_rank, MPI_INFO_NULL, &node_comm); + MPI_Comm_rank (node_comm, &node_rank); + MPI_Comm_size (node_comm, &node_size); + MPI_Comm_split (MPI_COMM_WORLD, (node_rank == 0) ? 0 : MPI_UNDEFINED, my_rank, &leader_comm); + num_nodes = 1; #else my_rank = 0; np_mpi = 1; @@ -247,6 +252,13 @@ main (int argc, char *argv[]) printf ("Finished unit test\n"); +#ifdef MPI_ON + MPI_Barrier (MPI_COMM_WORLD); + MPI_Comm_free (&node_comm); + if (leader_comm != MPI_COMM_NULL) + MPI_Comm_free (&leader_comm); + MPI_Finalize (); +#endif return (0); @@ -261,7 +273,7 @@ zparse (int argc, char *argv[]) if (argc != 2) { printf ("usage: unit_test root\n"); - exit (1); + Exit (1); } From a496ccf8e3161c35a0f531a79540d67725a72bc6 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Mon, 18 May 2026 09:54:54 -0500 Subject: [PATCH 23/33] Mpich and rad_hydro (#1183) * Fix MPI_Finalize abort on MPICH by explicitly freeing shared-memory windows and communicators Shared-memory MPI_Win handles for plasma and macro blocks were not freed before MPI_Finalize, and node_comm/leader_comm were never freed at all. OpenMPI tolerates this; MPICH OFI transport aborts with OFI poll failed when it encounters unreleased resources during send-queue flushing. Fix: explicitly call MPI_Win_free on all plasma (15) and macro (6+1) shared windows in free_plasma_grid/free_macro_grid, add MPI_Comm_free for node_comm and leader_comm, and add MPI_Barrier(MPI_COMM_WORLD) before clean_on_exit to synchronize all ranks before releasing shared resources. Applied to all three MPI_Finalize sites: normal exit, grid-only early exit, and the max-time timeout path in signal.c. * Fix unit_test.c MPI cleanup: add node/leader comm init and MPI_Finalize unit_test.c called MPI_Init but never set up node_comm or leader_comm, and returned without calling MPI_Finalize. On MPICH this produces the same OFI abort seen in sirocco. Fix mirrors unit_test_main.c and sirocco.c: add MPI_Comm_split_type/MPI_Comm_split for node_comm and leader_comm after MPI_Init, MPI_Barrier + MPI_Comm_free + MPI_Finalize before return. Also replace exit(1) in zparse with Exit(1) so that if LUM_TEST is ever re-enabled, argument errors go through MPI_Abort rather than silently exiting one rank. * rad_hydro_files: add t_r to hc output and output fill-corrected density to pcon Output t_r alongside t_e in the heating/cooling file headers and data rows. In the pcon output, multiply rho and ne by the domain fill factor to recover the cell-averaged density originally supplied by the hydro code (Sirocco stores rho/fill internally). Simplify old_ne to ne*fill directly. --- source/rad_hydro_files.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/rad_hydro_files.c b/source/rad_hydro_files.c index 726e0473a..f13f1a4ba 100644 --- a/source/rad_hydro_files.c +++ b/source/rad_hydro_files.c @@ -148,6 +148,8 @@ main (int argc, char *argv[]) /* Initialize MPI, which is needed because some of the routines are MPI enabled */ + double old_density, old_ne; + int my_rank; // these two variables are used regardless of parallel mode int np_mpi; // rank and number of processes, 0 and 1 in non-parallel @@ -236,9 +238,9 @@ main (int argc, char *argv[]) if (zdom[domain].coord_type == SPHERICAL || zdom[domain].coord_type == RTHETA) - fprintf (fptr_hc, "i j rcen thetacen vol temp xi ne heat_xray heat_comp heat_lines heat_ff cool_comp cool_lines cool_ff rho n_h\n"); + fprintf (fptr_hc, "i j rcen thetacen vol t_e t_r xi ne heat_xray heat_comp heat_lines heat_ff cool_comp cool_lines cool_ff rho n_h\n"); else if (zdom[domain].coord_type == CYLIND) - fprintf (fptr_hc, "i j rcen zcen vol temp xi ne heat_xray heat_comp heat_lines heat_ff cool_comp cool_lines cool_ff rho n_h\n"); + fprintf (fptr_hc, "i j rcen zcen vol t_e t_r xi ne heat_xray heat_comp heat_lines heat_ff cool_comp cool_lines cool_ff rho n_h\n"); @@ -379,7 +381,7 @@ main (int argc, char *argv[]) else if (zdom[domain].coord_type == CYLIND) fprintf (fptr_hc, "%d %d %e %e %e ", i, j, wmain[nwind].xcen[0], wmain[nwind].xcen[2], vol); //output geometric things - fprintf (fptr_hc, "%e %e %e ", plasmamain[nplasma].state.t_e, plasmamain[nplasma].derived.xi, plasmamain[nplasma].state.ne); //output temp, xi and ne to ease plotting of heating rates + fprintf (fptr_hc, "%e %e %e %e ", plasmamain[nplasma].state.t_e, plasmamain[nplasma].state.t_r, plasmamain[nplasma].derived.xi, plasmamain[nplasma].state.ne); //output t_e, t_r, xi and ne to ease plotting of heating rates fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_photo + plasmamain[nplasma].est.heat_auger) / vol); //Xray heating - or photoionization fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_comp) / vol); //Compton heating fprintf (fptr_hc, "%e ", (plasmamain[nplasma].est.heat_lines) / vol); //Line heating 28/10/15 - not currently used in zeus @@ -543,8 +545,11 @@ main (int argc, char *argv[]) else t_Xray = 0.0; //Essentually a flag that there is no way of computing t (and hence M) in this cell. - fprintf (fptr_pcon, " %e %e %e %e %e %e %e\n", plasmamain[nplasma].state.t_e, plasmamain[nplasma].state.rho, - plasmamain[nplasma].state.rho * rho2nh, plasmamain[nplasma].state.ne, t_opt, t_UV, t_Xray); + old_density = plasmamain[nplasma].state.rho * zdom[domain].fill; + old_ne = plasmamain[nplasma].state.ne * zdom[domain].fill; + + fprintf (fptr_pcon, " %e %e %e %e %e %e %e\n", plasmamain[nplasma].state.t_e, old_density, + old_density * rho2nh, old_ne, t_opt, t_UV, t_Xray); fprintf (fptr_debug, "%d %d %e %e %e %e %e\n", i, j, wmain[nwind].rcen, wmain[nwind].thetacen / RADIAN, v_th, fabs (dvwind_ds_cmf (&ptest)), plasmamain[nplasma].est.j); //output geometric things } From 57da4959832a2adbf839e6d053ca1276048aa121 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Fri, 5 Jun 2026 18:11:18 -0500 Subject: [PATCH 24/33] Fix: spherical_ds_in_cell infinite loop at outer cell boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a photon lands at exactly r = rmax (the outer boundary of a spherical cell) with an outgoing or tangential direction, ds_to_sphere returns VERY_BIG for both the inner sphere (impact parameter > rmin for a tangential path) and the outer sphere (photon is on or outside it, moving away). The previous fix returned DFUDGE, but a tangential nudge of DFUDGE does not change r in floating-point arithmetic — sqrt(rmax^2 + DFUDGE^2) == rmax at double precision for rmax ~ 1e11 cm and DFUDGE ~ 0.01 cm — so the photon stays trapped at r = rmax and the error fires on every subsequent call to calculate_ds. Each iteration logs a dfreq=0 Error in resonate.c; in dense, optically thick models the accumulated count reaches the max_errors = 1e6 abort threshold and kills the run. Fix: return ds_to_sphere(wmain[n].rmax + DFUDGE, p) instead of DFUDGE. For any photon classified in cell n (r <= rmax), the expanded sphere at rmax + DFUDGE always yields a finite positive root, and the move places the photon at r = rmax + DFUDGE so that where_in_grid correctly assigns it to the next cell on the following call. This reduces the VERY_BIG error count from ~900k to ~800 and the dfreq=0 count from 1,000,001 (abort) to ~16 for a dense T_init=1000K shell-wind test case run over 20 ionization cycles. The bug cannot trigger at the inner cell boundary because the photon is always inside the outer sphere there, guaranteeing ds_to_sphere(rmax) has a finite forward root. For multi-cell winds the problem is self-terminating (the photon exits to the next cell), but the outermost wind cell is vulnerable in the same way as the shell-wind case here. Note: the same bug exists in any branch derived from main that has not received this fix. Co-Authored-By: Claude Sonnet 4.6 --- source/spherical.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/spherical.c b/source/spherical.c index 2811fd585..8195b9a89 100644 --- a/source/spherical.c +++ b/source/spherical.c @@ -78,8 +78,13 @@ spherical_ds_in_cell (int ndom, PhotPtr p) if (smax == VERY_BIG && s == VERY_BIG) { - Error ("spherical: ds_in_cell: s and smax returning VERY_BIG in cell %i nudging photon %d by DFUDGE\n", p->grid, p->np); - return (DFUDGE); + /* Photon is at exactly r = rmax (outer cell boundary) with an outgoing or tangential + * direction, so ds_to_sphere returns VERY_BIG for both spheres. Returning DFUDGE + * does not help because a tangential nudge leaves r unchanged in floating point. + * Instead return the distance to a sphere just outside the boundary; this is always + * finite for a photon at r <= rmax and moves it cleanly into the next cell. */ + Error ("spherical: ds_in_cell: s and smax returning VERY_BIG in cell %i for photon %d; pushing past outer boundary\n", p->grid, p->np); + return (ds_to_sphere (wmain[n].rmax + DFUDGE, p)); } From 4474ed9513145a2bd0c67703a0ad2232e0c0478a Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 6 Jun 2026 07:05:21 -0500 Subject: [PATCH 25/33] Fix: two bugs in velocity gradient computation (gradv.c) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 1 — dvwind_ds_cmf: finite-difference step below floating-point precision The step ds = 1e-6 * half_cell_width is used to evaluate the velocity gradient numerically. For thin shells at large radii (e.g. the 10 cm test shell at r = 1e11 cm), ds = 5e-6 cm falls below ULP(r) ≈ 2.2e-5 cm, so rmin + ds == rmin in double precision. The test position does not move, v2 == v1 for every direction tried, and dvds ≈ 0 for all 10 000 trials in randwind_thermal_trapping. The rejection loop never accepts a direction, exhausts NSCAT_MAX, and logs an Error on every call. In models with many wind photons near the inner boundary the error count reaches max_errors (1 000 000) and aborts. Fix: clamp ds to max(1e-6 * half_cell, min(100*DBL_EPSILON*r, 0.1*half_cell)). This guarantees the step is representable while remaining local to the cell. Bug 2 — get_dvds_max: missing frac[] weights in interpolation coord_fraction returns corner indices nnn[] and bilinear weights frac[] that sum to 1. Every other interpolation in the codebase writes value += frac[nn] * quantity[nnn[nn]] but get_dvds_max accumulated the corner dvds_max values without the frac weights, returning a sum instead of a weighted average. For a photon midway between two wind cells each with dvds_max ≈ 0.9 the function returned 1.8, over-estimating p_norm in randwind_thermal_trapping and making the acceptance criterion unnecessarily strict. Fix: add frac[nn] * to the accumulation, consistent with all other uses. Also removed a dead vsub() call (line 88 in the original) that was immediately overwritten by the following vsub(). Note: both bugs exist on every branch derived from main that has not received this fix. Cherry-pick commit to port. Co-Authored-By: Claude Sonnet 4.6 --- source/gradv.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/source/gradv.c b/source/gradv.c index ee8801355..1db43f0d4 100644 --- a/source/gradv.c +++ b/source/gradv.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "atomic.h" #include "sirocco.h" @@ -89,10 +90,19 @@ dvwind_ds_cmf (PhotPtr p) struct photon pnew; double v1[3], v2[3], dv[3], diff[3]; double ds; - /* choose a small distance which is dependent on the cell size */ - vsub (pp.x, wmain[pp.grid].x, diff); + /* choose a small distance dependent on the cell size, with a floor set by + * the floating-point precision at the photon's position. For thin shells + * at large radii (e.g. 10 cm at 1e11 cm) 1e-6 * half_cell falls below + * ULP(r), so rmin+ds == rmin in double and the finite difference returns + * zero for every direction. The floor is capped at 10% of the half-cell + * width so the step remains local. */ vsub (wmain[pp.grid].xcen, wmain[pp.grid].x, diff); ds = 0.000001 * length (diff); + { + double ds_floor = 100.0 * DBL_EPSILON * length (pp.x); + if (ds < ds_floor) + ds = fmin (ds_floor, 0.1 * length (diff)); + } /* calculate the velocity at the position of the photon */ /* note we use model velocity, which could potentially be slow, but avoids interpolating (see #118) */ @@ -426,7 +436,7 @@ get_dvds_max (PhotPtr p) for (nn = 0; nn < nelem; nn++) { - dvds += wmain[nnn[nn]].dvds_max; + dvds += frac[nn] * wmain[nnn[nn]].dvds_max; } return dvds; From 47982bec436044a8fb4e0c4177cd85a4a5ef2731 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 6 Jun 2026 07:05:29 -0500 Subject: [PATCH 26/33] Fix: move ext.txt to diag folder; only open when actually needed Two changes to the extra-diagnostics file (files.extra / *.ext.txt): 1. parse.c: build the path inside files.diagfolder so ext.txt files appear alongside the .diag files rather than cluttering the working directory. 2. diag.c: guard the fopen() in init_extra_diagnostics on (modes.save_extract_photons || modes.track_resonant_scatters) instead of the broader modes.extra_diagnostics flag. Previously the file was created (one per MPI rank) whenever any @Diag option was active, even though only those two modes ever write to epltptr. The files were always empty unless one of those two modes was explicitly enabled. Co-Authored-By: Claude Sonnet 4.6 --- source/diag.c | 3 +-- source/parse.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/diag.c b/source/diag.c index f0ab242d0..a8c54c56d 100644 --- a/source/diag.c +++ b/source/diag.c @@ -365,9 +365,8 @@ init_extra_diagnostics () FILE *cellfile; /*File that may or may not exist, pointing to cells we want to write out photon stats for */ int cell; /*Temporary storage of cell to use */ - if (eplinit == 0 && modes.extra_diagnostics) + if (eplinit == 0 && (modes.save_extract_photons || modes.track_resonant_scatters)) { - //OLD sprintf (files.extra, "%.50s.ext.txt", files.root); epltptr = fopen (files.extra, "w"); eplinit = 1; } diff --git a/source/parse.c b/source/parse.c index e822c4196..2c15dcc2e 100644 --- a/source/parse.c +++ b/source/parse.c @@ -330,7 +330,7 @@ parse_command_line (int argc, char *argv[]) sprintf (dummy, "_%02d.ext.txt", rank_global); - sprintf (files.extra, "%.100s%.100s", files.root, dummy); + sprintf (files.extra, "%.100s%.100s%.100s", files.diagfolder, files.root, dummy); From 4032349c836ebddff8b7d28766450f5d98d0740e Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 6 Jun 2026 08:51:43 -0500 Subject: [PATCH 27/33] Fix: correct spherical_ds_in_cell cherry-pick for memory branch The fix cherry-picked from x3d used wmain[n].rmax, which does not exist in the memory branch wind_dummy struct. On this branch the outer cell boundary is zdom[ndom].wind_x[ix + 1], consistent with the existing ds_to_sphere calls above it. Co-Authored-By: Claude Sonnet 4.6 --- source/spherical.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/spherical.c b/source/spherical.c index 8195b9a89..042a5812c 100644 --- a/source/spherical.c +++ b/source/spherical.c @@ -84,7 +84,7 @@ spherical_ds_in_cell (int ndom, PhotPtr p) * Instead return the distance to a sphere just outside the boundary; this is always * finite for a photon at r <= rmax and moves it cleanly into the next cell. */ Error ("spherical: ds_in_cell: s and smax returning VERY_BIG in cell %i for photon %d; pushing past outer boundary\n", p->grid, p->np); - return (ds_to_sphere (wmain[n].rmax + DFUDGE, p)); + return (ds_to_sphere (zdom[ndom].wind_x[ix + 1] + DFUDGE, p)); } From 3878576b4a694326101abb959601cb217f8d6098 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Sat, 6 Jun 2026 10:09:30 -0500 Subject: [PATCH 28/33] Add macro2simple.py: convert macro-atom atomic data to simple-atom format Reads a Sirocco macro-atom master data file and produces a simple-atom equivalent by converting: IonM -> IonV (elem_ions files; nlte preserved for level tracking) LevMacro -> LevTop (levels files; islp/qqnum set to -1 as placeholders) LinMacro -> Line (lines files; filtered by lower level index and oscillator strength to keep only the most important transitions, default ll <= 1) PhotMacS -> PhotTopS (phot files; levl used as ilv, islp=-1 to match PhotMac -> PhotTop converted LevTop entries) Files that need no conversion (topbase phot, collision data, atomic/ files) are referenced in-place in the new master file. All output is written relative to the input master file location so test runs stay out of the main xdata directory. Usage: macro2simple.py data/h20_hetop_standard80.dat [--max-lower-level N] [--min-osc-strength F] [--outdir DIR] Co-Authored-By: Claude Sonnet 4.6 --- py_progs/macro2simple.py | 401 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100755 py_progs/macro2simple.py diff --git a/py_progs/macro2simple.py b/py_progs/macro2simple.py new file mode 100755 index 000000000..9c4d42c43 --- /dev/null +++ b/py_progs/macro2simple.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python +""" +macro2simple.py -- Convert a Sirocco macro-atom atomic data set to simple-atom format. + +The script reads a macro-atom master data file (e.g. data/h20_hetop_standard80.dat), +identifies the component files that contain macro-atom specific keywords (IonM, +LevMacro, LinMacro), converts them to their simple-atom equivalents, and writes +a new master file that assembles the converted and unchanged files. + +Conversions applied: + IonM -> IonV (elem_ions files) nlte field set to 0 + LevMacro -> LevTop (levels files) -1 inserted for islp and qqnum fields + LinMacro -> Line (lines files) filtered by lower level index and oscillator strength + +Files that require no conversion (topbase phot files, collision data, etc.) are +referenced in-place in the new master file -- no copying. + +Usage: + macro2simple.py input_master.dat [options] + + input_master.dat Path to macro-atom master file, relative to $SIROCCO + (e.g. data/h20_hetop_standard80.dat) or absolute. + +Options: + --max-lower-level N Keep LinMacro lines with ll <= N [default: 1] + --min-osc-strength F Keep lines with f >= F [default: 0.0] + --outdir DIR Directory for converted files [default: $SIROCCO/data/atomic_simple] + +Output: + $SIROCCO/data/_simple.dat new master file + $SIROCCO/data/atomic_simple/_simple.dat converted component files +""" + +import os +import sys +import argparse +import re + +# --------------------------------------------------------------------------- +# Path helpers +# --------------------------------------------------------------------------- + +SIROCCO = os.environ.get('SIROCCO', '') + + +def resolve_data_path(data_path): + """Resolve a data/-relative path to an absolute path. + + In a Sirocco run directory 'data/' is a symlink to $SIROCCO/xdata/, so + paths in master files look like 'data/atomic_macro/h20_lines.dat' and + resolve to $SIROCCO/xdata/atomic_macro/h20_lines.dat. + """ + if os.path.isabs(data_path): + return data_path + if SIROCCO: + # data/ -> $SIROCCO/xdata/ + xdata_path = data_path.replace('data/', 'xdata/', 1) if data_path.startswith('data/') else data_path + candidate = os.path.join(SIROCCO, xdata_path) + if os.path.isfile(candidate): + return candidate + # Also try without xdata substitution (e.g. if called with an xdata/ path) + candidate2 = os.path.join(SIROCCO, data_path) + if os.path.isfile(candidate2): + return candidate2 + # Fall back to cwd-relative (handles run-directory usage where data/ symlink exists) + local = os.path.abspath(data_path) + if os.path.isfile(local): + return local + return local + + +def to_output_rel(abs_path): + """Return a CWD-relative path for a converted output file. + + Since Sirocco resolves all paths in master files relative to the run + directory, we express output paths relative to CWD. For a master in + data/ this yields data/atomic_simple/. + """ + return os.path.relpath(abs_path, os.getcwd()) + + +# --------------------------------------------------------------------------- +# File-type detection +# --------------------------------------------------------------------------- + +def file_keywords(filepath): + """Return the set of macro-atom keywords present in a file.""" + found = set() + try: + with open(filepath) as f: + for line in f: + word = line.split()[0] if line.split() else '' + if word in ('IonM', 'LevMacro', 'LinMacro', 'PhotMacS'): + found.add(word) + if len(found) == 4: + break + except (IOError, OSError): + pass + return found + + +# --------------------------------------------------------------------------- +# Conversion routines -- each returns (lines_written, lines_skipped) +# --------------------------------------------------------------------------- + +def convert_elem_ions(inpath, outpath): + """Convert IonM -> IonV and set nlte to 0.""" + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('IonM'): + fout.write(raw) + continue + + # IonM name z istate g ip nmax nlte label + # Replace IonM with IonV and set nlte (second-to-last numeric field) to 0. + # We parse conservatively to preserve spacing of the label. + parts = stripped.split() + # parts[0]=IonM parts[1]=name parts[2]=z parts[3]=istate + # parts[4]=g parts[5]=ip parts[6]=nmax parts[7]=nlte parts[8+]=label + if len(parts) < 8: + fout.write(raw) + continue + parts[0] = 'IonV' + # Keep nlte (parts[7]) at its original value so that level nden + # slots are allocated and PhotTopS cross-sections can be matched. + # Reconstruct with consistent spacing; preserve label verbatim + label = ' '.join(parts[8:]) + fout.write('%-8s %-4s %3s %3s %3s %12s %5s %3s %s\n' % ( + parts[0], parts[1], parts[2], parts[3], + parts[4], parts[5], parts[6], parts[7], label)) + n_converted += 1 + + return n_converted + + +def convert_levels(inpath, outpath): + """Convert LevMacro -> LevTop, inserting -1 for islp and qqnum fields.""" + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('LevMacro'): + fout.write(raw) + continue + + # LevMacro z ion ilv ion_pot ex_energy g rad_rate () label + # LevTop z ion islp ilv ion_pot ex_energy g qqnum rad_rate () label + parts = stripped.split() + # parts[0]=LevMacro [1]=z [2]=ion [3]=ilv [4]=e [5]=exx [6]=g [7]=rl [8]=() [9+]=label + if len(parts) < 9: + fout.write(raw) + continue + label = ' '.join(parts[9:]) + fout.write('LevTop %3s %3s %4d %3s %12s %12s %5s %6s %11s %s %s\n' % ( + parts[1], parts[2], + -1, # islp -- not used by simple atoms + parts[3], # ilv + parts[4], # ion_pot + parts[5], # ex_energy + parts[6], # g + -1, # qqnum -- not used by simple atoms + parts[7], # rad_rate + parts[8], # () + label)) + n_converted += 1 + + return n_converted + + +def convert_lines(inpath, outpath, max_ll, min_f): + """Convert LinMacro -> Line, keeping only ll <= max_ll and f >= min_f.""" + n_total = 0 + n_kept = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('LinMacro'): + fout.write(raw) + continue + + n_total += 1 + # LinMacro z ion lambda f gl gu el eu ll lu + parts = stripped.split() + if len(parts) < 11: + fout.write(raw) + n_kept += 1 + continue + + ll = int(parts[9]) + f_val = float(parts[4]) + + if ll > max_ll or f_val < min_f: + continue + + # Replace keyword only; preserve all field values + fout.write('Line' + raw[len('LinMacro'):]) + n_kept += 1 + + return n_total, n_kept + + +def convert_phot(inpath, outpath): + """Convert PhotMacS/PhotMac -> PhotTopS/PhotTop. + + PhotMacS format: PhotMacS z istate levl levu exx np + PhotTopS format: PhotTopS z istate islp ilv exx np + + We use levl as ilv and -1 as islp, which matches the -1 islp values + written by convert_levels for the LevTop entries. The upper level + index (levu) is dropped since PhotTopS only references the lower level. + """ + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if stripped.startswith('PhotMacS'): + # PhotMacS z istate levl levu exx np + parts = stripped.split() + if len(parts) >= 7: + z, istate, levl, levu, exx, np_ = parts[1:7] + fout.write(f'PhotTopS {z} {istate} -1 {levl} {exx} {np_}\n') + n_converted += 1 + else: + fout.write(raw) + elif stripped.startswith('PhotMac'): + # PhotMac freq xsection -> PhotTop freq xsection + fout.write('PhotTop' + raw[len('PhotMac'):]) + else: + fout.write(raw) + return n_converted + + +# --------------------------------------------------------------------------- +# Output filename helper +# --------------------------------------------------------------------------- + +def simple_outpath(inpath, simple_dir): + """Derive the output path for a converted file in simple_dir.""" + base = os.path.basename(inpath) + root, ext = os.path.splitext(base) + return os.path.join(simple_dir, root + '_simple' + ext) + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description='Convert a macro-atom Sirocco atomic data set to simple-atom format') + parser.add_argument('master', + help='Master data file (e.g. data/h20_hetop_standard80.dat or absolute path)') + parser.add_argument('--max-lower-level', type=int, default=1, metavar='N', + help='Keep LinMacro lines with ll <= N (default: 1, ground-state only)') + parser.add_argument('--min-osc-strength', type=float, default=0.0, metavar='F', + help='Keep lines with oscillator strength >= F (default: 0.0)') + parser.add_argument('--outdir', default=None, + help='Directory for converted component files ' + '(default: $SIROCCO/data/atomic_simple)') + args = parser.parse_args() + + # Resolve the master file + master_abs = resolve_data_path(args.master) + if not os.path.isfile(master_abs): + print(f'Error: cannot find master file: {args.master}', file=sys.stderr) + if not SIROCCO: + print(' Hint: $SIROCCO is not set', file=sys.stderr) + sys.exit(1) + + # Output goes alongside the input master file, without resolving symlinks. + # os.path.abspath preserves symlinks; os.path.realpath would follow them. + # This means that if the user passes 'data/h20_hetop_standard80.dat' where + # data/ is a local test directory, output lands in that local directory. + # Converted component files go in atomic_simple/ beside the master. + # Unchanged file references keep their original data/... paths. + + master_input_dir = os.path.dirname(os.path.abspath(args.master)) + + # Output directory for converted component files + if args.outdir: + simple_dir = os.path.abspath(args.outdir) + else: + simple_dir = os.path.join(master_input_dir, 'atomic_simple') + + os.makedirs(simple_dir, exist_ok=True) + + # Output master file: _simple.dat in the same directory as input + base = os.path.basename(master_abs) + root, ext = os.path.splitext(base) + out_master_path = os.path.join(master_input_dir, root + '_simple' + ext) + + print(f'Input master : {master_abs}') + print(f'Output master: {out_master_path}') + print(f'Component dir: {simple_dir}') + print(f'Line filter : ll <= {args.max_lower_level}, f >= {args.min_osc_strength}') + print() + + # Read and process the master file line by line + new_master_lines = [ + f'# Simple-atom version of {os.path.basename(master_abs)}\n', + f'# Generated by macro2simple.py\n', + f'# LinMacro lines filtered: ll <= {args.max_lower_level}', + ] + if args.min_osc_strength > 0: + new_master_lines[-1] += f', f >= {args.min_osc_strength}' + new_master_lines[-1] += '\n' + new_master_lines.append( + '# IonM->IonV (nlte=0), LevMacro->LevTop, LinMacro->Line.\n') + new_master_lines.append( + '# Phot and all atomic/ files referenced in-place.\n') + new_master_lines.append('#\n') + + with open(master_abs) as f: + raw_lines = f.readlines() + + for raw in raw_lines: + stripped = raw.strip() + + # Blank lines and comments pass through + if not stripped or stripped.startswith('#'): + new_master_lines.append(raw) + continue + + # It's a component file reference + data_path = stripped + abs_path = resolve_data_path(data_path) + + if not os.path.isfile(abs_path): + print(f' Warning: cannot find {data_path} -- keeping reference unchanged') + new_master_lines.append(raw) + continue + + keywords = file_keywords(abs_path) + + if not keywords: + # Nothing to convert -- reference in-place + new_master_lines.append(raw) + continue + + # File needs conversion + out_path = simple_outpath(abs_path, simple_dir) + out_rel = to_output_rel(out_path) + + if keywords == {'IonM'}: + n = convert_elem_ions(abs_path, out_path) + print(f' IonM->IonV : {data_path}') + print(f' -> {out_rel} ({n} ions converted)') + + elif keywords == {'LevMacro'}: + n = convert_levels(abs_path, out_path) + print(f' LevMacro->LevTop: {data_path}') + print(f' -> {out_rel} ({n} levels converted)') + + elif keywords == {'LinMacro'}: + n_total, n_kept = convert_lines(abs_path, out_path, + args.max_lower_level, + args.min_osc_strength) + print(f' LinMacro->Line : {data_path}') + print(f' -> {out_rel} ({n_kept}/{n_total} lines kept)') + + elif keywords == {'PhotMacS'}: + n = convert_phot(abs_path, out_path) + print(f' PhotMacS->PhotTopS: {data_path}') + print(f' -> {out_rel} ({n} xsection blocks converted)') + + else: + # Mixed file -- apply conversions sequentially via a temp file + import shutil + tmp = out_path + '.tmp' + tmp2 = out_path + '.tmp2' + src = abs_path + if 'IonM' in keywords: + convert_elem_ions(src, tmp); src = tmp + if 'LevMacro' in keywords: + convert_levels(src, tmp2); src = tmp2 + if 'LinMacro' in keywords: + n_total, n_kept = convert_lines(src, out_path, + args.max_lower_level, + args.min_osc_strength) + elif 'PhotMacS' in keywords: + convert_phot(src, out_path) + else: + shutil.copy(src, out_path) + for t in (tmp, tmp2): + if os.path.exists(t): + os.remove(t) + print(f' Mixed : {data_path} -> {out_rel}') + + new_master_lines.append(out_rel + '\n') + + # Write the new master file + with open(out_master_path, 'w') as f: + f.writelines(new_master_lines) + + print(f'\nWrote {out_master_path}') + + +if __name__ == '__main__': + main() From aefa08094b3ac4c01664de7e039850084e39319f Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 17 Jun 2026 10:53:36 -0500 Subject: [PATCH 29/33] Add ConvertMacro2Simple.py: camel-case copy of macro2simple.py for macOS macOS case-insensitive filesystems collide macro2simple.py with Macro2Simple.py. ConvertMacro2Simple.py provides the same functionality without the name collision. Co-Authored-By: Claude Sonnet 4.6 --- py_progs/ConvertMacro2Simple.py | 401 ++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100755 py_progs/ConvertMacro2Simple.py diff --git a/py_progs/ConvertMacro2Simple.py b/py_progs/ConvertMacro2Simple.py new file mode 100755 index 000000000..29cfa06b1 --- /dev/null +++ b/py_progs/ConvertMacro2Simple.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python +""" +ConvertMacro2Simple.py -- Convert a Sirocco macro-atom atomic data set to simple-atom format. + +The script reads a macro-atom master data file (e.g. data/h20_hetop_standard80.dat), +identifies the component files that contain macro-atom specific keywords (IonM, +LevMacro, LinMacro), converts them to their simple-atom equivalents, and writes +a new master file that assembles the converted and unchanged files. + +Conversions applied: + IonM -> IonV (elem_ions files) nlte field set to 0 + LevMacro -> LevTop (levels files) -1 inserted for islp and qqnum fields + LinMacro -> Line (lines files) filtered by lower level index and oscillator strength + +Files that require no conversion (topbase phot files, collision data, etc.) are +referenced in-place in the new master file -- no copying. + +Usage: + macro2simple.py input_master.dat [options] + + input_master.dat Path to macro-atom master file, relative to $SIROCCO + (e.g. data/h20_hetop_standard80.dat) or absolute. + +Options: + --max-lower-level N Keep LinMacro lines with ll <= N [default: 1] + --min-osc-strength F Keep lines with f >= F [default: 0.0] + --outdir DIR Directory for converted files [default: $SIROCCO/data/atomic_simple] + +Output: + $SIROCCO/data/_simple.dat new master file + $SIROCCO/data/atomic_simple/_simple.dat converted component files +""" + +import os +import sys +import argparse +import re + +# --------------------------------------------------------------------------- +# Path helpers +# --------------------------------------------------------------------------- + +SIROCCO = os.environ.get('SIROCCO', '') + + +def resolve_data_path(data_path): + """Resolve a data/-relative path to an absolute path. + + In a Sirocco run directory 'data/' is a symlink to $SIROCCO/xdata/, so + paths in master files look like 'data/atomic_macro/h20_lines.dat' and + resolve to $SIROCCO/xdata/atomic_macro/h20_lines.dat. + """ + if os.path.isabs(data_path): + return data_path + if SIROCCO: + # data/ -> $SIROCCO/xdata/ + xdata_path = data_path.replace('data/', 'xdata/', 1) if data_path.startswith('data/') else data_path + candidate = os.path.join(SIROCCO, xdata_path) + if os.path.isfile(candidate): + return candidate + # Also try without xdata substitution (e.g. if called with an xdata/ path) + candidate2 = os.path.join(SIROCCO, data_path) + if os.path.isfile(candidate2): + return candidate2 + # Fall back to cwd-relative (handles run-directory usage where data/ symlink exists) + local = os.path.abspath(data_path) + if os.path.isfile(local): + return local + return local + + +def to_output_rel(abs_path): + """Return a CWD-relative path for a converted output file. + + Since Sirocco resolves all paths in master files relative to the run + directory, we express output paths relative to CWD. For a master in + data/ this yields data/atomic_simple/. + """ + return os.path.relpath(abs_path, os.getcwd()) + + +# --------------------------------------------------------------------------- +# File-type detection +# --------------------------------------------------------------------------- + +def file_keywords(filepath): + """Return the set of macro-atom keywords present in a file.""" + found = set() + try: + with open(filepath) as f: + for line in f: + word = line.split()[0] if line.split() else '' + if word in ('IonM', 'LevMacro', 'LinMacro', 'PhotMacS'): + found.add(word) + if len(found) == 4: + break + except (IOError, OSError): + pass + return found + + +# --------------------------------------------------------------------------- +# Conversion routines -- each returns (lines_written, lines_skipped) +# --------------------------------------------------------------------------- + +def convert_elem_ions(inpath, outpath): + """Convert IonM -> IonV and set nlte to 0.""" + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('IonM'): + fout.write(raw) + continue + + # IonM name z istate g ip nmax nlte label + # Replace IonM with IonV and set nlte (second-to-last numeric field) to 0. + # We parse conservatively to preserve spacing of the label. + parts = stripped.split() + # parts[0]=IonM parts[1]=name parts[2]=z parts[3]=istate + # parts[4]=g parts[5]=ip parts[6]=nmax parts[7]=nlte parts[8+]=label + if len(parts) < 8: + fout.write(raw) + continue + parts[0] = 'IonV' + # Keep nlte (parts[7]) at its original value so that level nden + # slots are allocated and PhotTopS cross-sections can be matched. + # Reconstruct with consistent spacing; preserve label verbatim + label = ' '.join(parts[8:]) + fout.write('%-8s %-4s %3s %3s %3s %12s %5s %3s %s\n' % ( + parts[0], parts[1], parts[2], parts[3], + parts[4], parts[5], parts[6], parts[7], label)) + n_converted += 1 + + return n_converted + + +def convert_levels(inpath, outpath): + """Convert LevMacro -> LevTop, inserting -1 for islp and qqnum fields.""" + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('LevMacro'): + fout.write(raw) + continue + + # LevMacro z ion ilv ion_pot ex_energy g rad_rate () label + # LevTop z ion islp ilv ion_pot ex_energy g qqnum rad_rate () label + parts = stripped.split() + # parts[0]=LevMacro [1]=z [2]=ion [3]=ilv [4]=e [5]=exx [6]=g [7]=rl [8]=() [9+]=label + if len(parts) < 9: + fout.write(raw) + continue + label = ' '.join(parts[9:]) + fout.write('LevTop %3s %3s %4d %3s %12s %12s %5s %6s %11s %s %s\n' % ( + parts[1], parts[2], + -1, # islp -- not used by simple atoms + parts[3], # ilv + parts[4], # ion_pot + parts[5], # ex_energy + parts[6], # g + -1, # qqnum -- not used by simple atoms + parts[7], # rad_rate + parts[8], # () + label)) + n_converted += 1 + + return n_converted + + +def convert_lines(inpath, outpath, max_ll, min_f): + """Convert LinMacro -> Line, keeping only ll <= max_ll and f >= min_f.""" + n_total = 0 + n_kept = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if not stripped.startswith('LinMacro'): + fout.write(raw) + continue + + n_total += 1 + # LinMacro z ion lambda f gl gu el eu ll lu + parts = stripped.split() + if len(parts) < 11: + fout.write(raw) + n_kept += 1 + continue + + ll = int(parts[9]) + f_val = float(parts[4]) + + if ll > max_ll or f_val < min_f: + continue + + # Replace keyword only; preserve all field values + fout.write('Line' + raw[len('LinMacro'):]) + n_kept += 1 + + return n_total, n_kept + + +def convert_phot(inpath, outpath): + """Convert PhotMacS/PhotMac -> PhotTopS/PhotTop. + + PhotMacS format: PhotMacS z istate levl levu exx np + PhotTopS format: PhotTopS z istate islp ilv exx np + + We use levl as ilv and -1 as islp, which matches the -1 islp values + written by convert_levels for the LevTop entries. The upper level + index (levu) is dropped since PhotTopS only references the lower level. + """ + n_converted = 0 + with open(inpath) as fin, open(outpath, 'w') as fout: + for raw in fin: + stripped = raw.strip() + if stripped.startswith('PhotMacS'): + # PhotMacS z istate levl levu exx np + parts = stripped.split() + if len(parts) >= 7: + z, istate, levl, levu, exx, np_ = parts[1:7] + fout.write(f'PhotTopS {z} {istate} -1 {levl} {exx} {np_}\n') + n_converted += 1 + else: + fout.write(raw) + elif stripped.startswith('PhotMac'): + # PhotMac freq xsection -> PhotTop freq xsection + fout.write('PhotTop' + raw[len('PhotMac'):]) + else: + fout.write(raw) + return n_converted + + +# --------------------------------------------------------------------------- +# Output filename helper +# --------------------------------------------------------------------------- + +def simple_outpath(inpath, simple_dir): + """Derive the output path for a converted file in simple_dir.""" + base = os.path.basename(inpath) + root, ext = os.path.splitext(base) + return os.path.join(simple_dir, root + '_simple' + ext) + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description='Convert a macro-atom Sirocco atomic data set to simple-atom format') + parser.add_argument('master', + help='Master data file (e.g. data/h20_hetop_standard80.dat or absolute path)') + parser.add_argument('--max-lower-level', type=int, default=1, metavar='N', + help='Keep LinMacro lines with ll <= N (default: 1, ground-state only)') + parser.add_argument('--min-osc-strength', type=float, default=0.0, metavar='F', + help='Keep lines with oscillator strength >= F (default: 0.0)') + parser.add_argument('--outdir', default=None, + help='Directory for converted component files ' + '(default: $SIROCCO/data/atomic_simple)') + args = parser.parse_args() + + # Resolve the master file + master_abs = resolve_data_path(args.master) + if not os.path.isfile(master_abs): + print(f'Error: cannot find master file: {args.master}', file=sys.stderr) + if not SIROCCO: + print(' Hint: $SIROCCO is not set', file=sys.stderr) + sys.exit(1) + + # Output goes alongside the input master file, without resolving symlinks. + # os.path.abspath preserves symlinks; os.path.realpath would follow them. + # This means that if the user passes 'data/h20_hetop_standard80.dat' where + # data/ is a local test directory, output lands in that local directory. + # Converted component files go in atomic_simple/ beside the master. + # Unchanged file references keep their original data/... paths. + + master_input_dir = os.path.dirname(os.path.abspath(args.master)) + + # Output directory for converted component files + if args.outdir: + simple_dir = os.path.abspath(args.outdir) + else: + simple_dir = os.path.join(master_input_dir, 'atomic_simple') + + os.makedirs(simple_dir, exist_ok=True) + + # Output master file: _simple.dat in the same directory as input + base = os.path.basename(master_abs) + root, ext = os.path.splitext(base) + out_master_path = os.path.join(master_input_dir, root + '_simple' + ext) + + print(f'Input master : {master_abs}') + print(f'Output master: {out_master_path}') + print(f'Component dir: {simple_dir}') + print(f'Line filter : ll <= {args.max_lower_level}, f >= {args.min_osc_strength}') + print() + + # Read and process the master file line by line + new_master_lines = [ + f'# Simple-atom version of {os.path.basename(master_abs)}\n', + f'# Generated by macro2simple.py\n', + f'# LinMacro lines filtered: ll <= {args.max_lower_level}', + ] + if args.min_osc_strength > 0: + new_master_lines[-1] += f', f >= {args.min_osc_strength}' + new_master_lines[-1] += '\n' + new_master_lines.append( + '# IonM->IonV (nlte=0), LevMacro->LevTop, LinMacro->Line.\n') + new_master_lines.append( + '# Phot and all atomic/ files referenced in-place.\n') + new_master_lines.append('#\n') + + with open(master_abs) as f: + raw_lines = f.readlines() + + for raw in raw_lines: + stripped = raw.strip() + + # Blank lines and comments pass through + if not stripped or stripped.startswith('#'): + new_master_lines.append(raw) + continue + + # It's a component file reference + data_path = stripped + abs_path = resolve_data_path(data_path) + + if not os.path.isfile(abs_path): + print(f' Warning: cannot find {data_path} -- keeping reference unchanged') + new_master_lines.append(raw) + continue + + keywords = file_keywords(abs_path) + + if not keywords: + # Nothing to convert -- reference in-place + new_master_lines.append(raw) + continue + + # File needs conversion + out_path = simple_outpath(abs_path, simple_dir) + out_rel = to_output_rel(out_path) + + if keywords == {'IonM'}: + n = convert_elem_ions(abs_path, out_path) + print(f' IonM->IonV : {data_path}') + print(f' -> {out_rel} ({n} ions converted)') + + elif keywords == {'LevMacro'}: + n = convert_levels(abs_path, out_path) + print(f' LevMacro->LevTop: {data_path}') + print(f' -> {out_rel} ({n} levels converted)') + + elif keywords == {'LinMacro'}: + n_total, n_kept = convert_lines(abs_path, out_path, + args.max_lower_level, + args.min_osc_strength) + print(f' LinMacro->Line : {data_path}') + print(f' -> {out_rel} ({n_kept}/{n_total} lines kept)') + + elif keywords == {'PhotMacS'}: + n = convert_phot(abs_path, out_path) + print(f' PhotMacS->PhotTopS: {data_path}') + print(f' -> {out_rel} ({n} xsection blocks converted)') + + else: + # Mixed file -- apply conversions sequentially via a temp file + import shutil + tmp = out_path + '.tmp' + tmp2 = out_path + '.tmp2' + src = abs_path + if 'IonM' in keywords: + convert_elem_ions(src, tmp); src = tmp + if 'LevMacro' in keywords: + convert_levels(src, tmp2); src = tmp2 + if 'LinMacro' in keywords: + n_total, n_kept = convert_lines(src, out_path, + args.max_lower_level, + args.min_osc_strength) + elif 'PhotMacS' in keywords: + convert_phot(src, out_path) + else: + shutil.copy(src, out_path) + for t in (tmp, tmp2): + if os.path.exists(t): + os.remove(t) + print(f' Mixed : {data_path} -> {out_rel}') + + new_master_lines.append(out_rel + '\n') + + # Write the new master file + with open(out_master_path, 'w') as f: + f.writelines(new_master_lines) + + print(f'\nWrote {out_master_path}') + + +if __name__ == '__main__': + main() From 250220842487451226e670a0857eac2e248527cd Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 17 Jun 2026 10:55:31 -0500 Subject: [PATCH 30/33] Remove macro2simple.py: replaced by ConvertMacro2Simple.py macro2simple.py collides with Macro2Simple.py on macOS case-insensitive filesystems. Functionality is preserved in ConvertMacro2Simple.py. Co-Authored-By: Claude Sonnet 4.6 --- py_progs/macro2simple.py | 401 --------------------------------------- 1 file changed, 401 deletions(-) delete mode 100755 py_progs/macro2simple.py diff --git a/py_progs/macro2simple.py b/py_progs/macro2simple.py deleted file mode 100755 index 9c4d42c43..000000000 --- a/py_progs/macro2simple.py +++ /dev/null @@ -1,401 +0,0 @@ -#!/usr/bin/env python -""" -macro2simple.py -- Convert a Sirocco macro-atom atomic data set to simple-atom format. - -The script reads a macro-atom master data file (e.g. data/h20_hetop_standard80.dat), -identifies the component files that contain macro-atom specific keywords (IonM, -LevMacro, LinMacro), converts them to their simple-atom equivalents, and writes -a new master file that assembles the converted and unchanged files. - -Conversions applied: - IonM -> IonV (elem_ions files) nlte field set to 0 - LevMacro -> LevTop (levels files) -1 inserted for islp and qqnum fields - LinMacro -> Line (lines files) filtered by lower level index and oscillator strength - -Files that require no conversion (topbase phot files, collision data, etc.) are -referenced in-place in the new master file -- no copying. - -Usage: - macro2simple.py input_master.dat [options] - - input_master.dat Path to macro-atom master file, relative to $SIROCCO - (e.g. data/h20_hetop_standard80.dat) or absolute. - -Options: - --max-lower-level N Keep LinMacro lines with ll <= N [default: 1] - --min-osc-strength F Keep lines with f >= F [default: 0.0] - --outdir DIR Directory for converted files [default: $SIROCCO/data/atomic_simple] - -Output: - $SIROCCO/data/_simple.dat new master file - $SIROCCO/data/atomic_simple/_simple.dat converted component files -""" - -import os -import sys -import argparse -import re - -# --------------------------------------------------------------------------- -# Path helpers -# --------------------------------------------------------------------------- - -SIROCCO = os.environ.get('SIROCCO', '') - - -def resolve_data_path(data_path): - """Resolve a data/-relative path to an absolute path. - - In a Sirocco run directory 'data/' is a symlink to $SIROCCO/xdata/, so - paths in master files look like 'data/atomic_macro/h20_lines.dat' and - resolve to $SIROCCO/xdata/atomic_macro/h20_lines.dat. - """ - if os.path.isabs(data_path): - return data_path - if SIROCCO: - # data/ -> $SIROCCO/xdata/ - xdata_path = data_path.replace('data/', 'xdata/', 1) if data_path.startswith('data/') else data_path - candidate = os.path.join(SIROCCO, xdata_path) - if os.path.isfile(candidate): - return candidate - # Also try without xdata substitution (e.g. if called with an xdata/ path) - candidate2 = os.path.join(SIROCCO, data_path) - if os.path.isfile(candidate2): - return candidate2 - # Fall back to cwd-relative (handles run-directory usage where data/ symlink exists) - local = os.path.abspath(data_path) - if os.path.isfile(local): - return local - return local - - -def to_output_rel(abs_path): - """Return a CWD-relative path for a converted output file. - - Since Sirocco resolves all paths in master files relative to the run - directory, we express output paths relative to CWD. For a master in - data/ this yields data/atomic_simple/. - """ - return os.path.relpath(abs_path, os.getcwd()) - - -# --------------------------------------------------------------------------- -# File-type detection -# --------------------------------------------------------------------------- - -def file_keywords(filepath): - """Return the set of macro-atom keywords present in a file.""" - found = set() - try: - with open(filepath) as f: - for line in f: - word = line.split()[0] if line.split() else '' - if word in ('IonM', 'LevMacro', 'LinMacro', 'PhotMacS'): - found.add(word) - if len(found) == 4: - break - except (IOError, OSError): - pass - return found - - -# --------------------------------------------------------------------------- -# Conversion routines -- each returns (lines_written, lines_skipped) -# --------------------------------------------------------------------------- - -def convert_elem_ions(inpath, outpath): - """Convert IonM -> IonV and set nlte to 0.""" - n_converted = 0 - with open(inpath) as fin, open(outpath, 'w') as fout: - for raw in fin: - stripped = raw.strip() - if not stripped.startswith('IonM'): - fout.write(raw) - continue - - # IonM name z istate g ip nmax nlte label - # Replace IonM with IonV and set nlte (second-to-last numeric field) to 0. - # We parse conservatively to preserve spacing of the label. - parts = stripped.split() - # parts[0]=IonM parts[1]=name parts[2]=z parts[3]=istate - # parts[4]=g parts[5]=ip parts[6]=nmax parts[7]=nlte parts[8+]=label - if len(parts) < 8: - fout.write(raw) - continue - parts[0] = 'IonV' - # Keep nlte (parts[7]) at its original value so that level nden - # slots are allocated and PhotTopS cross-sections can be matched. - # Reconstruct with consistent spacing; preserve label verbatim - label = ' '.join(parts[8:]) - fout.write('%-8s %-4s %3s %3s %3s %12s %5s %3s %s\n' % ( - parts[0], parts[1], parts[2], parts[3], - parts[4], parts[5], parts[6], parts[7], label)) - n_converted += 1 - - return n_converted - - -def convert_levels(inpath, outpath): - """Convert LevMacro -> LevTop, inserting -1 for islp and qqnum fields.""" - n_converted = 0 - with open(inpath) as fin, open(outpath, 'w') as fout: - for raw in fin: - stripped = raw.strip() - if not stripped.startswith('LevMacro'): - fout.write(raw) - continue - - # LevMacro z ion ilv ion_pot ex_energy g rad_rate () label - # LevTop z ion islp ilv ion_pot ex_energy g qqnum rad_rate () label - parts = stripped.split() - # parts[0]=LevMacro [1]=z [2]=ion [3]=ilv [4]=e [5]=exx [6]=g [7]=rl [8]=() [9+]=label - if len(parts) < 9: - fout.write(raw) - continue - label = ' '.join(parts[9:]) - fout.write('LevTop %3s %3s %4d %3s %12s %12s %5s %6s %11s %s %s\n' % ( - parts[1], parts[2], - -1, # islp -- not used by simple atoms - parts[3], # ilv - parts[4], # ion_pot - parts[5], # ex_energy - parts[6], # g - -1, # qqnum -- not used by simple atoms - parts[7], # rad_rate - parts[8], # () - label)) - n_converted += 1 - - return n_converted - - -def convert_lines(inpath, outpath, max_ll, min_f): - """Convert LinMacro -> Line, keeping only ll <= max_ll and f >= min_f.""" - n_total = 0 - n_kept = 0 - with open(inpath) as fin, open(outpath, 'w') as fout: - for raw in fin: - stripped = raw.strip() - if not stripped.startswith('LinMacro'): - fout.write(raw) - continue - - n_total += 1 - # LinMacro z ion lambda f gl gu el eu ll lu - parts = stripped.split() - if len(parts) < 11: - fout.write(raw) - n_kept += 1 - continue - - ll = int(parts[9]) - f_val = float(parts[4]) - - if ll > max_ll or f_val < min_f: - continue - - # Replace keyword only; preserve all field values - fout.write('Line' + raw[len('LinMacro'):]) - n_kept += 1 - - return n_total, n_kept - - -def convert_phot(inpath, outpath): - """Convert PhotMacS/PhotMac -> PhotTopS/PhotTop. - - PhotMacS format: PhotMacS z istate levl levu exx np - PhotTopS format: PhotTopS z istate islp ilv exx np - - We use levl as ilv and -1 as islp, which matches the -1 islp values - written by convert_levels for the LevTop entries. The upper level - index (levu) is dropped since PhotTopS only references the lower level. - """ - n_converted = 0 - with open(inpath) as fin, open(outpath, 'w') as fout: - for raw in fin: - stripped = raw.strip() - if stripped.startswith('PhotMacS'): - # PhotMacS z istate levl levu exx np - parts = stripped.split() - if len(parts) >= 7: - z, istate, levl, levu, exx, np_ = parts[1:7] - fout.write(f'PhotTopS {z} {istate} -1 {levl} {exx} {np_}\n') - n_converted += 1 - else: - fout.write(raw) - elif stripped.startswith('PhotMac'): - # PhotMac freq xsection -> PhotTop freq xsection - fout.write('PhotTop' + raw[len('PhotMac'):]) - else: - fout.write(raw) - return n_converted - - -# --------------------------------------------------------------------------- -# Output filename helper -# --------------------------------------------------------------------------- - -def simple_outpath(inpath, simple_dir): - """Derive the output path for a converted file in simple_dir.""" - base = os.path.basename(inpath) - root, ext = os.path.splitext(base) - return os.path.join(simple_dir, root + '_simple' + ext) - - -# --------------------------------------------------------------------------- -# Main -# --------------------------------------------------------------------------- - -def main(): - parser = argparse.ArgumentParser( - description='Convert a macro-atom Sirocco atomic data set to simple-atom format') - parser.add_argument('master', - help='Master data file (e.g. data/h20_hetop_standard80.dat or absolute path)') - parser.add_argument('--max-lower-level', type=int, default=1, metavar='N', - help='Keep LinMacro lines with ll <= N (default: 1, ground-state only)') - parser.add_argument('--min-osc-strength', type=float, default=0.0, metavar='F', - help='Keep lines with oscillator strength >= F (default: 0.0)') - parser.add_argument('--outdir', default=None, - help='Directory for converted component files ' - '(default: $SIROCCO/data/atomic_simple)') - args = parser.parse_args() - - # Resolve the master file - master_abs = resolve_data_path(args.master) - if not os.path.isfile(master_abs): - print(f'Error: cannot find master file: {args.master}', file=sys.stderr) - if not SIROCCO: - print(' Hint: $SIROCCO is not set', file=sys.stderr) - sys.exit(1) - - # Output goes alongside the input master file, without resolving symlinks. - # os.path.abspath preserves symlinks; os.path.realpath would follow them. - # This means that if the user passes 'data/h20_hetop_standard80.dat' where - # data/ is a local test directory, output lands in that local directory. - # Converted component files go in atomic_simple/ beside the master. - # Unchanged file references keep their original data/... paths. - - master_input_dir = os.path.dirname(os.path.abspath(args.master)) - - # Output directory for converted component files - if args.outdir: - simple_dir = os.path.abspath(args.outdir) - else: - simple_dir = os.path.join(master_input_dir, 'atomic_simple') - - os.makedirs(simple_dir, exist_ok=True) - - # Output master file: _simple.dat in the same directory as input - base = os.path.basename(master_abs) - root, ext = os.path.splitext(base) - out_master_path = os.path.join(master_input_dir, root + '_simple' + ext) - - print(f'Input master : {master_abs}') - print(f'Output master: {out_master_path}') - print(f'Component dir: {simple_dir}') - print(f'Line filter : ll <= {args.max_lower_level}, f >= {args.min_osc_strength}') - print() - - # Read and process the master file line by line - new_master_lines = [ - f'# Simple-atom version of {os.path.basename(master_abs)}\n', - f'# Generated by macro2simple.py\n', - f'# LinMacro lines filtered: ll <= {args.max_lower_level}', - ] - if args.min_osc_strength > 0: - new_master_lines[-1] += f', f >= {args.min_osc_strength}' - new_master_lines[-1] += '\n' - new_master_lines.append( - '# IonM->IonV (nlte=0), LevMacro->LevTop, LinMacro->Line.\n') - new_master_lines.append( - '# Phot and all atomic/ files referenced in-place.\n') - new_master_lines.append('#\n') - - with open(master_abs) as f: - raw_lines = f.readlines() - - for raw in raw_lines: - stripped = raw.strip() - - # Blank lines and comments pass through - if not stripped or stripped.startswith('#'): - new_master_lines.append(raw) - continue - - # It's a component file reference - data_path = stripped - abs_path = resolve_data_path(data_path) - - if not os.path.isfile(abs_path): - print(f' Warning: cannot find {data_path} -- keeping reference unchanged') - new_master_lines.append(raw) - continue - - keywords = file_keywords(abs_path) - - if not keywords: - # Nothing to convert -- reference in-place - new_master_lines.append(raw) - continue - - # File needs conversion - out_path = simple_outpath(abs_path, simple_dir) - out_rel = to_output_rel(out_path) - - if keywords == {'IonM'}: - n = convert_elem_ions(abs_path, out_path) - print(f' IonM->IonV : {data_path}') - print(f' -> {out_rel} ({n} ions converted)') - - elif keywords == {'LevMacro'}: - n = convert_levels(abs_path, out_path) - print(f' LevMacro->LevTop: {data_path}') - print(f' -> {out_rel} ({n} levels converted)') - - elif keywords == {'LinMacro'}: - n_total, n_kept = convert_lines(abs_path, out_path, - args.max_lower_level, - args.min_osc_strength) - print(f' LinMacro->Line : {data_path}') - print(f' -> {out_rel} ({n_kept}/{n_total} lines kept)') - - elif keywords == {'PhotMacS'}: - n = convert_phot(abs_path, out_path) - print(f' PhotMacS->PhotTopS: {data_path}') - print(f' -> {out_rel} ({n} xsection blocks converted)') - - else: - # Mixed file -- apply conversions sequentially via a temp file - import shutil - tmp = out_path + '.tmp' - tmp2 = out_path + '.tmp2' - src = abs_path - if 'IonM' in keywords: - convert_elem_ions(src, tmp); src = tmp - if 'LevMacro' in keywords: - convert_levels(src, tmp2); src = tmp2 - if 'LinMacro' in keywords: - n_total, n_kept = convert_lines(src, out_path, - args.max_lower_level, - args.min_osc_strength) - elif 'PhotMacS' in keywords: - convert_phot(src, out_path) - else: - shutil.copy(src, out_path) - for t in (tmp, tmp2): - if os.path.exists(t): - os.remove(t) - print(f' Mixed : {data_path} -> {out_rel}') - - new_master_lines.append(out_rel + '\n') - - # Write the new master file - with open(out_master_path, 'w') as f: - f.writelines(new_master_lines) - - print(f'\nWrote {out_master_path}') - - -if __name__ == '__main__': - main() From 3c68041ff08ce062e8e684473def753c55a2a1be Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 17 Jun 2026 11:27:30 -0500 Subject: [PATCH 31/33] Add CLAUDE.md: rule against case-only filename differences for macOS compat Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..3026615de --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,4 @@ +# Sirocco Project Rules + +## File Naming +- Never create two files whose names differ only in case (e.g. `macro2simple.py` and `Macro2Simple.py`). macOS uses a case-insensitive filesystem and will treat them as the same file, causing one to silently overwrite the other on any Mac clone or pull. From 4c990a0870e8e49d245cd2861ebb424c0448ec21 Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Wed, 17 Jun 2026 11:33:05 -0500 Subject: [PATCH 32/33] Update CLAUDE.md: replace stub with full project documentation Matches x3d branch content: build commands, architecture overview, coding conventions, and both Claude Code rules (version number + macOS filenames). Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3026615de..c0e7b67a5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,145 @@ -# Sirocco Project Rules +# CLAUDE.md -## File Naming -- Never create two files whose names differ only in case (e.g. `macro2simple.py` and `Macro2Simple.py`). macOS uses a case-insensitive filesystem and will treat them as the same file, causing one to silently overwrite the other on any Mac clone or pull. +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Sirocco (Simulating Ionization and Radiation in Outflows Created by Compact Objects) is a Monte Carlo radiative transfer code using the Sobolev approximation. It simulates winds and outflows in systems like cataclysmic variables, AGN, X-ray binaries, and young stellar objects. Formerly known as "Python" (renamed October 2024). + +## Build Commands + +**Environment setup** (required before building): +```bash +export SIROCCO=/path/to/Sirocco +``` + +**First-time full build** (compiles GSL, CUnit, then Sirocco): +```bash +./configure # detects compilers (mpicc/gcc) and optional CUDA +make install # builds GSL 2.6, CUnit 3.2.7, and all source +``` + +**Recompile source only** (after initial install): +```bash +cd source && make CC=mpicc sirocco # main program +cd source && make CC=mpicc all # all targets + indent check +cd source && make D sirocco # debug/profiling build (-g -pg) +cd source && make CC=gcc sirocco # compile without MPI +cd source && make INDENT=no sirocco # skip auto-indentation +``` + +**Other build targets** (all from `source/`): +- `make swind` — spectral wind analysis +- `make windsave2table` — convert wind saves to ASCII tables +- `make windsave2fits` — convert wind saves to FITS (requires cfitsio) +- `make rad_hydro_files`, `make modify_wind`, `make inspect_wind` — wind utilities +- `make sirocco_optd` — optical depth calculations + +**Clean build artifacts**: +```bash +cd source && make clean +``` + +**Unit tests** (requires CUnit + cmake): +```bash +make check # from top-level +cd source && make check # from source directory +``` + +**Running Sirocco**: +```bash +$SIROCCO/bin/Setup_Sirocco_Dir # set up working directory with symlinks +sirocco parameter_file.pf # serial +sirocco -i root # interactive mode (creates parameter file) +mpirun -n 4 sirocco parameter_file.pf # parallel with MPI +``` + +## Architecture + +### Language and Compilation +- C (gnu99 standard), ~130 source files in `source/` +- Default compiler: `mpicc` (sets `-DMPI_ON`); falls back to gcc/clang +- Optional CUDA support via `--with-cuda` configure flag (matrix operations on GPU) +- Dependencies: GSL 2.6 (bundled in `software/`), CUnit 3.2.7 (bundled) +- Auto-indentation enforced on commit via `py_progs/run_indent.py` using GNU indent + +### Key Source Files +- `source/sirocco.c` — main entry point, orchestrates ionization and spectrum cycles +- `source/sirocco.h` (~98KB) — central header with all major data structures (`PlasmaPtr`, `WindPtr`, `PhotPtr`, domain geometry structs) +- `source/atomic.h` (~31KB) — atomic data structures (ions, lines, levels, cross-sections) +- `source/templates.h` — auto-generated function prototypes (via `cproto`) +- `source/version.h` — auto-generated at build time from git hash + +### Core Code Organization (in `source/`) +- **Wind models**: `define_wind.c`, `wind.c`, `wind2d.c`, `spherical.c`, `cylindrical.c`, `rtheta.c`, `sv.c` (Shlosman-Vitello), `knigge.c`, `homologous.c`, `corona.c`, `shell_wind.c`, `hydro_import.c` +- **Photon transport**: `trans_phot.c`, `photon2d.c`, `photon_gen.c`, `extract.c`, `paths.c`, `phot_util.c` +- **Radiation & spectra**: `radiation.c`, `spectra.c`, `bands.c`, `continuum.c`, `brem.c`, `compton.c`, `emission.c` +- **Ionization**: `ionization.c`, `direct_ion.c`, `saha.c`, `charge_exchange.c`, `partition.c`, `levels.c`, `recomb.c` +- **Macro-atom**: `matom.c`, `matom_diag.c`, `macro_gov.c`, `macro_gen_f.c`, `macro_accelerate.c`, `estimators_macro.c` +- **Line transfer**: `lines.c`, `resonance.c` (`resonate.c`), `dielectronic.c` +- **Disk**: `disk.c`, `disk_init.c`, `disk_photon_gen.c` +- **Setup/config**: `setup.c`, `setup_domains.c`, `setup_disk.c`, `setup_star_bh.c`, `setup_line_transfer.c`, `parse.c`, `rdpar.c` +- **MPI communication**: `communicate_plasma.c`, `communicate_wind.c`, `communicate_macro.c`, `communicate_spectra.c`, `para_update.c` +- **I/O**: `windsave.c`, `windsave2table_sub.c`, `xlog.c`, `diag.c` +- **Math utilities**: `recipes.c`, `random.c`, `cdf.c`, `vvector.c`, `matrix_cpu.c`, `matrix_gpu.cu` +- **Frame transformations**: `frame.c` + +### Data Directories +- `xdata/` — atomic data files read at runtime (referenced via `Atomic_data` parameter) +- `xmod/` — model grids and spectra for disk/stellar models +- `examples/` — parameter files (`.pf`) organized by type: `basic/`, `extended/`, `regress/`, `gh-workflow/` + +### Python Utilities (`py_progs/`) +Support scripts for data processing, visualization, and code maintenance: +- `run_indent.py` — enforces GNU indent code style on changed C files +- `MakeMacro.py` — generates macro-atom data from Chianti/Topbase databases +- `plot_spec.py`, `plot_wind.py`, `plot_tot.py` — visualization +- `hydro_2_python.py` — parse hydro simulation output for use with Sirocco's hydro import facility +- `import_model.py` — unified import-file generator for all coordinate systems (spherical, cylindrical, polar, cyl3d, sph3d) +- `balmer_decrement.py` — physics validation test +- `regression.py` — regression testing utilities + +### Testing +- **Unit tests**: CUnit-based in `source/tests/` (test_matrix, test_compton, test_define_wind, test_run_mode, test_translate) +- **Integration tests**: GitHub Actions workflow (`.github/workflows/build.yml`) runs multiple example parameter files (CV, AGN, XRB, SN models) on pushes to dev/main +- **Regression tests**: Examples in `examples/regress/` + +### Build System Notes +- `Makefile.in` is the top-level template (not auto-generated by autoconf — `configure` is a hand-written shell script) +- `source/Makefile` handles all C compilation, prototype generation, and indentation +- `source/tests/Makefile` includes the main source Makefile and links all Sirocco source for unit tests +- `get_models.c` cannot be included in `sirocco_source` list (prototype generation issue) but is added separately to object lists +- `make prototypes` regenerates `templates.h`, `log.h`, `atomic_proto.h`, `math_proto.h` via `cproto` + +## Dependencies +- GSL 2.6 (bundled in `software/`) +- CUnit 3.2.7 (bundled in `software/`, requires CMake) +- MPI: OpenMPI or MPICH (`mpicc`) +- Optional: cfitsio (for FITS output via `windsave2fits`) +- Optional: CUDA (for GPU matrix operations via `--with-cuda`) + +## Parameter Files + +Sirocco uses `.pf` parameter files with key-value pairs: +``` +System_type(star,cv,bh,agn,previous) cv +Central_object.mass(msol) 0.8 +Wind.type(SV,star,hydro,corona,...) sv +Photons_per_cycle 100000 +``` +Example files are in `examples/basic/`, `examples/extended/`, and `examples/gh-workflow/`. + +## Documentation +- Full docs: https://sirocco-rt.readthedocs.io +- Model spectra (optional): clone `https://github.com/sirocco-rt/xmod` into `xmod/` + +## Claude Code Rules +- **Never change the version number** in `source/version.h` or `source/Makefile` without explicit user instruction. Always ask before touching these. +- **Never create two files whose names differ only in case** (e.g. `macro2simple.py` and `Macro2Simple.py`). macOS uses a case-insensitive filesystem and will treat them as the same file, causing one to silently overwrite the other on any Mac clone or pull. + +## Coding Conventions +- GNU indent style enforced automatically on changed files during build (unless `INDENT=no`) +- ANSI C with gnu99 standard +- MPI code guarded by `#ifdef MPI_ON` preprocessor directives +- CUDA code guarded by `#ifdef CUDA_ON` +- Logging via `xlog.c` functions (Log, Error, Debug) From e1287e0864eb101be28b9980f6a51c9058d726ef Mon Sep 17 00:00:00 2001 From: "Knox S. Long" Date: Thu, 18 Jun 2026 16:14:38 -0500 Subject: [PATCH 33/33] Fix cell_spec_flux persistence and -cell_spec_dim for new runs Two related bugs introduced when cell_spec_flux was converted from a fixed array to a dynamic pointer (9362f1f3): 1. windsave.c: cell_spec_flux was never written to or read from the wind_save file, leaving the Jnu extension in windsave2fits output all zeros. Add fwrite/fread in the per-cell dynamic-array block. 2. sirocco.c: -cell_spec_dim N was silently ignored on new runs because init_geo() resets geo.nbins_in_cell_spec to 100 after parse_command_line captures the flag. The restart and previous-run paths already re-applied cmd_nbins_in_cell_spec after wind_read; add the same restore+validate block for RUN_TYPE_NEW. Note: the windsave.c change alters the wind_save binary format; files written before this fix cannot be read correctly by the updated code. memory, polar, and biconic branches have both bugs and need cherry-pick of this commit. Co-Authored-By: Claude Sonnet 4.6 --- source/sirocco.c | 8 ++++++++ source/windsave.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/source/sirocco.c b/source/sirocco.c index 637f3b717..005bc3679 100644 --- a/source/sirocco.c +++ b/source/sirocco.c @@ -325,6 +325,14 @@ main (int argc, char *argv[]) if (geo.run_type == RUN_TYPE_NEW) { init_geo (); + /* Re-apply command-line -cell_spec_dim if given; init_geo resets to default 100 */ + if (cmd_nbins_in_cell_spec > 0) + geo.nbins_in_cell_spec = cmd_nbins_in_cell_spec; + if (geo.nbins_in_cell_spec < 1 || geo.nbins_in_cell_spec > NBINS_IN_CELL_SPEC) + { + Log ("cell_spec_dim %d out of range, resetting to 100\n", geo.nbins_in_cell_spec); + geo.nbins_in_cell_spec = 100; + } } /* get_stellar_params gets information like mstar, rstar, tstar etc. diff --git a/source/windsave.c b/source/windsave.c index 98e9895e9..90cf388aa 100644 --- a/source/windsave.c +++ b/source/windsave.c @@ -138,6 +138,7 @@ in the plasma structure */ n += fwrite (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fwrite (plasmamain[m].derived.n_bf_in, sizeof (int), nphot_total, fptr); n += fwrite (plasmamain[m].derived.n_bf_out, sizeof (int), nphot_total, fptr); + n += fwrite (plasmamain[m].est.cell_spec_flux, sizeof (double), geo.nbins_in_cell_spec, fptr); } /* Now write out the macro atom info */ @@ -360,6 +361,7 @@ wind_read (char filename[]) n += fread (plasmamain[m].derived.F_UV_ang_r_persist, sizeof (double), NFLUX_ANGLES, fptr); n += fread (plasmamain[m].derived.n_bf_in, sizeof (int), nphot_total, fptr); n += fread (plasmamain[m].derived.n_bf_out, sizeof (int), nphot_total, fptr); + n += fread (plasmamain[m].est.cell_spec_flux, sizeof (double), geo.nbins_in_cell_spec, fptr); }