def main(stop_time, run_simu=True, make_graphs=True): if run_simu: meteo = pd.read_csv(METEO_FILEPATH, index_col='t') Eabs_df = pd.read_csv(CARIBU_FILEPATH) # define the time step in hours for each simulator senescwheat_ts = 2 growthwheat_ts = 2 farquharwheat_ts = 2 elongwheat_ts = 2 cnwheat_ts = 1 hour_to_second_conversion_factor = 3600 # read adelwheat inputs at t0 adel_wheat = AdelDyn(seed=1234, scene_unit='m') g = adel_wheat.load(dir=ADELWHEAT_INPUTS_DIRPATH) # adel_wheat.plot(g) # create empty dataframes to shared data between the models shared_axes_inputs_outputs_df = pd.DataFrame() shared_organs_inputs_outputs_df = pd.DataFrame() shared_hiddenzones_inputs_outputs_df = pd.DataFrame() shared_elements_inputs_outputs_df = pd.DataFrame() shared_soils_inputs_outputs_df = pd.DataFrame() # read the inputs at t0 and create the facades # caribu caribu_facade_ = caribu_facade.CaribuFacade( g, shared_elements_inputs_outputs_df, adel_wheat) # senescwheat senescwheat_roots_inputs_t0 = pd.read_csv( SENESCWHEAT_ROOTS_INPUTS_FILEPATH) senescwheat_axes_inputs_t0 = pd.read_csv( SENESCWHEAT_AXES_INPUTS_FILEPATH) senescwheat_elements_inputs_t0 = pd.read_csv( SENESCWHEAT_ELEMENTS_INPUTS_FILEPATH) senescwheat_facade_ = senescwheat_facade.SenescWheatFacade( g, senescwheat_ts * hour_to_second_conversion_factor, senescwheat_roots_inputs_t0, senescwheat_axes_inputs_t0, senescwheat_elements_inputs_t0, shared_organs_inputs_outputs_df, shared_axes_inputs_outputs_df, shared_elements_inputs_outputs_df) # growthwheat growthwheat_hiddenzones_inputs_t0 = pd.read_csv( GROWTHWHEAT_HIDDENZONE_INPUTS_FILEPATH) growthwheat_organ_inputs_t0 = pd.read_csv( GROWTHWHEAT_ORGANS_INPUTS_FILEPATH) growthwheat_root_inputs_t0 = pd.read_csv( GROWTHWHEAT_ROOTS_INPUTS_FILEPATH) growthwheat_axes_inputs_t0 = pd.read_csv( GROWTHWHEAT_AXES_INPUTS_FILEPATH) growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade( g, growthwheat_ts * hour_to_second_conversion_factor, growthwheat_hiddenzones_inputs_t0, growthwheat_organ_inputs_t0, growthwheat_root_inputs_t0, growthwheat_axes_inputs_t0, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_axes_inputs_outputs_df) # farquharwheat farquharwheat_elements_inputs_t0 = pd.read_csv( FARQUHARWHEAT_INPUTS_FILEPATH) farquharwheat_axes_inputs_t0 = pd.read_csv( FARQUHARWHEAT_AXES_INPUTS_FILEPATH) update_parameters_farquharwheat = { 'MODEL_VERSION': 'Barillot2016' } # Use the initial version of the photosynthesis sub-model (as in Barillot et al. 2016, and in Gauthier et al. 2020) farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade( g, farquharwheat_elements_inputs_t0, farquharwheat_axes_inputs_t0, shared_elements_inputs_outputs_df, update_parameters=update_parameters_farquharwheat) # elongwheat # Only for temperature related computations elongwheat_hiddenzones_inputs_t0 = pd.read_csv( ELONGWHEAT_HZ_INPUTS_FILEPATH) elongwheat_elements_inputs_t0 = pd.read_csv( ELONGWHEAT_ELEMENTS_INPUTS_FILEPATH) elongwheat_axes_inputs_t0 = pd.read_csv( ELONGWHEAT_AXES_INPUTS_FILEPATH) elongwheat_facade_ = elongwheat_facade.ElongWheatFacade( g, elongwheat_ts * hour_to_second_conversion_factor, elongwheat_axes_inputs_t0, elongwheat_hiddenzones_inputs_t0, elongwheat_elements_inputs_t0, shared_axes_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, adel_wheat, option_static=True) # cnwheat cnwheat_organs_inputs_t0 = pd.read_csv(CNWHEAT_ORGANS_INPUTS_FILEPATH) cnwheat_hiddenzones_inputs_t0 = pd.read_csv( CNWHEAT_HIDDENZONE_INPUTS_FILEPATH) cnwheat_elements_inputs_t0 = pd.read_csv( CNWHEAT_ELEMENTS_INPUTS_FILEPATH) cnwheat_soils_inputs_t0 = pd.read_csv(CNWHEAT_SOILS_INPUTS_FILEPATH) update_cnwheat_parameters = { 'roots': { 'K_AMINO_ACIDS_EXPORT': 25 * 3E-5, 'K_NITRATE_EXPORT': 25 * 1E-6 } } cnwheat_facade_ = cnwheat_facade.CNWheatFacade( g, cnwheat_ts * hour_to_second_conversion_factor, CULM_DENSITY, update_cnwheat_parameters, cnwheat_organs_inputs_t0, cnwheat_hiddenzones_inputs_t0, cnwheat_elements_inputs_t0, cnwheat_soils_inputs_t0, shared_axes_inputs_outputs_df, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_soils_inputs_outputs_df) # adel_wheat.update_geometry(g) # NE FONCTIONNE PAS car MTG non compatible (pas de top et base element) # adel_wheat.plot(g) # define organs for which the variable 'max_proteins' is fixed forced_max_protein_elements = {(1, 'MS', 9, 'blade', 'LeafElement1'), (1, 'MS', 10, 'blade', 'LeafElement1'), (1, 'MS', 11, 'blade', 'LeafElement1'), (2, 'MS', 9, 'blade', 'LeafElement1'), (2, 'MS', 10, 'blade', 'LeafElement1'), (2, 'MS', 11, 'blade', 'LeafElement1')} # define the start and the end of the whole simulation (in hours) start_time = 0 stop_time = stop_time # define lists of dataframes to store the inputs and the outputs of the models at each step. axes_all_data_list = [] organs_all_data_list = [ ] # organs which belong to axes: roots, phloem, grains elements_all_data_list = [] soils_all_data_list = [] all_simulation_steps = [] # to store the steps of the simulation # run the simulators current_time_of_the_system = time.time() for t_elongwheat in range( start_time, stop_time, elongwheat_ts): # Only to compute temperature related variable # run ElongWheat print('t elongwheat is {}'.format(t_elongwheat)) Tair, Tsoil = meteo.loc[t_elongwheat, ['air_temperature', 'air_temperature']] elongwheat_facade_.run(Tair, Tsoil, option_static=True) for t_senescwheat in range(t_elongwheat, t_elongwheat + elongwheat_ts, senescwheat_ts): # run SenescWheat print('t senescwheat is {}'.format(t_senescwheat)) senescwheat_facade_.run(forced_max_protein_elements, postflowering_stages=True) # Test for fully senesced shoot tissues #TODO: Make the model to work even if the whole shoot is dead but the roots are alived if sum(senescwheat_facade_._shared_elements_inputs_outputs_df[ 'green_area']) <= 0.25E-6: break for t_growthwheat in range(t_senescwheat, t_senescwheat + senescwheat_ts, growthwheat_ts): # run GrowthWheat print('t growthwheat is {}'.format(t_growthwheat)) growthwheat_facade_.run(postflowering_stages=True) for t_farquharwheat in range( t_growthwheat, t_growthwheat + growthwheat_ts, farquharwheat_ts): # get the meteo of the current step Tair, ambient_CO2, RH, Ur, PARi = meteo.loc[ t_farquharwheat, [ 'air_temperature', 'ambient_CO2', 'humidity', 'Wind', 'PARi' ]] # get PARa for current step aggregated_PARa = calculate_PARa_from_df( g, Eabs_df, PARi, multiple_sources=False) print('t caribu is {}'.format(t_farquharwheat)) # caribu_facade_.run(energy=PARi,sun_sky_option='sky') caribu_facade_.update_shared_MTG( {'PARa': aggregated_PARa}) caribu_facade_.update_shared_dataframes( {'PARa': aggregated_PARa}) # run FarquharWheat print('t farquhar is {}'.format(t_farquharwheat)) farquharwheat_facade_.run(Tair, ambient_CO2, RH, Ur) for t_cnwheat in range( t_farquharwheat, t_farquharwheat + senescwheat_ts, cnwheat_ts): Tair, Tsoil = meteo.loc[ t_cnwheat, ['air_temperature', 'air_temperature']] # run CNWheat print('t cnwheat is {}'.format(t_cnwheat)) cnwheat_facade_.run(Tair=Tair, Tsoil=Tsoil) # append the inputs and outputs at current step to global lists all_simulation_steps.append(t_cnwheat) axes_all_data_list.append( shared_axes_inputs_outputs_df.copy()) organs_all_data_list.append( shared_organs_inputs_outputs_df.copy()) elements_all_data_list.append( shared_elements_inputs_outputs_df.copy()) soils_all_data_list.append( shared_soils_inputs_outputs_df.copy()) else: continue break execution_time = int(time.time() - current_time_of_the_system) print('\n', 'Simulation run in ', str(datetime.timedelta(seconds=execution_time))) # write all inputs and outputs to CSV files all_axes_inputs_outputs = pd.concat(axes_all_data_list, keys=all_simulation_steps) all_axes_inputs_outputs.reset_index(0, inplace=True) all_axes_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_axes_inputs_outputs.to_csv( AXES_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_organs_inputs_outputs = pd.concat(organs_all_data_list, keys=all_simulation_steps) all_organs_inputs_outputs.reset_index(0, inplace=True) all_organs_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_organs_inputs_outputs.to_csv( ORGANS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_elements_inputs_outputs = pd.concat(elements_all_data_list, keys=all_simulation_steps) all_elements_inputs_outputs.reset_index(0, inplace=True) all_elements_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_elements_inputs_outputs.to_csv( ELEMENTS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_soils_inputs_outputs = pd.concat(soils_all_data_list, keys=all_simulation_steps) all_soils_inputs_outputs.reset_index(0, inplace=True) all_soils_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_soils_inputs_outputs.to_csv( SOILS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) # -POST-PROCESSING## if make_graphs: # POST PROCESSINGS states_df_dict = {} for states_filepath in (AXES_STATES_FILEPATH, ORGANS_STATES_FILEPATH, ELEMENTS_STATES_FILEPATH, SOILS_STATES_FILEPATH): # assert states_filepaths were not opened during simulation run meaning that other filenames were saved path, filename = os.path.split(states_filepath) filename = os.path.splitext(filename)[0] newfilename = 'ACTUAL_{}.csv'.format(filename) newpath = os.path.join(path, newfilename) assert not os.path.isfile(newpath), \ "File {} was saved because {} was opened during simulation run. Rename it before running postprocessing".format(newfilename, states_filepath) # Retrieve outputs dataframes from precedent simulation run states_df = pd.read_csv(states_filepath) states_file_basename = os.path.basename(states_filepath).split( '.')[0] states_df_dict[states_file_basename] = states_df time_grid = states_df_dict['elements_states']['t'] delta_t = (time_grid.unique()[1] - time_grid.unique()[0]) * HOUR_TO_SECOND_CONVERSION_FACTOR # run the postprocessing axes_postprocessing_file_basename = os.path.basename( AXES_POSTPROCESSING_FILEPATH).split('.')[0] organs_postprocessing_file_basename = os.path.basename( ORGANS_POSTPROCESSING_FILEPATH).split('.')[0] elements_postprocessing_file_basename = os.path.basename( ELEMENTS_POSTPROCESSING_FILEPATH).split('.')[0] soils_postprocessing_file_basename = os.path.basename( SOILS_POSTPROCESSING_FILEPATH).split('.')[0] postprocessing_df_dict = {} (postprocessing_df_dict[axes_postprocessing_file_basename], _, postprocessing_df_dict[organs_postprocessing_file_basename], postprocessing_df_dict[elements_postprocessing_file_basename], postprocessing_df_dict[soils_postprocessing_file_basename]) \ = cnwheat_facade.CNWheatFacade.postprocessing(axes_outputs_df=states_df_dict[os.path.basename(AXES_STATES_FILEPATH).split('.')[0]], organs_outputs_df=states_df_dict[os.path.basename(ORGANS_STATES_FILEPATH).split('.')[0]], hiddenzone_outputs_df=None, elements_outputs_df=states_df_dict[os.path.basename(ELEMENTS_STATES_FILEPATH).split('.')[0]], soils_outputs_df=states_df_dict[os.path.basename(SOILS_STATES_FILEPATH).split('.')[0]], delta_t=delta_t) # save the postprocessing to disk for postprocessing_file_basename, postprocessing_filepath in ( (axes_postprocessing_file_basename, AXES_POSTPROCESSING_FILEPATH), (organs_postprocessing_file_basename, ORGANS_POSTPROCESSING_FILEPATH), (elements_postprocessing_file_basename, ELEMENTS_POSTPROCESSING_FILEPATH), (soils_postprocessing_file_basename, SOILS_POSTPROCESSING_FILEPATH)): postprocessing_df_dict[postprocessing_file_basename].to_csv( postprocessing_filepath, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION + 5)) # - GRAPHS # Retrieve last computed post-processing dataframes axes_postprocessing_file_basename = os.path.basename( AXES_POSTPROCESSING_FILEPATH).split('.')[0] organs_postprocessing_file_basename = os.path.basename( ORGANS_POSTPROCESSING_FILEPATH).split('.')[0] elements_postprocessing_file_basename = os.path.basename( ELEMENTS_POSTPROCESSING_FILEPATH).split('.')[0] soils_postprocessing_file_basename = os.path.basename( SOILS_POSTPROCESSING_FILEPATH).split('.')[0] postprocessing_df_dict = {} for (postprocessing_filepath, postprocessing_file_basename) in ( (AXES_POSTPROCESSING_FILEPATH, axes_postprocessing_file_basename), (ORGANS_POSTPROCESSING_FILEPATH, organs_postprocessing_file_basename), (ELEMENTS_POSTPROCESSING_FILEPATH, elements_postprocessing_file_basename), (SOILS_POSTPROCESSING_FILEPATH, soils_postprocessing_file_basename)): postprocessing_df = pd.read_csv(postprocessing_filepath) postprocessing_df_dict[ postprocessing_file_basename] = postprocessing_df # Generate graphs cnwheat_facade.CNWheatFacade.graphs( axes_postprocessing_df=postprocessing_df_dict[ axes_postprocessing_file_basename], hiddenzones_postprocessing_df=None, organs_postprocessing_df=postprocessing_df_dict[ organs_postprocessing_file_basename], elements_postprocessing_df=postprocessing_df_dict[ elements_postprocessing_file_basename], soils_postprocessing_df=postprocessing_df_dict[ soils_postprocessing_file_basename], graphs_dirpath=GRAPHS_DIRPATH)
def test_run(overwrite_desired_data=False): # --------------------------------------------- # ----- CONFIGURATION OF THE SIMULATION ------- # --------------------------------------------- # -- INPUTS CONFIGURATION -- # Path of the directory which contains the inputs of the model INPUTS_DIRPATH = 'inputs' # Name of the CSV files which describes the initial state of the system AXES_INITIAL_STATE_FILENAME = 'axes_initial_state.csv' ORGANS_INITIAL_STATE_FILENAME = 'organs_initial_state.csv' HIDDENZONES_INITIAL_STATE_FILENAME = 'hiddenzones_initial_state.csv' ELEMENTS_INITIAL_STATE_FILENAME = 'elements_initial_state.csv' SOILS_INITIAL_STATE_FILENAME = 'soils_initial_state.csv' METEO_FILENAME = 'meteo_Ljutovac2002.csv' # Read the inputs from CSV files and create inputs dataframes inputs_dataframes = {} for inputs_filename in (AXES_INITIAL_STATE_FILENAME, ORGANS_INITIAL_STATE_FILENAME, HIDDENZONES_INITIAL_STATE_FILENAME, ELEMENTS_INITIAL_STATE_FILENAME, SOILS_INITIAL_STATE_FILENAME): inputs_dataframe = pd.read_csv( os.path.join(INPUTS_DIRPATH, inputs_filename)) inputs_dataframes[inputs_filename] = inputs_dataframe.where( inputs_dataframe.notnull(), None) # -- SIMULATION PARAMETERS -- START_TIME = 0 SIMULATION_LENGTH = 24 PLANT_DENSITY = {1: 410} # define the time step in hours for each simulator CARIBU_TIMESTEP = 4 SENESCWHEAT_TIMESTEP = 2 FARQUHARWHEAT_TIMESTEP = 2 ELONGWHEAT_TIMESTEP = 1 GROWTHWHEAT_TIMESTEP = 1 CNWHEAT_TIMESTEP = 1 # Name of the CSV files which contains the meteo data meteo = pd.read_csv(os.path.join(INPUTS_DIRPATH, METEO_FILENAME), index_col='t') # -- OUTPUTS CONFIGURATION -- # Path of the directory which contains the inputs of the model OUTPUTS_DIRPATH = 'outputs' # Name of the CSV files which will contain the outputs of the model DESIRED_AXES_OUTPUTS_FILENAME = 'desired_axes_outputs.csv' DESIRED_ORGANS_OUTPUTS_FILENAME = 'desired_organs_outputs.csv' DESIRED_HIDDENZONES_OUTPUTS_FILENAME = 'desired_hiddenzones_outputs.csv' DESIRED_ELEMENTS_OUTPUTS_FILENAME = 'desired_elements_outputs.csv' DESIRED_SOILS_OUTPUTS_FILENAME = 'desired_soils_outputs.csv' ACTUAL_AXES_OUTPUTS_FILENAME = 'actual_axes_outputs.csv' ACTUAL_ORGANS_OUTPUTS_FILENAME = 'actual_organs_outputs.csv' ACTUAL_HIDDENZONES_OUTPUTS_FILENAME = 'actual_hiddenzones_outputs.csv' ACTUAL_ELEMENTS_OUTPUTS_FILENAME = 'actual_elements_outputs.csv' ACTUAL_SOILS_OUTPUTS_FILENAME = 'actual_soils_outputs.csv' # create empty dataframes to shared data between the models shared_axes_inputs_outputs_df = pd.DataFrame() shared_organs_inputs_outputs_df = pd.DataFrame() shared_hiddenzones_inputs_outputs_df = pd.DataFrame() shared_elements_inputs_outputs_df = pd.DataFrame() shared_soils_inputs_outputs_df = pd.DataFrame() # define lists of dataframes to store the inputs and the outputs of the models at each step. axes_all_data_list = [] organs_all_data_list = [ ] # organs which belong to axes: roots, phloem, grains hiddenzones_all_data_list = [] elements_all_data_list = [] soils_all_data_list = [] all_simulation_steps = [] # to store the steps of the simulation # -- ADEL and MTG CONFIGURATION -- # read adelwheat inputs at t0 adel_wheat = AdelDyn(seed=1, scene_unit='m', leaves=echap_leaves(xy_model='Soissons_byleafclass')) g = adel_wheat.load(dir=INPUTS_DIRPATH) # --------------------------------------------- # ----- CONFIGURATION OF THE FACADES ------- # --------------------------------------------- # -- ELONGWHEAT (created first because it is the only facade to add new metamers) -- # Initial states elongwheat_hiddenzones_initial_state = inputs_dataframes[ HIDDENZONES_INITIAL_STATE_FILENAME][ elongwheat_facade.converter.HIDDENZONE_TOPOLOGY_COLUMNS + [ i for i in elongwheat_facade.simulation.HIDDENZONE_INPUTS if i in inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns ]].copy() elongwheat_elements_initial_state = inputs_dataframes[ ELEMENTS_INITIAL_STATE_FILENAME][ elongwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [ i for i in elongwheat_facade.simulation.ELEMENT_INPUTS if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns ]].copy() elongwheat_axes_initial_state = inputs_dataframes[ AXES_INITIAL_STATE_FILENAME][ elongwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [ i for i in elongwheat_facade.simulation.AXIS_INPUTS if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns ]].copy() phytoT = os.path.join(INPUTS_DIRPATH, 'phytoT.csv') # Update some parameters update_cnwheat_parameters = {'SL_ratio_d': 0.25} # Facade initialisation elongwheat_facade_ = elongwheat_facade.ElongWheatFacade( g, ELONGWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR, elongwheat_axes_initial_state, elongwheat_hiddenzones_initial_state, elongwheat_elements_initial_state, shared_axes_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, adel_wheat, phytoT, update_cnwheat_parameters) # -- CARIBU -- caribu_facade_ = caribu_facade.CaribuFacade( g, shared_elements_inputs_outputs_df, adel_wheat) # -- SENESCWHEAT -- # Initial states senescwheat_roots_initial_state = inputs_dataframes[ ORGANS_INITIAL_STATE_FILENAME].loc[ inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME]['organ'] == 'roots'][senescwheat_facade.converter.ROOTS_TOPOLOGY_COLUMNS + [ i for i in senescwheat_facade.converter.SENESCWHEAT_ROOTS_INPUTS if i in inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns ]].copy() senescwheat_elements_initial_state = inputs_dataframes[ ELEMENTS_INITIAL_STATE_FILENAME][ senescwheat_facade.converter.ELEMENTS_TOPOLOGY_COLUMNS + [ i for i in senescwheat_facade.converter.SENESCWHEAT_ELEMENTS_INPUTS if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns ]].copy() senescwheat_axes_initial_state = inputs_dataframes[ AXES_INITIAL_STATE_FILENAME][ senescwheat_facade.converter.AXES_TOPOLOGY_COLUMNS + [ i for i in senescwheat_facade.converter.SENESCWHEAT_AXES_INPUTS if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns ]].copy() # Update some parameters update_cnwheat_parameters = {'AGE_EFFECT_SENESCENCE': 10000} # Facade initialisation senescwheat_facade_ = senescwheat_facade.SenescWheatFacade( g, SENESCWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR, senescwheat_roots_initial_state, senescwheat_axes_initial_state, senescwheat_elements_initial_state, shared_organs_inputs_outputs_df, shared_axes_inputs_outputs_df, shared_elements_inputs_outputs_df, update_cnwheat_parameters) # -- FARQUHARWHEAT -- # Initial states farquharwheat_elements_initial_state = inputs_dataframes[ ELEMENTS_INITIAL_STATE_FILENAME][ farquharwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [ i for i in farquharwheat_facade.converter.FARQUHARWHEAT_ELEMENTS_INPUTS if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns ]].copy() farquharwheat_axes_initial_state = inputs_dataframes[ AXES_INITIAL_STATE_FILENAME][ farquharwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [ i for i in farquharwheat_facade.converter.FARQUHARWHEAT_AXES_INPUTS if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns ]].copy() # Facade initialisation farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade( g, farquharwheat_elements_initial_state, farquharwheat_axes_initial_state, shared_elements_inputs_outputs_df) # -- GROWTHWHEAT -- # Initial states growthwheat_hiddenzones_initial_state = inputs_dataframes[ HIDDENZONES_INITIAL_STATE_FILENAME][ growthwheat_facade.converter.HIDDENZONE_TOPOLOGY_COLUMNS + [ i for i in growthwheat_facade.simulation.HIDDENZONE_INPUTS if i in inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns ]].copy() growthwheat_elements_initial_state = inputs_dataframes[ ELEMENTS_INITIAL_STATE_FILENAME][ growthwheat_facade.converter.ELEMENT_TOPOLOGY_COLUMNS + [ i for i in growthwheat_facade.simulation.ELEMENT_INPUTS if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns ]].copy() growthwheat_root_initial_state = inputs_dataframes[ ORGANS_INITIAL_STATE_FILENAME].loc[ inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME]['organ'] == 'roots'][growthwheat_facade.converter.ROOT_TOPOLOGY_COLUMNS + [ i for i in growthwheat_facade.simulation.ROOT_INPUTS if i in inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns ]].copy() growthwheat_axes_initial_state = inputs_dataframes[ AXES_INITIAL_STATE_FILENAME][ growthwheat_facade.converter.AXIS_TOPOLOGY_COLUMNS + [ i for i in growthwheat_facade.simulation.AXIS_INPUTS if i in inputs_dataframes[AXES_INITIAL_STATE_FILENAME].columns ]].copy() # Update some parameters update_cnwheat_parameters = {'VMAX_ROOTS_GROWTH_PREFLO': 0.02885625} # Facade initialisation growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade( g, GROWTHWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR, growthwheat_hiddenzones_initial_state, growthwheat_elements_initial_state, growthwheat_root_initial_state, growthwheat_axes_initial_state, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_axes_inputs_outputs_df, update_cnwheat_parameters) # -- CNWHEAT -- # Initial states cnwheat_organs_initial_state = inputs_dataframes[ ORGANS_INITIAL_STATE_FILENAME][[ i for i in cnwheat_facade.cnwheat_converter.ORGANS_VARIABLES if i in inputs_dataframes[ORGANS_INITIAL_STATE_FILENAME].columns ]].copy() cnwheat_hiddenzones_initial_state = inputs_dataframes[ HIDDENZONES_INITIAL_STATE_FILENAME][[ i for i in cnwheat_facade.cnwheat_converter.HIDDENZONE_VARIABLES if i in inputs_dataframes[HIDDENZONES_INITIAL_STATE_FILENAME].columns ]].copy() cnwheat_elements_initial_state = inputs_dataframes[ ELEMENTS_INITIAL_STATE_FILENAME][[ i for i in cnwheat_facade.cnwheat_converter.ELEMENTS_VARIABLES if i in inputs_dataframes[ELEMENTS_INITIAL_STATE_FILENAME].columns ]].copy() cnwheat_soils_initial_state = inputs_dataframes[ SOILS_INITIAL_STATE_FILENAME][[ i for i in cnwheat_facade.cnwheat_converter.SOILS_VARIABLES if i in inputs_dataframes[SOILS_INITIAL_STATE_FILENAME].columns ]].copy() # Update some parameters update_cnwheat_parameters = { 'roots': { 'K_AMINO_ACIDS_EXPORT': 3E-5, 'K_NITRATE_EXPORT': 1E-6 } } # Facade initialisation cnwheat_facade_ = cnwheat_facade.CNWheatFacade( g, CNWHEAT_TIMESTEP * HOUR_TO_SECOND_CONVERSION_FACTOR, PLANT_DENSITY, cnwheat_organs_initial_state, cnwheat_hiddenzones_initial_state, cnwheat_elements_initial_state, cnwheat_soils_initial_state, shared_axes_inputs_outputs_df, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_soils_inputs_outputs_df, update_cnwheat_parameters) # --------------------------------------------- # ----- RUN OF THE SIMULATION ------- # --------------------------------------------- for t_caribu in range(START_TIME, SIMULATION_LENGTH, CARIBU_TIMESTEP): # run Caribu PARi = meteo.loc[t_caribu, ['PARi_MA4']].iloc[0] DOY = meteo.loc[t_caribu, ['DOY']].iloc[0] hour = meteo.loc[t_caribu, ['hour']].iloc[0] caribu_facade_.run(energy=PARi, DOY=DOY, hourTU=hour, latitude=48.85, sun_sky_option='sky', heterogeneous_canopy=True, plant_density=PLANT_DENSITY[1]) for t_senescwheat in range(t_caribu, t_caribu + CARIBU_TIMESTEP, SENESCWHEAT_TIMESTEP): # run SenescWheat senescwheat_facade_.run() # Run the rest of the model if the plant is alive for t_farquharwheat in range(t_senescwheat, t_senescwheat + SENESCWHEAT_TIMESTEP, FARQUHARWHEAT_TIMESTEP): # get the meteo of the current step Ta, ambient_CO2, RH, Ur = meteo.loc[t_farquharwheat, [ 'air_temperature_MA2', 'ambient_CO2_MA2', 'humidity_MA2', 'Wind_MA2' ]] # run FarquharWheat farquharwheat_facade_.run(Ta, ambient_CO2, RH, Ur) for t_elongwheat in range( t_farquharwheat, t_farquharwheat + FARQUHARWHEAT_TIMESTEP, ELONGWHEAT_TIMESTEP): # run ElongWheat Tair, Tsoil = meteo.loc[ t_elongwheat, ['air_temperature', 'soil_temperature']] elongwheat_facade_.run(Tair, Tsoil, option_static=False) # Update geometry adel_wheat.update_geometry(g) for t_growthwheat in range( t_elongwheat, t_elongwheat + ELONGWHEAT_TIMESTEP, GROWTHWHEAT_TIMESTEP): # run GrowthWheat growthwheat_facade_.run() for t_cnwheat in range( t_growthwheat, t_growthwheat + GROWTHWHEAT_TIMESTEP, CNWHEAT_TIMESTEP): if t_cnwheat > 0: # run CNWheat Tair = meteo.loc[t_elongwheat, 'air_temperature'] Tsoil = meteo.loc[t_elongwheat, 'soil_temperature'] cnwheat_facade_.run(Tair, Tsoil) # append outputs at current step to global lists all_simulation_steps.append(t_cnwheat) axes_all_data_list.append( shared_axes_inputs_outputs_df.copy()) organs_all_data_list.append( shared_organs_inputs_outputs_df.copy()) hiddenzones_all_data_list.append( shared_hiddenzones_inputs_outputs_df.copy()) elements_all_data_list.append( shared_elements_inputs_outputs_df.copy()) soils_all_data_list.append( shared_soils_inputs_outputs_df.copy()) # compare actual to desired outputs at each scale level (an exception is raised if the test failed) for (outputs_df_list, desired_outputs_filename, actual_outputs_filename, state_variables_names) \ in ((axes_all_data_list, DESIRED_AXES_OUTPUTS_FILENAME, ACTUAL_AXES_OUTPUTS_FILENAME, AXES_INDEX_COLUMNS), (organs_all_data_list, DESIRED_ORGANS_OUTPUTS_FILENAME, ACTUAL_ORGANS_OUTPUTS_FILENAME, ORGANS_INDEX_COLUMNS), (hiddenzones_all_data_list, DESIRED_HIDDENZONES_OUTPUTS_FILENAME, ACTUAL_HIDDENZONES_OUTPUTS_FILENAME, HIDDENZONES_INDEX_COLUMNS), (elements_all_data_list, DESIRED_ELEMENTS_OUTPUTS_FILENAME, ACTUAL_ELEMENTS_OUTPUTS_FILENAME, ELEMENTS_INDEX_COLUMNS), (soils_all_data_list, DESIRED_SOILS_OUTPUTS_FILENAME, ACTUAL_SOILS_OUTPUTS_FILENAME, SOILS_INDEX_COLUMNS)): outputs_df = pd.concat(outputs_df_list, ignore_index=True) outputs_df = outputs_df.loc[:, state_variables_names] # compare only the values of the compartments cnwheat_tools.compare_actual_to_desired( OUTPUTS_DIRPATH, outputs_df, desired_outputs_filename, actual_outputs_filename, precision=PRECISION, overwrite_desired_data=overwrite_desired_data)
def main(stop_time, run_simu=True, make_graphs=True): if run_simu: meteo = pd.read_csv(METEO_FILEPATH, index_col='t') Eabs_df = pd.read_csv(CARIBU_FILEPATH) # define the time step in hours for each simulator senescwheat_ts = 2 growthwheat_ts = 2 farquharwheat_ts = 2 elongwheat_ts = 2 cnwheat_ts = 1 hour_to_second_conversion_factor = 3600 # read adelwheat inputs at t0 adel_wheat = AdelDyn(seed=1234, scene_unit='m') g = adel_wheat.load(dir=ADELWHEAT_INPUTS_DIRPATH) # adel_wheat.plot(g) # create empty dataframes to shared data between the models shared_axes_inputs_outputs_df = pd.DataFrame() shared_organs_inputs_outputs_df = pd.DataFrame() shared_hiddenzones_inputs_outputs_df = pd.DataFrame() shared_elements_inputs_outputs_df = pd.DataFrame() shared_soils_inputs_outputs_df = pd.DataFrame() # read the inputs at t0 and create the facades # caribu caribu_facade_ = caribu_facade.CaribuFacade(g, shared_elements_inputs_outputs_df, adel_wheat) # senescwheat senescwheat_roots_inputs_t0 = pd.read_csv(SENESCWHEAT_ROOTS_INPUTS_FILEPATH) senescwheat_axes_inputs_t0 = pd.read_csv(SENESCWHEAT_AXES_INPUTS_FILEPATH) senescwheat_elements_inputs_t0 = pd.read_csv(SENESCWHEAT_ELEMENTS_INPUTS_FILEPATH) senescwheat_facade_ = senescwheat_facade.SenescWheatFacade(g, senescwheat_ts * hour_to_second_conversion_factor, senescwheat_roots_inputs_t0, senescwheat_axes_inputs_t0, senescwheat_elements_inputs_t0, shared_organs_inputs_outputs_df, shared_axes_inputs_outputs_df, shared_elements_inputs_outputs_df) # growthwheat growthwheat_hiddenzones_inputs_t0 = pd.read_csv(GROWTHWHEAT_HIDDENZONE_INPUTS_FILEPATH) growthwheat_organ_inputs_t0 = pd.read_csv(GROWTHWHEAT_ORGANS_INPUTS_FILEPATH) growthwheat_root_inputs_t0 = pd.read_csv(GROWTHWHEAT_ROOTS_INPUTS_FILEPATH) growthwheat_axes_inputs_t0 = pd.read_csv(GROWTHWHEAT_AXES_INPUTS_FILEPATH) growthwheat_facade_ = growthwheat_facade.GrowthWheatFacade(g, growthwheat_ts * hour_to_second_conversion_factor, growthwheat_hiddenzones_inputs_t0, growthwheat_organ_inputs_t0, growthwheat_root_inputs_t0, growthwheat_axes_inputs_t0, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_axes_inputs_outputs_df) # farquharwheat farquharwheat_elements_inputs_t0 = pd.read_csv(FARQUHARWHEAT_INPUTS_FILEPATH) farquharwheat_axes_inputs_t0 = pd.read_csv(FARQUHARWHEAT_AXES_INPUTS_FILEPATH) update_parameters_farquharwheat = {'MODEL_VERSION': 'Barillot2016'} # Use the initial version of the photosynthesis sub-model (as in Barillot et al. 2016, and in Gauthier et al. 2020) farquharwheat_facade_ = farquharwheat_facade.FarquharWheatFacade(g, farquharwheat_elements_inputs_t0, farquharwheat_axes_inputs_t0, shared_elements_inputs_outputs_df, update_parameters=update_parameters_farquharwheat) # elongwheat # Only for temperature related computations elongwheat_hiddenzones_inputs_t0 = pd.read_csv(ELONGWHEAT_HZ_INPUTS_FILEPATH) elongwheat_elements_inputs_t0 = pd.read_csv(ELONGWHEAT_ELEMENTS_INPUTS_FILEPATH) elongwheat_axes_inputs_t0 = pd.read_csv(ELONGWHEAT_AXES_INPUTS_FILEPATH) elongwheat_facade_ = elongwheat_facade.ElongWheatFacade(g, elongwheat_ts * hour_to_second_conversion_factor, elongwheat_axes_inputs_t0, elongwheat_hiddenzones_inputs_t0, elongwheat_elements_inputs_t0, shared_axes_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, adel_wheat, option_static=True) # cnwheat cnwheat_organs_inputs_t0 = pd.read_csv(CNWHEAT_ORGANS_INPUTS_FILEPATH) cnwheat_hiddenzones_inputs_t0 = pd.read_csv(CNWHEAT_HIDDENZONE_INPUTS_FILEPATH) cnwheat_elements_inputs_t0 = pd.read_csv(CNWHEAT_ELEMENTS_INPUTS_FILEPATH) cnwheat_soils_inputs_t0 = pd.read_csv(CNWHEAT_SOILS_INPUTS_FILEPATH) update_cnwheat_parameters = {'roots': {'K_AMINO_ACIDS_EXPORT': 25*3E-5, 'K_NITRATE_EXPORT': 25*1E-6}} cnwheat_facade_ = cnwheat_facade.CNWheatFacade(g, cnwheat_ts * hour_to_second_conversion_factor, CULM_DENSITY, update_cnwheat_parameters, cnwheat_organs_inputs_t0, cnwheat_hiddenzones_inputs_t0, cnwheat_elements_inputs_t0, cnwheat_soils_inputs_t0, shared_axes_inputs_outputs_df, shared_organs_inputs_outputs_df, shared_hiddenzones_inputs_outputs_df, shared_elements_inputs_outputs_df, shared_soils_inputs_outputs_df) # adel_wheat.update_geometry(g) # NE FONCTIONNE PAS car MTG non compatible (pas de top et base element) # adel_wheat.plot(g) # define organs for which the variable 'max_proteins' is fixed forced_max_protein_elements = {(1, 'MS', 9, 'blade', 'LeafElement1'), (1, 'MS', 10, 'blade', 'LeafElement1'), (1, 'MS', 11, 'blade', 'LeafElement1'), (2, 'MS', 9, 'blade', 'LeafElement1'), (2, 'MS', 10, 'blade', 'LeafElement1'), (2, 'MS', 11, 'blade', 'LeafElement1')} # define the start and the end of the whole simulation (in hours) start_time = 0 stop_time = stop_time # define lists of dataframes to store the inputs and the outputs of the models at each step. axes_all_data_list = [] organs_all_data_list = [] # organs which belong to axes: roots, phloem, grains elements_all_data_list = [] soils_all_data_list = [] all_simulation_steps = [] # to store the steps of the simulation # run the simulators current_time_of_the_system = time.time() try: for t_elongwheat in range(start_time, stop_time, elongwheat_ts): # Only to compute temperature related variable # run ElongWheat print('t elongwheat is {}'.format(t_elongwheat)) Tair, Tsoil = meteo.loc[t_elongwheat, ['air_temperature', 'air_temperature']] elongwheat_facade_.run(Tair, Tsoil, option_static=True) for t_senescwheat in range(t_elongwheat, t_elongwheat + elongwheat_ts, senescwheat_ts): # run SenescWheat print('t senescwheat is {}'.format(t_senescwheat)) senescwheat_facade_.run(forced_max_protein_elements, postflowering_stages=True) # Test for fully senesced shoot tissues #TODO: Make the model to work even if the whole shoot is dead but the roots are alived if sum(senescwheat_facade_._shared_elements_inputs_outputs_df['green_area']) <= 0.25E-6: break for t_growthwheat in range(t_senescwheat, t_senescwheat + senescwheat_ts, growthwheat_ts): # run GrowthWheat print('t growthwheat is {}'.format(t_growthwheat)) growthwheat_facade_.run(postflowering_stages=True) for t_farquharwheat in range(t_growthwheat, t_growthwheat + growthwheat_ts, farquharwheat_ts): # get the meteo of the current step Tair, ambient_CO2, RH, Ur, PARi = meteo.loc[t_farquharwheat, ['air_temperature', 'ambient_CO2', 'humidity', 'Wind', 'PARi']] # get PARa for current step aggregated_PARa = calculate_PARa_from_df(g, Eabs_df, PARi, multiple_sources=False) print('t caribu is {}'.format(t_farquharwheat)) # caribu_facade_.run(energy=PARi,sun_sky_option='sky') caribu_facade_.update_shared_MTG({'PARa': aggregated_PARa}) caribu_facade_.update_shared_dataframes({'PARa': aggregated_PARa}) # run FarquharWheat print('t farquhar is {}'.format(t_farquharwheat)) farquharwheat_facade_.run(Tair, ambient_CO2, RH, Ur) for t_cnwheat in range(t_farquharwheat, t_farquharwheat + senescwheat_ts, cnwheat_ts): Tair, Tsoil = meteo.loc[t_cnwheat, ['air_temperature', 'air_temperature']] # run CNWheat print('t cnwheat is {}'.format(t_cnwheat)) cnwheat_facade_.run(Tair=Tair, Tsoil=Tsoil) # append the inputs and outputs at current step to global lists all_simulation_steps.append(t_cnwheat) axes_all_data_list.append(shared_axes_inputs_outputs_df.copy()) organs_all_data_list.append(shared_organs_inputs_outputs_df.copy()) elements_all_data_list.append(shared_elements_inputs_outputs_df.copy()) soils_all_data_list.append(shared_soils_inputs_outputs_df.copy()) else: continue break except Exception as ex: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) print(message, fname, exc_tb.tb_lineno) finally: execution_time = int(time.time() - current_time_of_the_system) print('\n', 'Simulation run in ', str(datetime.timedelta(seconds=execution_time))) # write all inputs and outputs to CSV files all_axes_inputs_outputs = pd.concat(axes_all_data_list, keys=all_simulation_steps) all_axes_inputs_outputs.reset_index(0, inplace=True) all_axes_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_axes_inputs_outputs.to_csv(AXES_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_organs_inputs_outputs = pd.concat(organs_all_data_list, keys=all_simulation_steps) all_organs_inputs_outputs.reset_index(0, inplace=True) all_organs_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_organs_inputs_outputs.to_csv(ORGANS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_elements_inputs_outputs = pd.concat(elements_all_data_list, keys=all_simulation_steps) all_elements_inputs_outputs.reset_index(0, inplace=True) all_elements_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_elements_inputs_outputs.to_csv(ELEMENTS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) all_soils_inputs_outputs = pd.concat(soils_all_data_list, keys=all_simulation_steps) all_soils_inputs_outputs.reset_index(0, inplace=True) all_soils_inputs_outputs.rename({'level_0': 't'}, axis=1, inplace=True) all_soils_inputs_outputs.to_csv(SOILS_STATES_FILEPATH, na_rep='NA', index=False, float_format='%.{}f'.format(INPUTS_OUTPUTS_PRECISION)) # -POST-PROCESSING## if make_graphs: generate_graphs()
from alinea.adel.echap_leaf import echap_leaves # adelwheat inputs at t0 ADELWHEAT_INPUTS_DIRPATH = os.path.join( INPUTS_DIRPATH, 'adelwheat' ) # the directory adelwheat must contain files 'adel0000.pckl' and 'scene0000.bgeom' adel_wheat = AdelDyn(seed=1234, scene_unit='m', leaves=echap_leaves(xy_model='Soissons_byleafclass')) # adel_wheat.pars = adel_wheat.read_pars(dir=ADELWHEAT_INPUTS_DIRPATH) g = adel_wheat.load(dir=ADELWHEAT_INPUTS_DIRPATH) hour_to_second_conversion_factor = 3600 elongwheat_facade_ = elongwheat_facade.ElongWheatFacade( g, elongwheat_ts * hour_to_second_conversion_factor, axis_outputs_df, hiddenzone_outputs_df, element_outputs_df, axis_outputs_df, hiddenzone_outputs_df, element_outputs_df, adel_wheat) adel_wheat.update_geometry(g) adel_wheat.plot(g) # --- SETUP RUN # --- MAIN # Initialization simulation # Create population simulation_ = elongwheat_simulation.Simulation(delta_t=delta_t) start_time = time.time() # Loop for several runs