- •РЕФЕРАТ
- •Записка к выпускной квалификационной работе изложена на 107 стр. машинописного текста, состоит из 3 разделов и включает 24 рисунка.
- •СОДЕРЖАНИЕ
- •ОПРЕДЕЛЕНИЯ, ОБОЗНАЧЕНИЯ И СОКРАЩЕНИЯ
- •ВВЕДЕНИЕ
- •1 Анализ задачи создания пользовательского интерфейса для OpenFOAM
- •1.1 Взаимодействие пользователя с OpenFOAM в процессе моделирования задачи
- •1.1.1 Предпроцессинг
- •1.1.2 Решение задачи и пост-процессинг
- •1.2 Основные требования к пользовательскому интерфейсу OpenFOAM
- •1.3 Функционал пользовательского интерфейса OpenFOAM
- •2 Определение средств для реализации пользовательского интерфейса OpenFOAM
- •2.1 Выбор операционной системы
- •2.2 Выбор языка программирования
- •2.3 Выбор IDE
- •3 Разработка пользовательского интерфейса для OpenFOAM
- •3.1 Структура приложения-интерфейса для OpenFOAM
- •3.2 Разработка классов объектов, хранящих информацию из файлов кейса OpenFOAM
- •3.2.1 Формат файлов кейсов OpenFOAM
- •3.2.2 Разработка абстрактного базового класса Dict
- •3.2.3 Разработка класса ControlDict
- •3.2.4 Разработка класса BlockMeshDict
- •3.2.5 Разработка класса Boundary
- •3.2.6 Разработка класса Field
- •3.2.7 Разработка класса Constant
- •3.2.8 Разработка класса SetFieldsDict
- •3.3 Разработка графического пользовательского интерфейса приложения
- •3.3.1 Внешний вид приложения
- •3.3.2 Вкладка «control»
- •3.3.2 Вкладка «blockMesh»
- •3.3.3 Вкладка «boundary»
- •3.3.4 Вкладка «Поля»
- •3.3.5 Вкладка «setFields»
- •3.3.6 Вкладка «Константы»
- •3.3.7 Вкладки «fvSolution» и «fvSchemes»
- •3.3.8 Вкладка «Запуск»
- •Заключение
- •СПИСОК ЛИТЕРАТУРЫ
- •ПРИЛОЖЕНИЕ А
- •Листинги ключевых частей программы
ПРИЛОЖЕНИЕ А
Листинги ключевых частей программы
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