mirror of
https://git.gfz-potsdam.de/naaice/iphreeqc.git
synced 2025-12-15 16:18:22 +01:00
d6a74675 Merge commit '4e80a54467a084df3b666c7d6fc56a4798fd3301' 4e80a544 Squashed 'phreeqcpp/' changes from 7c7fafd..c876219 0209fdf9 Merge commit 'b537589773f4819fe97ff8e5322bcd38c54b63f7' b5375897 Squashed 'phreeqcpp/' changes from e317dd0..7c7fafd git-subtree-dir: src git-subtree-split: d6a74675d73985977ceac1601b57463c1ee8c331
3382 lines
83 KiB
C++
3382 lines
83 KiB
C++
#include "Utils.h"
|
|
#include "Phreeqc.h"
|
|
#include <iostream>
|
|
|
|
#include "phqalloc.h"
|
|
#include "Temperature.h"
|
|
#include "cxxMix.h"
|
|
#include "Exchange.h"
|
|
#include "GasPhase.h"
|
|
#include "Reaction.h"
|
|
#include "PPassemblage.h"
|
|
#include "Use.h"
|
|
#include "SSassemblage.h"
|
|
#include "cxxKinetics.h"
|
|
#include "Surface.h"
|
|
#include "Solution.h"
|
|
|
|
#if defined(PHREEQCI_GUI)
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
#endif
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
clean_up(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Free all allocated memory, except strings
|
|
*/
|
|
int i, j;
|
|
#if defined MULTICHART
|
|
chart_handler.End_timer();
|
|
output_flush();
|
|
#if 0
|
|
// Wait for charts to end
|
|
while (0 != this->chart_handler.Get_active_charts())
|
|
{
|
|
System::Threading::Thread::Sleep(60);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
isotopes_x.clear();
|
|
/* model */
|
|
last_model.gas_phase.clear();
|
|
last_model.pp_assemblage.clear();
|
|
last_model.add_formula.clear();
|
|
last_model.si.clear();
|
|
last_model.ss_assemblage.clear();
|
|
last_model.surface_comp.clear();
|
|
last_model.surface_charge.clear();
|
|
/* model */
|
|
free_model_allocs();
|
|
|
|
/* species */
|
|
|
|
for (j = 0; j < (int)s.size(); j++)
|
|
{
|
|
s_free(s[j]);
|
|
delete s[j];
|
|
}
|
|
s.clear();
|
|
|
|
/* master species */
|
|
|
|
for (j = 0; j < (int)master.size(); j++)
|
|
{
|
|
master_free(master[j]);
|
|
}
|
|
master.clear();
|
|
|
|
/* elements */
|
|
|
|
for (j = 0; j < (int)elements.size(); j++)
|
|
{
|
|
delete elements[j];
|
|
}
|
|
elements.clear();
|
|
/* solutions */
|
|
Rxn_solution_map.clear();
|
|
/* surfaces */
|
|
Rxn_surface_map.clear();
|
|
/* exchange */
|
|
Rxn_exchange_map.clear();
|
|
/* pp assemblages */
|
|
Rxn_pp_assemblage_map.clear();
|
|
/* s_s assemblages */
|
|
Rxn_ss_assemblage_map.clear();
|
|
/* irreversible reactions */
|
|
Rxn_reaction_map.clear();
|
|
/* temperature */
|
|
Rxn_temperature_map.clear();
|
|
/* pressure */
|
|
Rxn_pressure_map.clear();
|
|
/* unknowns */
|
|
for (j = 0; j < (int)x.size(); j++)
|
|
{
|
|
unknown_free(x[j]);
|
|
}
|
|
x.clear();
|
|
/* mixtures */
|
|
Rxn_mix_map.clear();
|
|
/* phases */
|
|
for (j = 0; j < (int)phases.size(); j++)
|
|
{
|
|
phase_free(phases[j]);
|
|
delete phases[j];
|
|
}
|
|
phases.clear();
|
|
/* inverse */
|
|
for (j = 0; j < count_inverse; j++)
|
|
{
|
|
inverse_free(&(inverse[j]));
|
|
}
|
|
inverse.clear();
|
|
/* gases */
|
|
Rxn_gas_phase_map.clear();
|
|
/* kinetics */
|
|
Rxn_kinetics_map.clear();
|
|
x0_moles.clear();
|
|
m_temp.clear();
|
|
m_original.clear();
|
|
rk_moles.clear();
|
|
/* rates */
|
|
for (j = 0; j < (int)rates.size(); j++)
|
|
{
|
|
rate_free(&rates[j]);
|
|
}
|
|
rates.clear();
|
|
/* logk table */
|
|
for (j = 0; j < (int)logk.size(); j++)
|
|
{
|
|
logk[j]->add_logk.clear();
|
|
delete logk[j];
|
|
}
|
|
logk.clear();
|
|
save_values.clear();
|
|
save_strings.clear();
|
|
/* working pe*/
|
|
pe_x.clear();
|
|
/*species_list*/
|
|
species_list.clear();
|
|
/* transport data */
|
|
cell_data.clear();
|
|
/* advection */
|
|
advection_punch.clear();
|
|
advection_print.clear();
|
|
/* selected_output */
|
|
SelectedOutput_map.clear();
|
|
/* user_print and user_punch */
|
|
UserPunch_map.clear();
|
|
rate_free(user_print);
|
|
delete user_print;
|
|
/*
|
|
Clear llnl aqueous model parameters
|
|
*/
|
|
llnl_temp.clear();
|
|
llnl_adh.clear();
|
|
llnl_bdh.clear();
|
|
llnl_bdot.clear();
|
|
llnl_co2_coefs.clear();
|
|
/* master_isotope */
|
|
for (i = 0; i < (int)master_isotope.size(); i++)
|
|
{
|
|
delete master_isotope[i];
|
|
}
|
|
master_isotope.clear();
|
|
master_isotope_map.clear();
|
|
/* calculate_value */
|
|
for (i = 0; i < (int)calculate_value.size(); i++)
|
|
{
|
|
calculate_value_free(calculate_value[i]);
|
|
delete calculate_value[i];
|
|
}
|
|
calculate_value.clear();
|
|
calculate_value_map.clear();
|
|
/* isotope_ratio */
|
|
for (i = 0; i < (int)isotope_ratio.size(); i++)
|
|
{
|
|
delete isotope_ratio[i];
|
|
}
|
|
isotope_ratio.clear();
|
|
isotope_ratio_map.clear();
|
|
/* isotope_alpha */
|
|
for (i = 0; i < (int)isotope_alpha.size(); i++)
|
|
{
|
|
delete isotope_alpha[i];
|
|
}
|
|
isotope_alpha.clear();
|
|
isotope_alpha_map.clear();
|
|
/* tally table */
|
|
free_tally_table();
|
|
/* CVODE memory */
|
|
free_cvode();
|
|
/* pitzer */
|
|
pitzer_clean_up();
|
|
/* sit */
|
|
sit_clean_up();
|
|
/* elements, species, phases*/
|
|
elements_map.clear();
|
|
species_map.clear();
|
|
phases_map.clear();
|
|
logk_map.clear();
|
|
/* strings */
|
|
strings_map_clear();
|
|
/* delete basic interpreter */
|
|
basic_free();
|
|
/* change_surf */
|
|
change_surf = (struct Change_Surf *) free_check_null(change_surf);
|
|
/* miscellaneous work space */
|
|
elt_list.clear();
|
|
trxn.token.clear();
|
|
mb_unknowns.clear();
|
|
line = (char *) free_check_null(line);
|
|
line_save = (char *) free_check_null(line_save);
|
|
/* free user database name if defined */
|
|
dump_file_name = (char *) free_check_null(dump_file_name);
|
|
#ifdef PHREEQCI_GUI
|
|
free_spread();
|
|
#endif
|
|
title_x.clear();
|
|
last_title_x.clear();
|
|
count_inverse = 0;
|
|
|
|
sformatf_buffer = (char *) free_check_null(sformatf_buffer);
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
reinitialize(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/* solutions */
|
|
Rxn_solution_map.clear();
|
|
/* surfaces */
|
|
Rxn_surface_map.clear();
|
|
/* exchange */
|
|
Rxn_exchange_map.clear();
|
|
/* pp assemblages */
|
|
Rxn_pp_assemblage_map.clear();
|
|
/* s_s assemblages */
|
|
Rxn_ss_assemblage_map.clear();
|
|
/* gases */
|
|
Rxn_gas_phase_map.clear();
|
|
/* kinetics */
|
|
Rxn_kinetics_map.clear();
|
|
/* irreversible reactions */
|
|
Rxn_reaction_map.clear();
|
|
// Temperature
|
|
Rxn_temperature_map.clear();
|
|
// Pressure
|
|
Rxn_pressure_map.clear();
|
|
return (OK);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to CReaction
|
|
*
|
|
* ********************************************************************** */
|
|
CReaction::CReaction(void)
|
|
{
|
|
for (size_t i = 0; i < MAX_LOG_K_INDICES; i++) this->logk[i] = 0.0;
|
|
for (size_t i = 0; i < 3; i++) this->dz[i] = 0.0;
|
|
}
|
|
CReaction::CReaction(size_t ntoken)
|
|
{
|
|
for (size_t i = 0; i < MAX_LOG_K_INDICES; i++) this->logk[i] = 0.0;
|
|
for (size_t i = 0; i < 3; i++) this->dz[i] = 0.0;
|
|
this->token.resize(ntoken);
|
|
}
|
|
void CReaction::Set_logk(double* d)
|
|
{
|
|
for (size_t i = 0; i < MAX_LOG_K_INDICES; i++)logk[i] = d[i];
|
|
}
|
|
void CReaction::Set_dz(double* d)
|
|
{
|
|
for (size_t i = 0; i < 3; i++) dz[i] = d[i];
|
|
}
|
|
CReaction Phreeqc::CReaction_internal_copy(CReaction& rxn_ref)
|
|
{
|
|
CReaction rxn;
|
|
for (size_t i = 0; i < MAX_LOG_K_INDICES; i++) rxn.logk[i] = rxn_ref.logk[i];
|
|
for (size_t i = 0; i < 3; i++) rxn.dz[i] = rxn_ref.dz[i];
|
|
rxn.Get_tokens().resize(rxn_ref.Get_tokens().size());
|
|
for (size_t i = 0; i < rxn_ref.Get_tokens().size(); i++)
|
|
{
|
|
rxn.token[i].s = (rxn_ref.token[i].s == NULL) ? NULL :
|
|
s_store(rxn_ref.token[i].s->name, rxn_ref.token[i].s->z, false);
|
|
rxn.token[i].coef = rxn_ref.token[i].coef;
|
|
rxn.token[i].name = (rxn_ref.token[i].name == NULL) ? NULL :
|
|
string_hsave(rxn_ref.token[i].name);
|
|
}
|
|
return rxn;
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
double Phreeqc::
|
|
rxn_find_coef(CReaction& r_ref, const char* str)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Finds coefficient of token in reaction.
|
|
* input: r_ptr, pointer to a reaction structure
|
|
* str, string to find as reaction token
|
|
*
|
|
* Return: 0.0, if token not found
|
|
* coefficient of token, if found.
|
|
*/
|
|
class rxn_token* r_token;
|
|
LDBLE coef;
|
|
|
|
r_token = &r_ref.token[1];
|
|
coef = 0.0;
|
|
while (r_token->s != NULL)
|
|
{
|
|
if (strcmp(r_token->s->name, str) == 0)
|
|
{
|
|
coef = r_token->coef;
|
|
break;
|
|
}
|
|
r_token++;
|
|
}
|
|
return (coef);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "element"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
element_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class element *element_ptr1, *element_ptr2;
|
|
element_ptr1 = *(const class element **) ptr1;
|
|
element_ptr2 = *(const class element **) ptr2;
|
|
/* return(strcmp_nocase(element_ptr1->name, element_ptr2->name)); */
|
|
return (strcmp(element_ptr1->name, element_ptr2->name));
|
|
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class element* Phreeqc::
|
|
element_store(const char * element)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "element" in the map for elements.
|
|
*
|
|
* If found, pointer to the appropriate element structure is returned.
|
|
*
|
|
* If the string is not found, a new entry is made at the end of
|
|
* the elements array (position count_elements) and count_elements is
|
|
* incremented. Pointer to the new structure is returned.
|
|
*
|
|
* Arguments:
|
|
* element input, std::string to be located or stored.
|
|
*
|
|
* Returns:
|
|
* The address of an elt structure that contains the element data.
|
|
*/
|
|
/*
|
|
* Search list
|
|
*/
|
|
std::map<std::string, class element *>::const_iterator it;
|
|
it = elements_map.find(element);
|
|
if (it != elements_map.end())
|
|
{
|
|
return (it->second);
|
|
}
|
|
/*
|
|
* Save new element structure and return pointer to it
|
|
*/
|
|
class element *elt_ptr = new class element;
|
|
elt_ptr->name = string_hsave(element);
|
|
elt_ptr->master = NULL;
|
|
elt_ptr->primary = NULL;
|
|
elt_ptr->gfw = 0.0;
|
|
elements.push_back(elt_ptr);
|
|
elements_map[element] = elt_ptr;
|
|
return (elt_ptr);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "elt_list"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
add_elt_list(const cxxNameDouble& nd, LDBLE coef)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
cxxNameDouble::const_iterator cit = nd.begin();
|
|
for (; cit != nd.end(); cit++)
|
|
{
|
|
if (count_elts >= (int)elt_list.size())
|
|
{
|
|
elt_list.resize(count_elts + 1);
|
|
}
|
|
elt_list[count_elts].elt = element_store(cit->first.c_str());
|
|
elt_list[count_elts].coef = cit->second * coef;
|
|
count_elts++;
|
|
}
|
|
return (OK);
|
|
}
|
|
int Phreeqc::
|
|
add_elt_list(const std::vector<class elt_list>& el, double coef)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class elt_list* elt_list_ptr = &el[0];
|
|
|
|
for (; elt_list_ptr->elt != NULL; elt_list_ptr++)
|
|
{
|
|
if (count_elts >= elt_list.size())
|
|
{
|
|
elt_list.resize(count_elts + 1);
|
|
}
|
|
elt_list[count_elts].elt = elt_list_ptr->elt;
|
|
elt_list[count_elts].coef = elt_list_ptr->coef * coef;
|
|
count_elts++;
|
|
}
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
change_hydrogen_in_elt_list(LDBLE charge)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
int j;
|
|
int found_h, found_o;
|
|
LDBLE coef_h, coef_o, coef;
|
|
found_h = -1;
|
|
found_o = -1;
|
|
coef_h = 0.0;
|
|
coef_o = 0.0;
|
|
elt_list_combine();
|
|
for (j = 0; j < count_elts; j++)
|
|
{
|
|
if (strcmp(elt_list[j].elt->name, "H") == 0)
|
|
{
|
|
found_h = j;
|
|
coef_h = elt_list[j].coef;
|
|
}
|
|
else if (strcmp(elt_list[j].elt->name, "O") == 0)
|
|
{
|
|
found_o = j;
|
|
coef_o = elt_list[j].coef;
|
|
}
|
|
}
|
|
coef = coef_h - 2 * coef_o - charge;
|
|
if (found_h < 0 && found_o < 0)
|
|
return (OK);
|
|
if (found_h >= 0 && found_o < 0)
|
|
return (OK);
|
|
if (found_h < 0 && found_o >= 0)
|
|
{
|
|
elt_list[count_elts].elt = s_hplus->primary->elt;
|
|
elt_list[count_elts].coef = coef;
|
|
count_elts++;
|
|
elt_list_combine();
|
|
return (OK);
|
|
}
|
|
elt_list[found_h].coef = coef;
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
elt_list_combine(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Function goes through the list of elements pointed to by elt_list
|
|
* and combines the coefficients of elements that are the same.
|
|
* Assumes elt_list has been sorted by element name.
|
|
*/
|
|
{
|
|
int i, j;
|
|
|
|
//if (count_elts < 1)
|
|
//{
|
|
// output_msg("elt_list_combine: How did this happen?\n");
|
|
// return (ERROR);
|
|
//}
|
|
if (count_elts <= 1)
|
|
{
|
|
return (OK);
|
|
}
|
|
qsort(&elt_list[0], count_elts,
|
|
sizeof(class elt_list), Phreeqc::elt_list_compare);
|
|
j = 0;
|
|
for (i = 1; i < count_elts; i++)
|
|
{
|
|
if (elt_list[i].elt == elt_list[j].elt)
|
|
{
|
|
elt_list[j].coef += elt_list[i].coef;
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
if (i != j)
|
|
{
|
|
elt_list[j].elt = elt_list[i].elt;
|
|
elt_list[j].coef = elt_list[i].coef;
|
|
}
|
|
}
|
|
}
|
|
count_elts = j + 1;
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
elt_list_compare(const void* ptr1, const void* ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class elt_list* a, * b;
|
|
|
|
a = (const class elt_list*)ptr1;
|
|
b = (const class elt_list*)ptr2;
|
|
return (strncmp(a->elt->name, b->elt->name, MAX_LENGTH));
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
std::vector<class elt_list> Phreeqc::
|
|
elt_list_internal_copy(const std::vector<class elt_list>& el)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
std::vector<class elt_list> new_elt_list;
|
|
if (el.size() == 0) return new_elt_list;
|
|
const class elt_list* elt_list_ptr = &el[0];
|
|
|
|
new_elt_list.resize(el.size());
|
|
size_t count = 0;
|
|
for (; elt_list_ptr->elt != NULL; elt_list_ptr++)
|
|
{
|
|
new_elt_list[count].elt = element_store(elt_list_ptr->elt->name);
|
|
new_elt_list[count].coef = elt_list_ptr->coef;
|
|
count++;
|
|
}
|
|
new_elt_list[count].elt = NULL;
|
|
return new_elt_list;
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
std::vector<class elt_list> Phreeqc::
|
|
elt_list_vsave(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Takes data from work space elt_list, allocates a new elt_list structure,
|
|
* copies data from work space to new structure, and returns pointer to
|
|
* new structure.
|
|
*/
|
|
size_t j;
|
|
std::vector<class elt_list> new_elt_list;
|
|
/*
|
|
* Sort elements in reaction and combine
|
|
*/
|
|
elt_list_combine();
|
|
/*
|
|
* Malloc space and store element data
|
|
*/
|
|
new_elt_list.resize(count_elts + 1);
|
|
for (j = 0; j < count_elts; j++)
|
|
{
|
|
new_elt_list[j].elt = elt_list[j].elt;
|
|
new_elt_list[j].coef = elt_list[j].coef;
|
|
}
|
|
new_elt_list[count_elts].elt = NULL;
|
|
return new_elt_list;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
cxxNameDouble Phreeqc::
|
|
elt_list_NameDouble(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Takes data from work space elt_list, makes NameDouble
|
|
*/
|
|
cxxNameDouble nd;
|
|
for (int i = 0; i < count_elts; i++)
|
|
{
|
|
nd.add(elt_list[i].elt->name, elt_list[i].coef);
|
|
}
|
|
return (nd);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "inverse"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class inverse * Phreeqc::
|
|
inverse_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Allocates space for a new inverse structure at position count_inverse.
|
|
* Initializes structure.
|
|
* arguments
|
|
* input: none
|
|
* output: pointer to an inverse structure
|
|
* return: OK
|
|
*/
|
|
{
|
|
class inverse *inverse_ptr = NULL;
|
|
inverse.resize(count_inverse + 1);
|
|
inverse_ptr = &(inverse[count_inverse++]);
|
|
/*
|
|
* Initialize variables
|
|
*/
|
|
inverse_ptr->description = NULL;
|
|
inverse_ptr->count_solns = 0;
|
|
/*
|
|
* allocate space for pointers in structure to NULL
|
|
*/
|
|
inverse_ptr->count_solns = 0;
|
|
|
|
return (inverse_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
inverse_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Compare inverse values for n_user
|
|
*/
|
|
const class inverse *nptr1;
|
|
const class inverse *nptr2;
|
|
|
|
nptr1 = (const class inverse *) ptr1;
|
|
nptr2 = (const class inverse *) ptr2;
|
|
if (nptr1->n_user > nptr2->n_user)
|
|
return (1);
|
|
if (nptr1->n_user < nptr2->n_user)
|
|
return (-1);
|
|
return (0);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
inverse_delete(int i)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Deletes inverse i from list (i is not user number),
|
|
* Frees memory allocated to inverse struct
|
|
* Input: i, number of inverse struct to delete
|
|
* Return: OK
|
|
*/
|
|
inverse_free(&(inverse[i]));
|
|
inverse.erase(inverse.begin() + (size_t)i);
|
|
count_inverse--;
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
inverse_free(class inverse *inverse_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Free all memory for an inverse structure.
|
|
*/
|
|
int i;
|
|
|
|
inverse_ptr->description =
|
|
(char *) free_check_null(inverse_ptr->description);
|
|
/* Free solns */
|
|
inverse_ptr->solns.clear();
|
|
|
|
/* Free uncertainties */
|
|
inverse_ptr->uncertainties.clear();
|
|
inverse_ptr->ph_uncertainties.clear();
|
|
|
|
/* Free force_solns */
|
|
inverse_ptr->force_solns.clear();
|
|
|
|
/* Free elts */
|
|
for (i = 0; i < inverse_ptr->elts.size(); i++)
|
|
{
|
|
inverse_ptr->elts[i].uncertainties.clear();
|
|
};
|
|
inverse_ptr->elts.clear();
|
|
|
|
/* Free isotopes */
|
|
for (i = 0; i < inverse_ptr->isotopes.size(); i++)
|
|
{
|
|
inverse_ptr->isotopes[i].uncertainties.clear();
|
|
};
|
|
inverse_ptr->isotopes.clear();
|
|
|
|
for (i = 0; i < inverse_ptr->i_u.size(); i++)
|
|
{
|
|
inverse_ptr->i_u[i].uncertainties.clear();
|
|
};
|
|
inverse_ptr->i_u.clear();
|
|
|
|
/* Free phases */
|
|
for (i = 0; i < inverse_ptr->phases.size(); i++)
|
|
{
|
|
inverse_ptr->phases[i].isotopes.clear();
|
|
}
|
|
inverse_ptr->phases.clear();
|
|
|
|
/* Free carbon derivatives */
|
|
inverse_ptr->dalk_dph.clear();
|
|
inverse_ptr->dalk_dc.clear();
|
|
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
inverse_isotope_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
int i;
|
|
const class inv_isotope *iso_ptr1, *iso_ptr2;
|
|
|
|
iso_ptr1 = (const class inv_isotope *) ptr1;
|
|
iso_ptr2 = (const class inv_isotope *) ptr2;
|
|
i = strcmp_nocase(iso_ptr1->elt_name, iso_ptr2->elt_name);
|
|
if (i != 0)
|
|
return (i);
|
|
if (iso_ptr1->isotope_number < iso_ptr2->isotope_number)
|
|
{
|
|
return (-1);
|
|
}
|
|
else if (iso_ptr1->isotope_number > iso_ptr2->isotope_number)
|
|
{
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class inverse * Phreeqc::
|
|
inverse_search(int n_user, int *n)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/* Linear search of the structure array "inverse" for user number n_user.
|
|
*
|
|
* Arguments:
|
|
* n_user input, user number
|
|
* n output, position in inverse
|
|
*
|
|
* Returns:
|
|
* if found, the address of the inverse element
|
|
* if not found, NULL
|
|
*
|
|
*/
|
|
int i;
|
|
for (i = 0; i < count_inverse; i++)
|
|
{
|
|
if (inverse[i].n_user == n_user)
|
|
{
|
|
*n = i;
|
|
return (&(inverse[i]));
|
|
}
|
|
}
|
|
/*
|
|
* An inverse structure with n_user was not found
|
|
*/
|
|
return (NULL);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
inverse_sort(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Sort array of inverse structures
|
|
*/
|
|
if (count_inverse > 1)
|
|
{
|
|
qsort(&inverse[0], (size_t) count_inverse,
|
|
sizeof(class inverse), inverse_compare);
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "master"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
master_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Allocates space to a master structure and initializes the space.
|
|
* arguments: void
|
|
* return: pointer to a master structure
|
|
*/
|
|
{
|
|
class master *ptr = new class master;
|
|
/*
|
|
* set pointers in structure to NULL
|
|
*/
|
|
ptr->in = FALSE;
|
|
ptr->number = -1;
|
|
ptr->last_model = -1;
|
|
ptr->type = 0;
|
|
ptr->primary = FALSE;
|
|
ptr->coef = 0.0;
|
|
ptr->total = 0.0;
|
|
ptr->isotope_ratio = 0;
|
|
ptr->isotope_ratio_uncertainty = 0;
|
|
ptr->isotope = 0;
|
|
ptr->total_primary = 0;
|
|
ptr->elt = NULL;
|
|
ptr->alk = 0.0;
|
|
ptr->gfw = 0.0;
|
|
ptr->gfw_formula = NULL;
|
|
ptr->unknown = NULL;
|
|
ptr->s = NULL;
|
|
ptr->pe_rxn = NULL;
|
|
ptr->minor_isotope = FALSE;
|
|
return (ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
master_delete(const char* cptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Delete master species: Free memory of master species structure, free
|
|
* the structure, and remove from array master.
|
|
*
|
|
* Input
|
|
* ptr character string with name of element or valence state
|
|
* Returns
|
|
* TRUE if master species was deleted.
|
|
* FALSE if master species was not found.
|
|
*/
|
|
int n;
|
|
|
|
if (master_search(cptr, &n) == NULL)
|
|
return (FALSE);
|
|
master_free(master[n]);
|
|
master.erase(master.begin() + n);
|
|
return (TRUE);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
master_free(class master *master_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Free memory pointed to by master species pointer, master_ptr.
|
|
* Frees master_ptr itself.
|
|
*/
|
|
if (master_ptr == NULL)
|
|
return (ERROR);
|
|
delete master_ptr;
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
master_bsearch(const char* cptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Uses binary search. Assumes master is in sort order.
|
|
* Find master species for string (*cptr) containing name of element or valence state.
|
|
*
|
|
* Input: cptr pointer to string containing element name
|
|
*
|
|
* Return: pointer to master structure containing name cptr or NULL.
|
|
*/
|
|
void *void_ptr;
|
|
if (master.size() == 0)
|
|
{
|
|
return (NULL);
|
|
}
|
|
void_ptr = bsearch((const char *) cptr,
|
|
(char *) &master[0],
|
|
master.size(),
|
|
sizeof(class master *), master_compare_string);
|
|
if (void_ptr == NULL)
|
|
{
|
|
void_ptr = bsearch(cptr,
|
|
(char*)&master[0],
|
|
master.size(),
|
|
sizeof(class master*), master_compare_string);
|
|
}
|
|
if (void_ptr == NULL)
|
|
{
|
|
return (NULL);
|
|
}
|
|
else
|
|
{
|
|
return (*(class master **) void_ptr);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
master_compare_string(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const char *string_ptr;
|
|
const class master *master_ptr;
|
|
|
|
string_ptr = (const char *) ptr1;
|
|
master_ptr = *(const class master **) ptr2;
|
|
return (strcmp_nocase(string_ptr, master_ptr->elt->name));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
master_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class master *master_ptr1, *master_ptr2;
|
|
master_ptr1 = *(const class master **) ptr1;
|
|
master_ptr2 = *(const class master **) ptr2;
|
|
return (strcmp_nocase(master_ptr1->elt->name, master_ptr2->elt->name));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
master_bsearch_primary(const char* cptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Find primary master species for first element in the string, cptr.
|
|
* Uses binary search. Assumes master is in sort order.
|
|
*/
|
|
int l;
|
|
const char* cptr1;
|
|
class master *master_ptr_primary;
|
|
/*
|
|
* Find element name
|
|
*/
|
|
cptr1 = cptr;
|
|
{
|
|
std::string elt;
|
|
get_elt(&cptr1, elt, &l);
|
|
/*
|
|
* Search master species list
|
|
*/
|
|
master_ptr_primary = master_bsearch(elt.c_str());
|
|
}
|
|
if (master_ptr_primary == NULL)
|
|
{
|
|
input_error++;
|
|
error_string = sformatf(
|
|
"Could not find primary master species for %s.", cptr);
|
|
error_msg(error_string, CONTINUE);
|
|
}
|
|
return (master_ptr_primary);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
master_bsearch_secondary(const char* cptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Find secondary master species that corresponds to the primary master species.
|
|
* i.e. S(6) for S.
|
|
*/
|
|
int l;
|
|
const char* cptr1;
|
|
std::string elt;
|
|
class master *master_ptr_primary, *master_ptr=NULL, *master_ptr_secondary=NULL;
|
|
/*
|
|
* Find element name
|
|
*/
|
|
cptr1 = cptr;
|
|
get_elt(&cptr1, elt, &l);
|
|
/*
|
|
* Search master species list
|
|
*/
|
|
master_ptr_primary = master_bsearch(elt.c_str());
|
|
if (master_ptr_primary == NULL)
|
|
{
|
|
input_error++;
|
|
error_string = sformatf(
|
|
"Could not find primary master species for %s.", cptr);
|
|
error_msg(error_string, CONTINUE);
|
|
}
|
|
/*
|
|
* If last in list or not redox
|
|
*/
|
|
if (master_ptr_primary)
|
|
{
|
|
if ((master_ptr_primary->number >= (int)master.size() - 1) ||
|
|
(master[(size_t)master_ptr_primary->number + 1]->elt->primary != master_ptr_primary))
|
|
{
|
|
return(master_ptr_primary);
|
|
}
|
|
/*
|
|
* Find secondary master with same species as primary
|
|
*/
|
|
master_ptr = NULL;
|
|
for (size_t j = master_ptr_primary->number + 1; j < master.size(); j++)
|
|
{
|
|
if (master[j]->s == master_ptr_primary->s)
|
|
{
|
|
master_ptr = master[j];
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
*
|
|
*/
|
|
if (master_ptr != NULL && master_ptr->elt != NULL && (master_ptr->elt->primary == master_ptr_primary))
|
|
{
|
|
master_ptr_secondary = master_ptr;
|
|
}
|
|
else
|
|
{
|
|
input_error++;
|
|
error_string = sformatf(
|
|
"Could not find secondary master species for %s.", cptr);
|
|
error_msg(error_string, STOP);
|
|
}
|
|
|
|
|
|
return (master_ptr_secondary);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
master_search(const char* cptr, int *n)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Linear search of master to find master species in string, cptr.
|
|
* Returns pointer if found. n contains position in array master.
|
|
* Returns NULL if not found.
|
|
*/
|
|
int i;
|
|
class master *master_ptr;
|
|
/*
|
|
* Search master species list
|
|
*/
|
|
*n = -999;
|
|
for (i = 0; i < (int)master.size(); i++)
|
|
{
|
|
if (strcmp(cptr, master[i]->elt->name) == 0)
|
|
{
|
|
*n = i;
|
|
master_ptr = master[i];
|
|
return (master_ptr);
|
|
}
|
|
}
|
|
return (NULL);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "phases"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class phase * Phreeqc::
|
|
phase_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Allocates space to a phase structure and initializes
|
|
* arguments: void
|
|
* return: pointer to new phase structure
|
|
*/
|
|
class phase *phase_ptr;
|
|
/*
|
|
* Allocate space
|
|
*/
|
|
phase_ptr = new class phase;
|
|
/*
|
|
* Initialize space
|
|
*/
|
|
phase_init(phase_ptr);
|
|
return (phase_ptr);
|
|
}
|
|
#ifdef OBSOLETE
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
phase_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Compares names of phases for sort
|
|
*/
|
|
const class phase *phase_ptr1, *phase_ptr2;
|
|
phase_ptr1 = *(const class phase **) ptr1;
|
|
phase_ptr2 = *(const class phase **) ptr2;
|
|
return (strcmp_nocase(phase_ptr1->name, phase_ptr2->name));
|
|
}
|
|
#endif
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
phase_compare_string(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const char *char_ptr;
|
|
const class phase *phase_ptr;
|
|
char_ptr = (const char *) ptr1;
|
|
phase_ptr = *(const class phase **) ptr2;
|
|
return (strcmp_nocase(char_ptr, phase_ptr->name));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
phase_delete(int i)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Deletes phase i from list, phases
|
|
* Frees memory allocated to phase[i] and renumbers phases to remove number i.
|
|
* Input: i, number of phase
|
|
* Return: OK
|
|
*/
|
|
phase_free(phases[i]);
|
|
phases.erase(phases.begin() + (size_t)i);
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
phase_free(class phase *phase_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Frees memory allocated within phase[i], does not free phase structure
|
|
* Input: i, number of phase
|
|
* Return: OK
|
|
*/
|
|
if (phase_ptr == NULL)
|
|
return (ERROR);
|
|
phase_ptr->next_elt.clear();
|
|
phase_ptr->next_sys_total.clear();;
|
|
phase_ptr->add_logk.clear();
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class phase * Phreeqc::
|
|
phase_bsearch(const char* cptr, int *j, int print)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/* Binary search the structure array "phases" for a name that is equal to
|
|
* cptr. Assumes array phases is in sort order.
|
|
*
|
|
* Arguments:
|
|
* name input, a character string to be located in phases.
|
|
* j index number in array phases.
|
|
*
|
|
* Returns:
|
|
* if found, pointer to phase structure.
|
|
* if not found, NULL
|
|
*
|
|
*/
|
|
void *void_ptr;
|
|
|
|
void_ptr = NULL;
|
|
if ((int)phases.size() > 0)
|
|
{
|
|
void_ptr = (void *)
|
|
bsearch((char *) cptr,
|
|
(char *) &phases[0],
|
|
phases.size(),
|
|
sizeof(class phase *), phase_compare_string);
|
|
}
|
|
if (void_ptr == NULL && print == TRUE)
|
|
{
|
|
error_string = sformatf( "Could not find phase in list, %s.", cptr);
|
|
error_msg(error_string, CONTINUE);
|
|
}
|
|
|
|
if (void_ptr == NULL)
|
|
{
|
|
*j = -1;
|
|
return (NULL);
|
|
}
|
|
|
|
*j = (int) ((class phase **) void_ptr - &phases[0]);
|
|
return (*(class phase **) void_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
phase_init(class phase *phase_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* set pointers in phase structure to NULL
|
|
*/
|
|
{
|
|
int i;
|
|
|
|
phase_ptr->name = NULL;
|
|
phase_ptr->formula = NULL;
|
|
phase_ptr->in = FALSE;
|
|
phase_ptr->lk = 0.0;
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
phase_ptr->logk[i] = 0.0;
|
|
phase_ptr->original_units = kjoules;
|
|
phase_ptr->add_logk.clear();
|
|
phase_ptr->moles_x = 0;
|
|
phase_ptr->delta_max = 0;
|
|
phase_ptr->p_soln_x = 0;
|
|
phase_ptr->fraction_x = 0;
|
|
phase_ptr->log10_lambda = 0;
|
|
phase_ptr->log10_fraction_x = 0;
|
|
phase_ptr->dn = 0;
|
|
phase_ptr->dnb = 0;
|
|
phase_ptr->dnc = 0;
|
|
phase_ptr->gn = 0;
|
|
phase_ptr->gntot = 0;
|
|
phase_ptr->t_c = 0.0;
|
|
phase_ptr->p_c = 0.0;
|
|
phase_ptr->omega = 0.0;
|
|
phase_ptr->pr_a = 0.0;
|
|
phase_ptr->pr_b = 0.0;
|
|
phase_ptr->pr_alpha = 0.0;
|
|
phase_ptr->pr_tk = 0;
|
|
phase_ptr->pr_p = 0;
|
|
phase_ptr->pr_phi = 1.0;
|
|
phase_ptr->pr_aa_sum2 = 0;
|
|
for (i = 0; i < 9; i++)
|
|
phase_ptr->delta_v[i] = 0.0;
|
|
phase_ptr->pr_si_f = 0;
|
|
phase_ptr->pr_in = false;
|
|
phase_ptr->type = SOLID;
|
|
phase_ptr->check_equation = TRUE;
|
|
phase_ptr->replaced = 0;
|
|
phase_ptr->in_system = 1;
|
|
phase_ptr->original_deltav_units = cm3_per_mol;
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class phase * Phreeqc::
|
|
phase_store(const char *name_in)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "name" in the map for phases.
|
|
*
|
|
* If found, pointer to the appropriate phase structure is returned.
|
|
*
|
|
* If the string is not found, a new entry is made at the end of
|
|
* the phases array (position count_phases), it is added to the map,
|
|
* and the new structure is returned.
|
|
*
|
|
* Arguments:
|
|
* name input, character string to be located or stored.
|
|
*
|
|
* Returns:
|
|
* The address of a phase structure that contains the phase data.
|
|
* If phase existed, it is reinitialized. The structure returned
|
|
* contains only the name of the phase.
|
|
*/
|
|
class phase *phase_ptr = NULL;
|
|
/*
|
|
* Search list
|
|
*/
|
|
std::string name = name_in;
|
|
str_tolower(name);
|
|
std::map<std::string, class phase*>::iterator p_it =
|
|
phases_map.find(name);
|
|
if (p_it != phases_map.end())
|
|
{
|
|
phase_ptr = p_it->second;
|
|
phase_free(phase_ptr);
|
|
phase_init(phase_ptr);
|
|
phase_ptr->name = string_hsave(name_in);
|
|
return (phase_ptr);
|
|
}
|
|
/*
|
|
* Make new phase structure and return pointer to it
|
|
*/
|
|
size_t n = phases.size();
|
|
phases.resize(n + 1);
|
|
phases[n] = phase_alloc();
|
|
/* set name in phase structure */
|
|
phases[n]->name = string_hsave(name_in);
|
|
/*
|
|
* Update map
|
|
*/
|
|
phases_map[name] = phases[n];
|
|
return (phases[n]);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "rates"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class rate * Phreeqc::
|
|
rate_bsearch(const char* cptr, int *j)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/* Binary search the structure array "rates" for a name that is equal to
|
|
* cptr. Assumes array rates is in sort order.
|
|
*
|
|
* Arguments:
|
|
* name input, a character string to be located in rates.
|
|
* j index number in array rates.
|
|
*
|
|
* Returns:
|
|
* if found, pointer to rate structure.
|
|
* if not found, NULL
|
|
*
|
|
*/
|
|
void *void_ptr;
|
|
|
|
if (rates.size() == 0)
|
|
{
|
|
*j = -1;
|
|
return (NULL);
|
|
}
|
|
void_ptr = (void *)
|
|
bsearch((char *) cptr,
|
|
(char *) &rates[0],
|
|
rates.size(),
|
|
sizeof(class rate *), rate_compare_string);
|
|
|
|
if (void_ptr == NULL)
|
|
{
|
|
*j = -1;
|
|
return (NULL);
|
|
}
|
|
|
|
*j = (int) ((class rate *) void_ptr - &rates[0]);
|
|
return ((class rate *) void_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
rate_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Compares names of rates for sort
|
|
*/
|
|
const class rate *rate_ptr1, *rate_ptr2;
|
|
rate_ptr1 = *(const class rate **) ptr1;
|
|
rate_ptr2 = *(const class rate **) ptr2;
|
|
return (strcmp_nocase(rate_ptr1->name, rate_ptr2->name));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
rate_compare_string(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const char *char_ptr;
|
|
const class rate *rate_ptr;
|
|
char_ptr = (const char *) ptr1;
|
|
rate_ptr = *(const class rate **) ptr2;
|
|
return (strcmp_nocase(char_ptr, rate_ptr->name));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
rate_free(class rate *rate_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Frees memory allocated within rate[i], does not free rate structure
|
|
* Input: i, number of rate
|
|
* Return: OK
|
|
*/
|
|
|
|
|
|
if (rate_ptr == NULL)
|
|
return (ERROR);
|
|
rate_ptr->commands.clear();
|
|
if (rate_ptr->linebase != NULL)
|
|
{
|
|
char cmd[] = "new; quit";
|
|
basic_run(cmd, rate_ptr->linebase, rate_ptr->varbase, rate_ptr->loopbase);
|
|
rate_ptr->linebase = NULL;
|
|
rate_ptr->varbase = NULL;
|
|
rate_ptr->loopbase = NULL;
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class rate * Phreeqc::
|
|
rate_copy(const class rate *rate_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Copies a rate to new allocated space
|
|
*/
|
|
if (rate_ptr == NULL)
|
|
return (NULL);
|
|
class rate* rate_new = new class rate;
|
|
rate_new->name = string_hsave(rate_ptr->name);
|
|
rate_new->commands = rate_ptr->commands;
|
|
rate_new->new_def = TRUE;
|
|
rate_new->linebase = NULL;
|
|
rate_new->varbase = NULL;
|
|
rate_new->loopbase = NULL;
|
|
return (rate_new);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class rate * Phreeqc::
|
|
rate_search(const char *name_in, int *n)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/* Linear search of the structure array "rates" for name.
|
|
*
|
|
* Arguments:
|
|
* name input, name of rate
|
|
* n output, position in rates
|
|
*
|
|
* Returns:
|
|
* if found, the address of the pp_assemblage element
|
|
* if not found, NULL
|
|
*/
|
|
std::map<const char *, int>::iterator it;
|
|
|
|
const char * name;
|
|
name = string_hsave(name_in);
|
|
|
|
it = rates_map.find(name);
|
|
if (it != rates_map.end())
|
|
{
|
|
*n = it->second;
|
|
if (*n >= 0)
|
|
{
|
|
return &(rates[it->second]);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int i;
|
|
*n = -1;
|
|
for (i = 0; i < (int)rates.size(); i++)
|
|
{
|
|
if (strcmp_nocase(rates[i].name, name) == 0)
|
|
{
|
|
*n = i;
|
|
rates_map[name] = i;
|
|
return (&(rates[i]));
|
|
}
|
|
}
|
|
/*
|
|
* rate name not found
|
|
*/
|
|
rates_map[name] = *n;
|
|
return (NULL);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
rate_sort(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Sort array of rate structures
|
|
*/
|
|
if (rates.size() > 1)
|
|
{
|
|
qsort(&rates[0], rates.size(), sizeof(class rate),
|
|
rate_compare);
|
|
}
|
|
return (OK);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "species"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class species * Phreeqc::
|
|
s_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Allocates space to a species structure, initializes
|
|
* arguments: void
|
|
* return: pointer to a species structure
|
|
*/
|
|
{
|
|
class species *s_ptr;
|
|
s_ptr = new class species;
|
|
/*
|
|
* set pointers in structure to NULL, variables to zero
|
|
*/
|
|
s_init(s_ptr);
|
|
|
|
return (s_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
s_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class species *s_ptr1, *s_ptr2;
|
|
s_ptr1 = *(const class species **) ptr1;
|
|
s_ptr2 = *(const class species **) ptr2;
|
|
return (strcmp(s_ptr1->name, s_ptr2->name));
|
|
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
s_delete(int i)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Delete species i: free memory and renumber array of pointers, s.
|
|
*/
|
|
s_free(s[i]);
|
|
s[i] = (class species *) free_check_null(s[i]);
|
|
s.erase(s.begin() + i);
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
s_free(class species *s_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Free space allocated for species structure, s_ptr. Does not free s_ptr.
|
|
*/
|
|
if (s_ptr == NULL)
|
|
return (ERROR);
|
|
s_ptr->next_elt.clear();
|
|
s_ptr->next_secondary.clear();
|
|
s_ptr->next_sys_total.clear();
|
|
s_ptr->add_logk.clear();
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
s_init(class species *s_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* return: pointer to a species structure
|
|
*/
|
|
{
|
|
int i;
|
|
/*
|
|
* set pointers in structure to NULL
|
|
*/
|
|
s_ptr->name = NULL;
|
|
s_ptr->mole_balance = NULL;
|
|
s_ptr->in = FALSE;
|
|
s_ptr->number = 0;
|
|
s_ptr->primary = NULL;
|
|
s_ptr->secondary = NULL;
|
|
s_ptr->gfw = 0.0;
|
|
s_ptr->z = 0.0;
|
|
s_ptr->dw = 0.0;
|
|
s_ptr->dw_t = 0.0;
|
|
s_ptr->dw_a = 0.0;
|
|
s_ptr->dw_a2 = 0.0;
|
|
s_ptr->dw_a3 = 0.0;
|
|
s_ptr->erm_ddl = 1.0;
|
|
s_ptr->equiv = 0;
|
|
s_ptr->alk = 0.0;
|
|
s_ptr->carbon = 0.0;
|
|
s_ptr->co2 = 0.0;
|
|
s_ptr->h = 0.0;
|
|
s_ptr->o = 0.0;
|
|
s_ptr->dha = 0.0;
|
|
s_ptr->dhb = 0.0;
|
|
s_ptr->a_f = 0.0;
|
|
s_ptr->lk = 0.0;
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
s_ptr->logk[i] = 0.0;
|
|
}
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
s_ptr->Jones_Dole[i] = 0.0;
|
|
}
|
|
/* VP: Density Start */
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
s_ptr->millero[i] = 0.0;
|
|
}
|
|
/* VP: Density End */
|
|
s_ptr->original_units = kjoules;
|
|
s_ptr->add_logk.clear();
|
|
s_ptr->lg = 0.0;
|
|
s_ptr->lg_pitzer = 0.0;
|
|
s_ptr->lm = 0.0;
|
|
s_ptr->la = 0.0;
|
|
s_ptr->dg = 0.0;
|
|
s_ptr->dg_total_g = 0;
|
|
s_ptr->moles = 0.0;
|
|
s_ptr->type = 0;
|
|
s_ptr->gflag = 0;
|
|
s_ptr->exch_gflag = 0;
|
|
s_ptr->check_equation = TRUE;
|
|
s_ptr->tot_g_moles = 0;
|
|
s_ptr->tot_dh2o_moles = 0;
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
s_ptr->cd_music[i] = 0.0;
|
|
}
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
s_ptr->dz[i] = 0.0;
|
|
}
|
|
s_ptr->original_deltav_units = cm3_per_mol;
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
class species* Phreeqc::
|
|
s_search(const char* name)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "name" in the species_map.
|
|
*
|
|
* Arguments:
|
|
* name input, a character string to be located in species.
|
|
*
|
|
* Returns:
|
|
* If found, pointer to the appropriate species structure is returned.
|
|
* else, NULL pointer is returned.
|
|
*/
|
|
class species* s_ptr = NULL;
|
|
std::map<std::string, class species*>::iterator s_it =
|
|
species_map.find(name);
|
|
if (s_it != species_map.end())
|
|
{
|
|
s_ptr = s_it->second;
|
|
}
|
|
return (s_ptr);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
class species * Phreeqc::
|
|
s_store(const char *name, LDBLE l_z, int replace_if_found)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "name" in the map for species.
|
|
*
|
|
* Pointer to a species structure is always returned.
|
|
*
|
|
* If the string is not found, a new entry is made at the end of
|
|
* the elements array (position count_elements) and count_elements is
|
|
* incremented. A new entry is made in the map. Pointer to
|
|
* the new structure is returned.
|
|
* If "name" is found and replace is true, pointers in old species structure
|
|
* are freed and replaced with additional input.
|
|
* If "name" is found and replace is false, the old species structure is not
|
|
* modified and a pointer to it is returned.
|
|
*
|
|
* Arguments:
|
|
* name input, character string to be found in "species".
|
|
* l_z input, charge on "name"
|
|
* replace_if_found input, TRUE means reinitialize species if found
|
|
* FALSE means just return pointer if found.
|
|
*
|
|
* Returns:
|
|
* pointer to species structure "s" where "name" can be found.
|
|
*/
|
|
|
|
/*
|
|
* Search list
|
|
*/
|
|
class species* s_ptr = NULL;
|
|
s_ptr = s_search(name);
|
|
if (s_ptr != NULL && replace_if_found == FALSE)
|
|
{
|
|
return (s_ptr);
|
|
}
|
|
else if (s_ptr != NULL && replace_if_found == TRUE)
|
|
{
|
|
s_free(s_ptr);
|
|
s_init(s_ptr);
|
|
}
|
|
else
|
|
{
|
|
size_t n = s.size();
|
|
s.resize(n + 1);
|
|
/* Make new species structure */
|
|
s[n] = s_alloc();
|
|
s_ptr = s[n];
|
|
}
|
|
/* set name and z in pointer in species structure */
|
|
s_ptr->name = string_hsave(name);
|
|
s_ptr->z = l_z;
|
|
/*
|
|
* Update map
|
|
*/
|
|
species_map[name] = s_ptr;
|
|
return (s_ptr);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
isotope_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
int i;
|
|
const class isotope *iso_ptr1, *iso_ptr2;
|
|
|
|
iso_ptr1 = (const class isotope *) ptr1;
|
|
iso_ptr2 = (const class isotope *) ptr2;
|
|
i = strcmp_nocase(iso_ptr1->elt_name, iso_ptr2->elt_name);
|
|
if (i != 0)
|
|
return (i);
|
|
if (iso_ptr1->isotope_number < iso_ptr2->isotope_number)
|
|
{
|
|
return (-1);
|
|
}
|
|
else if (iso_ptr1->isotope_number > iso_ptr2->isotope_number)
|
|
{
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "species_list"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
species_list_compare(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
int j;
|
|
const char *name1, *name2;
|
|
const class species_list *nptr1, *nptr2;
|
|
|
|
nptr1 = (const class species_list *) ptr1;
|
|
nptr2 = (const class species_list *) ptr2;
|
|
|
|
/*
|
|
* Put H+ first
|
|
*/
|
|
if (nptr1->master_s != nptr2->master_s)
|
|
{
|
|
/*
|
|
if (nptr1->master_s == s_hplus)
|
|
return (-1);
|
|
if (nptr2->master_s == s_hplus)
|
|
return (1);
|
|
*/
|
|
if ((strcmp(nptr1->master_s->name,"H+") == 0) || (strcmp(nptr1->master_s->name,"H3O+") == 0))
|
|
return (-1);
|
|
if ((strcmp(nptr2->master_s->name,"H+") == 0) || (strcmp(nptr2->master_s->name,"H3O+") == 0))
|
|
return (1);
|
|
}
|
|
/*
|
|
* Other element valence states
|
|
*/
|
|
if (nptr1->master_s->secondary != NULL)
|
|
{
|
|
name1 = nptr1->master_s->secondary->elt->name;
|
|
}
|
|
else
|
|
{
|
|
name1 = nptr1->master_s->primary->elt->name;
|
|
}
|
|
if (nptr2->master_s->secondary != NULL)
|
|
{
|
|
name2 = nptr2->master_s->secondary->elt->name;
|
|
}
|
|
else
|
|
{
|
|
name2 = nptr2->master_s->primary->elt->name;
|
|
}
|
|
/*
|
|
* Compare name of primary or secondary master species; log molality
|
|
*/
|
|
|
|
j = strcmp(name1, name2);
|
|
|
|
/*
|
|
* Different master species
|
|
*/
|
|
if (j != 0)
|
|
return (j);
|
|
|
|
/*
|
|
* Else, descending order by log molality
|
|
*/
|
|
if (nptr1->s->lm > nptr2->s->lm)
|
|
{
|
|
return (-1);
|
|
}
|
|
else if (nptr1->s->lm < nptr2->s->lm)
|
|
{
|
|
return (1);
|
|
}
|
|
else
|
|
{
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
species_list_compare_alk(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class species_list *nptr1, *nptr2;
|
|
LDBLE alk1, alk2;
|
|
|
|
nptr1 = (const class species_list *) ptr1;
|
|
nptr2 = (const class species_list *) ptr2;
|
|
/*
|
|
* Else, descending order by log molality
|
|
*/
|
|
alk1 = fabs(under(nptr1->s->lm) * nptr1->s->alk);
|
|
alk2 = fabs(under(nptr2->s->lm) * nptr2->s->alk);
|
|
|
|
if (alk1 > alk2)
|
|
{
|
|
return (-1);
|
|
}
|
|
else if (alk1 < alk2)
|
|
{
|
|
return (1);
|
|
}
|
|
else
|
|
{
|
|
return (0);
|
|
}
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
species_list_compare_master(const void *ptr1, const void *ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const char *name1, *name2;
|
|
const class species_list *nptr1, *nptr2;
|
|
|
|
nptr1 = (const class species_list *) ptr1;
|
|
nptr2 = (const class species_list *) ptr2;
|
|
|
|
/*
|
|
* Put H+ first
|
|
*/
|
|
if (nptr1->master_s != nptr2->master_s)
|
|
{
|
|
/*
|
|
if (nptr1->master_s == s_hplus)
|
|
return (-1);
|
|
if (nptr2->master_s == s_hplus)
|
|
return (1);
|
|
*/
|
|
if ((strcmp(nptr1->master_s->name,"H+") == 0) || (strcmp(nptr1->master_s->name,"H3O+") == 0))
|
|
return (-1);
|
|
if ((strcmp(nptr2->master_s->name,"H+") == 0) || (strcmp(nptr2->master_s->name,"H3O+") == 0))
|
|
return (1);
|
|
}
|
|
/*
|
|
* Other element valence states
|
|
*/
|
|
if (nptr1->master_s->secondary != NULL)
|
|
{
|
|
name1 = nptr1->master_s->secondary->elt->name;
|
|
}
|
|
else
|
|
{
|
|
name1 = nptr1->master_s->primary->elt->name;
|
|
}
|
|
if (nptr2->master_s->secondary != NULL)
|
|
{
|
|
name2 = nptr2->master_s->secondary->elt->name;
|
|
}
|
|
else
|
|
{
|
|
name2 = nptr2->master_s->primary->elt->name;
|
|
}
|
|
/*
|
|
* Compare name of primary or secondary master species; log molality
|
|
*/
|
|
|
|
return (strcmp(name1, name2));
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
species_list_sort(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Sort list using rules in species_list_compare
|
|
*/
|
|
if (species_list.size() > 1)
|
|
{
|
|
qsort(&species_list[0], species_list.size(),
|
|
sizeof(class species_list), species_list_compare);
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "surface"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
struct Change_Surf * Phreeqc::
|
|
change_surf_alloc(int count)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
if (count == 1)
|
|
return (change_surf);
|
|
change_surf =
|
|
(struct Change_Surf *) PHRQ_realloc(change_surf,
|
|
(size_t) count *
|
|
sizeof(struct Change_Surf));
|
|
if (change_surf == NULL)
|
|
malloc_error();
|
|
change_surf[count - 1].cell_no = -99;
|
|
change_surf[count - 1].next = FALSE;
|
|
change_surf[count - 2].next = TRUE;
|
|
|
|
return (change_surf);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
class master * Phreeqc::
|
|
surface_get_psi_master(const char *name, int plane)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
class master *master_ptr;
|
|
std::string token;
|
|
|
|
if (name == NULL)
|
|
return (NULL);
|
|
token = name;
|
|
token.append("_psi");
|
|
switch (plane)
|
|
{
|
|
case SURF_PSI:
|
|
break;
|
|
case SURF_PSI1:
|
|
token.append("b");
|
|
break;
|
|
case SURF_PSI2:
|
|
token.append("d");
|
|
break;
|
|
default:
|
|
error_msg("Unknown plane for surface_get_psi_master", STOP);
|
|
}
|
|
master_ptr = master_bsearch(token.c_str());
|
|
return (master_ptr);
|
|
}
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "trxn"
|
|
*
|
|
* ********************************************************************** */
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
bool Phreeqc::
|
|
phase_rxn_to_trxn(class phase* phase_ptr, CReaction& rxn_ref)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Copy reaction from reaction structure to
|
|
* temp reaction structure.
|
|
*/
|
|
int l;
|
|
const char* cptr;
|
|
LDBLE l_z;
|
|
trxn.token.resize(rxn_ref.size());
|
|
trxn.token[0].name = phase_ptr->formula;
|
|
/* charge */
|
|
cptr = phase_ptr->formula;
|
|
{
|
|
std::string token;
|
|
get_token(&cptr, token, &l_z, &l);
|
|
}
|
|
trxn.token[0].z = l_z;
|
|
trxn.token[0].s = NULL;
|
|
trxn.token[0].unknown = NULL;
|
|
/*trxn.token[0].coef = -1.0; */
|
|
/* check for leading coefficient of 1.0 for phase did not work */
|
|
trxn.token[0].coef = phase_ptr->rxn.token[0].coef;
|
|
for (size_t i = 1; rxn_ref.token[i].s != NULL; i++)
|
|
{
|
|
trxn.token[i].name = rxn_ref.token[i].s->name;
|
|
trxn.token[i].z = rxn_ref.token[i].s->z;
|
|
trxn.token[i].s = NULL;
|
|
trxn.token[i].unknown = NULL;
|
|
trxn.token[i].coef = rxn_ref.token[i].coef;
|
|
count_trxn = i + 1;
|
|
}
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
bool Phreeqc::
|
|
trxn_add(CReaction& r_ref, double coef, bool combine)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Adds reactions together.
|
|
*
|
|
* Global variable count_trxn determines which position in trxn is used.
|
|
* If count_trxn=0, then the equation effectively is copied into trxn.
|
|
* If count_trxn>0, then new equation is added to existing equation.
|
|
*
|
|
* Arguments:
|
|
* *r_ptr points to rxn structure to add.
|
|
*
|
|
* coef added equation is multiplied by coef.
|
|
* combine if TRUE, reaction is reaction is sorted and
|
|
* like terms combined.
|
|
*/
|
|
/*
|
|
* Accumulate log k for reaction
|
|
*/
|
|
if (count_trxn == 0)
|
|
{
|
|
for (int i = 0; i < MAX_LOG_K_INDICES; i++) trxn.logk[i] = r_ref.Get_logk()[i];
|
|
for (int i = 0; i < 3; i++) trxn.dz[i] = r_ref.Get_dz()[i];
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < MAX_LOG_K_INDICES; i++) trxn.logk[i] += coef * r_ref.Get_logk()[i];
|
|
for (int i = 0; i < 3; i++) trxn.dz[i] += coef * r_ref.Get_dz()[i];
|
|
}
|
|
/*
|
|
* Copy equation into work space
|
|
*/
|
|
class rxn_token* next_token = &r_ref.token[0];
|
|
while (next_token->s != NULL)
|
|
{
|
|
if (count_trxn + 1 > trxn.token.size())
|
|
trxn.token.resize(count_trxn + 1);
|
|
trxn.token[count_trxn].name = next_token->s->name;
|
|
trxn.token[count_trxn].s = next_token->s;
|
|
trxn.token[count_trxn].coef = coef * next_token->coef;
|
|
count_trxn++;
|
|
next_token++;
|
|
}
|
|
if (combine == TRUE)
|
|
trxn_combine();
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
bool Phreeqc::
|
|
trxn_add_phase(CReaction& r_ref, double coef, bool combine)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Adds reactions together.
|
|
*
|
|
* Global variable count_trxn determines which position in trxn is used.
|
|
* If count_trxn=0, then the equation effectively is copied into trxn.
|
|
* If count_trxn>0, then new equation is added to existing equation.
|
|
*
|
|
* Arguments:
|
|
* *r_ptr points to rxn structure to add.
|
|
*
|
|
* coef added equation is multiplied by coef.
|
|
* combine if TRUE, reaction is reaction is sorted and
|
|
* like terms combined.
|
|
*/
|
|
int i;
|
|
class rxn_token* next_token;
|
|
/*
|
|
* Accumulate log k for reaction
|
|
*/
|
|
if (count_trxn == 0)
|
|
{
|
|
memcpy((void*)trxn.logk, (void*)r_ref.Get_logk(),
|
|
(size_t)MAX_LOG_K_INDICES * sizeof(double));
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++) trxn.logk[i] += coef * r_ref.Get_logk()[i];
|
|
}
|
|
/*
|
|
* Copy equation into work space
|
|
*/
|
|
next_token = &r_ref.token[0];
|
|
while (next_token->s != NULL || next_token->name != NULL)
|
|
{
|
|
if (count_trxn + 1 > trxn.token.size())
|
|
trxn.token.resize(count_trxn + 1);
|
|
if (next_token->s != NULL)
|
|
{
|
|
trxn.token[count_trxn].name = next_token->s->name;
|
|
trxn.token[count_trxn].s = next_token->s;
|
|
}
|
|
else
|
|
{
|
|
trxn.token[count_trxn].name = next_token->name;
|
|
trxn.token[count_trxn].s = NULL;
|
|
}
|
|
trxn.token[count_trxn].coef = coef * next_token->coef;
|
|
count_trxn++;
|
|
next_token++;
|
|
}
|
|
if (combine)
|
|
trxn_combine();
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_combine(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Combines coefficients of tokens that are equal in temporary
|
|
* reaction structure, trxn.
|
|
*/
|
|
int j, k;
|
|
/*
|
|
* Sort trxn species
|
|
*/
|
|
trxn_sort();
|
|
/*
|
|
* Combine trxn tokens
|
|
*/
|
|
j = 1;
|
|
for (k = 2; k < count_trxn; k++)
|
|
{
|
|
if (trxn.token[k].s != NULL)
|
|
{
|
|
if ((j > 0) && (trxn.token[k].s == trxn.token[j].s))
|
|
{
|
|
trxn.token[j].coef += trxn.token[k].coef;
|
|
if (equal(trxn.token[j].coef, 0.0, 1e-5))
|
|
j--;
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
if (k != j)
|
|
{
|
|
trxn.token[j].name = trxn.token[k].name;
|
|
trxn.token[j].s = trxn.token[k].s;
|
|
trxn.token[j].coef = trxn.token[k].coef;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((j > 0) && (trxn.token[k].s == trxn.token[j].s)
|
|
&& (trxn.token[k].name == trxn.token[j].name))
|
|
{
|
|
trxn.token[j].coef += trxn.token[k].coef;
|
|
if (equal(trxn.token[j].coef, 0.0, 1e-5))
|
|
j--;
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
if (k != j)
|
|
{
|
|
trxn.token[j].name = trxn.token[k].name;
|
|
trxn.token[j].s = trxn.token[k].s;
|
|
trxn.token[j].coef = trxn.token[k].coef;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
count_trxn = j + 1; /* number excluding final NULL */
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_compare(const void* ptr1, const void* ptr2)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
const class rxn_token_temp* rxn_token_temp_ptr1, * rxn_token_temp_ptr2;
|
|
rxn_token_temp_ptr1 = (const class rxn_token_temp*)ptr1;
|
|
rxn_token_temp_ptr2 = (const class rxn_token_temp*)ptr2;
|
|
return (strcmp(rxn_token_temp_ptr1->name, rxn_token_temp_ptr2->name));
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
bool Phreeqc::
|
|
trxn_copy(CReaction& rxn_ref)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Copies trxn to a reaction structure.
|
|
*
|
|
* Input: rxn_ptr, pointer to reaction structure to copy trxn to.
|
|
*
|
|
*/
|
|
int i;
|
|
/*
|
|
* Copy logk data
|
|
*/
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
rxn_ref.logk[i] = trxn.logk[i];
|
|
}
|
|
/*
|
|
* Copy dz data
|
|
*/
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
rxn_ref.dz[i] = trxn.dz[i];
|
|
}
|
|
/*
|
|
* Copy tokens
|
|
*/
|
|
rxn_ref.Get_tokens().resize(count_trxn + 1);
|
|
for (size_t i = 0; i < count_trxn; i++)
|
|
{
|
|
rxn_ref.Get_tokens()[i].s = trxn.token[i].s;
|
|
rxn_ref.Get_tokens()[i].name = trxn.token[i].name;
|
|
rxn_ref.Get_tokens()[i].coef = trxn.token[i].coef;
|
|
}
|
|
rxn_ref.token[count_trxn].s = NULL;
|
|
rxn_ref.token[count_trxn].name = NULL;
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
LDBLE Phreeqc::
|
|
trxn_find_coef(const char *str, int start)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Finds coefficient of specified token in trxn.
|
|
* Input: str, token name in reaction.
|
|
*
|
|
* Return: 0.0, if token not found.
|
|
* coefficient of token, if token found.
|
|
*/
|
|
int i;
|
|
LDBLE coef;
|
|
|
|
coef = 0.0;
|
|
for (i = start; i < count_trxn; i++)
|
|
{
|
|
if (strcmp(trxn.token[i].s->name, str) == 0)
|
|
{
|
|
coef = trxn.token[i].coef;
|
|
break;
|
|
}
|
|
}
|
|
return (coef);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_multiply(LDBLE coef)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Multiplies temporary reaction, trxn, by a constant
|
|
*
|
|
* Arguments:
|
|
* input: coef multiplier.
|
|
*/
|
|
int i;
|
|
/*
|
|
* Multiply log k for reaction
|
|
*/
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
trxn.logk[i] *= coef;
|
|
}
|
|
/*
|
|
* Multiply dz for reaction
|
|
*/
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
trxn.dz[i] *= coef;
|
|
}
|
|
/*
|
|
* Multiply coefficients of reaction
|
|
*/
|
|
for (i = 0; i < count_trxn; i++)
|
|
{
|
|
trxn.token[i].coef *= coef;
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_print(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Prints trxn
|
|
*/
|
|
int i;
|
|
/*
|
|
* Print log k for reaction
|
|
*/
|
|
|
|
output_msg(sformatf( "\tlog k data:\n"));
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
output_msg(sformatf( "\t\t%f\n", (double) trxn.logk[i]));
|
|
}
|
|
|
|
/*
|
|
* Print dz for reaction
|
|
*/
|
|
output_msg(sformatf( "\tdz data:\n"));
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
output_msg(sformatf( "\t\t%f\n", (double) trxn.dz[i]));
|
|
}
|
|
/*
|
|
* Print stoichiometry
|
|
*/
|
|
output_msg(sformatf( "\tReaction stoichiometry\n"));
|
|
for (i = 0; i < count_trxn; i++)
|
|
{
|
|
output_msg(sformatf( "\t\t%-20s\t%10.2f\n", trxn.token[i].name,
|
|
(double) trxn.token[i].coef));
|
|
}
|
|
output_msg(sformatf( "\n"));
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_reverse_k(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Changes K from dissociation to association and back
|
|
*/
|
|
int i;
|
|
/*
|
|
* Accumulate log k for reaction
|
|
*/
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
trxn.logk[i] = -trxn.logk[i];
|
|
}
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
trxn.dz[i] = -trxn.dz[i];
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_sort(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Compare names in tokens in trxn array for sorting
|
|
*/
|
|
if (count_trxn - 1 > 1)
|
|
{
|
|
qsort(&trxn.token[1],
|
|
(size_t)count_trxn - 1,
|
|
sizeof(class rxn_token_temp),
|
|
trxn_compare);
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
trxn_swap(const char *token)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Moves specified token to initial position in reaction.
|
|
* Input: token, token name to move to initial position.
|
|
*
|
|
* Return: ERROR, if token not found.
|
|
* OK, if token moved to initial position.
|
|
*/
|
|
int i, j;
|
|
LDBLE coef;
|
|
/*
|
|
* Locate token
|
|
*/
|
|
for (j = 0; j < count_trxn; j++)
|
|
{
|
|
if (strcmp(trxn.token[j].s->name, token) == 0)
|
|
break;
|
|
}
|
|
if (j >= count_trxn)
|
|
{
|
|
input_error++;
|
|
error_string = sformatf( "Could not find token in equation, %s.", token);
|
|
error_msg(error_string, CONTINUE);
|
|
for (i = 0; i < count_trxn; i++)
|
|
{
|
|
output_msg(sformatf( "%f\t%s\t",
|
|
(double) trxn.token[i].coef, trxn.token[i].name));
|
|
}
|
|
output_msg(sformatf( "\n"));
|
|
return (ERROR);
|
|
}
|
|
/*
|
|
* Swap token to first position
|
|
*/
|
|
trxn.token[count_trxn].name = trxn.token[0].name;
|
|
trxn.token[count_trxn].s = trxn.token[0].s;
|
|
trxn.token[count_trxn].coef = trxn.token[0].coef;
|
|
|
|
trxn.token[0].name = trxn.token[j].name;
|
|
trxn.token[0].s = trxn.token[j].s;
|
|
trxn.token[0].coef = trxn.token[j].coef;
|
|
|
|
trxn.token[j].name = trxn.token[count_trxn].name;
|
|
trxn.token[j].s = trxn.token[count_trxn].s;
|
|
trxn.token[j].coef = trxn.token[count_trxn].coef;
|
|
/*
|
|
* Make coefficient of token -1.0
|
|
*/
|
|
coef = -1.0 / trxn.token[0].coef;
|
|
trxn_multiply(coef);
|
|
return (OK);
|
|
}
|
|
|
|
/* **********************************************************************
|
|
*
|
|
* Routines related to structure "unknown"
|
|
*
|
|
* ********************************************************************** */
|
|
/* ---------------------------------------------------------------------- */
|
|
class unknown * Phreeqc::
|
|
unknown_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Allocates space to an "unknown" structure
|
|
* arguments: void
|
|
* return: pointer to an "unknown" structure
|
|
*/
|
|
class unknown *unknown_ptr;
|
|
/*
|
|
* Allocate space
|
|
*/
|
|
unknown_ptr = new class unknown;
|
|
/*
|
|
* set pointers in structure to NULL
|
|
*/
|
|
unknown_ptr->type = 0;
|
|
unknown_ptr->moles = 0.0;
|
|
unknown_ptr->ln_moles = 0.0;
|
|
unknown_ptr->f = 0.0;
|
|
unknown_ptr->sum = 0.0;
|
|
unknown_ptr->delta = 0.0;
|
|
unknown_ptr->la = 0.0;
|
|
unknown_ptr->number = 0;
|
|
unknown_ptr->description = NULL;
|
|
unknown_ptr->phase = NULL;
|
|
unknown_ptr->si = 0.0;
|
|
unknown_ptr->s = NULL;
|
|
unknown_ptr->exch_comp = NULL;
|
|
unknown_ptr->pp_assemblage_comp_name = NULL;
|
|
unknown_ptr->pp_assemblage_comp_ptr = NULL;
|
|
unknown_ptr->ss_name = NULL;
|
|
unknown_ptr->ss_ptr = NULL;
|
|
unknown_ptr->ss_comp_name = NULL;
|
|
unknown_ptr->ss_comp_ptr = NULL;
|
|
unknown_ptr->ss_comp_number = 0;
|
|
unknown_ptr->ss_in = FALSE;
|
|
unknown_ptr->surface_comp = NULL;
|
|
unknown_ptr->related_moles = 0.0;
|
|
unknown_ptr->potential_unknown = NULL;
|
|
unknown_ptr->potential_unknown1 = NULL;
|
|
unknown_ptr->potential_unknown2 = NULL;
|
|
unknown_ptr->phase_unknown = NULL;
|
|
unknown_ptr->surface_charge = NULL;
|
|
unknown_ptr->mass_water = 0.0;
|
|
unknown_ptr->dissolve_only = FALSE;
|
|
unknown_ptr->inert_moles = 0.0;
|
|
unknown_ptr->V_m = 0.0;
|
|
unknown_ptr->pressure = 0.0;
|
|
unknown_ptr->mb_number = 0;
|
|
unknown_ptr->iteration = 0;
|
|
|
|
return (unknown_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
unknown_delete(int i)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Delete unknown from list x
|
|
*/
|
|
unknown_free(x[i]);
|
|
x.erase(x.begin() + (size_t)i);
|
|
count_unknowns--;
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
unknown_free(class unknown *unknown_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Frees space allocated to an unknown structure, frees unknown_ptr.
|
|
*/
|
|
if (unknown_ptr == NULL)
|
|
return (ERROR);
|
|
unknown_ptr->master.clear();
|
|
if (unknown_ptr->type == SURFACE_CB)
|
|
{
|
|
/*
|
|
surface_charge_free(unknown_ptr->surface_charge);
|
|
unknown_ptr->surface_charge = (struct surface_charge *) free_check_null(unknown_ptr->surface_charge);
|
|
*/
|
|
}
|
|
unknown_ptr->comp_unknowns.clear();
|
|
delete unknown_ptr;
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
system_duplicate(int i, int save_old)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
Utilities::Rxn_copy(Rxn_solution_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_pp_assemblage_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_exchange_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_surface_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_gas_phase_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_kinetics_map, i, save_old);
|
|
|
|
Utilities::Rxn_copy(Rxn_ss_assemblage_map, i, save_old);
|
|
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class logk * Phreeqc::
|
|
logk_store(const char *name_in, int replace_if_found)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "name" in the map for logk.
|
|
*
|
|
* Pointer to a logk structure is always returned.
|
|
*
|
|
* If the string is not found, a new entry is made in the map. Pointer to
|
|
* the new structure is returned.
|
|
* If "name" is found and replace is true, pointers in old logk structure
|
|
* are freed and replaced with additional input.
|
|
* If "name" is found and replace is false, the old logk structure is not
|
|
* modified and a pointer to it is returned.
|
|
*
|
|
* Arguments:
|
|
* name input, character string to be found in "logk".
|
|
* replace_if_found input, TRUE means reinitialize logk structure if found
|
|
* FALSE means just return pointer if found.
|
|
*
|
|
* Returns:
|
|
* pointer to logk structure "logk" where "name" can be found.
|
|
*/
|
|
/*
|
|
* Search list
|
|
*/
|
|
class logk* logk_ptr = NULL;
|
|
std::string name = name_in;
|
|
str_tolower(name);
|
|
std::map<std::string, class logk*>::iterator it =
|
|
logk_map.find(name);
|
|
|
|
if (it != logk_map.end() && replace_if_found == FALSE)
|
|
{
|
|
logk_ptr = it->second;
|
|
return (logk_ptr);
|
|
}
|
|
else if (it != logk_map.end() && replace_if_found == TRUE)
|
|
{
|
|
logk_ptr = it->second;
|
|
logk_init(logk_ptr);
|
|
}
|
|
else
|
|
{
|
|
/* Make new logk structure */
|
|
size_t n = logk.size();
|
|
logk.resize(n + 1);
|
|
logk[n] = logk_alloc();
|
|
logk_ptr = logk[n];
|
|
}
|
|
/* set name and z in pointer in logk structure */
|
|
logk_ptr->name = string_hsave(name_in);
|
|
/*
|
|
* Update map
|
|
*/
|
|
logk_map[name] = logk_ptr;
|
|
return (logk_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class logk * Phreeqc::
|
|
logk_alloc(void)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Allocates space to a logk structure, initializes
|
|
* arguments: void
|
|
* return: pointer to a logk structure
|
|
*/
|
|
{
|
|
class logk *logk_ptr;
|
|
logk_ptr = new class logk;
|
|
/*
|
|
* set pointers in structure to NULL, variables to zero
|
|
*/
|
|
logk_init(logk_ptr);
|
|
|
|
return (logk_ptr);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
logk_init(class logk *logk_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* return: pointer to a logk structure
|
|
*/
|
|
{
|
|
int i;
|
|
/*
|
|
* set pointers in structure to NULL
|
|
*/
|
|
logk_ptr->name = NULL;
|
|
/*
|
|
* set variables = 0
|
|
*/
|
|
logk_ptr->lk = 0.0;
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
logk_ptr->log_k[i] = 0.0;
|
|
logk_ptr->log_k_original[i] = 0.0;
|
|
}
|
|
logk_ptr->add_logk.clear();
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
logk_copy2orig(class logk *logk_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* Copies log k data to logk_original
|
|
*/
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_LOG_K_INDICES; i++)
|
|
{
|
|
logk_ptr->log_k_original[i] = logk_ptr->log_k[i];
|
|
}
|
|
return (OK);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
class logk * Phreeqc::
|
|
logk_search(const char *name_in)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Function locates the string "name" in the map for logk.
|
|
*
|
|
* Arguments:
|
|
* name input, character string to be found in "logk".
|
|
*
|
|
* Returns:
|
|
* pointer to logk structure "logk" where "name" can be found.
|
|
* or NULL if not found.
|
|
*/
|
|
class logk *logk_ptr;
|
|
/*
|
|
* Search list
|
|
*/
|
|
std::string name = name_in;
|
|
str_tolower(name);
|
|
std::map<std::string, class logk*>::iterator l_it =
|
|
logk_map.find(name);
|
|
if (l_it != logk_map.end())
|
|
{
|
|
logk_ptr = l_it->second;
|
|
return (logk_ptr);
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
entity_exists(const char *name, int n_user)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Reads solution, 0 Solution
|
|
* reaction, 1 Reaction
|
|
* exchange, 2 Exchange
|
|
* surface, 3 Surface
|
|
* gas_phase, 4 Gas_phase
|
|
* equilibrium_phases, 5 Pure_phase
|
|
* solid_solution, 6 Ss_phase
|
|
* kinetics, 7 Kinetics
|
|
* mix, 8 Mix
|
|
* reaction_temperature 9 Temperature
|
|
* unknown 10 UnKnown
|
|
*/
|
|
int return_value;
|
|
char token[MAX_LENGTH];
|
|
enum entity_type type;
|
|
/*
|
|
* Read keyword
|
|
*/
|
|
strncpy(token, name, MAX_LENGTH-1);
|
|
token[MAX_LENGTH-1] = '\0';
|
|
type = get_entity_enum(token);
|
|
return_value = TRUE;
|
|
switch (type)
|
|
{
|
|
case UnKnown:
|
|
warning_msg
|
|
("EXISTS expecting keyword solution, mix, kinetics, reaction, reaction_temperature, equilibrium_phases, exchange, surface, gas_phase, or solid_solutions.");
|
|
return_value = 2;
|
|
break;
|
|
case Solution: /* Solution */
|
|
if (Utilities::Rxn_find(Rxn_solution_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Pure_phase: /* Pure phases */
|
|
if (Utilities::Rxn_find(Rxn_pp_assemblage_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Reaction: /* Reaction */
|
|
if (Utilities::Rxn_find(Rxn_reaction_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Mix: /* Mix */
|
|
if (Utilities::Rxn_find(Rxn_mix_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Exchange: /* Ex */
|
|
if (Utilities::Rxn_find(Rxn_exchange_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Surface: /* Surface */
|
|
if (Utilities::Rxn_find(Rxn_surface_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Temperature:
|
|
if (Utilities::Rxn_find(Rxn_temperature_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
case Pressure:
|
|
if (Utilities::Rxn_find(Rxn_pressure_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
case Gas_phase: /* Gas */
|
|
if (Utilities::Rxn_find(Rxn_gas_phase_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Kinetics: /* Kinetics */
|
|
if (Utilities::Rxn_find(Rxn_kinetics_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
case Ss_phase: /* solid_solutions */
|
|
if (Utilities::Rxn_find(Rxn_ss_assemblage_map, n_user) == NULL)
|
|
{
|
|
return_value = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
return (return_value);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
enum entity_type Phreeqc::
|
|
get_entity_enum(char *name)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
/*
|
|
* Reads solution, 0 Solution
|
|
* reaction, 1 Reaction
|
|
* exchange, 2 Exchange
|
|
* surface, 3 Surface
|
|
* gas_phase, 4 Gas_phase
|
|
* equilibrium_phases, 5 Pure_phase
|
|
* solid_solution, 6 Ss_phase
|
|
* kinetics, 7 Kinetics
|
|
* mix, 8 Mix
|
|
* reaction_temperature 9 Temperature
|
|
* reaction_pressure
|
|
* unknown 10 UnKnown
|
|
*
|
|
*/
|
|
int i;
|
|
const char* cptr;
|
|
char token[MAX_LENGTH];
|
|
/*
|
|
* Read keyword
|
|
*/
|
|
cptr = name;
|
|
copy_token(token, &cptr, &i);
|
|
check_key(token);
|
|
|
|
switch (next_keyword)
|
|
{
|
|
case Keywords::KEY_SOLUTION: /* Solution */
|
|
return (Solution);
|
|
break;
|
|
case Keywords::KEY_EQUILIBRIUM_PHASES: /* Pure phases */
|
|
return (Pure_phase);
|
|
break;
|
|
case Keywords::KEY_REACTION: /* Reaction */
|
|
return (Reaction);
|
|
break;
|
|
case Keywords::KEY_MIX: /* Mix */
|
|
return (Mix);
|
|
break;
|
|
case Keywords::KEY_EXCHANGE: /* Ex */
|
|
return (Exchange);
|
|
break;
|
|
case Keywords::KEY_SURFACE: /* Surface */
|
|
return (Surface);
|
|
break;
|
|
case Keywords::KEY_REACTION_TEMPERATURE: /* Temperature */
|
|
return (Temperature);
|
|
break;
|
|
case Keywords::KEY_REACTION_PRESSURE: /* Pressure */
|
|
return (Pressure);
|
|
break;
|
|
case Keywords::KEY_GAS_PHASE: /* Gas */
|
|
return (Gas_phase);
|
|
break;
|
|
case Keywords::KEY_KINETICS: /* Kinetics */
|
|
return (Kinetics);
|
|
break;
|
|
case Keywords::KEY_SOLID_SOLUTIONS: /* solid_solutions */
|
|
return (Ss_phase);
|
|
break;
|
|
default:
|
|
warning_msg
|
|
("EXISTS expecting keyword solution, mix, kinetics, reaction, reaction_temperature, equilibrium_phases, exchange, surface, gas_phase, or solid_solutions.");
|
|
break;
|
|
}
|
|
return (UnKnown);
|
|
}
|
|
|
|
/*
|
|
* copier routines
|
|
*/
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
copier_add(class copier *copier_ptr, int n_user, int start, int end)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* add new set of copy instructions
|
|
*/
|
|
{
|
|
copier_ptr->n_user.push_back(n_user);
|
|
copier_ptr->start.push_back(start);
|
|
copier_ptr->end.push_back(end);
|
|
return (OK);
|
|
}
|
|
/* ---------------------------------------------------------------------- */
|
|
int Phreeqc::
|
|
copier_clear(class copier* copier_ptr)
|
|
/* ---------------------------------------------------------------------- */
|
|
/*
|
|
* clear copier
|
|
*/
|
|
{
|
|
copier_ptr->n_user.clear();
|
|
copier_ptr->start.clear();
|
|
copier_ptr->end.clear();
|
|
return (OK);
|
|
}
|
|
|
|
#include "StorageBin.h"
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
void Phreeqc::
|
|
Use2cxxStorageBin(cxxStorageBin & sb)
|
|
/* ---------------------------------------------------------------------- */
|
|
{
|
|
//Add everything from use structure to storagebin sb
|
|
|
|
sb.Get_system().Set_io(sb.Get_io());
|
|
if (use.Get_mix_in())
|
|
{
|
|
cxxMix *entity = use.Get_mix_ptr();
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Mix(use.Get_n_mix_user(), entity);
|
|
}
|
|
|
|
// put mix solutions in sb
|
|
cxxMix * mix_ptr = use.Get_mix_ptr();
|
|
std::map<int, LDBLE>::const_iterator cit;
|
|
for (cit = mix_ptr->Get_mixComps().begin(); cit != mix_ptr->Get_mixComps().end(); cit++)
|
|
{
|
|
cxxSolution *entity = Utilities::Rxn_find(Rxn_solution_map, cit->first);
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Solution(cit->first, entity);
|
|
}
|
|
}
|
|
}
|
|
else if (use.Get_solution_in())
|
|
{
|
|
cxxSolution *entity = Utilities::Rxn_find(Rxn_solution_map, use.Get_n_solution_user());
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Solution(use.Get_n_solution_user(), entity);
|
|
}
|
|
}
|
|
if (use.Get_pp_assemblage_in())
|
|
{
|
|
cxxPPassemblage *entity_ptr = Utilities::Rxn_find(Rxn_pp_assemblage_map, use.Get_n_pp_assemblage_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_PPassemblage(use.Get_n_pp_assemblage_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_exchange_in())
|
|
{
|
|
cxxExchange *entity_ptr = Utilities::Rxn_find(Rxn_exchange_map, use.Get_n_exchange_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Exchange(use.Get_n_exchange_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_surface_in())
|
|
{
|
|
cxxSurface *entity_ptr = Utilities::Rxn_find(Rxn_surface_map, use.Get_n_surface_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Surface(use.Get_n_surface_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_gas_phase_in())
|
|
{
|
|
cxxGasPhase *entity_ptr = Utilities::Rxn_find(Rxn_gas_phase_map, use.Get_n_gas_phase_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_GasPhase(use.Get_n_gas_phase_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_ss_assemblage_in())
|
|
{
|
|
cxxSSassemblage *entity_ptr = Utilities::Rxn_find(Rxn_ss_assemblage_map, use.Get_n_ss_assemblage_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_SSassemblage(use.Get_n_ss_assemblage_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_kinetics_in())
|
|
{
|
|
cxxKinetics *entity_ptr = Utilities::Rxn_find(Rxn_kinetics_map, use.Get_n_kinetics_user());
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Kinetics(use.Get_n_kinetics_user(), entity_ptr);
|
|
}
|
|
}
|
|
if (use.Get_reaction_in())
|
|
{
|
|
cxxReaction *entity = Utilities::Rxn_find(Rxn_reaction_map, use.Get_n_reaction_user());
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Reaction(use.Get_n_reaction_user(), entity);
|
|
}
|
|
}
|
|
if (use.Get_temperature_in())
|
|
{
|
|
cxxTemperature *entity = Utilities::Rxn_find(Rxn_temperature_map, use.Get_n_temperature_user());
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Temperature(use.Get_n_temperature_user(), entity);
|
|
}
|
|
}
|
|
if (use.Get_pressure_in())
|
|
{
|
|
cxxPressure *entity = Utilities::Rxn_find(Rxn_pressure_map, use.Get_n_pressure_user());
|
|
if (entity != NULL)
|
|
{
|
|
sb.Set_Pressure(use.Get_n_pressure_user(), entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Phreeqc::
|
|
phreeqc2cxxStorageBin(cxxStorageBin & sb)
|
|
//
|
|
// Fills StorageBin sb with all reactants from phreeqc instance.
|
|
// equivalent to old import_phreeqc.
|
|
//
|
|
{
|
|
// Solutions
|
|
{
|
|
std::map<int, cxxSolution>::iterator it;
|
|
for (it = Rxn_solution_map.begin(); it != Rxn_solution_map.end(); it++)
|
|
{
|
|
sb.Set_Solution(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// Exchangers
|
|
{
|
|
std::map<int, cxxExchange>::iterator it;
|
|
for (it = Rxn_exchange_map.begin(); it != Rxn_exchange_map.end(); it++)
|
|
{
|
|
sb.Set_Exchange(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// GasPhases
|
|
{
|
|
std::map<int, cxxGasPhase>::iterator it;
|
|
for (it = Rxn_gas_phase_map.begin(); it != Rxn_gas_phase_map.end(); it++)
|
|
{
|
|
sb.Set_GasPhase(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
|
|
// Kinetics
|
|
{
|
|
std::map<int, cxxKinetics>::iterator it;
|
|
for (it = Rxn_kinetics_map.begin(); it != Rxn_kinetics_map.end(); it++)
|
|
{
|
|
sb.Set_Kinetics(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// PPassemblages
|
|
{
|
|
std::map<int, cxxPPassemblage>::iterator it;
|
|
for (it = Rxn_pp_assemblage_map.begin(); it != Rxn_pp_assemblage_map.end(); it++)
|
|
{
|
|
sb.Set_PPassemblage(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// SSassemblages
|
|
{
|
|
std::map<int, cxxSSassemblage>::iterator it;
|
|
for (it = Rxn_ss_assemblage_map.begin(); it != Rxn_ss_assemblage_map.end(); it++)
|
|
{
|
|
sb.Set_SSassemblage(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// Surfaces
|
|
{
|
|
std::map<int, cxxSurface>::iterator it;
|
|
for (it = Rxn_surface_map.begin(); it != Rxn_surface_map.end(); it++)
|
|
{
|
|
sb.Set_Surface(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
// Mixes
|
|
{
|
|
std::map<int, cxxMix>::iterator it;
|
|
for (it = Rxn_mix_map.begin(); it != Rxn_mix_map.end(); it++)
|
|
{
|
|
sb.Set_Mix(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
|
|
// Reactions
|
|
{
|
|
std::map<int, cxxReaction>::iterator it;
|
|
for (it = Rxn_reaction_map.begin(); it != Rxn_reaction_map.end(); it++)
|
|
{
|
|
sb.Set_Reaction(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
|
|
// Temperatures
|
|
{
|
|
std::map<int, cxxTemperature>::iterator it;
|
|
for (it = Rxn_temperature_map.begin(); it != Rxn_temperature_map.end(); it++)
|
|
{
|
|
sb.Set_Temperature(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
|
|
// Pressures
|
|
{
|
|
std::map<int, cxxPressure>::iterator it;
|
|
for (it = Rxn_pressure_map.begin(); it != Rxn_pressure_map.end(); it++)
|
|
{
|
|
sb.Set_Pressure(it->second.Get_n_user(), &(it->second));
|
|
}
|
|
}
|
|
}
|
|
|
|
void Phreeqc::
|
|
phreeqc2cxxStorageBin(cxxStorageBin & sb, int n)
|
|
//
|
|
// copy phreeqc reactants numbered n to StorageBin sb
|
|
//
|
|
{
|
|
// Solutions
|
|
{
|
|
cxxSolution *entity_ptr = Utilities::Rxn_find(Rxn_solution_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Solution(n, entity_ptr);
|
|
}
|
|
}
|
|
// Exchangers
|
|
{
|
|
cxxExchange *entity_ptr = Utilities::Rxn_find(Rxn_exchange_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Exchange(n, entity_ptr);
|
|
}
|
|
}
|
|
|
|
// GasPhases
|
|
{
|
|
cxxGasPhase *entity_ptr = Utilities::Rxn_find(Rxn_gas_phase_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_GasPhase(n, entity_ptr);
|
|
}
|
|
}
|
|
|
|
// Kinetics
|
|
{
|
|
cxxKinetics *entity_ptr = Utilities::Rxn_find(Rxn_kinetics_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Kinetics(n, entity_ptr);
|
|
}
|
|
}
|
|
// PPassemblages
|
|
{
|
|
cxxPPassemblage *entity_ptr = Utilities::Rxn_find(Rxn_pp_assemblage_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_PPassemblage(n, entity_ptr);
|
|
}
|
|
}
|
|
// SSassemblages
|
|
{
|
|
cxxSSassemblage *entity_ptr = Utilities::Rxn_find(Rxn_ss_assemblage_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_SSassemblage(n, entity_ptr);
|
|
}
|
|
}
|
|
// Surfaces
|
|
{
|
|
cxxSurface *entity_ptr = Utilities::Rxn_find(Rxn_surface_map, n);
|
|
if (entity_ptr != NULL)
|
|
{
|
|
sb.Set_Surface(n, entity_ptr);
|
|
}
|
|
}
|
|
}
|
|
void Phreeqc::
|
|
cxxStorageBin2phreeqc(cxxStorageBin & sb, int n)
|
|
//
|
|
// copy all reactants from storage bin number n to phreeqc
|
|
// replaces any existing reactants in phreeqc
|
|
//
|
|
{
|
|
// Solutions
|
|
{
|
|
std::map < int, cxxSolution >::const_iterator it = sb.Get_Solutions().find(n);
|
|
if (it != sb.Get_Solutions().end())
|
|
{
|
|
Rxn_solution_map[n] = it->second;
|
|
}
|
|
}
|
|
// Exchangers
|
|
{
|
|
std::map < int, cxxExchange >::const_iterator it = sb.Get_Exchangers().find(n);
|
|
if (it != sb.Get_Exchangers().end())
|
|
{
|
|
Rxn_exchange_map[n] = it->second;
|
|
}
|
|
}
|
|
|
|
// GasPhases
|
|
{
|
|
std::map < int, cxxGasPhase >::const_iterator it = sb.Get_GasPhases().find(n);
|
|
if (it != sb.Get_GasPhases().end())
|
|
{
|
|
Rxn_gas_phase_map[n] = it->second;
|
|
}
|
|
}
|
|
|
|
// Kinetics
|
|
{
|
|
std::map < int, cxxKinetics >::const_iterator it = sb.Get_Kinetics().find(n);
|
|
if (it != sb.Get_Kinetics().end())
|
|
{
|
|
Rxn_kinetics_map[n] = it->second;
|
|
}
|
|
}
|
|
// PPassemblages
|
|
{
|
|
std::map < int, cxxPPassemblage >::const_iterator it = sb.Get_PPassemblages().find(n);
|
|
if (it != sb.Get_PPassemblages().end())
|
|
{
|
|
Rxn_pp_assemblage_map[n] = it->second;
|
|
}
|
|
}
|
|
// SSassemblages
|
|
{
|
|
std::map < int, cxxSSassemblage >::const_iterator it = sb.Get_SSassemblages().find(n);
|
|
if (it != sb.Get_SSassemblages().end())
|
|
{
|
|
Rxn_ss_assemblage_map[n] = it->second;
|
|
}
|
|
}
|
|
// Surfaces
|
|
{
|
|
std::map < int, cxxSurface >::const_iterator it = sb.Get_Surfaces().find(n);
|
|
if (it != sb.Get_Surfaces().end())
|
|
{
|
|
Rxn_surface_map[n] = it->second;
|
|
}
|
|
}
|
|
// Mixes
|
|
{
|
|
std::map < int, cxxMix >::const_iterator it = sb.Get_Mixes().find(n);
|
|
if (it != sb.Get_Mixes().end())
|
|
{
|
|
Rxn_mix_map[n] = it->second;
|
|
}
|
|
}
|
|
|
|
// Reactions
|
|
{
|
|
std::map < int, cxxReaction >::const_iterator it = sb.Get_Reactions().find(n);
|
|
if (it != sb.Get_Reactions().end())
|
|
{
|
|
Rxn_reaction_map[n] = it->second;
|
|
}
|
|
}
|
|
// Temperatures
|
|
{
|
|
std::map < int, cxxTemperature >::const_iterator it = sb.Get_Temperatures().find(n);
|
|
if (it != sb.Get_Temperatures().end())
|
|
{
|
|
Rxn_temperature_map[n] = it->second;
|
|
}
|
|
}
|
|
// Pressures
|
|
{
|
|
std::map < int, cxxPressure >::const_iterator it = sb.Get_Pressures().find(n);
|
|
if (it != sb.Get_Pressures().end())
|
|
{
|
|
Rxn_pressure_map[n] = it->second;
|
|
}
|
|
}
|
|
}
|
|
void Phreeqc::
|
|
cxxStorageBin2phreeqc(cxxStorageBin & sb)
|
|
//
|
|
// copy data from storage bin to phreeqc
|
|
// replaces any existing reactants in phreeqc
|
|
//
|
|
{
|
|
// Solutions
|
|
{
|
|
std::map < int, cxxSolution >::const_iterator it = sb.Get_Solutions().begin();
|
|
for ( ; it != sb.Get_Solutions().end(); it++)
|
|
{
|
|
Rxn_solution_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// Exchangers
|
|
{
|
|
std::map < int, cxxExchange >::const_iterator it = sb.Get_Exchangers().begin();
|
|
for ( ; it != sb.Get_Exchangers().end(); it++)
|
|
{
|
|
Rxn_exchange_map[it->first] = it->second;
|
|
}
|
|
}
|
|
|
|
// GasPhases
|
|
{
|
|
std::map < int, cxxGasPhase >::const_iterator it = sb.Get_GasPhases().begin();
|
|
for ( ; it != sb.Get_GasPhases().end(); it++)
|
|
{
|
|
Rxn_gas_phase_map[it->first] = it->second;
|
|
}
|
|
}
|
|
|
|
// Kinetics
|
|
{
|
|
std::map < int, cxxKinetics >::const_iterator it = sb.Get_Kinetics().begin();
|
|
for ( ; it != sb.Get_Kinetics().end(); it++)
|
|
{
|
|
Rxn_kinetics_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// PPassemblages
|
|
{
|
|
std::map < int, cxxPPassemblage >::const_iterator it = sb.Get_PPassemblages().begin();
|
|
for ( ; it != sb.Get_PPassemblages().end(); it++)
|
|
{
|
|
Rxn_pp_assemblage_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// SSassemblages
|
|
{
|
|
std::map < int, cxxSSassemblage >::const_iterator it = sb.Get_SSassemblages().begin();
|
|
for ( ; it != sb.Get_SSassemblages().end(); it++)
|
|
{
|
|
Rxn_ss_assemblage_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// Surfaces
|
|
{
|
|
std::map < int, cxxSurface >::const_iterator it = sb.Get_Surfaces().begin();
|
|
for ( ; it != sb.Get_Surfaces().end(); it++)
|
|
{
|
|
Rxn_surface_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// Mixes
|
|
{
|
|
std::map < int, cxxMix >::const_iterator it = sb.Get_Mixes().begin();
|
|
for ( ; it != sb.Get_Mixes().end(); it++)
|
|
{
|
|
Rxn_mix_map[it->first] = it->second;
|
|
}
|
|
}
|
|
|
|
// Reactions
|
|
{
|
|
std::map < int, cxxReaction >::const_iterator it = sb.Get_Reactions().begin();
|
|
for ( ; it != sb.Get_Reactions().end(); it++)
|
|
{
|
|
Rxn_reaction_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// Temperatures
|
|
{
|
|
std::map < int, cxxTemperature >::const_iterator it = sb.Get_Temperatures().begin();
|
|
for ( ; it != sb.Get_Temperatures().end(); it++)
|
|
{
|
|
Rxn_temperature_map[it->first] = it->second;
|
|
}
|
|
}
|
|
// Pressures
|
|
{
|
|
std::map < int, cxxPressure >::const_iterator it = sb.Get_Pressures().begin();
|
|
for ( ; it != sb.Get_Pressures().end(); it++)
|
|
{
|
|
Rxn_pressure_map[it->first] = it->second;
|
|
}
|
|
}
|
|
}
|
|
|
|
|