Пример #1
0
/* ---------------------------------------------------------------------- */
static int
reaction_calc (struct irrev *irrev_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *    Go through irreversible reaction initially to
 *    determine a list of elements and amounts in 
 *    the reaction.
 */
  int i, j, return_value;
  LDBLE coef;
  char token[MAX_LENGTH];
  char *ptr;
  struct phase *phase_ptr;
/*
 *   Go through list and generate list of elements and
 *   coefficient of elements in reaction
 */
  return_value = OK;
  count_elts = 0;
  paren_count = 0;

  for (i = 0; i < irrev_ptr->count_list; i++)
  {
    coef = irrev_ptr->list[i].coef;
    strcpy (token, irrev_ptr->list[i].name);
    phase_ptr = phase_bsearch (token, &j, FALSE);
/*
 *   Reactant is a pure phase, copy formula into token
 */
    if (phase_ptr != NULL)
    {
      add_elt_list (phase_ptr->next_elt, coef);
    }
    else
    {
      ptr = &(token[0]);
      get_elts_in_species (&ptr, coef);
    }
  }
/*
 *   Check that all elements are in database
 */
  for (i = 0; i < count_elts; i++)
  {
    if (elt_list[i].elt->master == NULL)
    {
      sprintf (error_string, "Element or phase not defined in database, %s.",
	       elt_list[i].elt->name);
      error_msg (error_string, CONTINUE);
      input_error++;
      return_value = ERROR;
    }
  }
  irrev_ptr->elts = elt_list_save ();

  return (return_value);
}
Пример #2
0
/* ---------------------------------------------------------------------- */
int
gas_phase_check (struct gas_phase *gas_phase_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *   Check for missing elements
 */
  int i, j;

  struct gas_comp *gas_comp_ptr;
  struct master *master_ptr;

  if (gas_phase_ptr == NULL)
    return (OK);
  gas_comp_ptr = gas_phase_ptr->comps;
/*
 *   Check that all elements are in solution for phases with zero mass
 */
  for (i = 0; i < gas_phase_ptr->count_comps; i++)
  {
    count_elts = 0;
    paren_count = 0;
    if (gas_comp_ptr[i].moles <= 0.0)
    {
      add_elt_list (gas_comp_ptr[i].phase->next_elt, 1.0);
      for (j = 0; j < count_elts; j++)
      {
	master_ptr = elt_list[j].elt->primary;
	if (master_ptr->s == s_hplus)
	{
	  continue;
	}
	else if (master_ptr->s == s_h2o)
	{
	  continue;
	}
	else if (master_ptr->total > MIN_TOTAL)
	{
	  continue;
	}
	else
	{
	  if (state != ADVECTION && state != TRANSPORT && state != PHAST)
	  {
	    sprintf (error_string,
		     "Element %s is contained in gas %s (which has 0.0 mass),\nbut is not in solution or other phases.",
		     elt_list[j].elt->name, gas_comp_ptr[i].phase->name);
	    warning_msg (error_string);
	  }
	}
      }
    }
  }
  return (OK);
}
Пример #3
0
/* ---------------------------------------------------------------------- */
int
add_gas_phase (struct gas_phase *gas_phase_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *   Accumulate gas data in master->totals and _x variables.
 */
  int i;

  struct gas_comp *gas_comp_ptr;
  struct master *master_ptr;

  if (gas_phase_ptr == NULL)
    return (OK);
  gas_comp_ptr = gas_phase_ptr->comps;
/*
 *   calculate reaction
 */
  count_elts = 0;
  paren_count = 0;
  for (i = 0; i < gas_phase_ptr->count_comps; i++)
  {
    add_elt_list (gas_comp_ptr[i].phase->next_elt, gas_comp_ptr[i].moles);
  }
/*
 *   Sort elements in reaction and combine
 */
  if (count_elts > 0)
  {
    qsort (elt_list, (size_t) count_elts,
	   (size_t) sizeof (struct elt_list), elt_list_compare);
    elt_list_combine ();
  }
/*
 *   Add gas elements to totals
 */
  for (i = 0; i < count_elts; i++)
  {
    master_ptr = elt_list[i].elt->primary;
    if (master_ptr->s == s_hplus)
    {
      total_h_x += elt_list[i].coef;
    }
    else if (master_ptr->s == s_h2o)
    {
      total_o_x += elt_list[i].coef;
    }
    else
    {
      master_ptr->total += elt_list[i].coef;
    }
  }
  return (OK);
}
Пример #4
0
/* ---------------------------------------------------------------------- */
int
add_pp_assemblage (struct pp_assemblage *pp_assemblage_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *   Add a small amount of each phase if necessary to insure
 *   all elements exist in solution.
 */
  int i, j;
  LDBLE amount_to_add, total;
  char token[MAX_LENGTH];
  char *ptr;
  struct pure_phase *pure_phase_ptr;
  struct master *master_ptr;

  if (check_pp_assemblage (pp_assemblage_ptr) == OK)
    return (OK);
/*
 *   Go through list and generate list of elements and
 *   coefficient of elements in reaction
 */
  count_elts = 0;
  paren_count = 0;
/*
 *   Check that all elements are in solution for phases with greater than zero mass
 */
  pure_phase_ptr = pp_assemblage_ptr->pure_phases;
  for (j = 0; j < pp_assemblage_ptr->count_comps; j++)
  {
    count_elts = 0;
    paren_count = 0;
    amount_to_add = 0.0;
    pure_phase_ptr[j].delta = 0.0;
    if (pure_phase_ptr[j].add_formula != NULL)
    {
      strcpy (token, pure_phase_ptr[j].add_formula);
      ptr = &(token[0]);
      get_elts_in_species (&ptr, 1.0);
    }
    else
    {
      strcpy (token, pure_phase_ptr[j].phase->formula);
      add_elt_list (pure_phase_ptr[j].phase->next_elt, 1.0);
    }
    if (pure_phase_ptr[j].moles > 0.0)
    {
      for (i = 0; i < count_elts; i++)
      {
	master_ptr = elt_list[i].elt->primary;
	if (master_ptr->s == s_hplus)
	{
	  continue;
	}
	else if (master_ptr->s == s_h2o)
	{
	  continue;
	}
	else if (master_ptr->total > MIN_TOTAL)
	{
	  continue;
	}
	else
	{
	  total = (-master_ptr->total + 1e-10) / elt_list[i].coef;
	  if (amount_to_add < total)
	  {
	    amount_to_add = total;
	  }
	}
      }
      if (pure_phase_ptr[j].moles < amount_to_add)
      {
	amount_to_add = pure_phase_ptr[j].moles;
      }
    }
    if (amount_to_add > 0.0)
    {
      pure_phase_ptr[j].moles -= amount_to_add;
      pure_phase_ptr[j].delta = amount_to_add;
/*
 *   Add reaction to totals
 */
      for (i = 0; i < count_elts; i++)
      {
	master_ptr = elt_list[i].elt->primary;
	if (master_ptr->s == s_hplus)
	{
	  total_h_x += elt_list[i].coef * amount_to_add;
	}
	else if (master_ptr->s == s_h2o)
	{
	  total_o_x += elt_list[i].coef * amount_to_add;
	}
	else
	{
	  master_ptr->total += elt_list[i].coef * amount_to_add;
	}
      }
    }
  }
  return (OK);
}
Пример #5
0
/* ---------------------------------------------------------------------- */
int
s_s_assemblage_check (struct s_s_assemblage *s_s_assemblage_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *   Check for missing elements
 */
  int i, j, k, l;
  struct master *master_ptr;

  if (s_s_assemblage_ptr == NULL)
    return (OK);
/*
 *   Check that all elements are in solution for phases with zero mass
 */
  for (i = 0; i < s_s_assemblage_ptr->count_s_s; i++)
  {
    for (j = 0; j < s_s_assemblage_ptr->s_s[i].count_comps; j++)
    {
      count_elts = 0;
      paren_count = 0;
      if (s_s_assemblage_ptr->s_s[i].comps[j].moles <= 0.0)
      {
	add_elt_list (s_s_assemblage_ptr->s_s[i].comps[j].phase->next_elt,
		      1.0);
	for (l = 0; l < count_elts; l++)
	{
	  master_ptr = elt_list[l].elt->primary;
	  if (master_ptr->s == s_hplus)
	  {
	    continue;
	  }
	  else if (master_ptr->s == s_h2o)
	  {
	    continue;
	  }
	  else if (master_ptr->total > MIN_TOTAL_SS)
	  {
	    continue;
	  }
	  else
	  {
	    if (state != ADVECTION && state != TRANSPORT && state != PHAST)
	    {
	      sprintf (error_string,
		       "Element %s is contained in solid solution %s (which has 0.0 mass),\nbut is not in solution or other phases.",
		       elt_list[l].elt->name,
		       s_s_assemblage_ptr->s_s[i].comps[j].phase->name);
	      warning_msg (error_string);
	    }
	  }
	  /*
	   *   Make la's of all master species for the element small, 
	   *   so SI will be small
	   *   and no mass transfer will be calculated
	   */
	  for (k = 0; k < count_master; k++)
	  {
	    if (master[k]->elt->primary == master_ptr)
	    {
	      master[k]->s->la = -9999.999;
	    }
	  }
	}
      }
    }
  }
  return (OK);
}
Пример #6
0
/* ---------------------------------------------------------------------- */
int
pp_assemblage_check (struct pp_assemblage *pp_assemblage_ptr)
/* ---------------------------------------------------------------------- */
{
/*
 *   Check for missing elements
 */
  int i, j, k;
  char token[MAX_LENGTH];
  char *ptr;
  struct pure_phase *pure_phase_ptr;
  struct master *master_ptr;

  if (check_pp_assemblage (pp_assemblage_ptr) == OK)
    return (OK);
/*
 *   Check that all elements are in solution for phases with zero mass
 */
  pure_phase_ptr = pp_assemblage_ptr->pure_phases;
  for (j = 0; j < pp_assemblage_ptr->count_comps; j++)
  {
    count_elts = 0;
    paren_count = 0;
    if (pure_phase_ptr[j].moles <= 0.0)
    {
      pure_phase_ptr[j].delta = 0.0;
      if (pure_phase_ptr[j].add_formula != NULL)
      {
	strcpy (token, pure_phase_ptr[j].add_formula);
	ptr = &(token[0]);
	get_elts_in_species (&ptr, 1.0);
      }
      else
      {
	strcpy (token, pure_phase_ptr[j].phase->formula);
	add_elt_list (pure_phase_ptr[j].phase->next_elt, 1.0);
      }
      for (i = 0; i < count_elts; i++)
      {
	master_ptr = elt_list[i].elt->primary;
	if (master_ptr->s == s_hplus)
	{
	  continue;
	}
	else if (master_ptr->s == s_h2o)
	{
	  continue;
	}
	else if (master_ptr->total > MIN_TOTAL)
	{
	  continue;
	}
	else
	{
	  if (state != ADVECTION && state != TRANSPORT && state != PHAST)
	  {
	    sprintf (error_string,
		     "Element %s is contained in %s (which has 0.0 mass),"
		     "\t\nbut is not in solution or other phases.",
		     elt_list[i].elt->name, pure_phase_ptr[j].phase->name);
	    warning_msg (error_string);
	  }
/*
 *   Make la's of all master species for the element small, so SI will be small
 *   and no mass transfer will be calculated
 */
	  for (k = 0; k < count_master; k++)
	  {
	    if (master[k]->elt->primary == master_ptr)
	    {
	      master[k]->s->la = -9999.999;
	    }
	  }
	}
      }
    }
  }
  return (OK);
}
Пример #7
0
/* ---------------------------------------------------------------------- */
int
sum_diffuse_layer (struct surface_charge *surface_charge_ptr1)
/* ---------------------------------------------------------------------- */
{
  int i, j, count_g;
  LDBLE mass_water_surface;
  LDBLE molality, moles_excess, moles_surface;

  if (use.surface_ptr == NULL)
    return (OK);
/*
 *   Find position of component in list of components
 */
  i = 0;

  for (j = 0; j < use.surface_ptr->count_charge; j++)
  {
    if (&(use.surface_ptr->charge[j]) == surface_charge_ptr1)
    {
      i = j;
      break;
    }
  }
  if (j >= use.surface_ptr->count_charge)
  {
    sprintf (error_string, "In sum_diffuse_layer, component not found, %s.",
	     surface_charge_ptr1->name);
    error_msg (error_string, STOP);
  }
/*
 *   Loop through all surface components, calculate each H2O surface (diffuse layer),
 *   H2O aq, and H2O bulk (diffuse layers plus aqueous).
 */
  count_elts = 0;
  paren_count = 0;
  mass_water_surface = surface_charge_ptr1->mass_water;
  for (j = 0; j < count_s_x; j++)
  {
    if (s_x[j]->type > HPLUS)
      continue;
    molality = under (s_x[j]->lm);
    count_g = s_x[j]->diff_layer[i].count_g;
#ifdef SKIP
    moles_excess = mass_water_bulk_x *
/*			s_x[j]->diff_layer[i].charge->g[count_g].g * molality; */
      surface_charge_ptr1->g[count_g].g * molality;
#endif
    moles_excess =
      mass_water_aq_x * molality * surface_charge_ptr1->g[count_g].g;

    moles_surface = mass_water_surface * molality + moles_excess;
/*
 *   Accumulate elements in diffuse layer
 */
    add_elt_list (s_x[j]->next_elt, moles_surface);
  }
  add_elt_list (s_h2o->next_elt, mass_water_surface / gfw_water);

  if (count_elts > 0)
  {
    qsort (elt_list, (size_t) count_elts,
	   (size_t) sizeof (struct elt_list), elt_list_compare);
    elt_list_combine ();
  }
  return (OK);
}
Пример #8
0
/* ---------------------------------------------------------------------- */
int Phreeqc::
build_fixed_volume_gas(void)
/* ---------------------------------------------------------------------- */
{
/*
 *   Put coefficients into lists to sum iaps to test for equilibrium
 *   Put coefficients into lists to build jacobian for 
 *      sum of partial pressures equation and
 *      mass balance equations for elements contained in gases
 */
	int row, col;
	struct master *master_ptr;
	struct rxn_token *rxn_ptr;
	struct unknown *unknown_ptr;
	LDBLE coef, coef_elt;

	if (gas_unknown == NULL)
		return (OK);
	cxxGasPhase *gas_phase_ptr = use.Get_gas_phase_ptr();
	for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++)
	{
		const cxxGasComp *comp_ptr = &(gas_phase_ptr->Get_gas_comps()[i]);
		int j;
		struct phase *phase_ptr = phase_bsearch(comp_ptr->Get_phase_name().c_str(), &j, FALSE);
/*
 *   Determine elements in gas component
 */
		count_elts = 0;
		paren_count = 0;
		if (phase_ptr->rxn_x == NULL)
			continue;
		add_elt_list(phase_ptr->next_elt, 1.0);
#define COMBINE
#ifdef COMBINE
		change_hydrogen_in_elt_list(0);
#endif
/*
 *   Build mass balance sums for each element in gas
 */
		if (debug_prep == TRUE)
		{
			output_msg(sformatf( "\n\tMass balance summations %s.\n\n",
					   phase_ptr->name));
		}

		/* All elements in gas */
		for (j = 0; j < count_elts; j++)
		{
			unknown_ptr = NULL;
			if (strcmp(elt_list[j].elt->name, "H") == 0)
			{
				unknown_ptr = mass_hydrogen_unknown;
			}
			else if (strcmp(elt_list[j].elt->name, "O") == 0)
			{
				unknown_ptr = mass_oxygen_unknown;
			}
			else
			{
				if (elt_list[j].elt->primary->in == TRUE)
				{
					unknown_ptr = elt_list[j].elt->primary->unknown;
				}
				else if (elt_list[j].elt->primary->s->secondary != NULL)
				{
					unknown_ptr =
						elt_list[j].elt->primary->s->secondary->unknown;
				}
			}
			if (unknown_ptr != NULL)
			{
				coef = elt_list[j].coef;
				store_mb(&(gas_unknowns[i]->moles), &(unknown_ptr->f), coef);
				if (debug_prep == TRUE)
				{
					output_msg(sformatf( "\t\t%-24s%10.3f\n",
							   unknown_ptr->description, (double) coef));
				}
			}
		}
		if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE)
		{
			/* Total pressure of gases */
			store_mb(&(phase_ptr->p_soln_x), &(gas_unknown->f),
					 1.0);
		}
/*
 *   Build jacobian sums for mass balance equations
 */
		if (debug_prep == TRUE)
		{
			output_msg(sformatf( "\n\tJacobian summations %s.\n\n",
					   phase_ptr->name));
		}
		for (j = 0; j < count_elts; j++)
		{
			unknown_ptr = NULL;
			if (strcmp(elt_list[j].elt->name, "H") == 0)
			{
				unknown_ptr = mass_hydrogen_unknown;
			}
			else if (strcmp(elt_list[j].elt->name, "O") == 0)
			{
				unknown_ptr = mass_oxygen_unknown;
			}
			else
			{
				if (elt_list[j].elt->primary->in == TRUE)
				{
					unknown_ptr = elt_list[j].elt->primary->unknown;
				}
				else if (elt_list[j].elt->primary->s->secondary != NULL)
				{
					unknown_ptr =
						elt_list[j].elt->primary->s->secondary->unknown;
				}
			}
			if (unknown_ptr == NULL)
			{
				continue;
			}
			if (debug_prep == TRUE)
			{
				output_msg(sformatf( "\n\t%s.\n",
						   unknown_ptr->description));
			}
			row = unknown_ptr->number * (count_unknowns + 1);
			coef_elt = elt_list[j].coef;
			for (rxn_ptr = phase_ptr->rxn_x->token + 1;
				 rxn_ptr->s != NULL; rxn_ptr++)
			{

				if (rxn_ptr->s->secondary != NULL
					&& rxn_ptr->s->secondary->in == TRUE)
				{
					master_ptr = rxn_ptr->s->secondary;
				}
				else if (rxn_ptr->s->primary != NULL && rxn_ptr->s->primary->in == TRUE)
				{
					master_ptr = rxn_ptr->s->primary;
				}
				else
				{
					master_ptr = master_bsearch_primary(rxn_ptr->s->name);
					master_ptr->s->la = -999.0;
				}
				if (debug_prep == TRUE)
				{
					output_msg(sformatf( "\t\t%s\n",
							   master_ptr->s->name));
				}
				if (master_ptr->unknown == NULL)
				{
					continue;
				}
				if (master_ptr->in == FALSE)
				{
					error_string = sformatf(
							"Element, %s, in phase, %s, is not in model.",
							master_ptr->elt->name, phase_ptr->name);
					error_msg(error_string, CONTINUE);
					input_error++;
				}
				col = master_ptr->unknown->number;
				coef = coef_elt * rxn_ptr->coef;
				store_jacob(&(gas_unknowns[i]->moles),
							&(array[row + col]), coef);
				if (debug_prep == TRUE)
				{
					output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n",
							   master_ptr->s->name, (double) coef,
							   row / (count_unknowns + 1), col));
				}
			}
			if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE)
			{
				/* derivative wrt total moles of gas */
				store_jacob(&(phase_ptr->fraction_x),
							&(array[row + gas_unknown->number]), coef_elt);
				if (debug_prep == TRUE)
				{
					output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n",
							   "gas moles", (double) elt_list[j].coef,
							   row / (count_unknowns + 1),
							   gas_unknown->number));
				}
			}
		}
/*
 *   Build jacobian sums for sum of partial pressures equation
 */
		if (gas_phase_ptr->Get_type() != cxxGasPhase::GP_PRESSURE)
			continue;
		if (debug_prep == TRUE)
		{
			output_msg(sformatf( "\n\tPartial pressure eqn %s.\n\n",
					   phase_ptr->name));
		}
		unknown_ptr = gas_unknown;
		row = unknown_ptr->number * (count_unknowns + 1);
		for (rxn_ptr = phase_ptr->rxn_x->token + 1; rxn_ptr->s != NULL; rxn_ptr++)
		{
			if (rxn_ptr->s != s_eminus && rxn_ptr->s->in == FALSE)
			{
				error_string = sformatf(
					"Element in species, %s, in phase, %s, is not in model.",
					rxn_ptr->s->name, phase_ptr->name);
				warning_msg(error_string);
			}
			else
			{
				if (rxn_ptr->s->secondary != NULL
					&& rxn_ptr->s->secondary->in == TRUE)
				{
					master_ptr = rxn_ptr->s->secondary;
				}
				else if (rxn_ptr->s->primary != NULL && rxn_ptr->s->primary->in == TRUE)
				{
					master_ptr = rxn_ptr->s->primary;
				}
				else
				{
					master_ptr = master_bsearch_primary(rxn_ptr->s->name);
					if (master_ptr && master_ptr->s)
					{
						master_ptr->s->la = -999.0;
					}
				}

				if (master_ptr == NULL)
				{
					error_string = sformatf(
						"Master species for %s, in phase, %s, is not in model.",
						rxn_ptr->s->name, phase_ptr->name);
					error_msg(error_string, CONTINUE);
					input_error++;
				}
				else
				{
					if (debug_prep == TRUE)
					{
						output_msg(sformatf( "\t\t%s\n", master_ptr->s->name));
					}
					if (master_ptr->unknown == NULL)
					{
						assert(false);
						continue;
					}
					if (master_ptr->in == FALSE)
					{
						error_string = sformatf(
							"Element, %s, in phase, %s, is not in model.",
							master_ptr->elt->name, phase_ptr->name);
						warning_msg(error_string);
					}
					col = master_ptr->unknown->number;
					coef = rxn_ptr->coef;
					store_jacob(&(phase_ptr->p_soln_x), &(array[row + col]), coef);
					if (debug_prep == TRUE)
					{
						output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n",
							master_ptr->s->name, (double) coef,
							row / (count_unknowns + 1), col));
					}
				}
			}
		}
	}
	return (OK);
}