本文目的是通过读取两个时刻的颗粒信息文件,识别这两个时刻下某个求解范围或进程内具有相同编号的颗粒的信息变化情况。
对于两个时刻的VTK文件而言,其包含的颗粒可能是不一致的,因此还需要对这两个时刻此求解范围或进程内包含的相同颗粒进行识别。颗粒的VTK文件格式可参考颗粒VTK文件格式总结。
对应的求解程序如下(程序的解释已以注释的方式记录在cpp文件中;此外,由于这里需要对具有相同ID的颗粒在不同时刻下的不同信息进行对比,因而找到具有相同ID的颗粒之后将其不同时刻下的信息进行了整合并输出):
/**
* @file vtkpost.cpp
* @brief
* @version
* @date Fri 25 Jan 2019 08:22:00 AM CST
******************************************************************************/
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
using namespace std;
/* The last space is necessary. */
const string idmarker = "SCALARS id float 1 ";
const string nmarker = "DATASET POLYDATA ";
const string pmarker = "DATASET POLYDATA ";
const string tmarker = "SCALARS type float 1 ";
const string rmarker = "SCALARS radius float 1 ";
const string vmarker = "VECTORS velocity float ";
const string amarker = "VECTORS omega float ";
const string fmarker = "VECTORS force float ";
const string fdmarker = "VECTORS fdrag float ";
const string fcmarker = "VECTORS collide float ";
typedef struct {
int id, type;
double xo, yo, zo; // old position
double xn, yn, zn; // new position
double uo, vo, wo; // old velocity
double un, vn, wn; // new velocity
double du, dv, dw; // velocity changes
double mu; // magitude of velocity changes
double rp; // radius
double auo, avo, awo; // old angular velocity
double aun, avn, awn; // new angular velocity
double dau, dav, daw; // angular velocity changes
double fxo, fyo, fzo; // old force
double fxn, fyn, fzn; // new force
double fdxo, fdyo, fdzo; // old drag force
double fdxn, fdyn, fdzn; // new drag force
double fcxo, fcyo, fczo; // old collide force
double fcxn, fcyn, fczn; // new collide force
} Vtkout;
/* Find the mapping relations between reading sequence and the particle id */
map<int, int> find_seq2ids(const char *name);
/* Extract indices from the mapping relations. */
set<int> extract_id(const map<int, int> &mapping);
/* Find common indices between ...1.vtk and ...2.vtk. */
set<int> find_comm_id(
const set<int> &ids1,
const set<int> &ids2);
/* Generate mapping relations from reading sequence to common indices */
map<int, int> generate_ids2seq(const set<int> &commids);
/* Read the information of the common partiles in ...1.vtk and ...2.vtk. */
vector<Vtkout> read_comm_info(
const char *name1,
const map<int, int> &map1,
const char *name2,
const map<int, int> &map2,
const set<int> &commids,
const map<int, int> &commids2seq);
/* Write all collected data to a dat file. */
void write_data(const vector<Vtkout> &data);
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
/* Only file name should be modified if necessary. */
const char *name1 = "./part120000001.vtk";
const char *name2 = "./part120000002.vtk";
/* Use map1 and map2 to record the mapping relations between reading
* sequence and particle indices of file 1 and file2, respectively.*/
const map<int, int> map1 = find_seq2ids(name1);
const map<int, int> map2 = find_seq2ids(name2);
const set<int> ids1 = extract_id(map1);
const set<int> ids2 = extract_id(map2);
const int np1 = ids1.size();
const int np2 = ids2.size();
cout << "Particle number in file " << name1 << " is " << np1 << endl;
cout << "Particle number in file " << name2 << " is " << np2 << endl;
const set<int> commids = find_comm_id(ids1, ids2);
const map<int, int> ids2seq = generate_ids2seq(commids);
const int comm_np = commids.size();
cout << "Common particle number is " << comm_np << endl;
vector<Vtkout> data =
read_comm_info(name1, map1, name2, map2, commids, ids2seq);
/* for (auto it = ids2seq.begin(); it != ids2seq.end(); it++) { */
/* cout << it->first << "\t" << it->second << endl; */
/* } */
/* for (int i = 0; i < 10; i++) { */
/* cout << data[i].xo << "\t" << data[i].yo << "\t" << data[i].zo << endl; */
/* } */
write_data(data);
return 0;
}
/*----------------------------------------------------------------------------*/
/* Find the mapping relations between reading sequence and the particle id */
map<int, int> find_seq2ids(const char *name)
{
map<int, int> seq2ids;
ifstream fin;
string stmp, line;
int np, id;
/* Read all indices in ...1.vtk. */
fin.open(name, ios::in);
while (getline(fin, line)) {
/* Find the particle number in current vtk file. */
if (line == nmarker) {
fin >> stmp >> np >> stmp;
}
/* Read all indices and insert all indices to a set. */
if (line == idmarker) {
for (int i = 0; i < np; i++) {
getline(fin, line);
fin >> id;
seq2ids.insert(pair<int, int>(i, id));
}
}
}
fin.close();
return seq2ids;
}
/* Extract indices from the mapping relations. */
set<int> extract_id(const map<int, int> &mapping)
{
set<int> ids;
for (auto it = mapping.begin(); it != mapping.end(); it++) {
ids.insert(it->second);
}
return ids;
}
/* Find common indices between ...1.vtk and ...2.vtk. */
set<int> find_comm_id(
const set<int> &ids1,
const set<int> &ids2)
{
set<int> commids;
for (auto it = ids2.begin(); it != ids2.end(); it++) {
if (ids1.find(*it) != ids1.end()) {
commids.insert(*it);
}
}
return commids;
}
/* Generate mapping relations from reading sequence to common indices */
map<int, int> generate_ids2seq(const set<int> &commids)
{
int count = 0;
map<int, int> ids2seq;
for (auto it = commids.begin(); it != commids.end(); it++) {
ids2seq.insert(pair<int, int>(*it, count));
count++;
}
return ids2seq;
}
/* Read the information of the common partiles in ...1.vtk and ...2.vtk. */
vector<Vtkout> read_comm_info(
const char *name1,
const map<int, int> &map1,
const char *name2,
const map<int, int> &map2,
const set<int> &commids,
const map<int, int> &commids2seq)
{
const int np1 = map1.size();
const int np2 = map2.size();
const int comm_np = commids.size();
int itmp;
double xtmp, ytmp, ztmp, dtmp;
string stmp, line;
ifstream fin;
vector<Vtkout> data(comm_np);
/* Read all information from ...1.vtk */
fin.open(name1, ios::in);
while (getline(fin, line)) {
if (line == pmarker) {
cout << "Find pmarker" << endl;
getline(fin, line);
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].id = m1it->second;
data[cit->second].xo = xtmp;
data[cit->second].yo = ytmp;
data[cit->second].zo = ztmp;
}
}
}
if (line == vmarker) {
cout << "Find vmarker" << endl;
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].uo = xtmp;
data[cit->second].vo = ytmp;
data[cit->second].wo = ztmp;
}
}
}
if (line == amarker) {
cout << "Find amarker" << endl;
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].auo = xtmp;
data[cit->second].avo = ytmp;
data[cit->second].awo = ztmp;
}
}
}
if (line == fmarker) {
cout << "Find fmarker" << endl;
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].fxo = xtmp;
data[cit->second].fyo = ytmp;
data[cit->second].fzo = ztmp;
}
}
}
if (line == fdmarker) {
cout << "Find fdmarker" << endl;
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].fdxo = xtmp;
data[cit->second].fdyo = ytmp;
data[cit->second].fdzo = ztmp;
}
}
}
if (line == fcmarker) {
cout << "Find fcmarker" << endl;
for (int i = 0; i < np1; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].fcxo = xtmp;
data[cit->second].fcyo = ytmp;
data[cit->second].fczo = ztmp;
}
}
}
if (line == tmarker) {
cout << "Find tmarker" << endl;
getline(fin, line);
for (int i = 0; i < np1; i++) {
fin >> itmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].type = itmp;
}
}
}
if (line == rmarker) {
cout << "Find rmarker" << endl;
getline(fin, line);
for (int i = 0; i < np1; i++) {
fin >> dtmp;
map<int, int>::const_iterator m1it = map1.find(i);
if (commids.find(m1it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m1it->second);
data[cit->second].rp = dtmp;
}
}
}
}
fin.close();
/* Read all information from ...2.vtk */
fin.open(name2, ios::in);
while (getline(fin, line)) {
if (line == pmarker) {
cout << "Find pmarker" << endl;
getline(fin, line);
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].xn = xtmp;
data[cit->second].yn = ytmp;
data[cit->second].zn = ztmp;
}
}
}
if (line == vmarker) {
cout << "Find vmarker" << endl;
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].un = xtmp;
data[cit->second].vn = ytmp;
data[cit->second].wn = ztmp;
}
}
}
if (line == amarker) {
cout << "Find amarker" << endl;
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].aun = xtmp;
data[cit->second].avn = ytmp;
data[cit->second].awn = ztmp;
}
}
}
if (line == fmarker) {
cout << "Find fmarker" << endl;
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].fxn = xtmp;
data[cit->second].fyn = ytmp;
data[cit->second].fzn = ztmp;
}
}
}
if (line == fdmarker) {
cout << "Find fdmarker" << endl;
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].fdxn = xtmp;
data[cit->second].fdyn = ytmp;
data[cit->second].fdzn = ztmp;
}
}
}
if (line == fcmarker) {
cout << "Find fcmarker" << endl;
for (int i = 0; i < np2; i++) {
fin >> xtmp >> ytmp >> ztmp;
map<int, int>::const_iterator m2it = map2.find(i);
if (commids.find(m2it->second) != commids.end()) {
map<int, int>::const_iterator cit = commids2seq.find(m2it->second);
data[cit->second].fcxn = xtmp;
data[cit->second].fcyn = ytmp;
data[cit->second].fczn = ztmp;
}
}
}
}
fin.close();
for (auto it = data.begin(); it != data.end(); it++) {
it->du = it->un - it->uo;
it->dv = it->vn - it->vo;
it->dw = it->wn - it->wo;
it->mu = sqrt(pow(it->du, 2) + pow(it->dv, 2) + pow(it->dw, 2));
it->dau = it->aun - it->auo;
it->dav = it->avn - it->avo;
it->daw = it->awn - it->awo;
}
return data;
}
void write_data(const vector<Vtkout> &data)
{
ofstream fout;
fout.open("result.dat");
fout << "id" << "\t" << "type" << "\t" << "rp" << "\t"
<< "xo" << "\t" << "yo" << "\t" << "zo" << "\t"
<< "xn" << "\t" << "yn" << "\t" << "zn" << "\t"
<< "uo" << "\t" << "vo" << "\t" << "wo" << "\t"
<< "un" << "\t" << "vn" << "\t" << "wn" << "\t"
<< "du" << "\t" << "dv" << "\t" << "dw" << "\t"
<< "mu" << "\t"
<< "auo" << "\t" << "avo" << "\t" << "awo" << "\t"
<< "aun" << "\t" << "avn" << "\t" << "awn" << "\t"
<< "dau" << "\t" << "dav" << "\t" << "daw" << "\t"
<< "fxo" << "\t" << "fyo" << "\t" << "fzo" << "\t"
<< "fxn" << "\t" << "fyn" << "\t" << "fzn" << "\t"
<< "fdxo" << "\t" << "fdyo" << "\t" << "fdzo" << "\t"
<< "fdxn" << "\t" << "fdyn" << "\t" << "fdzn" << "\t"
<< "fcxo" << "\t" << "fcyo" << "\t" << "fczo" << "\t"
<< "fcxn" << "\t" << "fcyn" << "\t" << "fczn" << "\t"
<< endl;
for (auto it = data.begin(); it != data.end(); it++) {
fout << it->id << "\t" << it->type << "\t" << it->rp << "\t"
<< it->xo << "\t" << it->yo << "\t" << it->zo << "\t"
<< it->xn << "\t" << it->yn << "\t" << it->zn << "\t"
<< it->uo << "\t" << it->vo << "\t" << it->wo << "\t"
<< it->un << "\t" << it->vn << "\t" << it->wn << "\t"
<< it->du << "\t" << it->dv << "\t" << it->dw << "\t"
<< it->mu << "\t"
<< it->auo << "\t" << it->avo << "\t" << it->awo << "\t"
<< it->aun << "\t" << it->avn << "\t" << it->awn << "\t"
<< it->dau << "\t" << it->dav << "\t" << it->daw << "\t"
<< it->fxo << "\t" << it->fyo << "\t" << it->fzo << "\t"
<< it->fxn << "\t" << it->fyn << "\t" << it->fzn << "\t"
<< it->fdxo << "\t" << it->fdyo << "\t" << it->fdzo << "\t"
<< it->fdxn << "\t" << it->fdyn << "\t" << it->fdzn << "\t"
<< it->fcxo << "\t" << it->fcyo << "\t" << it->fczo << "\t"
<< it->fcxn << "\t" << it->fcyn << "\t" << it->fczn << "\t"
<< endl;
}
fout.close();
}
相关的编译和运行命令如下:
# Compile:
g++ vtkpost.cpp -std=c++11 -o vtkpost
# Run:
./vtkpost
# Abbr. in results:
# postfix o: old
# postfix n: new
# prefix d: change
# f: force
# fd: drag
# fc: collide
# ......
# (also see from line 32 to line 48 in vtkpost.cpp)