Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Diplom3.pdf
Скачиваний:
143
Добавлен:
09.02.2015
Размер:
1.48 Mб
Скачать

ПРИЛОЖЕНИЕ А

Листинги ключевых частей программы

1. Классы SingleFieldValue, FieldValue, Parameter, и Dict

class SingleFieldValue //отдельное значение поля

{

public: SingleFieldValue()

{

for(int i = 0; i < 9; ++i)

val[i] = 0; //значение поля по умолчанию 0

}

double val[9]; //максимум 9 значений для тензорного поля double& operator[](uint index)

{

return val[index];

}

};

class FieldValue //значение поля, однородное или неоднородное

{

public: FieldValue()

{

isUniform = true; //по умолчанию значение однородное

}

SingleFieldValue uniformVal; //значение в случае однородного поля

QList<SingleFieldValue> nonUniformVal; //в случае неоднородного bool isUniform; //признак однородности

};

class Parameter //такстовый параметр словаря

{

public: Parameter()

{

}

Parameter(QByteArray paramName, QByteArray paramVal) : name(paramName), val(paramVal)

{

}

QByteArray name, val; //имя и значение параметра

QByteArray& operator[](int index)

{

if(index % 2 == 0) return name;

return val;

}

};

class Dict //базовый абстрактный класс, в нем реализованы основные функции { //для парсинга

public:

Dict(); //далее параметры заголовка

QByteArray version;

QByteArray format; QByteArray objClass; QByteArray location; QByteArray object;

78

QByteArray arr; //массив с содержимым считанного файла

int ind;

//индекс текущего сканируемого символа массива arr

int fileLen;

//Длина массива arr

virtual int CopyDict() = 0;

//функция-парсер

virtual int PrepareToSave() = 0;//записывает в массив arr

 

 

 

//cсодержимое объекта в нужном формате

protected:

 

//пропускает пробелы и комментарии

int ParseSenseless();

int ParseSemi();

 

//сканировать точку с запятой

int ParseOpeningParenthesis();//сканировать (

int ParseClosingParenthesis();//сканировать )

int ParseOpeningBrace();

 

//сканировать {

int ParseClosingBrace();

 

//сканировать}

int ParseOpeningSquareBrace();

//сканировать [

int ParseClosingSquareBrace();

//сканировать ]

int ParseOpeningBrocket();

//сканировать <

int ParseClosingBrocket();

//сканировать >

int ParseHeader();

 

 

//сканировать заголовок файла

int ParseHeaderParams();

 

//сканировать параметры заголовка

virtual int ParseClass(QByteArray) = 0; //сканировать класс из заголовка

virtual int ParseObject(QByteArray) = 0; //сканировать объект из

 

 

 

//заголовка

virtual int ParseLocation(QByteArray) = 0; //сканировать локацию из

 

 

 

//заголовка

void WriteHeader();

 

//вписать заголовок в массив arr

QByteArray GetWord();

//возвращает слово, начинающееся с индекса ind

QByteArray separators;

//содержит символы-разделители

QByteArray specSymbols; //содержит специальные симолвы (скобки,например)

uint line;

 

//номер сканируемой строки

//для патчей

//отображает строковый тип патча

QMap <QByteArray, int> strTypeToInt;

};

//в целое число

Dict::Dict(): //конструктор по умолчанию version("2.0"),

format("ascii"), objClass("dictionary"), ind(0),

fileLen(0), separators(" \t\n"), specSymbols(";"), line(1)

{

//инициализация ассоциативного массива, отображающего текстовые типы патчей в //целые числа

strTypeToInt["patch"] = BasicTypes_patch; strTypeToInt["symmetryPlane"] = BasicTypes_symmetryPlane; strTypeToInt["empty"] = BasicTypes_empty; strTypeToInt["wedge"] = BasicTypes_wedge; strTypeToInt["cyclic"] = BasicTypes_cyclic; strTypeToInt["wall"] = BasicTypes_wall; strTypeToInt["processor"] = BasicTypes_processor;

}

void Dict::WriteHeader() //функция для записи заголовка в массив arr

{

arr += "// This file was created using OpenFOAM interface tool. //\n"; arr += "FoamFile\n{\n\tversion\t\t";

arr += version;

arr += ";\n\tformat\t\t"; arr += format;

arr += ";\n\tclass\t\t";

79

arr += objClass;

if(!location.isEmpty()) //опциональное поле

{

arr += ";\n\tlocation\t\t"; arr += location;

}

arr += ";\n\tobject\t\t"; arr += object;

arr += ";\n}\n// * * * * * * * * * * * * * * * * * * * * * * * * * * * *

* * * * * * * * * //\n\n";

}

int Dict::ParseSenseless() //пропускает разделители и комментарии

{

QByteArray dbg;

//строка для дебага

bool again;

 

do

 

{

//если конец файла

if(ind >= fileLen)

return -1;

//возвращает -1

again = false;

 

//однострочный комментарий

if(ind < fileLen - 1 && arr[ind] == '/' && arr[ind + 1] == '/' )

{

while(ind < fileLen && arr[ind] != '\n')

{

dbg += arr[ind]; ++ind;

}

if(ind == fileLen) return -1; ++ind;

++line; again = true;

}

//многострочный комментарий

else if(ind < fileLen - 1 && arr[ind] == '/' && arr[ind + 1] == '*')

{

while(ind < fileLen - 1 && !(arr[ind] == '*' && arr[ind + 1] == '/'))

{

if(arr[ind] == '\n') ++line;

dbg += arr[ind]; ++ind;

}

if(ind == fileLen - 1) return -1; ind += 2;

again = true;

}

//символы - разделители else if(separators.indexOf(arr[ind]) != -1)

{

while(ind < fileLen && separators.indexOf(arr[ind]) != -1)

{

if(arr[ind] == '\n') ++line;

dbg += arr[ind]; ++ind;

}

if(ind == fileLen) return -1; again = true;

}

}while(again);

80

#ifdef SHOW_SENSELESS

qDebug(dbg); //вывод в окно дебаггера

#endif return 0;

}

int Dict::ParseHeader() //сканировать заголовок

{

int retval;

QByteArray buf = GetWord();

if(buf != "FoamFile") //если нет имени словаря FoamFile=>ошибка return ParseError_noHeader;

if(ParseSenseless() == -1) return -1;

if(arr[ind] != '{') //начало содержимого словаря return ParseError_noHeaderBody;

++ind;

if(ind >= fileLen) return -1;

while(arr[ind] != '}') //в теле парсим параметры заголовка

{

retval = ParseHeaderParams(); if(retval != 0)

return retval;

}

if(ParseSenseless() == -1) return -1;

if(arr[ind] != '}') //конец подсловаря FoamFile return ParseError_headerBodyNotClosed;

++ind; return 0;

}

QByteArray Dict::GetWord() //возвращает слово на позиции ind

{

QByteArray retval;

//пока символ — не разделитель и не специальный символ

while(ind < fileLen && (separators + specSymbols).indexOf(arr[ind]) == -1)

retval += arr[ind++]; //прибавляем букву в конец слова

#ifdef SHOW_CURRENT_WORD

qDebug(retval); //дебаг #endif

return retval;

}

int Dict::ParseHeaderParams() //сканирует параметры заголовка

{

int r;

 

QByteArray param, val;

//у параметра есть текстовые имя и значение

if(ParseSenseless() == -1)

return -1;

//считываем сначала имя параметра

param = GetWord();

if(ParseSenseless() == -1)

return -1;

 

val = GetWord();

//затем его значение

if(ParseSenseless() == -1)

return -1;

//параметр version

if(param == "version")

{

 

version = val;

 

}

else if(param == "format") //параметр format

{

if(val == "ascii")

81

format = val;

else

return ParseError_invalidParamVal;

}

else if(param == "class") //параметр class

{

if((r = ParseClass(val)) != 0) return r;

}

else if(param == "location")

{

if((r = ParseLocation(val)) != 0) //параметр location return r;

}

else if(param == "object") //параметр object

{

if((r = ParseObject(val)) != 0) return r;

}

 

 

else

 

 

return ParseError_unknownParam;

//неизвестный параметр => ошибка

if(arr[ind] != ';')

 

//пропущена точка с запятой

return ParseError_semiMissing;

 

++ind;

 

 

if(ParseSenseless() == -1)

 

return -1;

 

 

return 0;

 

 

}

 

 

int Dict::ParseSemi()

//сканировать точку с запятой

{

 

 

if(arr[ind] != ';')

 

 

return ParseError_semiMissing; ++ind;

return 0;

}

int Dict::ParseOpeningParenthesis() //сканировать (

{

if(arr[ind] != '(')

return parseError_noOpeningParenthesis; ++ind;

return 0;

}

int Dict::ParseClosingParenthesis()//сканировать )

{

if(arr[ind] != ')')

return parseError_noClosingParenthesis; ++ind;

return 0;

}

int Dict::ParseOpeningBrace()//сканировать {

{

if(arr[ind] != '{')

return parseError_noOpeningBrace; ++ind;

return 0;

}

int Dict::ParseClosingBrace()//сканировать }

{

if(arr[ind] != '}')

return parseError_noClosingBrace; ++ind;

return 0;

82

}

int Dict::ParseOpeningSquareBrace()//сканировать [

{

if(arr[ind] != '[')

return parseError_noOpeningSquareBrace; ++ind;

return 0;

}

int Dict::ParseClosingSquareBrace()//сканировать ]

{

if(arr[ind] != ']')

return parseError_noClosingSquareBrace; ++ind;

return 0;

}

int Dict::ParseOpeningBrocket()//сканировать <

{

if(arr[ind] != '<')

return parseError_noOpeningBrocket; ++ind;

return 0;

}

int Dict::ParseClosingBrocket()//сканировать >

{

if(arr[ind] != '>')

return parseError_noClosingBrocket; ++ind;

return 0;

}

2. Класс ControlDict

class ControlDict : public Dict

{

public:

//ассоциативные массивы для отображения целочисленого значения параметра //перечислимого типа в строку

QMap <int, QByteArray> enumParamVal_StringByNum[7];

//ассоциативный массив для отображения строкового имени перечислимого //параметра в его целочисленный индекс в QComboBox-е

QMap <QByteArray, int> enumParamName_NumByString;

public:

 

 

ControlDict();

 

 

int enumParams[7];

//что какой означает - см. в конструкторе

QByteArray stringParams[2];

//строковые параметры

double doubleParams[4]; //дробные параметры

uint intParams[3];

//целочисленные параметры

bool boolParams[1]; //логические параметры

 

//список с именами строковых параметров

QList <QByteArray> stringParamsList;

 

//список с именами double параметров

QList <QByteArray> doubleParamsList;

 

//список с именами Int-параметров

QList <QByteArray> intParamsList;

 

//список с именами bool-параметров

QList <QByteArray> boolParamsList;

//другие параметры, значения и имена которых задаются строками

QList <Parameter> otherParams;

 

int CopyDict();

//функция-парсер

int PrepareToSave();//записывает содержимое полей класса в массив arr в //формате, требуемом OpenFOAM

private:

83

int ParseControlParams(); //Сканирует параметры controlDict-а void ShowParseStatus(int r); //выводит в дебаг процесс парсинга

void InitDefaultParamVals(); //инициализировать значения параметров по //умолчанию

void SaveDefaultParamVals(); //сохранить значения параметров, для которых //существует значение по умолчанию

void RestoreDefaultParamVals();//восстановить значения параметров по //умолчанию

int ParseClass(QByteArray val); //Сканирует класс из заголовка int ParseLocation(QByteArray val);//Сканирует путь из заголовка

int ParseObject(QByteArray val);//Сканирует поле «объект» из заголовка int enumSaved[5]; //сохраненные значения параметров по умолчанию

 

//перечислимого типа

double doubleSaved[1];

//-||- типа

double

uint

intSaved[2];

//-||-

типа

uint

bool

boolSaved[1];

//-||-

типа

bool

}; ControlDict::ControlDict()

{

//инициализация ассоциативных массивов enumParamVal_StringByNum[0][StartFrom_firstTime = QByteArray("firstTime"); enumParamVal_StringByNum[0][StartFrom_startTime] = QByteArray("startTime"); enumParamVal_StringByNum[0][StartFrom_latestTime]=QByteArray("latestTime"); enumParamVal_StringByNum[1][StopAt_endTime] = QByteArray("endTime"); enumParamVal_StringByNum[1][StopAt_writeNow] = QByteArray("writeNow"); enumParamVal_StringByNum[1][StopAt_noWriteNow] = QByteArray("noWriteNow"); enumParamVal_StringByNum[1][StopAt_nextWrite] = QByteArray("nextWrite"); enumParamVal_StringByNum[2][WriteControl_timeStep]= QByteArray("timeStep"); enumParamVal_StringByNum[2][WriteControl_runTime] = QByteArray("runTime"); enumParamVal_StringByNum[2][WriteControl_adjustableRunTime]

=QByteArray("adjustableRunTime"); enumParamVal_StringByNum[2][WriteControl_cpuTime] = QByteArray("cpuTime"); enumParamVal_StringByNum[2][WriteControl_clockTime] =

QByteArray("clockTime"); enumParamVal_StringByNum[3][WriteFormat_ascii] = QByteArray("ascii"); enumParamVal_StringByNum[3][WriteFormat_binary] = QByteArray("binary"); enumParamVal_StringByNum[4][WriteCompression_off] = QByteArray("off"); enumParamVal_StringByNum[4][WriteCompression_on] = QByteArray("on"); enumParamVal_StringByNum[4][WriteCompression_compressed] =

QByteArray("uncompressed"); enumParamVal_StringByNum[4][WriteCompression_uncompressed] =

QByteArray("compressed"); enumParamVal_StringByNum[4][WriteCompression_false] = QByteArray("false"); enumParamVal_StringByNum[4][WriteCompression_true] = QByteArray("true"); enumParamVal_StringByNum[4][WriteCompression_no] = QByteArray("no"); enumParamVal_StringByNum[4][WriteCompression_yes] = QByteArray("yes"); enumParamVal_StringByNum[5][TimeFormat_fixed] = QByteArray("fixed"); enumParamVal_StringByNum[5][TimeFormat_scientific] =

QByteArray("scientific"); enumParamVal_StringByNum[5][TimeFormat_general] = QByteArray("general"); enumParamVal_StringByNum[6][GraphFormat_raw] = QByteArray("raw"); enumParamVal_StringByNum[6][GraphFormat_gnuplot] = QByteArray("gnuplot"); enumParamVal_StringByNum[6][GraphFormat_xmgr] = QByteArray("xmgr"); enumParamVal_StringByNum[6][GraphFormat_jplot] = QByteArray("jplot"); enumParamName_NumByString["startFrom"] = 1; enumParamName_NumByString["stopAt"] = 2; enumParamName_NumByString["writeControl"] = 3; enumParamName_NumByString["writeFormat"] = 4; enumParamName_NumByString["writeCompression"] = 5; enumParamName_NumByString["timeFormat"] = 6; enumParamName_NumByString["graphFormat"] = 7;

for(int i = 0; i < 7; i++)

84

enumParams[i] = -1; ind = 0;

//инициализация списков имен параметров stringParamsList += "application"; stringParamsList += "libs"; doubleParamsList += "startTime"; doubleParamsList += "endTime"; doubleParamsList += "deltaT"; doubleParamsList += "writeInterval"; intParamsList += "purgeWrite"; intParamsList += "writePrecision"; intParamsList += "timePrecision"; boolParamsList += "runTimeModifiable";

//инициализировать значения параметров по умолчанию

InitDefaultParamVals();

}

int ControlDict::ParseClass(QByteArray val)//сканировать класс

{

if(val == "dictionary")

{

objClass = val; return 0;

}

else

return ParseError_invalidParamVal;

}

int ControlDict::ParseLocation(QByteArray val)//сканировать путь

{

if(val == "\"system\"")

{

location = val; return 0;

}

else

return ParseError_invalidParamVal;

}

int ControlDict::ParseObject(QByteArray val)//сканировать объект

{

if(val == "controlDict")

{

object = val; return 0;

}

else

return ParseError_invalidParamVal;

}

void ControlDict::SaveDefaultParamVals()//сохранить значения параметров,

{ //для которых существует значение по умолчанию enumSaved[0] = enumParams[2];

doubleSaved[0] = doubleParams[0]; enumSaved[1] = enumParams[3]; intSaved[0] = intParams[0]; enumSaved[2] = enumParams[4]; enumSaved[3] = enumParams[5]; intSaved[1] = intParams[1]; enumSaved[4] = enumParams[6]; boolSaved[0] = boolParams[0];

}

void ControlDict::RestoreDefaultParamVals()//восстановить значения параметров //для которых существует значение по умолчанию, из сохраненных

{

enumParams[2] = enumSaved[0];

85

doubleParams[0] = doubleSaved[0]; enumParams[3] = enumSaved[1]; intParams[0] = intSaved[0]; enumParams[4] = enumSaved[2]; enumParams[5] = enumSaved[3]; intParams[1] = intSaved[1]; enumParams[6] = enumSaved[4]; boolParams[0] = boolSaved[0];

}

void ControlDict::InitDefaultParamVals()

//инициализировать значения параметров по умолчанию

{

enumParams[2] = WriteControl_timeStep; doubleParams[0] = 0;

enumParams[3] = WriteFormat_ascii; intParams[0] = 6;

enumParams[4] = WriteCompression_off; enumParams[5] = TimeFormat_general; intParams[1] = 6;

enumParams[6] = GraphFormat_raw; boolParams[0] = true;

}

int ControlDict::ParseControlParams()//сканировать параметры controlDict-а

{

QByteArray param, val;//текстовые имя параметра и его значение uint itemp;

double dtemp;

bool convOk; //признак успешной конвертации if(ParseSenseless() == -1)

return -1; param = GetWord();

if(ParseSenseless() == -1) return -1;

val = GetWord(); if(ParseSenseless() == -1)

return -1; int m;

if((m = enumParamName_NumByString[param]) != 0) //если параметр перечислимого типа

{

--m;

itemp = enumParamVal_StringByNum[m].key(val); //получаем ключ текстового параметра param

if(itemp == 0) //нет такого ключа, параметр неверный return ParseError_invalidParamVal;

enumParams[m] = itemp;

}

else if((m = stringParamsList.indexOf(param)) != -1) //параметр строковый

{

if(val == "")

return ParseError_invalidParamVal; stringParams[m] = val;

}

else if((m = doubleParamsList.indexOf(param)) != -1) //параметр типа double

{

dtemp = val.toDouble(&convOk); if(!convOk)

return ParseError_invalidParamVal; doubleParams[m] = dtemp;

}

86

else if((m = intParamsList.indexOf(param)) != -1)

//параметр типа int

{

 

itemp = val.toUInt(&convOk);

 

if(!convOk)

 

return ParseError_invalidParamVal;

 

intParams[m] = itemp;

 

}

 

else if((m = boolParamsList.indexOf(param)) != -1)

//параметр типа bool

{

if(val == "true" || val == "yes" || val == "on") boolParams[m] = true;

else if(val == "false" || val == "no" || val == "off") boolParams[m] = false;

else

return ParseError_invalidParamVal;

}

else

{

Parameter p(param, val); otherParams.append(p);

}

if(arr[ind] != ';')

return ParseError_semiMissing; ++ind;

ParseSenseless(); return 0;

}

void ControlDict::ShowParseStatus(int r)

//выводит в debug состояние парсера

{

QByteArray

dbg("Parser returned: ");

dbg += QByteArray::number(r);

dbg += "\nHeader info:\n";

 

dbg += "\tversion: ";

 

dbg += version;

 

 

dbg += "\n\tformat: ";

 

dbg += format;

 

 

dbg += "\n\tclass: ";

 

dbg += objClass;

 

 

dbg += "\n\tlocation: ";

 

dbg += location;

 

 

dbg += "\n\tojbect: ";

 

dbg += object;

 

 

dbg += "\n\nParams:\n";

 

for(int

i = 0; i < 7; i++)

//перечислимый тип

{

 

 

 

 

dbg

+=

"\tenumParams[";

 

dbg

+=

QByteArray::number(i);

dbg

+=

"]:

";

 

dbg

+=

enumParamVal_StringByNum[i][enumParams[i]];

dbg

+=

'\n';

 

 

}

 

 

 

 

for(int

i = 0; i < 2; i++)

//строковый тип

{

 

 

 

 

dbg

+=

"\tstringParams[";

dbg

+=

QByteArray::number(i);

dbg

+=

"]:

";

 

dbg

+=

stringParams[i];

 

dbg

+=

'\n';

 

 

}

 

 

 

 

for(int

i = 0; i < 4; i++)

 

{

 

 

 

 

87

dbg +=

"\tdoubleParams["; //тип double

dbg +=

QByteArray::number(i);

dbg +=

"]:

";

dbg

+=

QByteArray::number(doubleParams[i]);

dbg

+=

'\n';

 

}

for(int i = 0; i < 3; i++)

{

dbg +=

"\tintParams[";

//Тип int

dbg +=

QByteArray::number(i);

dbg +=

"]:

";

 

dbg

+=

QByteArray::number(intParams[i]);

dbg

+=

'\n';

 

 

}

for(int i = 0; i < 1; i++)

{

dbg +=

"\tboolParams[";

//тип bool

dbg

+=

QByteArray::number(i);

dbg

+=

"]:

";

 

if(boolParams[i])

 

 

dbg +=

"true";

 

else

dbg += "false"; dbg += '\n';

}

dbg += "\nind = ";

dbg += QByteArray::number(ind);//выводит текущий индекс dbg += "\nline = ";

dbg += QByteArray::number(line);//выводит строку, на которой закончилось //сканирование

qDebug(dbg.data());

}

int ControlDict::CopyDict() //функция-парсер

{

ind = 0; line = 1; int r = 0;

fileLen = arr.length(); #ifdef SHOWPARSESTATUS_CONTROL

qDebug("======= controlDict parse status ======="); #endif

SaveDefaultParamVals();

InitDefaultParamVals(); //когда открывается словарь, где не прописаны default параметры, поставить их значение на default

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

r = ParseHeader(); //сканирвать заголовок if(r != 0)

goto ret;

while(ind < fileLen) //до конца файла парсим параметры

{

r = ParseControlParams(); if(r != 0)

goto ret;

}

ret:

#ifdef SHOWPARSESTATUS_CONTROL ShowParseStatus(r);

#endif

88

if(r != 0)

RestoreDefaultParamVals(); //если словарь не открылся, восстанавливаем значения default-параметров

return r;

}

 

 

int ControlDict::PrepareToSave()

 

 

{

 

 

arr.clear();

 

 

//заголовок

 

 

WriteHeader();

 

 

arr += "application\t\t";

//application

arr += stringParams[0].data();

 

 

arr += ";\n\n";

 

 

arr += "startFrom\t\t";

//startFrom

 

arr += enumParamVal_StringByNum[0][enumParams[0]];

arr += ";\n\n";

 

 

if(enumParams[0] == StartFrom_startTime)

//startTime

{

 

 

arr += "startTime\t\t";

 

 

 

arr += QByteArray::number(doubleParams[0]);

 

arr += ";\n\n";

 

 

 

}

 

 

 

arr += "stopAt\t\t";

//stopAt

 

arr += enumParamVal_StringByNum[1][enumParams[1]];

 

arr += ";\n\n";

 

 

 

if(enumParams[1] == StopAt_endTime)

//endTime

 

{

 

 

 

arr += "endTime\t\t";

 

 

 

arr += QByteArray::number(doubleParams[1]);

 

arr += ";\n\n";

 

 

 

}

 

 

 

arr += "deltaT\t\t";

 

//deltaT

 

arr += QByteArray::number(doubleParams[2]);

 

arr += ";\n\n";

 

 

 

if(enumParams[2] != WriteControl_timeStep)

//writeControl

{

 

 

 

arr += "writeControl\t\t";

arr += enumParamVal_StringByNum[2][enumParams[2]];

arr += ";\n\n";

 

}

 

arr += "writeInterval\t\t";

//writeInterval

arr += QByteArray::number(doubleParams[3]);

 

arr += ";\n\n";

 

if(intParams[0] != 0)

//purgeWrite

{

 

arr += "purgeWrite\t\t";

 

arr += QByteArray::number(intParams[0]);

 

arr += ";\n\n";

 

}

if(enumParams[3] != WriteFormat_ascii) //writeFormat

{

arr += "writeFormat\t\t";

arr += enumParamVal_StringByNum[3][enumParams[3]]; arr += ";\n\n";

}

if(intParams[1] != 6) //writePrecision

{

arr += "writePrecision\t\t";

arr += QByteArray::number(intParams[1]); arr += ";\n\n";

}

if(enumParams[4] != WriteCompression_off) //writeCompression

89

{

arr += "writeCompression\t\t";

arr += enumParamVal_StringByNum[4][enumParams[4]]; arr += ";\n\n";

}

if(enumParams[5] != TimeFormat_general) //timeFormat

{

arr += "timeFormat\t\t";

arr += enumParamVal_StringByNum[5][enumParams[5]]; arr += ";\n\n";

if(intParams[2] != 6)

{

arr += "timePrecision\t\t";

arr += QByteArray::number(intParams[2]); arr += ";\n\n";

}

}

if(enumParams[6] != GraphFormat_raw) //graphFormat

{

arr += "graphFormat\t\t";

arr += enumParamVal_StringByNum[6][enumParams[6]]; arr += ";\n\n";

}

if(boolParams[0] != true) //runTimeModifiable

{

arr += "runTimeModifiable\t\tfalse;\n\n";

}

if(!otherParams.isEmpty())

{

arr += "//Other parameters\n\n"; QList<Parameter>::iterator it = otherParams.begin(); for(; it != otherParams.end(); it++)

{

arr += it->name; arr += "\t\t"; arr += it->val; arr += ";\n\n";

}

}

return 0;

}

3. Классы Vertice, Block, Face, ArcEdge, BoundaryBM и BlockMeshDict

class Vertice //класс, представляющий вершину из списка vertices

{

public:

double x, y, z; //координаты вершины

Vertice()

{

x = y = z = 0;

}

Vertice(double _x, double _y, double _z)

{

x = _x; y = _y; z = _z;

}

double& operator[](uint index)

{

switch(index % 3)

{

90

case 0: return x; case 1: return y; case 2: return z;

}

return x;

}

};

class Block //класс, представляющий блок из списка blocks

{

public:

Block() : typeGrading(TypeGrading_simpleGrading)

{

for(int i = 0; i < 8; i++) vertLabels[i] = i; for(int i = 0; i < 3; i++) cellAmount[i] = 1; for(int i = 0; i < 12; i++) grading[i] = 1;

}

 

QByteArray name;

//имя блока

uint vertLabels[8]; //номера вершин, составляющих блок

uint cellAmount[3];//количество ячеек по осям X, Y и Z, на кот. //разбивается блок

int typeGrading; //тип расширения ячеек double grading[12]; //коэффициенты расширения

};

class Face //класс, представляющий грань из списка faces

{

public: Face()

{

for(int i = 0; i < 4; i++) num[i] = i;

}

Face(uint l1, uint l2, uint l3, uint l4)

{

num[0] = l1; num[1] = l2; num[2] = l3; num[3] = l4;

}

uint num[4]; //номера вершин, составляющих грань uint& operator[](uint index)

{

return num[index % 4];

}

};

class ArcEdge //класс, представляющий дугообразное ребро из списка edges

{

public:

ArcEdge() : v1(0), v2(1)

{

}

ArcEdge(uint _v1, uint _v2, Vertice _interpVert) : v1(_v1), v2(_v2), interpVert(_interpVert)

{

}

uint& operator[](uint index)

{

index = index % 2; if(index == 0)

return v1; return v2;

}

uint v1, v2; //номера вершин, соединяемых ребром Vertice interpVert; //точка интерполяции

91

};

//класс, представляющий патч из списка boundary

class BoundaryBM

{

 

 

 

public:

 

 

 

BoundaryBM() : type(BasicTypes_patch)

{

 

 

 

}

 

//имя патча

QByteArray name;

QByteArray neighbourPatch;//соседний патч (если тип cyclic)

int type;

//тип патча

 

QList<Face> faces;

//список граней патча

};

 

 

 

class BlockMeshDict : public Dict

{

 

 

 

public:

 

 

 

BlockMeshDict();

 

 

int CopyDict();

//функция-парсер

int PrepareToSave();

//записывает содержимое полей класса в строковое

 

 

//поле arr в формате, необходимом для blockMesh

void ShowParseStatus(int);//выводит в дебаг информацию о парсинге

double convertToMeters;

//масштаб

QList<Vertice> vertices;

//список вершин

QList<Block> blocks;

//список блоков

QList<ArcEdge> edges;

//список ребер

QList<BoundaryBM> bnd;

//список патчей

private:

 

 

int ParseClass(QByteArray);

//сканировать класс из заголовка

int

ParseObject(QByteArray);

//сканировать

объект из заголовка

int

ParseLocation(QByteArray);

//сканировать

путь из заголовка

int ParseVertice(); //сканировать

вершину

int

ParseBlock();

//сканировать

блок

int

ParseEdge();

//сканировать

ребро

int ParseBoundary();//сканировать патч

int ParseBoundaryParam(BoundaryBM&);//сканировать параметр патча int ParseFace(BoundaryBM&);//сканировать грань

int ParsePatch();//сканировать патч

};

BlockMeshDict::BlockMeshDict()

{

convertToMeters = 1; specSymbols = "(){};"; object = "blockMeshDict";

}

int BlockMeshDict::ParseClass(QByteArray val)//сканировать класс из заголовка

{

if(val != "dictionary")

return ParseError_invalidParamVal; objClass = val;

return 0;

}

int BlockMeshDict::ParseLocation(QByteArray val)

//сканировать путь из заголовка

{

if(val != "\"constant/polyMesh\"") return ParseError_invalidParamVal;

location = val; return 0;

}

int BlockMeshDict::ParseObject(QByteArray val)

//сканировать объект из заголовка

{

92

if(val != "blockMeshDict")

return ParseError_invalidParamVal; object = val;

return 0;

}

int BlockMeshDict::ParseVertice()

{

//сканировать вершину if(arr[ind] != '(')

return parseError_noVerticeCoordList; ++ind;

if(ParseSenseless() == -1) return -1;

Vertice v;

bool convOk;//признак успешной конверсии

for(int i = 0; i < 3; ++i) //три компоненты вектора

{

v[i] = GetWord().toDouble(&convOk); if(!convOk)

return parseError_invalidVerticeCoord; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return parseError_noVerticeCoordListClosure; ++ind;

//при успешном сканировании добавляем вершину

vertices.append(v);

 

return 0;

 

}

 

int BlockMeshDict::ParseBlock()

//сканировать блок

{

 

if(GetWord() != "hex")

return parseError_noHexInBlock; if(ParseSenseless() == -1)

return -1; if(arr[ind] != '(')

return parseError_noVerticeLabelsList; ++ind;

if(ParseSenseless() == -1) return -1;

Block b; bool convOk;

for(int i = 0; i < 8; ++i)

{//сканирвать номера вершин блока

b.vertLabels[i] = GetWord().toUInt(&convOk); if(!convOk)

return parseError_invalidVerticeLabel; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return parseError_noVerticeLabelsListClosure; ++ind;

if(ParseSenseless() == -1) return -1;

b.name = GetWord(); if(ParseSenseless() == -1)

return -1; if(arr[ind] != '(')

return parseError_noCellAmountList; ++ind;

93

if(ParseSenseless() == -1) return -1;

for(int i = 0; i < 3; ++i)

{

b.cellAmount[i] = GetWord().toUInt(&convOk); if(!convOk)

return parseError_invalidCellAmount; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return parseError_noCellAmountListClosure; ++ind;

if(ParseSenseless() == -1) return -1;

QByteArray typeGrading = GetWord(); if(typeGrading == "simpleGrading")

b.typeGrading = TypeGrading_simpleGrading; else if(typeGrading == "edgeGrading")

b.typeGrading = TypeGrading_edgeGrading;

else

return parseError_invalidTypeGrading; if(ParseSenseless() == -1)

return -1; if(arr[ind] != '(')

return parseError_noGradingList; ++ind;

if(ParseSenseless() == -1) return -1;

int lim;

if(b.typeGrading == TypeGrading_simpleGrading) lim = 3;

else

lim = 12;

for(int i = 0; i < lim; ++i)

{

b.grading[i] = GetWord().toDouble(&convOk); if(!convOk)

return parseError_invalidGrading; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return parseError_noGradingListClosure; ++ind;

//при успешном сканировании добавляем блок

blocks.append(b); return 0;

}

int BlockMeshDict::ParseEdge() //сканировать дугообразное ребро

{

bool convOk; ArcEdge e;

if(GetWord() != "arc")

return parseError_noArcInEdge; if(ParseSenseless() == -1)

return -1;

for(int i = 0; i < 2; ++i)

{

e[i] = GetWord().toUInt(&convOk); if(!convOk)

return parseError_invalidVerticeLabelInEdge;

94

if(ParseSenseless() == -1) return -1;

}

if(arr[ind] != '(')

return parseError_noInterpPointList; ++ind;

if(ParseSenseless() == -1) return -1;

for(int i = 0; i < 3; ++i)

{

e.interpVert[i] = GetWord().toDouble(&convOk); if(!convOk)

return parseError_invalidInterpPointCoord; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return parseError_noInterpPointListClosure; ++ind;

edges.append(e);//при успешном сканировании добавляем ребро в список return 0;

}

int BlockMeshDict::ParseBoundary()

{

BoundaryBM b;

b.name = GetWord(); //сначала имя патча if(b.name.isEmpty())

return parseError_noBoundaryName; if(ParseSenseless() == -1)

return -1; if(arr[ind] != '{')

return parseError_noBoundaryBlock; ++ind;

if(ParseSenseless() == -1) return -1;

int r;

while(arr[ind] != '}')

{

r = ParseBoundaryParam(b); if(r != 0)

return r; if(ParseSenseless() == -1)

return -1;

}

++ind;

bnd.append(b); //при успешном сканировании добавляем в список return 0;

}

int BlockMeshDict::ParseBoundaryParam(BoundaryBM &b)

//сканировать параметр патча

{

//имя параметра

QByteArray paramName = GetWord();

if(ParseSenseless() == -1) return -1;

if(paramName == "type" || paramName == "neighbourPatch") { //тогда сканируем только одно слово

QByteArray paramVal = GetWord();

if(paramName == "type") //сканируемый параметр - тип

{

if(strTypeToInt[paramVal] != 0) b.type = strTypeToInt[paramVal];

else

95

}

return parseError_invalidPatchType;

 

else

//neighbourPatch

{

 

b.neighbourPatch = paramVal;

}

}

else if(paramName == "faces")

{ //тогда сканируем список граней if(arr[ind] != '(')

return parseError_noFacesList; ++ind;

if(ParseSenseless() == -1) return -1;

while(arr[ind] != ')')

{

ParseFace(b); if(ParseSenseless() == -1)

return -1;

}

++ind;

}

if(ind == fileLen) return -1; if(arr[ind] != ';')

return ParseError_semiMissing; ++ind;

return 0;

}

int BlockMeshDict::ParseFace(BoundaryBM &b)

//сканирует одну грань из списка

{

if(arr[ind] != '(')

return parseError_noFaceList; ++ind;

if(ParseSenseless() == -1) return -1;

Face f; bool convOk;

for(int i = 0; i < 4; ++i)

{

f[i] = GetWord().toUInt(&convOk); if(!convOk)

return parseError_invalidVerticeLabelFace; if(ParseSenseless() == -1)

return -1;

}

if(arr[ind] != ')')

return

parseError_noFaceListClosure;

++ind;

 

 

b.faces.append(f);//при успешном сканировании добавляем в список

return 0;

 

 

}

 

//сканирует патч

int BlockMeshDict::ParsePatch()

{

 

 

BoundaryBM

b;

 

QByteArray

type = GetWord();

 

if(strTypeToInt[type] == 0)

 

return

parseError_invalidPatchType;

b.type = strTypeToInt[type];

 

if(ParseSenseless() == -1)

 

return

-1;

 

96

QByteArray name = GetWord(); if(name.isEmpty())

return parseError_invalidPatchName; b.name = name;

if(ParseSenseless() == -1) return -1;

if(arr[ind] != '(')

return parseError_noFacesList; ++ind;

if(ParseSenseless() == -1) return -1;

while(arr[ind] != ')')

{

ParseFace(b); if(ParseSenseless() == -1)

return -1;

}

++ind;

bnd.append(b); //при успешном сканировании добавляем в список return 0;

}

int BlockMeshDict::CopyDict() //функция-парсер

{

line = 1; //сброс индекса, номера строки ind = 0;

int r = 0;

fileLen = arr.length(); BlockMeshDict backupDict(*this); QByteArray word;

bool convOk;

bnd.clear(); //очистка всех списков; будем заполнять заново edges.clear();

blocks.clear(); vertices.clear();

#ifdef SHOWPARSESTATUS_BLOCKMESH

qDebug("======= blockMeshDict parse status ======="); #endif

//header

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

r = ParseHeader(); if(r != 0)

goto ret; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//convertToMeters

if(GetWord() != "convertToMeters")

{

r = parseError_noConvertToMetersEntry; goto ret;

}

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

97

convertToMeters = GetWord().toDouble(&convOk); if(!convOk)

{

r = parseError_invalidControlToMetersValue; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//vertices

if(GetWord() != "vertices")

{

r = parseError_noVerticesEntry; goto ret;

}

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

if(arr[ind] != '(')

{

r = parseError_noVerticesList; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//single vertices

while(arr[ind] != ')')

{

if((r = ParseVertice()) != 0) goto ret;

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

}

++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

++ind;

98

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//blocks

if(GetWord() != "blocks")

{

r = parseError_noBlocksEntry; goto ret;

}

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

if(arr[ind] != '(')

{

r = parseError_noBlocksList; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//single blocks

while(arr[ind] != ')')

{

if((r = ParseBlock()) != 0) goto ret;

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

}

++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//edges

if(GetWord() != "edges")

{

r = parseError_noEdgesEntry; goto ret;

}

if(ParseSenseless() == -1)

99

{

r = -1; goto ret;

}

if(arr[ind] != '(')

{

r = parseError_noEdgesList; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//single edges

while(arr[ind] != ')')

{

if((r = ParseEdge()) != 0) goto ret;

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

}

++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//patches or boundary

word = GetWord();

if(word != "patches" && word != "boundary")

{

r = parseError_noPatchesEntry; goto ret;

}

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

if(arr[ind] != '(')

{

r = parseError_noPatchesList; goto ret;

}

++ind; if(ParseSenseless() == -1)

100

{

 

 

r =

-1;

 

goto ret;

 

}

 

 

if(word

== "boundary")

 

{

 

 

while(arr[ind] != ')')

//single boundaries

{

 

 

 

r = ParseBoundary();

 

 

if(ParseSenseless() == -1)

 

 

{

 

 

r = -1;

 

 

goto ret;

 

 

}

 

}

 

 

}

 

 

else

// "patches"

 

{

 

 

while(arr[ind] != ')')

//single patches

{

r = ParsePatch(); if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

}

}

++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

++ind; if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

//mergePatchPairs

if(GetWord() != "mergePatchPairs")

{

r = parseError_noMergePatchPairsEntry; goto ret;

}

if(ParseSenseless() == -1)

{

r = -1; goto ret;

}

if(arr[ind] != '(')

{

r = parseError_noMergePatchPairsList; goto ret;

}

do

101

{

++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

}while(arr[ind] != ')'); ++ind;

if(ind == fileLen)

{

r = -1; goto ret;

}

if(arr[ind] != ';')

{

r = ParseError_semiMissing; goto ret;

}

ret:

if(r != 0)

*this = backupDict; #ifdef SHOWPARSESTATUS_BLOCKMESH

ShowParseStatus(r);

#endif return r;

}

int BlockMeshDict::PrepareToSave() //записывает содержимое класса в формате, //необходимом для blockMesh

{

arr.clear(); WriteHeader();

arr += "convertToMeters\t\t\t";

arr += QByteArray::number(convertToMeters); arr += ";\n\n";

arr += "vertices\n(\n"; QList<Vertice>::iterator vi = vertices.begin(); for(; vi != vertices.end(); vi++)

{

arr += "\t(";

for(int i = 0; i < 3; ++i)

{

arr += QByteArray::number((*vi)[i]); arr += ' ';

}

arr += ")\n";

}

arr += ");\n\n";

arr += "blocks\n(\n"; QList<Block>::iterator bi = blocks.begin(); for(; bi != blocks.end(); bi++)

{

arr += "\thex (";

for(int i = 0; i < 8; ++i)

{

arr += QByteArray::number(bi->vertLabels[i]); arr += ' ';

}

arr += ") "; arr += bi->name; arr += " (";

for(int i = 0; i < 3; ++i)

102

{

arr += QByteArray::number(bi->cellAmount[i]); arr += ' ';

}

arr += ") "; int lim;

if(bi->typeGrading == TypeGrading_simpleGrading)

{

lim = 3;

arr += "simpleGrading (";

}

else

{

lim = 12;

arr += "edgeGrading (";

}

for(int i = 0; i < lim; ++i)

{

arr += QByteArray::number(bi->grading[i]); arr += ' ';

}

arr += ")\n";

}

arr += ");\n\n"; arr += "edges\n(\n";

QList<ArcEdge>::iterator ei = edges.begin(); for(; ei != edges.end(); ei++)

{

arr += "\tarc ";

arr += QByteArray::number(ei->v1); arr += ' ';

arr += QByteArray::number(ei->v2); arr += " (";

for(int i = 0; i < 3; ++i)

{

arr += QByteArray::number(ei->interpVert[i]); arr += ' ';

}

arr += ")\n";

}

arr += ");\n\n";

arr += "boundary\n(\n"; QList<BoundaryBM>::iterator bndi = bnd.begin(); for(; bndi != bnd.end(); bndi++)

{

arr += '\t';

arr += bndi->name; arr += "\n\t{\n"; arr += "\t\ttype\t";

arr += strTypeToInt.key(bndi->type); arr += ";\n";

if(bndi->type == BasicTypes_cyclic)

{

arr += "\t\tneighbourPatch "; arr += bndi->neighbourPatch; arr += ";\n";

}

arr += "\t\tfaces\n\t\t(\n"; QList<Face>::iterator fi = bndi->faces.begin(); for(; fi != bndi->faces.end(); fi++)

{

arr += "\t\t\t(";

103

for(int i = 0; i < 4; ++i)

{

arr += QByteArray::number((*fi)[i]); arr += ' ';

}

arr += ")\n";

}

arr += "\t\t);\n\t}\n";

}

arr += ");\n\nmergePatchPairs\n(\n);"; return 0;

}

void BlockMeshDict::ShowParseStatus(int r)

//выводит в debug результат парсинга

{

PrepareToSave(); QByteArray dbg(arr);

dbg += "\n\nParser returned: "; dbg += QByteArray::number(r); dbg += "\nind = ";

dbg += QByteArray::number(ind); qDebug(dbg);

}

104

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]