示例#1
0
    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
示例#2
0
from VESIcal import core
from VESIcal import models
from VESIcal import sample_class
from VESIcal import calculate_classes
from VESIcal import batchfile

import numpy as np
import warnings as w
import sys
w.filterwarnings("ignore", message="rubicon.objc.ctypes_patch has only been tested ")

# -------------- MELTS preamble --------------- #
from thermoengine import equilibrate
# instantiate thermoengine equilibrate MELTS instance
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})
# --------------------------------------------- #

# -------------- BATCH PROCESSING ----------- #
class BatchFile(batchfile.BatchFile):
    """Performs model functions on a batchfile.BatchFile object
    """
    pass

    def get_XH2O_fluid(self, sample, temperature, pressure, H2O, CO2):
        """An internally used function to calculate fluid composition.
示例#3
0
	def calculate_degassing_paths(self, sample, temp, system='closed', init_vapor='None'):
		"""
		Calculates degassing path for one sample

		Parameters
		----------
		sample: dict
			Dictionary with values for sample composition as oxides in wt%. If pulling from an uploaded file
			with data for many samples, first call get_sample_oxide_comp() to get the sample desired. Then pass
			the result into this function.

		temp: float
			Temperature at which to calculate degassing paths, in degrees C.

		system: str
			OPTIONAL. Default value is 'closed'. Specifies the type of calculation performed, either closed system or closed
			system degassing. If closed is chosen, user can also specify the 'init_vapor' argument (see below).
			Possible inputs are 'open' and 'closed'.

		init_vapor: float
			OPTIONAL. Default value is 0.0. Specifies the amount of vapor (in wt%) coexisting with the melt before
			degassing.

		Returns
		-------
		pandas DataFrame object

		"""
		#--------------Preamble required for every MagmaSat method within Modeller---------------#
		# instantiate thermoengine equilibrate MELTS instance
		melts = equilibrate.MELTSmodel(self.model_version)

		# Suppress phases not required in the melts simulation
		self.oxides = melts.get_oxide_names()
		self.phases = melts.get_phase_names()

		for phase in self.phases:
		    melts.set_phase_inclusion_status({phase: False})
		melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True})
		#---------------------------------------------------------------------------------------#

		sample = normalize(sample)
		bulk_comp_orig = sample

		feasible = melts.set_bulk_composition(sample)

		# Get saturation pressure
		data = self.calculate_saturation_pressure(sample, temp)

		if system == 'closed':
			if init_vapor == 'None':
				P_array = np.arange(1.0, data['SaturationPressure_MPa']+10.0, 10)
				P_array = -np.sort(-P_array)
				output = melts.equilibrate_tp(temp, P_array)

				pressure = []
				H2Oliq = []
				CO2liq = []
				H2Ofl = []
				CO2fl = []
				fluid_wtper = []
				for i in range(len(output)):
				    (status, temp, p, xmlout) = output[i]
				    liq_comp = melts.get_composition_of_phase(xmlout, phase_name='Liquid')
				    fl_comp = melts.get_composition_of_phase(xmlout, phase_name='Fluid')
				    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)

				    pressure.append(p)
				    try:
				    	H2Oliq.append(liq_comp["H2O"])
				    except:
				    	H2Oliq.append(0)
				    try:
				    	CO2liq.append(liq_comp["CO2"])
				    except:
				    	CO2liq.append(0)
				    try:
				    	H2Ofl.append(fl_comp["H2O"])
				    except:
				    	H2Ofl.append(0)
				    try:
				    	CO2fl.append(fl_comp["CO2"])
				    except:
				    	CO2fl.append(0)
				    fluid_wtper.append(fl_wtper)

				    try:
				    	sample["H2O"] = liq_comp["H2O"]
				    except:
				    	sample["H2O"] = 0
				    try:
				    	sample["CO2"] = liq_comp["CO2"]
				    except:
				    	sample["CO2"] = 0
				    fluid_wtper.append(fl_wtper)

				sample = bulk_comp_orig
				feasible = melts.set_bulk_composition(sample)
				closed_degassing_df = pd.DataFrame(list(zip(pressure, H2Oliq, CO2liq, H2Ofl, CO2fl, fluid_wtper)), 
				                            columns =['pressure', 'H2Oliq', 'CO2liq', 'H2Ofl', 'CO2fl', 'fluid_wtper'])

				return closed_degassing_df

			else:
				P_array = np.arange(1.0, data['SaturationPressure_MPa'], 10)
				P_array = -np.sort(-P_array)
				fl_wtper = data["FluidSystem_wtper"]

				while fl_wtper <= init_vapor:
				    output = melts.equilibrate_tp(temp, data["SaturationPressure_MPa"])
				    (status, temp, 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)
				    sample["H2O"] += fl_comp["H2O"]*0.0005
				    sample["CO2"] += fl_comp["CO2"]*0.0005
				    sample = normalize(sample)
				    feasible = melts.set_bulk_composition(sample)

				output = melts.equilibrate_tp(temp, P_array)

				pressure = []
				H2Oliq = []
				CO2liq = []
				H2Ofl = []
				CO2fl = []
				fluid_wtper = []
				for i in range(len(output)):
				    (status, temp, p, xmlout) = output[i]
				    liq_comp = melts.get_composition_of_phase(xmlout, phase_name='Liquid')
				    fl_comp = melts.get_composition_of_phase(xmlout, phase_name='Fluid')
				    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)
				    
				    pressure.append(p)
				    try:
				    	H2Oliq.append(liq_comp["H2O"])
				    except:
				    	H2Oliq.append(0)
				    try:
				    	CO2liq.append(liq_comp["CO2"])
				    except:
				    	CO2liq.append(0)
				    try:
				    	H2Ofl.append(fl_comp["H2O"])
				    except:
				    	H2Ofl.append(0)
				    try:
				    	CO2fl.append(fl_comp["CO2"])
				    except:
				    	CO2fl.append(0)
				    fluid_wtper.append(fl_wtper)

				    try:
				    	sample["H2O"] = liq_comp["H2O"]
				    except:
				    	sample["H2O"] = 0
				    try:
				    	sample["CO2"] = liq_comp["CO2"]
				    except:
				    	sample["CO2"] = 0
				    fluid_wtper.append(fl_wtper)

				sample = bulk_comp_orig
				feasible = melts.set_bulk_composition(sample)
				fl_wtper = data["FluidSystem_wtper"]
				exsolved_degassing_df = pd.DataFrame(list(zip(pressure, H2Oliq, CO2liq, H2Ofl, CO2fl, fluid_wtper)), 
				                            columns =['pressure', 'H2Oliq', 'CO2liq', 'H2Ofl', 'CO2fl', 'fluid_wtper'])

				return exsolved_degassing_df

		elif system == 'open':
			P_array = np.arange(1.0, data['SaturationPressure_MPa']+10.0, 10)
			P_array = -np.sort(-P_array)

			pressure = []
			H2Oliq = []
			CO2liq = []
			H2Ofl = []
			CO2fl = []
			fluid_wtper = []
			for i in P_array:
			    fl_mass = 0.0
			    output = melts.equilibrate_tp(temp, i)
			    (status, temp, 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')
			    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)
			        try:
			        	H2Oliq.append(liq_comp["H2O"])
			        except:
			        	H2Oliq.append(0)
			        try:
			        	CO2liq.append(liq_comp["CO2"])
			        except:
			        	CO2liq.append(0)
			        try:
			            H2Ofl.append(fl_comp["H2O"])
			        except:
			            H2Ofl.append(0)
			        try:
			            CO2fl.append(fl_comp["CO2"])
			        except:
			            CO2fl.append(0)
			        fluid_wtper.append(fl_wtper)

			        try:
			        	sample["H2O"] = liq_comp["H2O"]
			        except:
			        	sample["H2O"] = 0
			        try:
			        	sample["CO2"] = liq_comp["CO2"]
			        except:
			        	sample["CO2"] = 0
			        sample = normalize(sample)

			        feasible = melts.set_bulk_composition(sample)

			sample = bulk_comp_orig
			feasible = melts.set_bulk_composition(sample) #this needs to be reset always!
			open_degassing_df = pd.DataFrame(list(zip(pressure, H2Oliq, CO2liq, H2Ofl, CO2fl, fluid_wtper)), 
			                            columns =['pressure', 'H2Oliq', 'CO2liq', 'H2Ofl', 'CO2fl', 'fluid_wtper'])

			return open_degassing_df
示例#4
0
	def calculate_saturation_pressure(self, sample, temp, print_status=False):
		"""
		Calculates the saturation pressure of one or more sample compositions, depending on what variable is passed to 'sample'.

		Parameters
		----------
		sample: dict or ExcelFile object
			Compositional information on one or more samples. A single sample can be passed as a dict or ExcelFile object.
			Multiple samples must be passed as an ExcelFile object.

		temp: float or str
			Temperature at which to calculate saturation pressures, in degrees C. Can be passed as float, in which case the
			passed value is used as the temperature for all samples. Alternatively, temperature information for each individual
			sample may already be present in the passed ExcelFile object. If so, pass the str value corresponding to the column
			title in the passed ExcelFile object.

		print_status: bool
			OPTIONAL: Default is False. If set to True, progress of the calculations will be printed to the terminal.

		Returns
		-------
		pandas DataFrame object or dict
			If sample is passes as dict, dict is returned. If sample is passed as ExcelFile object, pandas DataFrame is
			returned. Values returned are saturation pressure in MPa, the mass of fluid present, and the composition of the
			fluid present.
		"""
		#--------------Preamble required for every MagmaSat method within Modeller---------------#
		# instantiate thermoengine equilibrate MELTS instance
		melts = equilibrate.MELTSmodel(self.model_version)

		# Suppress phases not required in the melts simulation
		self.oxides = melts.get_oxide_names()
		self.phases = melts.get_phase_names()

		for phase in self.phases:
		    melts.set_phase_inclusion_status({phase: False})
		melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True})
		#---------------------------------------------------------------------------------------#

		oxides = self.oxides

		if isinstance(sample, dict):
			data = pd.DataFrame([v for v in sample.values()],
                    index=[k for k in sample.keys()])
			data = data.transpose()
		elif isinstance(sample, ExcelFile):
			data = sample.data
		else:
			raise InputError("sample must be type ExcelFile object or dict")

		if isinstance(temp, str):
			file_has_temp = True
		elif isinstance(temp, float):
			file_has_temp = False
		else:
			raise InputError("temp must be type str or float")

		# Do the melts equilibrations
		bulk_comp = {}
		startingP = []
		startingP_ref = []
		satP = []
		flmass = []
		flH2O = []
		flCO2 = []
		flsystem_wtper = []
		iterno = 0
		for index, row in data.iterrows():
			if iterno == 0:
				bulk_comp_orig = {oxide:  row[oxide] for oxide in oxides}
			
			bulk_comp = {oxide:  row[oxide] for oxide in oxides}
			feasible = melts.set_bulk_composition(bulk_comp)

			if file_has_temp == True:
				temp = row[temp]

			fluid_mass = 0.0
			press = 2000.0
			while fluid_mass <= 0.0:
				press -= 100.0

				output = melts.equilibrate_tp(temp, press, initialize=True)
				(status, temp, i, xmlout) = output[0]
				fluid_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid')

				if press <= 0:
					break

			startingP.append(press+100.0)
			iterno += 1

		data["StartingP"] = startingP

		for index, row in data.iterrows():
		    bulk_comp = {oxide:  row[oxide] for oxide in oxides}
		    feasible = melts.set_bulk_composition(bulk_comp)

		    if file_has_temp == True:
		        temp = row[temp]

		    fluid_mass = 0.0
		    press = row["StartingP"]
		    while fluid_mass <= 0.0:
		        press -= 10.0

		        output = melts.equilibrate_tp(temp, press, initialize=True)
		        (status, temp, i, xmlout) = output[0]
		        fluid_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid')

		        if press <= 0:
		            break

		    startingP_ref.append(press+10.0)

		data["StartingP_ref"] = startingP_ref

		for index, row in data.iterrows():
		    bulk_comp = {oxide:  row[oxide] for oxide in oxides}
		    feasible = melts.set_bulk_composition(bulk_comp)

		    if file_has_temp == True:
		        temp = row[temp]

		    fluid_mass = 0.0
		    press = row["StartingP_ref"]
		    while fluid_mass <= 0.0:
		        press -= 1.0

		        output = melts.equilibrate_tp(temp, press, initialize=True)
		        (status, temp, i, xmlout) = output[0]
		        fluid_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid')

		        if press <= 0:
		            break

		    satP.append(press)
		    flmass.append(fluid_mass)
		    flsystem_wtper.append(100 * fluid_mass / (fluid_mass +
		                          melts.get_mass_of_phase(xmlout, phase_name='Liquid')))

		    flcomp = melts.get_composition_of_phase(xmlout, phase_name='Fluid')
		    flH2O.append(flcomp["H2O"])
		    flCO2.append(flcomp["CO2"])

		    if print_status == True:
			    print(index)
			    print("Pressure = " + str(press))
			    print("Fluid mass = " + str(fluid_mass))
			    print("\n")

		data["SaturationPressure_MPa"] = satP
		data["FluidMassAtSaturation_grams"] = flmass
		data["H2Ofluid_wtper"] = flH2O
		data["CO2fluid_wtper"] = flCO2
		data["FluidSystem_wtper"] = flsystem_wtper
		del data["StartingP"]
		del data["StartingP_ref"]

		feasible = melts.set_bulk_composition(bulk_comp_orig) #this needs to be reset always!

		if isinstance(sample, dict):
			data = data.transpose()
			data = data.to_dict()
			return data[0]
		elif isinstance(sample, ExcelFile):
			return data
示例#5
0
	def plot_isobars_and_isopleths(self, isobars_df):
		"""
		Takes in a dataframe with calculated isobar and isopleth information (e.g., output from calculate_isobars_and_isopleths)
		and plots data as isobars (lines of constant pressure) and isopleths (lines of constant fluid composition). These lines
		represent the saturation pressures of the melt composition used to calculate the isobar and isopleth information.

		Parameters
		----------
		isobars_df: pandas DataFrame
			DataFrame object containing isobar and isopleth information as calculated by calculate_isobars_and_isopleths.

		Returns
		-------
		matplotlib object
			Plot with x-axis as H2O wt% in the melt and y-axis as CO2 wt% in the melt. Isobars, or lines of
			constant pressure at which the sample magma composition is saturated, and isopleths, or lines of constant
			fluid composition at which the sample magma composition is saturated, are plotted.
		"""
		#--------------Preamble required for every MagmaSat method within Modeller---------------#
		# instantiate thermoengine equilibrate MELTS instance
		melts = equilibrate.MELTSmodel(self.model_version)

		# Suppress phases not required in the melts simulation
		self.oxides = melts.get_oxide_names()
		self.phases = melts.get_phase_names()

		for phase in self.phases:
		    melts.set_phase_inclusion_status({phase: False})
		melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True})
		#---------------------------------------------------------------------------------------#

		P_vals = isobars_df.Pressure.unique()
		isobars_lists = isobars_df.values.tolist()

		# make a list of isopleth values to plot
		iso_step = 20.0
		isopleth_vals = np.arange(0+iso_step, 100.0, iso_step)

		# add zero values to volatiles list
		isobars_lists.append([0.0, 0.0, 0.0, 0.0])

		# draw the figure
		fig, ax1 = plt.subplots()

		# turn on interactive plotting
		plt.ion()

		plt.xlabel('H2O wt%')
		plt.ylabel('CO2 wt%')

		# Plot some stuff
		for pressure in P_vals:
		    ax1.plot([item[1] for item in isobars_lists if item[0] == pressure],
		             [item[2] for item in isobars_lists if item[0] == pressure])

		for val in isopleth_vals:
		    val_min = val-1.0
		    val_max = val+1.0
		    x_vals_iso = [item[1]
		        for item in isobars_lists if val_min <= item[3] <= val_max]
		    x_vals_iso.append(0)
		    x_vals_iso = sorted(x_vals_iso)
		    x_vals_iso = np.array(x_vals_iso)
		    y_vals_iso = [item[2]
		        for item in isobars_lists if val_min <= item[3] <= val_max]
		    y_vals_iso.append(0)
		    y_vals_iso = sorted(y_vals_iso)
		    y_vals_iso = np.array(y_vals_iso)

		    ax1.plot(x_vals_iso, y_vals_iso, ls='dashed', color='k')

		labels = P_vals
		ax1.legend(labels)

		return ax1
示例#6
0
	def calculate_isobars_and_isopleths(self, sample, temp, print_status=False, pressure_min='', pressure_max='', pressure_int='', pressure_list=''):
		"""
		Calculates isobars and isopleths at a constant temperature for a given sample. Isobars can be calculated
		for any number of pressures. Pressures can be passed as min, max, interval (100.0, 500.0, 100.0 would result
		in pressures of 100.0, 200.0, 300.0, 400.0, and 500.0 MPa). Alternatively pressures can be passed as a list of all
		desired pressures ([100.0, 200.0, 250.0, 300.0] would calculate isobars for each of those pressures in MPa).

		Parameters
		----------
		sample: dict
			Dictionary with values for sample composition as oxides in wt%.

		temp: float
			Temperature in degrees C.

		pressure_min: float
			OPTIONAL. If passed, also requires pressure_max and pressure_int be passed. If passed, do not pass
			pressure_list. Minimum pressure	value in MPa.

		pressure_max: float
			OPTIONAL. If passed, also requires pressure_min and pressure_int be passed. If passed, do not pass
			pressure_list. Maximum pressure value in MPa.

		pressure_int: float
			OPTIONAL: If passed, also requires pressure_min and pressure_max be passed. If passed, do not pass
			pressure_list. Interval between pressure values in MPa.

		pressure_list: list
			OPTIONAL: If passed, do not pass pressure_min, pressure_max, or pressure_int. List of all pressure
			values in MPa.

		print_status: bool
			OPTIONAL: Default is False. If set to True, progress of the calculations will be printed to the terminal.

		Returns
		-------
		pandas DataFrame object
			DataFrame containing calcualted isobar and isopleth information for the passed melt composition. Column titles
			are 'Pressure', 'H2Omelt', 'CO2melt', 'H2Ofl', and 'CO2fl'.
		"""
		#--------------Preamble required for every MagmaSat method within Modeller---------------#
		# instantiate thermoengine equilibrate MELTS instance
		melts = equilibrate.MELTSmodel(self.model_version)
		bulk_comp_orig = sample #for reset

		# Suppress phases not required in the melts simulation
		self.oxides = melts.get_oxide_names()
		self.phases = melts.get_phase_names()

		for phase in self.phases:
		    melts.set_phase_inclusion_status({phase: False})
		melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True})
		#---------------------------------------------------------------------------------------#

		if isinstance(pressure_min, float) and isinstance(pressure_list, list):
			raise InputError(
			    "Enter pressure either as min, max, int OR as list. Not both.")
		if isinstance(pressure_max, float) and isinstance(pressure_list, list):
			raise InputError(
			    "Enter pressure either as min, max, int OR as list. Not both.")
		if isinstance(pressure_int, float) and isinstance(pressure_list, list):
			raise InputError(
			    "Enter pressure either as min, max, int OR as list. Not both.")

		if isinstance(pressure_min, float):
			P_vals = np.arange(pressure_min, pressure_max+pressure_int, pressure_int)

		if isinstance(pressure_list, list):
			P_vals = pressure_list

		bulk_comp = sample
		phases = self.phases
		oxides = self.oxides
		phases = melts.get_phase_names()

		volatiles_at_saturation = []
		H2O_val = 0
		CO2_val = 0
		fluid_mass = 0.0

		# Calculate equilibrium phase assemblage for all P/T conditions, check if saturated in fluid...
		for i in P_vals:
		    if print_status == True:
		    	print("Calculating isobars at " + str(i) + " MPa")

		    for j in np.arange(0, 15.5, 0.5):
		        bulk_comp["H2O"] = j
		        while fluid_mass <= 0.0:
		            bulk_comp["CO2"] = CO2_val

		            melts.set_bulk_composition(bulk_comp)

		            output = melts.equilibrate_tp(temp, i, initialize=True)
		            (status, temp, i, xmlout) = output[0]
		            fluid_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid')

		            CO2_val = CO2_val + 0.1

		        if fluid_mass > 0.0:
		            liquid_comp = melts.get_composition_of_phase(
		                xmlout, phase_name='Liquid', mode='oxide_wt')
		            fluid_comp = melts.get_composition_of_phase(
		                xmlout, phase_name='Fluid')

		            if "H2O" in liquid_comp:
		                        H2O_liq = liquid_comp["H2O"]
		            else:
		                H2O_liq = 0

		            if "CO2" in liquid_comp:
		                CO2_liq = liquid_comp["CO2"]
		            else:
		                CO2_liq = 0

		            if "H2O" in fluid_comp:
		                H2O_fl = fluid_comp["H2O"]
		            else:
		                H2O_fl = 0.0
		            if "CO2" in fluid_comp:
		                CO2_fl = fluid_comp["CO2"]
		            else:
		                CO2_fl = 0.0
		            volatiles_at_saturation.append(
		                [i, H2O_liq, CO2_liq, H2O_fl, CO2_fl])
		            CO2_val = 0.0
		            fluid_mass = 0.0

		if print_status == True:
		    print("Done!")

		isobars_df = pd.DataFrame(volatiles_at_saturation, columns=[
		                          'Pressure', 'H2Omelt', 'CO2melt', 'H2Ofl', 'CO2fl'])

		feasible = melts.set_bulk_composition(bulk_comp_orig) #reset

		return isobars_df
示例#7
0
	def calculate_equilibrium_fluid_comp(self, sample, temp, press):
		"""
		Returns H2O and CO2 concentrations in wt% in a fluid in equilibrium with the given sample(s) at the given P/T condition.

		Parameters
		----------
		sample: dict or ExcelFile object
			Compositional information on one or more samples. A single sample can be passed as a dict or ExcelFile object.
			Multiple samples must be passed as an ExcelFile object.

		temp: float or str
			Temperature, in degrees C. Can be passed as float, in which case the
			passed value is used as the temperature for all samples. Alternatively, temperature information for each individual
			sample may already be present in the passed ExcelFile object. If so, pass the str value corresponding to the column
			title in the passed ExcelFile object.

		press: float or str
			Pressure, in MPa. Can be passed as float, in which case the
			passed value is used as the pressure for all samples. Alternatively, pressure information for each individual
			sample may already be present in the passed ExcelFile object. If so, pass the str value corresponding to the column
			title in the passed ExcelFile object.

		Returns
		-------
		dict 
			If dict is passed to sample, a dictionary of fluid composition in wt% with keys 'H2O' and 'CO2' is returned.
			If ExcelFile is passed to sample, a pandas DataFrame object is returned.
		"""
		#--------------Preamble required for every MagmaSat method within Modeller---------------#
		# instantiate thermoengine equilibrate MELTS instance
		melts = equilibrate.MELTSmodel(self.model_version)

		# Suppress phases not required in the melts simulation
		self.oxides = melts.get_oxide_names()
		self.phases = melts.get_phase_names()

		for phase in self.phases:
		    melts.set_phase_inclusion_status({phase: False})
		melts.set_phase_inclusion_status({'Fluid': True, 'Liquid': True})
		#---------------------------------------------------------------------------------------#

		if isinstance(sample, dict):
			bulk_comp_orig = sample #for reset
			data = pd.DataFrame([v for v in sample.values()],
                    index=[k for k in sample.keys()])
			data = data.transpose()
		elif isinstance(sample, ExcelFile):
			data = sample.data
		else:
			raise InputError("sample must be type ExcelFile object or dict")

		if isinstance(temp, str):
			file_has_temp = True
		elif isinstance(temp, float):
			file_has_temp = False
		else:
			raise InputError("temp must be type str or float")

		if isinstance(press, str):
			file_has_press = True
		elif isinstance(temp, float):
			file_has_press = False
		else:
			raise InputError("press must be type str or float")


		fluid_comp_H2O = []
		fluid_comp_CO2 = []
		for index, row in data.iterrows():
		    bulk_comp = {oxide:  row[oxide] for oxide in oxides}
		    feasible = melts.set_bulk_composition(bulk_comp)

		    if file_has_temp == True:
		        temp = row[temp]
		    if file_has_press == True:
		    	press = row[press]

		    output = melts.equilibrate_tp(temp, press, initialize=True)
		    (status, temp, i, xmlout) = output[0]
		    fluid_mass = melts.get_mass_of_phase(xmlout, phase_name='Fluid')

		    if fluid_mass > 0.0:
		    	fluid_comp = melts.get_composition_of_phase(xmlout, phase_name='Fluid')
		    	fluid_comp_H2O.append(fluid_comp['H2O'])
		    	fluid_comp_CO2.append(fluid_comp['CO2'])
		    else:
		    	fluid_comp_H2O.append(0)
		    	fluid_comp_CO2.append(0)

		data["H2Ofluid_wtper"] = fluid_comp_H2O
		data["CO2fluid_wtper"] = fluid_comp_CO2

		if isinstance(sample, dict):
			feasible = melts.set_bulk_composition(bulk_comp_orig) #reset
			data = pd.DataFrame({"H2O": data["H2Ofluid_wtper"],
								"CO2": data["CO2fluid_wtper"]})
			data = data.transpose()
			data = data.to_dict()
			return data[0]
		elif isinstance(sample, ExcelFile):
			return data