You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmCalculation/nmCalculationUtils.cpp

358 lines
11 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmCalculationUtils.h"
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <QCoreApplication>
#include <fstream>
#include <float.h>
#include "pch.h"
namespace
{
QString krigingText(const char* sourceText)
{
return QCoreApplication::translate("nmCalculationUtils", sourceText);
}
bool isFiniteValue(double value)
{
#ifdef _MSC_VER
return _finite(value) != 0;
#else
return std::isfinite(value);
#endif
}
void setKrigingError(QString* errorMessage, const QString& message)
{
if(errorMessage != NULL) {
*errorMessage = message;
}
}
}
nmCalculationUtils::nmCalculationUtils() {
}
double nmCalculationUtils::milliDarcyToDarcy(double dPermeabilityMilliDarcy)
{
// PEBI输入结构使用D数据层统一使用mD因此仅在求解器边界换算。
return dPermeabilityMilliDarcy / 1000.0;
}
bool nmCalculationUtils::copyFileToDir(QString filePath, QString destDir) {
// 如果文件不存在,则退出
if(!QFile::exists(filePath)) {
return false;
}
// 如果目标目录不存在,则创建
if(!QDir(destDir).exists()) {
if(!QDir().mkdir(destDir)) {
qWarning() << "cannot mkdir:" << destDir;
return false;
}
}
// 获取源文件的文件名
QString fileName = QFileInfo(filePath).fileName();
// 构造目标文件的完整路径
QString destinationFilePath = QDir(destDir).filePath(fileName);
// 如果目标文件已存在,则删除
if(QFile::exists(destinationFilePath)) {
QFile destinationFile(destinationFilePath);
if(!destinationFile.remove()) {
qWarning() << "cannot delete file:" << destinationFilePath;
return false;
}
}
// 拷贝文件
if(QFile::copy(filePath, destinationFilePath)) {
qDebug() << "file copy success:" << destinationFilePath;
return true;
} else {
qWarning() << "file copy failed:" << destinationFilePath;
return false;
}
return true;
}
bool nmCalculationUtils::createDirectoryIfNotExists(QString directoryPath) {
QDir dir(directoryPath);
// 检查目录是否存在
if(dir.exists()) {
// 目录已存在
return true;
}
// 尝试创建目录
if(dir.mkpath(directoryPath)) {
// 创建成功
return true;
}
// 创建失败
qDebug() << "创建目录失败,错误代码。";
return false;
}
bool nmCalculationUtils::copyFile(const std::string& sourcePath, const std::string& destinationPath) {
std::ifstream src(sourcePath, std::ios::binary); // 以二进制模式打开源文件
std::ofstream dst(destinationPath, std::ios::binary); // 以二进制模式打开目标文件
if(!src || !dst) {
std::cerr << "文件打开失败" << std::endl;
return false;
}
dst << src.rdbuf(); // 拷贝文件内容
return true;
}
bool nmCalculationUtils::removeDirectory(const QString &dirPath) {
QDir dir(dirPath);
if(!dir.exists()) {
qDebug() << "Directory does not exist.";
return true;
}
// 获取目录中的所有文件和目录
QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
foreach(QFileInfo fileInfo, fileList) {
if(fileInfo.isDir()) {
// 递归删除子目录
if(!removeDirectory(fileInfo.absoluteFilePath())) {
return false;
}
} else {
// 删除文件
if(!QFile::remove(fileInfo.absoluteFilePath())) {
qDebug() << "Failed to remove file:" << fileInfo.absoluteFilePath();
return false;
}
}
}
// 删除目录自身
if(!dir.rmdir(dirPath)) {
qDebug() << "Failed to remove directory:" << dirPath;
return false;
}
return true;
}
bool nmCalculationUtils::writeFile(const QStringList& content, const QString &filePath) {
QFile file(filePath);
//检查
if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning("Cannot open file for writing: %s", qPrintable(file.errorString()));
return false;
}
QTextStream out(&file);
out << content.join("\n");
file.close();
return true;
}
QStringList nmCalculationUtils::readFile(const QString &filePath) {
QStringList content;
// 打开文件
QFile file(filePath);
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Failed to open file:" << filePath;
return content;
}
// 使用QTextStream读取文件
QTextStream in(&file);
while(!in.atEnd()) {
// 读取一行
QString line = in.readLine();
// 将行内容放入QStringList
content.append(line);
}
// 关闭文件
file.close();
return content;
}
bool nmCalculationUtils::calculateKriging(
const QVector<QPointF>& targetPoints,
const QVector<QPointF>& measurementPoints,
const QVector<double>& measurementValues,
double nugget,
double sill,
double range,
int model,
const QString& licensePath,
QVector<double>& outputValues,
QString* errorMessage)
{
outputValues.clear();
setKrigingError(errorMessage, QString());
if(targetPoints.isEmpty()) {
setKrigingError(errorMessage, krigingText("No interpolation points are available."));
return false;
}
if(measurementPoints.size() < 2) {
setKrigingError(errorMessage,
krigingText("At least two measurement points are required."));
return false;
}
if(measurementPoints.size() != measurementValues.size()) {
setKrigingError(errorMessage,
krigingText("Measurement point coordinates and values do not match."));
return false;
}
if(!isFiniteValue(nugget) || !isFiniteValue(sill) ||
!isFiniteValue(range) || nugget < 0.0 || sill <= 0.0 || range <= 0.0) {
setKrigingError(errorMessage, krigingText("Kriging parameters are invalid."));
return false;
}
if(model < 0 || model > 2) {
setKrigingError(errorMessage, krigingText("The Kriging model is invalid."));
return false;
}
for(int i = 0; i < targetPoints.size(); ++i) {
if(!isFiniteValue(targetPoints[i].x()) || !isFiniteValue(targetPoints[i].y())) {
setKrigingError(errorMessage,
krigingText("An interpolation point contains an invalid coordinate."));
return false;
}
}
for(int i = 0; i < measurementPoints.size(); ++i) {
if(!isFiniteValue(measurementPoints[i].x()) ||
!isFiniteValue(measurementPoints[i].y()) ||
!isFiniteValue(measurementValues[i])) {
setKrigingError(errorMessage,
krigingText("A measurement point contains invalid data."));
return false;
}
for(int j = 0; j < i; ++j) {
if(measurementPoints[i] == measurementPoints[j]) {
setKrigingError(errorMessage,
krigingText("Measurement point coordinates cannot be duplicated."));
return false;
}
}
}
if(licensePath.isEmpty() || !QFileInfo(licensePath).exists()) {
setKrigingError(errorMessage, krigingText("The solver license file was not found."));
return false;
}
HMODULE dll = LoadLibrary(L"HX_NWTM.dll");
if(dll == NULL) {
setKrigingError(errorMessage, krigingText("Failed to load HX_NWTM.dll."));
return false;
}
typedef void (*HX_NWTM_KRINGING_Func)(HX_KRING_OUTPUT&,
const HX_KRING_INPUT,
std::string);
HX_NWTM_KRINGING_Func krigingFunction =
(HX_NWTM_KRINGING_Func)GetProcAddress(dll, "HX_NWTM_KRINGING");
if(krigingFunction == NULL) {
FreeLibrary(dll);
setKrigingError(errorMessage,
krigingText("The Kriging interface was not found in HX_NWTM.dll."));
return false;
}
// 求解器p参数每行保存{x, y}并保持targetPoints的原始顺序.
dVec2 targetData;
targetData.reserve(targetPoints.size());
for(int i = 0; i < targetPoints.size(); ++i) {
dVec1 point(2, 0.0);
point[0] = targetPoints[i].x();
point[1] = targetPoints[i].y();
targetData.push_back(point);
}
// 求解器v参数每行保存{x, y, value},坐标和值按相同下标配对.
dVec2 measurementData;
measurementData.reserve(measurementPoints.size());
for(int i = 0; i < measurementPoints.size(); ++i) {
dVec1 point(3, 0.0);
point[0] = measurementPoints[i].x();
point[1] = measurementPoints[i].y();
point[2] = measurementValues[i];
measurementData.push_back(point);
}
bool calculationSucceeded = true;
QString calculationError;
// 局部作用域保证求解器输入、输出对象在FreeLibrary前析构.
{
HX_KRING_INPUT input(nugget, sill, range, model,
targetData, measurementData);
HX_KRING_OUTPUT output;
try {
krigingFunction(output, input, licensePath.toStdString());
} catch(const std::exception& exception) {
calculationSucceeded = false;
calculationError = krigingText("Kriging calculation failed: %1")
.arg(QString::fromLocal8Bit(exception.what()));
} catch(...) {
calculationSucceeded = false;
calculationError = krigingText("Kriging calculation failed.");
}
if(calculationSucceeded &&
output.v.size() != static_cast<size_t>(targetPoints.size())) {
calculationSucceeded = false;
calculationError = krigingText(
"The Kriging result count does not match the interpolation points.");
}
if(calculationSucceeded) {
outputValues.reserve(targetPoints.size());
for(size_t i = 0; i < output.v.size(); ++i) {
if(!isFiniteValue(output.v[i])) {
calculationSucceeded = false;
calculationError = krigingText(
"The Kriging result contains an invalid value.");
break;
}
outputValues.append(output.v[i]);
}
}
}
FreeLibrary(dll);
if(!calculationSucceeded) {
outputValues.clear();
setKrigingError(errorMessage, calculationError);
}
return calculationSucceeded;
}