def crf_generic(calibval=None, sample=sample_class.Sample({}), bounds={}): comp = sample.get_composition(units='wtpt_oxides') testresults = [] for ox in sfvfCompRange: testresults.append(comp[ox] >= bounds[ox][0]) testresults.append(comp[ox] <= bounds[ox][1]) return all(testresults)
def crf_CarbonComp(calibval=None, sample=sample_class.Sample({})): comp = sample.get_composition(units='wtpt_oxides') test_results = [] for ox in carboncomprange.keys(): test_results.append(comp[ox] >= carboncomprange[ox][0] and comp[ox] <= carboncomprange[ox][1]) return all(test_results)
def crf_MixedComp(calibval=None, sample=sample_class.Sample({})): comp = sample.get_composition(units='wtpt_oxides') test_results = [] for ox in carboncomprange.keys(): test_results.append( comp[ox] >= np.min([watercomprange[ox][0], carboncomprange[ox][0]]) ) test_results.append( comp[ox] <= np.max([watercomprange[ox][1], carboncomprange[ox][1]]) ) return all(test_results)
def test(): """ This is a set of tests for the module, firstly to ensure all of the functions that should run, do run. Secondly, the output can be used to check the module reproduces the results in each of the manuscripts describing the models. """ sample_comp = {'SiO2':47.95, 'TiO2':1.67, 'Al2O3':17.32, 'FeO':10.24, 'Fe2O3':0.1, 'MgO':5.76, 'CaO':10.93, 'Na2O':3.45, 'K2O':1.99, 'P2O5':0.51, 'MnO':0.1, 'CO2':0.08, 'H2O':4.0} test_sample = sample_class.Sample(sample_comp) test_pressure = 2000.0 test_temperature = 1473.15 test_pressure_list = [1000.0,2000.0,5000.0] test_isopleth_list = [0.0,0.5,1.0] print("\n================================\n= MAGMASATPLUS TESTING ROUTINE =\n================================") print("\n This routine will check that key methods run using typical values of variables. \ The routine does not check that the results are correct (though this may be obvious from the outputs),\ nor does it check every possible iteration of methods and input types. It will check that an update hasn't \ COMPLETELY broken the module.") for i, model_name in zip(range(len(models.default_models)),list(models.default_models.keys())): print("\nTesting model {:d} of {:d}: {:s}".format(i+1,len(models.default_models),model_name)) ### calculate_dissolved_volatiles model = models.default_models[model_name] print("Model contains "+" ".join(model.volatile_species)) print("Testing calculate_dissolved_volatiles method...") if len(model.volatile_species) == 1: dissolved = model.calculate_dissolved_volatiles(pressure=test_pressure,temperature=test_temperature, sample=test_sample) else: X_fluid = 1.0/len(model.volatile_species) X_fluid = tuple(X_fluid for x in range(len(model.volatile_species))) print("Setting X_fluid to "+str(X_fluid)) dissolved = model.calculate_dissolved_volatiles(pressure=test_pressure,temperature=test_temperature, sample=test_sample,X_fluid=X_fluid) if len(model.volatile_species) == 1: print(" {:s} solubility at {:.0f} bars and {:.0f} K is {:.3f} wt%".format(model.volatile_species[0], test_pressure,test_temperature, dissolved)) else: for i,volatile in zip(range(len(model.volatile_species)),model.volatile_species): print(" {:s} solubility at {:.0f} bars and {:.0f} K is {:.3f} wt%".format(volatile, test_pressure,test_temperature, dissolved[i])) print("Testing calculate_dissolved_volatiles class interface...") if len(model.volatile_species) == 1: result = calculate_dissolved_volatiles(sample=test_sample,pressure=test_pressure, temperature=test_temperature,model=model_name) else: result = calculate_dissolved_volatiles(sample=test_sample,pressure=test_pressure, temperature=test_temperature,model=model_name, X_fluid=X_fluid) if len(model.volatile_species) == 1: print(" {:s} solubility at {:.0f} bars and {:.0f} K is {:.3f} wt%".format(model.volatile_species[0], test_pressure,test_temperature, result.result)) else: for volatile in model.volatile_species: print(" {:s} solubility at {:.0f} bars and {:.0f} K is {:.3f} wt%".format(volatile, test_pressure,test_temperature, result.result[volatile+'_liq'])) ### calculate_saturation_pressure print("Testing calculate_saturation_pressure method...") satP = model.calculate_saturation_pressure(sample=test_sample,temperature=test_temperature) if len(model.volatile_species) == 1: print(" A concentration of {:.2f} wt% {:s} is saturated at {:.0f} bars at {:.0f} K".format(test_sample.get_composition(model.volatile_species[0]), model.volatile_species[0],satP, test_temperature)) else: concstr = "" for volatile in model.volatile_species: concstr += "{:.2f}".format(test_sample.get_composition(volatile)) concstr += " wt% " concstr += volatile concstr += ", " print(" Concentrations of "+concstr[:-1]+" are saturated at {:.0f} bars at {:.0f} K".format(satP,test_temperature)) print("Testing calculate_saturation_pressure class interface...") satP = calculate_saturation_pressure(model=model_name,sample=test_sample,temperature=test_temperature).result if len(model.volatile_species) == 1: print(" A concentration of {:.2f} wt% {:s} is saturated at {:.0f} bars at {:.0f} K".format(test_sample.get_composition(model.volatile_species[0]), model.volatile_species[0],satP, test_temperature)) else: concstr = "" for volatile in model.volatile_species: concstr += "{:.2f}".format(test_sample.get_composition(volatile)) concstr += " wt% " concstr += volatile concstr += ", " print(" Concentrations of "+concstr[:-1]+" are saturated at {:.0f} bars at {:.0f} K".format(satP,test_temperature)) ### calculate_equilibrium_fluid_comp print("Testing calculate_equilibrium_fluid_comp method...") fluid = model.calculate_equilibrium_fluid_comp(sample=test_sample,temperature=test_temperature,pressure=test_pressure) if len(model.volatile_species) == 1: print(" A mole fraction of {:.2f} of {:s} is present in the fluid.".format(fluid,model.volatile_species[0])) else: fluidstr = "" for i,volatile in zip(range(len(model.volatile_species)),model.volatile_species): fluidstr += "{:.2f}".format(fluid[model.volatile_species[i]]) fluidstr += " " fluidstr += volatile fluidstr += ", " print(" Mole fractions of "+fluidstr +"are present in the fluid.") if np.sum(list(fluid.values())) != 0.0 and np.sum(list(fluid.values())) != 1.0: print(" WARNING: MOLE FRACTIONS DO NOT SUM TO 1.0") print("Testing calculate_equilibrium_fluid_comp class interface...") fluid = model.calculate_equilibrium_fluid_comp(model=model_name,sample=test_sample, temperature=test_temperature,pressure=test_pressure) if len(model.volatile_species) == 1: print(" A mole fraction of {:.2f} of {:s} is present in the fluid.".format(fluid,model.volatile_species[0])) else: fluidstr = "" for i,volatile in zip(range(len(model.volatile_species)),model.volatile_species): fluidstr += "{:.2f}".format(fluid[model.volatile_species[i]]) fluidstr += " " fluidstr += volatile fluidstr += ", " print(" Mole fractions of "+fluidstr +"are present in the fluid.") if np.sum(list(fluid.values())) != 0.0 and np.sum(list(fluid.values())) != 1.0: print(" WARNING: MOLE FRACTIONS DO NOT SUM TO 1.0") ### calculate_isobars_and_isopleths if len(model.volatile_species) > 1: print("Testing calculate_isobars_and_isopleths method...") isobars, isopleths = model.calculate_isobars_and_isopleths(pressure_list=test_pressure_list, isopleth_list=test_isopleth_list, sample=test_sample, temperature=test_temperature) print("Isobars:") print(isobars) print("\nIsopleths:") print(isopleths) print("Testing calculate_isobars_and_isopleths class interface...") isobars, isopleths = calculate_isobars_and_isopleths(model=model_name,pressure_list=test_pressure_list, isopleth_list=test_isopleth_list, sample=test_sample, temperature=test_temperature).result print("Isobars:") print(isobars) print("\nIsopleths:") print(isopleths) ### calculate_degassing_path test_sample = Sample(sample_comp) if len(model.volatile_species) > 1: print("Testing calculate_degassing_path method...") degassing = model.calculate_degassing_path(sample=test_sample,temperature=test_temperature) print(" Degassing path:") print(degassing) print("Testing calculate_degassing_path class interface...") degassing = calculate_degassing_path(model=model_name,sample=test_sample, temperature=test_temperature).result print(" Degassing path:") print(degassing) print("\nTesting routine complete.\n")
def crf_sfvf(calibval=None, sample=sample_class.Sample({})): return crf_generic(calibval, sample, sfvfCompRange)
def calculate_degassing_path(self, sample, temperature, pressure='saturation', fractionate_vapor=0.0, init_vapor=0.0, steps=50, **kwargs): """ Calculates degassing path for one sample Parameters ---------- sample: Sample class Magma major element composition. Legacy info follows, might still be useful? If pulling from an uploaded file with data for many samples, first call get_sample_composition() to get the sample desired. Then pass the result into this function. temperature: float Temperature at which to calculate degassing paths, in degrees C. pressure: float OPTIONAL. The perssure at which to begin the degassing calculations. Default value is 'saturation', which runs the calculation with the initial pressure at the saturation pressure. If a pressure greater than the saturation pressure is input, the calculation will start at saturation, since this is the first pressure at which any degassing will occur. fractionate_vapor: float OPTIONAL. Proportion of vapor removed at each pressure step. Default value is 0.0 (completely closed-system degassing). Specifies the type of calculation performed, either closed system (0.0) or open system (1.0) degassing. If any value between <1.0 is chosen, user can also specify the 'init_vapor' argument (see below). A value in between 0 and 1 will remove that proportion of vapor at each step. For example, for a value of 0.2, the calculation will remove 20% of the vapor and retain 80% of the vapor at each pressure step. init_vapor: float OPTIONAL. Default value is 0.0. Specifies the amount of vapor (in wt%) coexisting with the melt before degassing. steps: int OPTIONAL. Default value is 50. Specifies the number of steps in pressure space at which dissolved volatile concentrations are calculated. Returns ------- pandas DataFrame object """ sys.stdout.write("Finding saturation point... " ) # print start of calculation to terminal _sample = self.preprocess_sample(sample) # Normalize sample composition _normed_comp = _sample.get_composition(normalization='standard') _sample.change_composition(_normed_comp) _sample_dict = _sample.get_composition() # ------ RESET MELTS ------ # # MELTS needs to be reloaded here. If an unfeasible composition gets set inside of MELTS, # which can happen when running open-system degassing path calcs, the following calls to # MELTS will fail. This prevents that from happening. melts = equilibrate.MELTSmodel('1.2.0') # Suppress phases not required in the melts simulation phases = melts.get_phase_names() for phase in phases: melts.set_phase_inclusion_status({phase: False}) melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True}) melts.set_bulk_composition(_sample_dict) # ------------------------- # # Get saturation pressure data = self.calculate_saturation_pressure(sample=_sample, temperature=temperature, verbose=True) if pressure == 'saturation' or pressure >= data["SaturationP_bars"]: SatP_MPa = data["SaturationP_bars"] / 10.0 else: SatP_MPa = pressure / 10.0 # convert number of steps to step size MPa_step = SatP_MPa / steps if MPa_step < 1: MPa_step = 1 P_array = np.arange(1.0, SatP_MPa, MPa_step) P_array = -np.sort(-P_array) fl_wtper = data["FluidProportion_wt"] while fl_wtper <= init_vapor: output = melts.equilibrate_tp(temperature, SatP_MPa, initialize=True) (status, temperature, p, xmlout) = output[0] fl_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid') liq_mass = melts.get_mass_of_phase(xmlout, phase_name='Liquid') fl_comp = melts.get_composition_of_phase(xmlout, phase_name='Fluid') fl_wtper = 100 * fl_mass / (fl_mass + liq_mass) try: _sample_dict["H2O"] += fl_comp["H2O"] * 0.0005 except Exception: _sample_dict["H2O"] = _sample_dict["H2O"] * 1.1 try: _sample_dict["CO2"] += fl_comp["CO2"] * 0.0005 except Exception: _sample_dict["CO2"] = _sample_dict["CO2"] * 1.1 _sample = sample_class.Sample(_sample_dict) _sample_dict = _sample.get_composition(normalization='standard', units="wtpt_oxides") melts.set_bulk_composition(_sample_dict) # reset MELTS pressure = [] H2Oliq = [] CO2liq = [] H2Ofl = [] CO2fl = [] fluid_wtper = [] iterno = 0 sys.stdout.write( "\r") # carriage return to remove previous printed text for i in P_array: # Handle status_bar iterno += 1 percent = iterno / len(P_array) batchfile.status_bar.status_bar( percent, btext="Calculating degassing path...") fl_mass = 0.0 melts.set_bulk_composition(_sample_dict) output = melts.equilibrate_tp(temperature, i, initialize=True) (status, temperature, p, xmlout) = output[0] liq_comp = melts.get_composition_of_phase(xmlout, phase_name='Liquid') fl_comp = melts.get_composition_of_phase(xmlout, phase_name='Fluid', mode='component') liq_mass = melts.get_mass_of_phase(xmlout, phase_name='Liquid') fl_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid') fl_wtper = 100 * fl_mass / (fl_mass + liq_mass) if fl_mass > 0: pressure.append(p * 10.0) try: H2Oliq.append(liq_comp["H2O"]) except Exception: H2Oliq.append(0) try: CO2liq.append(liq_comp["CO2"]) except Exception: CO2liq.append(0) try: H2Ofl.append(fl_comp["Water"]) except Exception: H2Ofl.append(0) try: CO2fl.append(fl_comp["Carbon Dioxide"]) except Exception: CO2fl.append(0) fluid_wtper.append(fl_wtper) try: _sample_dict["H2O"] = ( liq_comp["H2O"] + (_sample_dict["H2O"] - liq_comp["H2O"]) * (1.0 - fractionate_vapor)) except Exception: _sample_dict["H2O"] = 0 try: _sample_dict["CO2"] = ( liq_comp["CO2"] + (_sample_dict["CO2"] - liq_comp["CO2"]) * (1.0 - fractionate_vapor)) except Exception: _sample_dict["CO2"] = 0 _sample = sample_class.Sample(_sample_dict) _sample_dict = _sample.get_composition(normalization='standard', units='wtpt_oxides') melts.set_bulk_composition( self.bulk_comp_orig) # this needs to be reset always! open_degassing_df = pd.DataFrame( list(zip(pressure, H2Oliq, CO2liq, H2Ofl, CO2fl, fluid_wtper)), columns=[ 'Pressure_bars', 'H2O_liq', 'CO2_liq', 'XH2O_fl', 'XCO2_fl', 'FluidProportion_wt' ]) open_degassing_df = open_degassing_df[ open_degassing_df.CO2_liq > 0.000001] open_degassing_df = open_degassing_df[ open_degassing_df.H2O_liq > 0.000001] return open_degassing_df