Skip to content

vulcan.vulcan

vulcan


Main module for running VULCAN. Contains the run_vulcan function, which executes the main VULCAN workflow, and the run_cli function, which serves as the entry point when running the script directly.

Imports

run_cli()

Entry point for the script when run directly.

Source code in src/vulcan/vulcan.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def run_cli():
    """Entry point for the script when run directly."""

    print('Starting VULCAN from command line')

    # Make config
    vulcan_cfg = Config()

    # Make output folder
    if not os.path.exists(vulcan_cfg.output_dir):
        os.makedirs(vulcan_cfg.output_dir)

    # Setup basic logging
    logpath = os.path.join(vulcan_cfg.output_dir, 'vulcan.log')
    setup_logger(logpath=logpath, logterm=True, level=vulcan_cfg.log_level)
    log = logging.getLogger('fwl.' + __name__)

    # Remake chem_funs by default. Disabled when passing -n flag.
    make_network = bool('-n' not in sys.argv)

    # Run model
    run_vulcan(vulcan_cfg, make_network)

run_vulcan(vulcan_cfg, make_network=True)

Run VULCAN with the given configuration.

Parameters:

Name Type Description Default
vulcan_cfg Config

The configuration object containing all settings for the VULCAN run.

required
make_network bool

Whether to remake the chemical network (chem_funs.py). Default is True.

True
Source code in src/vulcan/vulcan.py
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def run_vulcan(vulcan_cfg: Config, make_network: bool = True):
    """Run VULCAN with the given configuration.

    Parameters
    ----------
    vulcan_cfg : Config
        The configuration object containing all settings for the VULCAN run.
    make_network : bool, optional
        Whether to remake the chemical network (chem_funs.py). Default is True.
    """

    # make network?
    if make_network:
        log.debug('Making chem_funs.py ...')
        make_all(vulcan_cfg)
    else:
        log.debug('Skip making chem_funs.py')

    log.info('Running VULCAN')

    # Import modules for running VULCAN
    from . import build_atm, op, store

    ### read in the basic chemistry data
    with open(paths.COM_FILE, 'r') as f:
        columns = f.readline()  # reading in the first line
        num_ele = (
            len(columns.split()) - 2
        )  # number of elements (-2 for removing "species" and "mass")
    type_list = ['int' for i in range(num_ele)]
    type_list.insert(0, 'U20')
    type_list.append('float')

    ### create the instances for storing the variables and parameters
    data_var = store.Variables(vulcan_cfg)
    data_atm = store.AtmData(vulcan_cfg)
    data_para = store.Parameters(vulcan_cfg)

    # record starting CPU time
    data_para.start_time = time.time()

    # create atmosphere object
    make_atm = build_atm.Atm(vulcan_cfg)

    # for plotting and printing
    output = op.Output(vulcan_cfg)

    # write config to disk
    vulcan_cfg.write_file()

    # construct pico
    data_atm = make_atm.f_pico(data_atm)

    # construct Tco and Kzz
    data_atm = make_atm.load_TPK(data_atm)

    # construct Dzz (molecular diffusion)
    # Only setting up ms (the species molecular weight) if vulcan_cfg.use_moldiff == False
    make_atm.mol_diff(data_atm)

    # calculating the saturation pressure
    if vulcan_cfg.use_condense:
        make_atm.sp_sat(data_atm)

    # for reading rates
    rate = op.ReadRate(vulcan_cfg)

    # read-in network and calculating forward rates
    data_var = rate.read_rate(data_var, data_atm)

    # for low-T rates e.g. Jupiter
    if vulcan_cfg.use_lowT_limit_rates:
        data_var = rate.lim_lowT_rates(data_var, data_atm)

    # reversing rates
    data_var = rate.rev_rate(data_var, data_atm)

    # removing rates
    data_var = rate.remove_rate(data_var)

    # initialing y and ymix (the number density and the mixing ratio of every species)
    ini_abun = build_atm.InitialAbun(vulcan_cfg)
    data_var = ini_abun.ini_y(data_var, data_atm)

    # storing the initial total number of atmos
    data_var = ini_abun.ele_sum(data_var)

    # calculating mean molecular weight, dz, and dzi and plotting TP
    data_atm = make_atm.f_mu_dz(data_var, data_atm, output)

    # specify the BC
    make_atm.BC_flux(data_atm)

    # initialise environment for T(p) solver
    atmos = None
    if vulcan_cfg.agni_call_frq > 0:
        # setup julia
        from .agni import activate_julia, deallocate_atmos, init_agni_atmos

        activate_julia(vulcan_cfg)

        # setup AGNI atmosphere object
        atmos = init_agni_atmos(vulcan_cfg, data_atm, data_var)

    # ============== Execute VULCAN  ==============
    # time-steping in the while loop until conv() returns True or count > count_max

    # setting the numerical solver to the desinated one in vulcan_cfg
    solver = op.Ros2(vulcan_cfg)

    # Setting up for photo chemistry
    if vulcan_cfg.use_photo:
        rate.make_bins_read_cross(data_var, data_atm)
        # rate.read_cross(data_var)
        make_atm.read_sflux(data_var, data_atm)

        # computing the optical depth (tau), flux, and the photolisys rates (J) for the first time
        solver.compute_tau(data_var, data_atm)
        solver.compute_flux(data_var, data_atm)
        solver.compute_J(data_var, data_atm)
        # they will be updated in op.Integration by the assigned frequence

        # removing rates
        data_var = rate.remove_rate(data_var)

    # Assgining the specific solver corresponding to different B.C.s
    integ = op.Integration(solver, output, vulcan_cfg)
    solver.naming_solver(data_para)

    # Running the integration loop
    log.info(f'Starting VULCAN integration with {os.environ["OMP_NUM_THREADS"]} threads...')
    integ(data_var, data_atm, data_para, make_atm, atmos=atmos)

    # Save result to disk
    output.save_out(data_var, data_atm, data_para)

    # Deallocate AGNI
    if atmos:
        deallocate_atmos(atmos)