mirror of
https://git.gfz-potsdam.de/naaice/iphreeqc.git
synced 2025-12-15 16:18:22 +01:00
git-svn-id: svn://136.177.114.72/svn_GW/IPhreeqc/trunk@4106 1feff8c3-07ed-0310-ac33-dd36852eb9cd
968 lines
20 KiB
C++
968 lines
20 KiB
C++
#if defined(_DEBUG)
|
|
#pragma warning(disable : 4786) // disable truncation warning
|
|
#endif
|
|
#include <iostream> // std::cout
|
|
#include <fstream> // std::ifstream
|
|
#include <memory> // std::auto_ptr
|
|
#include <sstream> // std::istringstream
|
|
#include <cstdarg>
|
|
|
|
#if defined(_WIN32)
|
|
#include <windows.h> // ::OutputDebugString
|
|
#endif
|
|
|
|
#include "phreeqcns.hxx"
|
|
#include "ErrorReporter.hxx"
|
|
#include "SelectedOutput.hxx"
|
|
#include "Var.h"
|
|
#include "IPhreeqc.h"
|
|
#include "module_files.h"
|
|
|
|
#ifdef PHREEQC_CPP
|
|
extern int dump_entities(void);
|
|
extern int delete_entities(void);
|
|
extern int run_as_cells(void);
|
|
#endif
|
|
|
|
|
|
const char OUTPUT_FILENAME[] = "phreeqc.out";
|
|
const char ERROR_FILENAME[] = "phreeqc.err";
|
|
const char LOG_FILENAME[] = "phreeqc.log";
|
|
const char PUNCH_FILENAME[] = "selected.out";
|
|
|
|
|
|
const std::string& GetAccumulatedLines(void);
|
|
void ClearAccumulatedLines(void);
|
|
|
|
void EndRow(void);
|
|
void AddSelectedOutput(const char* name, const char* format, va_list argptr);
|
|
|
|
|
|
struct PhreeqcStop{};
|
|
|
|
struct IPhreeqc
|
|
{
|
|
// ctor
|
|
IPhreeqc(void)
|
|
: m_pIErrorReporter(0)
|
|
, m_bDatabaseLoaded(false)
|
|
, m_bSelectedOutputOn(false)
|
|
, m_sPunchFileName(NULL)
|
|
{
|
|
// initialize
|
|
UnLoadDatabase();
|
|
};
|
|
IPhreeqc(IErrorReporter *pIErrorReporter)
|
|
: m_pIErrorReporter(0)
|
|
, m_bDatabaseLoaded(false)
|
|
, m_bSelectedOutputOn(false)
|
|
, m_sPunchFileName(NULL)
|
|
{
|
|
// initialize
|
|
UnLoadDatabase();
|
|
};
|
|
~IPhreeqc(void)
|
|
{
|
|
UnLoadDatabase();
|
|
delete[] m_sPunchFileName;
|
|
};
|
|
IErrorReporter *m_pIErrorReporter;
|
|
bool m_bDatabaseLoaded;
|
|
bool m_bSelectedOutputOn;
|
|
char *m_sPunchFileName;
|
|
};
|
|
|
|
static std::string s_string_input;
|
|
static std::ostringstream s_oss;
|
|
static CErrorReporter<std::ostringstream> s_errorReporter;
|
|
static IPhreeqc s_IPhreeqc(&s_errorReporter);
|
|
|
|
static void check_database(const char *sz_routine);
|
|
|
|
static void do_run(const char* sz_routine, std::istream* pis, FILE* fp, int output_on, int error_on, int log_on, int selected_output_on, PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie);
|
|
|
|
|
|
int istream_getc(void *cookie);
|
|
int output_handler(const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args);
|
|
int open_handler(const int type, const char *file_name);
|
|
int handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args);
|
|
|
|
|
|
int
|
|
istream_getc(void *cookie)
|
|
{
|
|
if (cookie)
|
|
{
|
|
std::istream* is = (std::istream*)cookie;
|
|
return is->get();
|
|
}
|
|
return EOF;
|
|
}
|
|
|
|
int
|
|
handler(const int action, const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args)
|
|
{
|
|
int n = OK;
|
|
switch (action)
|
|
{
|
|
case ACTION_OPEN:
|
|
n = open_handler(type, err_str);
|
|
break;
|
|
|
|
case ACTION_OUTPUT:
|
|
n = output_handler(type, err_str, stop, cookie, format, args);
|
|
break;
|
|
|
|
default:
|
|
n = module_handler(action, type, err_str, stop, cookie, format, args);
|
|
break;
|
|
}
|
|
|
|
if (stop == STOP)
|
|
{
|
|
throw PhreeqcStop();
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int
|
|
output_handler(const int type, const char *err_str, const int stop, void *cookie, const char *format, va_list args)
|
|
{
|
|
IPhreeqc* pIPhreeqc = (IPhreeqc*) cookie;
|
|
|
|
switch (type)
|
|
{
|
|
case OUTPUT_ERROR:
|
|
if (pIPhreeqc && pIPhreeqc->m_pIErrorReporter)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "ERROR: " << err_str << "\n";
|
|
if (stop == STOP) {
|
|
oss << "Stopping.\n";
|
|
}
|
|
pIPhreeqc->m_pIErrorReporter->AddError(oss.str().c_str());
|
|
}
|
|
break;
|
|
|
|
case OUTPUT_PUNCH:
|
|
AddSelectedOutput(err_str, format, args);
|
|
break;
|
|
|
|
}
|
|
return module_handler(ACTION_OUTPUT, type, err_str, stop, cookie, format, args);
|
|
}
|
|
|
|
int
|
|
open_handler(const int type, const char *file_name)
|
|
{
|
|
int n = OK;
|
|
switch (type)
|
|
{
|
|
case OUTPUT_PUNCH:
|
|
if (file_name)
|
|
{
|
|
ASSERT(s_IPhreeqc.m_sPunchFileName != file_name);
|
|
if (s_IPhreeqc.m_sPunchFileName != file_name)
|
|
{
|
|
delete[] s_IPhreeqc.m_sPunchFileName;
|
|
s_IPhreeqc.m_sPunchFileName = NULL;
|
|
s_IPhreeqc.m_sPunchFileName = new char[::strlen(file_name) + 1];
|
|
::strcpy(s_IPhreeqc.m_sPunchFileName, file_name);
|
|
}
|
|
}
|
|
if (s_IPhreeqc.m_bSelectedOutputOn)
|
|
{
|
|
n = module_handler(ACTION_OPEN, type, file_name, CONTINUE, NULL, NULL, NULL);
|
|
}
|
|
break;
|
|
default:
|
|
n = module_handler(ACTION_OPEN, type, file_name, CONTINUE, NULL, NULL, NULL);
|
|
break;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int
|
|
LoadDatabase(const char* filename)
|
|
{
|
|
try
|
|
{
|
|
// cleanup
|
|
//
|
|
UnLoadDatabase();
|
|
|
|
CSelectedOutput::Instance()->Clear();
|
|
|
|
#if 0
|
|
// open stream
|
|
//
|
|
std::ifstream ifs;
|
|
ifs.open(filename);
|
|
if (!ifs.is_open())
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "LoadDatabase: Unable to open:" << "\"" << filename << "\".";
|
|
error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop
|
|
}
|
|
|
|
// read input
|
|
//
|
|
read_database(istream_getc, &ifs);
|
|
#else
|
|
// open file
|
|
//
|
|
FILE* f = fopen(filename, "r");
|
|
if (!f)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "LoadDatabase: Unable to open:" << "\"" << filename << "\".";
|
|
error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop
|
|
}
|
|
|
|
// read input
|
|
//
|
|
read_database(getc_callback, f);
|
|
#endif
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "LoadDatabase: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
s_IPhreeqc.m_bDatabaseLoaded = (input_error == 0);
|
|
return input_error;
|
|
}
|
|
|
|
int
|
|
LoadDatabaseString(const char* input)
|
|
{
|
|
try
|
|
{
|
|
// cleanup
|
|
//
|
|
UnLoadDatabase();
|
|
|
|
CSelectedOutput::Instance()->Clear();
|
|
|
|
std::string s(input);
|
|
std::istringstream iss(s);
|
|
|
|
// read input
|
|
//
|
|
read_database(istream_getc, &iss);
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "LoadDatabaseString: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
s_IPhreeqc.m_bDatabaseLoaded = (input_error == 0);
|
|
return input_error;
|
|
}
|
|
|
|
void
|
|
UnLoadDatabase(void)
|
|
{
|
|
// init IPhreeqc
|
|
//
|
|
s_IPhreeqc.m_pIErrorReporter = &s_errorReporter;
|
|
s_IPhreeqc.m_bDatabaseLoaded = false;
|
|
s_IPhreeqc.m_bSelectedOutputOn = false;
|
|
|
|
// clear error state
|
|
//
|
|
s_errorReporter.Clear();
|
|
|
|
// free selectedoutput
|
|
//
|
|
CSelectedOutput::Release();
|
|
|
|
// initialize phreeqc
|
|
//
|
|
clean_up();
|
|
add_output_callback(handler, &s_IPhreeqc);
|
|
do_initialize();
|
|
input_error = 0;
|
|
}
|
|
|
|
|
|
void
|
|
OutputLastError(void)
|
|
{
|
|
std::cout << s_errorReporter.GetOS()->str().c_str() << std::endl;
|
|
}
|
|
|
|
const char*
|
|
GetLastErrorString(void)
|
|
{
|
|
static std::string str;
|
|
str = s_errorReporter.GetOS()->str();
|
|
return str.c_str();
|
|
}
|
|
|
|
// COMMENT: {11/27/2006 7:00:49 PM}#if defined(_WIN32)
|
|
// COMMENT: {11/27/2006 7:00:49 PM}void
|
|
// COMMENT: {11/27/2006 7:00:49 PM}DebugOutputLastError(void)
|
|
// COMMENT: {11/27/2006 7:00:49 PM}{
|
|
// COMMENT: {11/27/2006 7:00:49 PM} std::istringstream iss(s_errorReporter.GetOS()->str());
|
|
// COMMENT: {11/27/2006 7:00:49 PM} std::string line;
|
|
// COMMENT: {11/27/2006 7:00:49 PM} while (std::getline(iss, line)) {
|
|
// COMMENT: {11/27/2006 7:00:49 PM} ::OutputDebugString(line.c_str());
|
|
// COMMENT: {11/27/2006 7:00:49 PM} ::OutputDebugString("\n");
|
|
// COMMENT: {11/27/2006 7:00:49 PM} }
|
|
// COMMENT: {11/27/2006 7:00:49 PM}}
|
|
// COMMENT: {11/27/2006 7:00:49 PM}#endif
|
|
|
|
|
|
VRESULT
|
|
AccumulateLine(const char *line)
|
|
{
|
|
try
|
|
{
|
|
s_errorReporter.Clear();
|
|
s_string_input.append(line);
|
|
s_string_input.append("\n");
|
|
return VR_OK;
|
|
}
|
|
catch (...)
|
|
{
|
|
s_errorReporter.AddError("AccumulateLine: An unhandled exception occured.\n");
|
|
}
|
|
return VR_OUTOFMEMORY;
|
|
}
|
|
|
|
int
|
|
Run(int output_on, int error_on, int log_on, int selected_output_on)
|
|
{
|
|
static const char *sz_routine = "Run";
|
|
try
|
|
{
|
|
// this may throw
|
|
check_database(sz_routine);
|
|
|
|
input_error = 0;
|
|
|
|
// create input stream
|
|
std::istringstream iss(GetAccumulatedLines());
|
|
|
|
// this may throw
|
|
do_run(sz_routine, &iss, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL);
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "Run: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
::ClearAccumulatedLines();
|
|
close_output_files();
|
|
return input_error;
|
|
}
|
|
|
|
int
|
|
RunFile(const char* filename, int output_on, int error_on, int log_on, int selected_output_on)
|
|
{
|
|
static const char *sz_routine = "RunFile";
|
|
try
|
|
{
|
|
// this may throw
|
|
check_database(sz_routine);
|
|
|
|
input_error = 0;
|
|
|
|
#if 0
|
|
// create input stream
|
|
std::ifstream ifs;
|
|
ifs.open(filename);
|
|
if (!ifs.is_open())
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "RunFile: Unable to open:" << "\"" << filename << "\".";
|
|
input_error = 1;
|
|
error_msg(oss.str().c_str(), STOP); // throws
|
|
}
|
|
|
|
// this may throw
|
|
do_run(sz_routine, &ifs, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL);
|
|
#else
|
|
// open file
|
|
//
|
|
FILE* f = fopen(filename, "r");
|
|
if (!f)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "RunFile: Unable to open:" << "\"" << filename << "\".";
|
|
error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop
|
|
}
|
|
|
|
// this may throw
|
|
do_run(sz_routine, NULL, f, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL);
|
|
#endif
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "RunFile: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
close_output_files();
|
|
return input_error;
|
|
}
|
|
|
|
int
|
|
RunString(const char* input, int output_on, int error_on, int log_on, int selected_output_on)
|
|
{
|
|
static const char *sz_routine = "RunString";
|
|
try
|
|
{
|
|
// this may throw
|
|
check_database(sz_routine);
|
|
|
|
input_error = 0;
|
|
|
|
// create input stream
|
|
std::string s(input);
|
|
std::istringstream iss(s);
|
|
|
|
// this may throw
|
|
do_run(sz_routine, &iss, NULL, output_on, error_on, log_on, selected_output_on, NULL, NULL, NULL);
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "RunString: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
close_output_files();
|
|
return input_error;
|
|
}
|
|
|
|
|
|
int
|
|
GetSelectedOutputRowCount(void)
|
|
{
|
|
return (int)CSelectedOutput::Instance()->GetRowCount();
|
|
}
|
|
|
|
int
|
|
GetSelectedOutputColumnCount(void)
|
|
{
|
|
return (int)CSelectedOutput::Instance()->GetColCount();
|
|
}
|
|
|
|
VRESULT
|
|
GetSelectedOutputValue(int row, int col, VAR* pVAR)
|
|
{
|
|
s_errorReporter.Clear();
|
|
if (!pVAR) {
|
|
s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDARG pVar is NULL.\n");
|
|
return VR_INVALIDARG;
|
|
}
|
|
|
|
VRESULT v = CSelectedOutput::Instance()->Get(row, col, pVAR);
|
|
switch (v) {
|
|
case VR_OK:
|
|
break;
|
|
case VR_OUTOFMEMORY:
|
|
s_errorReporter.AddError("GetSelectedOutputValue: VR_OUTOFMEMORY Out of memory.\n");
|
|
break;
|
|
case VR_BADVARTYPE:
|
|
s_errorReporter.AddError("GetSelectedOutputValue: VR_BADVARTYPE pVar must be initialized(VarInit) and/or cleared(VarClear).\n");
|
|
break;
|
|
case VR_INVALIDARG:
|
|
// not possible
|
|
break;
|
|
case VR_INVALIDROW:
|
|
s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDROW Row index out of range.\n");
|
|
break;
|
|
case VR_INVALIDCOL:
|
|
s_errorReporter.AddError("GetSelectedOutputValue: VR_INVALIDCOL Column index out of range.\n");
|
|
break;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
size_t
|
|
AddError(const char* error_msg)
|
|
{
|
|
return s_errorReporter.AddError(error_msg);
|
|
}
|
|
|
|
void
|
|
OutputLines(void)
|
|
{
|
|
std::cout << s_string_input.c_str() << std::endl;
|
|
}
|
|
|
|
// COMMENT: {11/27/2006 7:01:16 PM}#if defined(WIN32)
|
|
// COMMENT: {11/27/2006 7:01:16 PM}void
|
|
// COMMENT: {11/27/2006 7:01:16 PM}DebugOutputLines(void)
|
|
// COMMENT: {11/27/2006 7:01:16 PM}{
|
|
// COMMENT: {11/27/2006 7:01:16 PM} std::istringstream iss(s_string_input);
|
|
// COMMENT: {11/27/2006 7:01:16 PM} std::string line;
|
|
// COMMENT: {11/27/2006 7:01:16 PM} while (std::getline(iss, line)) {
|
|
// COMMENT: {11/27/2006 7:01:16 PM} ::OutputDebugString(line.c_str());
|
|
// COMMENT: {11/27/2006 7:01:16 PM} ::OutputDebugString("\n");
|
|
// COMMENT: {11/27/2006 7:01:16 PM} }
|
|
// COMMENT: {11/27/2006 7:01:16 PM}}
|
|
// COMMENT: {11/27/2006 7:01:16 PM}#endif
|
|
|
|
const std::string&
|
|
GetAccumulatedLines(void)
|
|
{
|
|
return s_string_input;
|
|
}
|
|
|
|
void
|
|
ClearAccumulatedLines(void)
|
|
{
|
|
s_string_input.erase();
|
|
}
|
|
|
|
int
|
|
RunWithCallback(PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie, int output_on, int error_on, int log_on, int selected_output_on)
|
|
{
|
|
static const char *sz_routine = "RunWithCallback";
|
|
try
|
|
{
|
|
// this may throw
|
|
check_database(sz_routine);
|
|
|
|
input_error = 0;
|
|
|
|
// this may throw
|
|
do_run(sz_routine, NULL, NULL, output_on, error_on, log_on, selected_output_on, pfn_pre, pfn_post, cookie);
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch(...)
|
|
{
|
|
const char *errmsg = "RunWithCallback: An unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
ClearAccumulatedLines();
|
|
close_output_files();
|
|
output_close(OUTPUT_DUMP); // this should be closed in close_output_files
|
|
return input_error;
|
|
}
|
|
|
|
|
|
int
|
|
CatchErrors(PFN_CATCH_CALLBACK pfn, void *cookie)
|
|
{
|
|
int rvalue = OK;
|
|
try
|
|
{
|
|
input_error = 0;
|
|
|
|
if (pfn)
|
|
{
|
|
rvalue = pfn(cookie);
|
|
}
|
|
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
catch (...)
|
|
{
|
|
const char errmsg[] = "CatchErrors: Unhandled exception occured.\n";
|
|
try
|
|
{
|
|
error_msg(errmsg, STOP); // throws PhreeqcStop
|
|
}
|
|
catch (PhreeqcStop)
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
return rvalue;
|
|
}
|
|
|
|
static void
|
|
check_database(const char* sz_routine)
|
|
{
|
|
s_errorReporter.Clear();
|
|
CSelectedOutput::Instance()->Clear();
|
|
|
|
if (!s_IPhreeqc.m_bDatabaseLoaded)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": No database is loaded";
|
|
input_error = 1;
|
|
error_msg(oss.str().c_str(), STOP); // throws PhreeqcStop
|
|
}
|
|
}
|
|
|
|
static void
|
|
do_run(const char* sz_routine, std::istream* pis, FILE* fp, int output_on, int error_on, int log_on, int selected_output_on, PFN_PRERUN_CALLBACK pfn_pre, PFN_POSTRUN_CALLBACK pfn_post, void *cookie)
|
|
{
|
|
std::auto_ptr<std::istringstream> auto_iss(NULL);
|
|
char token[MAX_LENGTH];
|
|
|
|
if (output_on)
|
|
{
|
|
if (output_open(OUTPUT_MESSAGE, OUTPUT_FILENAME) != OK)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Unable to open:" << "\"" << OUTPUT_FILENAME << "\".\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
}
|
|
if (error_on)
|
|
{
|
|
if (output_open(OUTPUT_ERROR, ERROR_FILENAME) != OK)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Unable to open:" << "\"" << ERROR_FILENAME << "\".\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
}
|
|
if (log_on)
|
|
{
|
|
if (output_open(OUTPUT_LOG, LOG_FILENAME) != OK)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Unable to open:" << "\"" << LOG_FILENAME << "\".\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
}
|
|
|
|
s_IPhreeqc.m_bSelectedOutputOn = (selected_output_on != 0);
|
|
|
|
/*
|
|
* call pre-run callback
|
|
*/
|
|
if (pfn_pre)
|
|
{
|
|
pfn_pre(cookie);
|
|
}
|
|
|
|
/*
|
|
* set read callback
|
|
*/
|
|
if (!pis)
|
|
{
|
|
if (fp)
|
|
{
|
|
set_read_callback(getc_callback, fp, FALSE);
|
|
}
|
|
else
|
|
{
|
|
std::auto_ptr<std::istringstream> a_iss(new std::istringstream(GetAccumulatedLines()));
|
|
auto_iss = a_iss;
|
|
set_read_callback(istream_getc, auto_iss.get(), FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
set_read_callback(istream_getc, pis, FALSE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Read input data for simulation
|
|
*/
|
|
for (simulation = 1; ; simulation++) {
|
|
|
|
#ifdef PHREEQ98
|
|
AddSeries = !connect_simulations;
|
|
#endif
|
|
sprintf(token, "Reading input data for simulation %d.", simulation);
|
|
|
|
output_msg(OUTPUT_GUI_ERROR, "\nSimulation %d\n", simulation);
|
|
|
|
#ifdef SWIG_SHARED_OBJ
|
|
int save_punch_in = punch.in;
|
|
#endif // SWIG_SHARED_OBJ
|
|
dup_print(token, TRUE);
|
|
if (read_input() == EOF) break;
|
|
|
|
#ifdef SWIG_SHARED_OBJ
|
|
if (simulation > 1 && save_punch_in == TRUE && punch.new_def == TRUE)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Warning SELECTED_OUTPUT has been redefined.\n";
|
|
warning_msg(oss.str().c_str());
|
|
|
|
}
|
|
if (simulation > 1 && keyword[39].keycount > 0)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Warning USER_PUNCH has been redefined.\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
#endif // SWIG_SHARED_OBJ
|
|
|
|
if (title_x != NULL) {
|
|
sprintf(token, "TITLE");
|
|
dup_print(token, TRUE);
|
|
if (pr.headings == TRUE) output_msg(OUTPUT_MESSAGE,"%s\n\n", title_x);
|
|
}
|
|
|
|
#ifdef SWIG_SHARED_OBJ
|
|
if (punch.in == TRUE)
|
|
{
|
|
//
|
|
// (punch.in == TRUE) when any "RUN" has contained
|
|
// a SELECTED_OUTPUT block since the last LoadDatabase call.
|
|
//
|
|
// Since LoadDatabase inititializes punch.in to FALSE
|
|
// (via UnLoadDatabase...do_initialize)
|
|
// and punch.in is set to TRUE in read_selected_output
|
|
//
|
|
// This causes the SELECTED_OUTPUT to contain the same headings
|
|
// until another SELECTED_OUTPUT is defined which sets the variable
|
|
// punch.new_def to TRUE
|
|
//
|
|
// WHAT IF A USER_PUNCH IS DEFINED?? IS punch.new_def SET TO
|
|
// TRUE ???
|
|
//
|
|
//
|
|
if (!selected_output_on) ASSERT(!::output_isopen(OUTPUT_PUNCH));
|
|
|
|
if (pr.punch == FALSE)
|
|
{
|
|
// No selected_output for this simulation
|
|
// this happens when
|
|
// PRINT; -selected_output false
|
|
// is given as input
|
|
// Note: this also disables the CSelectedOutput object
|
|
}
|
|
else
|
|
{
|
|
if (punch.new_def == FALSE)
|
|
{
|
|
if (selected_output_on && !::output_isopen(OUTPUT_PUNCH))
|
|
{
|
|
//
|
|
// LoadDatabase
|
|
// do_run -- containing SELECTED_OUTPUT ****TODO**** check -file option
|
|
// another do_run without SELECTED_OUTPUT
|
|
//
|
|
std::string filename = s_IPhreeqc.m_sPunchFileName;
|
|
output_open(OUTPUT_PUNCH, filename.c_str());
|
|
if (!::output_isopen(OUTPUT_PUNCH))
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Unable to open:" << "\"" << filename << "\".\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
else
|
|
{
|
|
// output selected_output headings
|
|
punch.new_def = TRUE;
|
|
tidy_punch();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (selected_output_on && !::output_isopen(OUTPUT_PUNCH))
|
|
{
|
|
// This is a special case which could not occur in
|
|
// phreeqc
|
|
//
|
|
// LoadDatabase
|
|
// do_run -- containing SELECTED_OUTPUT ****TODO**** check -file option
|
|
// another do_run with SELECTED_OUTPUT
|
|
//
|
|
std::string filename = PUNCH_FILENAME;
|
|
if (s_IPhreeqc.m_sPunchFileName && ::strlen(s_IPhreeqc.m_sPunchFileName))
|
|
{
|
|
filename = s_IPhreeqc.m_sPunchFileName;
|
|
}
|
|
output_open(OUTPUT_PUNCH, filename.c_str());
|
|
if (!::output_isopen(OUTPUT_PUNCH))
|
|
{
|
|
std::ostringstream oss;
|
|
oss << sz_routine << ": Unable to open:" << "\"" << filename << "\".\n";
|
|
warning_msg(oss.str().c_str());
|
|
}
|
|
else
|
|
{
|
|
// output selected_output headings
|
|
ASSERT(punch.new_def == TRUE);
|
|
tidy_punch();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!selected_output_on) ASSERT(!::output_isopen(OUTPUT_PUNCH));
|
|
/* the converse is not necessarily true */
|
|
|
|
n_user_punch_index = -1;
|
|
#endif // SWIG_SHARED_OBJ
|
|
tidy_model();
|
|
#ifdef PHREEQC_CPP
|
|
//test_classes();
|
|
#endif
|
|
#ifdef PHREEQ98
|
|
if (!phreeq98_debug) {
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Calculate distribution of species for initial solutions
|
|
*/
|
|
if (new_solution) initial_solutions(TRUE);
|
|
/*
|
|
* Calculate distribution for exchangers
|
|
*/
|
|
if (new_exchange) initial_exchangers(TRUE);
|
|
/*
|
|
* Calculate distribution for surfaces
|
|
*/
|
|
if (new_surface) initial_surfaces(TRUE);
|
|
/*
|
|
* Calculate initial gas composition
|
|
*/
|
|
if (new_gas_phase) initial_gas_phases(TRUE);
|
|
/*
|
|
* Calculate reactions
|
|
*/
|
|
reactions();
|
|
/*
|
|
* Calculate inverse models
|
|
*/
|
|
inverse_models();
|
|
/*
|
|
* Calculate advection
|
|
*/
|
|
if (use.advect_in == TRUE) {
|
|
dup_print ("Beginning of advection calculations.", TRUE);
|
|
advection();
|
|
}
|
|
/*
|
|
* Calculate transport
|
|
*/
|
|
if (use.trans_in == TRUE) {
|
|
dup_print ("Beginning of transport calculations.", TRUE);
|
|
transport();
|
|
}
|
|
|
|
#ifdef PHREEQC_CPP
|
|
/*
|
|
* run
|
|
*/
|
|
run_as_cells();
|
|
#endif
|
|
|
|
/*
|
|
* Copy
|
|
*/
|
|
if (new_copy) copy_entities();
|
|
#ifdef PHREEQC_CPP
|
|
|
|
/*
|
|
* dump
|
|
*/
|
|
dump_entities();
|
|
/*
|
|
* delete
|
|
*/
|
|
delete_entities();
|
|
#endif
|
|
|
|
/*
|
|
* End of simulation
|
|
*/
|
|
dup_print( "End of simulation.", TRUE);
|
|
#ifdef PHREEQ98
|
|
} /* if (!phreeq98_debug) */
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Display successful status
|
|
*/
|
|
do_status();
|
|
|
|
/*
|
|
* call post-run callback
|
|
*/
|
|
if (pfn_post)
|
|
{
|
|
pfn_post(cookie);
|
|
}
|
|
|
|
if (input_error > 0)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "<input>\n";
|
|
oss << s_string_input.c_str();
|
|
oss << "</input>\n";
|
|
error_msg(oss.str().c_str(), CONTINUE);
|
|
}
|
|
}
|