/* ---------------------------------------------------------------------- */ static int reaction_calc (struct irrev *irrev_ptr) /* ---------------------------------------------------------------------- */ { /* * Go through irreversible reaction initially to * determine a list of elements and amounts in * the reaction. */ int i, j, return_value; LDBLE coef; char token[MAX_LENGTH]; char *ptr; struct phase *phase_ptr; /* * Go through list and generate list of elements and * coefficient of elements in reaction */ return_value = OK; count_elts = 0; paren_count = 0; for (i = 0; i < irrev_ptr->count_list; i++) { coef = irrev_ptr->list[i].coef; strcpy (token, irrev_ptr->list[i].name); phase_ptr = phase_bsearch (token, &j, FALSE); /* * Reactant is a pure phase, copy formula into token */ if (phase_ptr != NULL) { add_elt_list (phase_ptr->next_elt, coef); } else { ptr = &(token[0]); get_elts_in_species (&ptr, coef); } } /* * Check that all elements are in database */ for (i = 0; i < count_elts; i++) { if (elt_list[i].elt->master == NULL) { sprintf (error_string, "Element or phase not defined in database, %s.", elt_list[i].elt->name); error_msg (error_string, CONTINUE); input_error++; return_value = ERROR; } } irrev_ptr->elts = elt_list_save (); return (return_value); }
/* ---------------------------------------------------------------------- */ int Phreeqc:: setup_fixed_volume_gas(void) /* ---------------------------------------------------------------------- */ { /* * Fill in data for gas phase unknown (sum of partial pressures) * in unknown structure */ if (use.Get_gas_phase_ptr() == NULL) return (OK); cxxGasPhase *gas_phase_ptr = use.Get_gas_phase_ptr(); /* * One for each gas component */ gas_unknowns.clear(); gas_unknown = NULL; gas_phase_ptr->Set_total_moles(0); for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++) { const cxxGasComp *comp_ptr = &(gas_phase_ptr->Get_gas_comps()[i]); int j; struct phase *phase_ptr = phase_bsearch(comp_ptr->Get_phase_name().c_str(), &j, FALSE); x[count_unknowns]->type = GAS_MOLES; x[count_unknowns]->description = phase_ptr->name; x[count_unknowns]->phase = phase_ptr; x[count_unknowns]->moles = comp_ptr->Get_moles(); if (x[count_unknowns]->moles <= 0) { x[count_unknowns]->moles = MIN_TOTAL; } x[count_unknowns]->ln_moles = log(x[count_unknowns]->moles); gas_unknowns.push_back(x[count_unknowns]); gas_phase_ptr->Set_total_moles(gas_phase_ptr->Get_total_moles() + x[count_unknowns]->moles); x[count_unknowns]->phase->moles_x = x[count_unknowns]->moles; count_unknowns++; } if (gas_unknowns.size() > 0) { gas_unknown = gas_unknowns[0]; } return (OK); }
/* ---------------------------------------------------------------------- */ int Phreeqc:: build_fixed_volume_gas(void) /* ---------------------------------------------------------------------- */ { /* * Put coefficients into lists to sum iaps to test for equilibrium * Put coefficients into lists to build jacobian for * sum of partial pressures equation and * mass balance equations for elements contained in gases */ int row, col; struct master *master_ptr; struct rxn_token *rxn_ptr; struct unknown *unknown_ptr; LDBLE coef, coef_elt; if (gas_unknown == NULL) return (OK); cxxGasPhase *gas_phase_ptr = use.Get_gas_phase_ptr(); for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++) { const cxxGasComp *comp_ptr = &(gas_phase_ptr->Get_gas_comps()[i]); int j; struct phase *phase_ptr = phase_bsearch(comp_ptr->Get_phase_name().c_str(), &j, FALSE); /* * Determine elements in gas component */ count_elts = 0; paren_count = 0; if (phase_ptr->rxn_x == NULL) continue; add_elt_list(phase_ptr->next_elt, 1.0); #define COMBINE #ifdef COMBINE change_hydrogen_in_elt_list(0); #endif /* * Build mass balance sums for each element in gas */ if (debug_prep == TRUE) { output_msg(sformatf( "\n\tMass balance summations %s.\n\n", phase_ptr->name)); } /* All elements in gas */ for (j = 0; j < count_elts; j++) { unknown_ptr = NULL; if (strcmp(elt_list[j].elt->name, "H") == 0) { unknown_ptr = mass_hydrogen_unknown; } else if (strcmp(elt_list[j].elt->name, "O") == 0) { unknown_ptr = mass_oxygen_unknown; } else { if (elt_list[j].elt->primary->in == TRUE) { unknown_ptr = elt_list[j].elt->primary->unknown; } else if (elt_list[j].elt->primary->s->secondary != NULL) { unknown_ptr = elt_list[j].elt->primary->s->secondary->unknown; } } if (unknown_ptr != NULL) { coef = elt_list[j].coef; store_mb(&(gas_unknowns[i]->moles), &(unknown_ptr->f), coef); if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%-24s%10.3f\n", unknown_ptr->description, (double) coef)); } } } if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE) { /* Total pressure of gases */ store_mb(&(phase_ptr->p_soln_x), &(gas_unknown->f), 1.0); } /* * Build jacobian sums for mass balance equations */ if (debug_prep == TRUE) { output_msg(sformatf( "\n\tJacobian summations %s.\n\n", phase_ptr->name)); } for (j = 0; j < count_elts; j++) { unknown_ptr = NULL; if (strcmp(elt_list[j].elt->name, "H") == 0) { unknown_ptr = mass_hydrogen_unknown; } else if (strcmp(elt_list[j].elt->name, "O") == 0) { unknown_ptr = mass_oxygen_unknown; } else { if (elt_list[j].elt->primary->in == TRUE) { unknown_ptr = elt_list[j].elt->primary->unknown; } else if (elt_list[j].elt->primary->s->secondary != NULL) { unknown_ptr = elt_list[j].elt->primary->s->secondary->unknown; } } if (unknown_ptr == NULL) { continue; } if (debug_prep == TRUE) { output_msg(sformatf( "\n\t%s.\n", unknown_ptr->description)); } row = unknown_ptr->number * (count_unknowns + 1); coef_elt = elt_list[j].coef; for (rxn_ptr = phase_ptr->rxn_x->token + 1; rxn_ptr->s != NULL; rxn_ptr++) { if (rxn_ptr->s->secondary != NULL && rxn_ptr->s->secondary->in == TRUE) { master_ptr = rxn_ptr->s->secondary; } else if (rxn_ptr->s->primary != NULL && rxn_ptr->s->primary->in == TRUE) { master_ptr = rxn_ptr->s->primary; } else { master_ptr = master_bsearch_primary(rxn_ptr->s->name); master_ptr->s->la = -999.0; } if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%s\n", master_ptr->s->name)); } if (master_ptr->unknown == NULL) { continue; } if (master_ptr->in == FALSE) { error_string = sformatf( "Element, %s, in phase, %s, is not in model.", master_ptr->elt->name, phase_ptr->name); error_msg(error_string, CONTINUE); input_error++; } col = master_ptr->unknown->number; coef = coef_elt * rxn_ptr->coef; store_jacob(&(gas_unknowns[i]->moles), &(array[row + col]), coef); if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n", master_ptr->s->name, (double) coef, row / (count_unknowns + 1), col)); } } if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE) { /* derivative wrt total moles of gas */ store_jacob(&(phase_ptr->fraction_x), &(array[row + gas_unknown->number]), coef_elt); if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n", "gas moles", (double) elt_list[j].coef, row / (count_unknowns + 1), gas_unknown->number)); } } } /* * Build jacobian sums for sum of partial pressures equation */ if (gas_phase_ptr->Get_type() != cxxGasPhase::GP_PRESSURE) continue; if (debug_prep == TRUE) { output_msg(sformatf( "\n\tPartial pressure eqn %s.\n\n", phase_ptr->name)); } unknown_ptr = gas_unknown; row = unknown_ptr->number * (count_unknowns + 1); for (rxn_ptr = phase_ptr->rxn_x->token + 1; rxn_ptr->s != NULL; rxn_ptr++) { if (rxn_ptr->s != s_eminus && rxn_ptr->s->in == FALSE) { error_string = sformatf( "Element in species, %s, in phase, %s, is not in model.", rxn_ptr->s->name, phase_ptr->name); warning_msg(error_string); } else { if (rxn_ptr->s->secondary != NULL && rxn_ptr->s->secondary->in == TRUE) { master_ptr = rxn_ptr->s->secondary; } else if (rxn_ptr->s->primary != NULL && rxn_ptr->s->primary->in == TRUE) { master_ptr = rxn_ptr->s->primary; } else { master_ptr = master_bsearch_primary(rxn_ptr->s->name); if (master_ptr && master_ptr->s) { master_ptr->s->la = -999.0; } } if (master_ptr == NULL) { error_string = sformatf( "Master species for %s, in phase, %s, is not in model.", rxn_ptr->s->name, phase_ptr->name); error_msg(error_string, CONTINUE); input_error++; } else { if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%s\n", master_ptr->s->name)); } if (master_ptr->unknown == NULL) { assert(false); continue; } if (master_ptr->in == FALSE) { error_string = sformatf( "Element, %s, in phase, %s, is not in model.", master_ptr->elt->name, phase_ptr->name); warning_msg(error_string); } col = master_ptr->unknown->number; coef = rxn_ptr->coef; store_jacob(&(phase_ptr->p_soln_x), &(array[row + col]), coef); if (debug_prep == TRUE) { output_msg(sformatf( "\t\t%-24s%10.3f\t%d\t%d\n", master_ptr->s->name, (double) coef, row / (count_unknowns + 1), col)); } } } } } return (OK); }