This function calculates and saves specific information of 2D and 3D elements that make up a surface: vertices, length/surface area, centroids and surface normal vectors.
The center of the whole geometry is calculated for the determination of the outer surface normal vectors. There is also the option to manually set a geometric center in the property files, e.g., for the case of a line/plane to set a point inside the whole geometry given by multiple surfaces since the geometric center is on the line/plane itself and the direction of the normal vector cannot be determined. Note: this will only work for convex geometries, to make this work for general geometries the user could specify a set of points inside the geometry from which the nearest one is used for a surface element to determine the outer normal vector.
1152 {
1153 TRACE();
1155
1157
1158 std::ostringstream fileName;
1159 fileName <<
solver().outputDir() <<
"surface_geometryInfo_" << fileNo << ParallelIo::fileExt();
1160
1161 ParallelIo file(fileName.str(), PIO_REPLACE, MPI_COMM_SELF);
1162 file.setAttribute(inputFileName, "inputFileName");
1163
1164
1165 std::vector<MFloat> vertices(noElements * nDim * nDim);
1166 std::vector<MFloat> geomMeasures(noElements);
1167 std::vector<MFloat> normalVecs(noElements * nDim);
1168
1170
1171
1173 for(
MInt i = 0; i < nDim; i++) {
1174 geomCenter[i] =
1175 Context::getSolverProperty<MFloat>(
"surfaceDataGeometryCenter_" + std::to_string(fileNo),
solverId(), AT_, i);
1176 }
1177 } else {
1178
1179 for(
MInt i = 0; i < noElements; i++) {
1180 for(
MInt dim = 0; dim < nDim; dim++) {
1181 geomCenter[dim] += coordinates[i * nDim + dim];
1182 }
1183 }
1184 for(
MInt dim = 0; dim < nDim; dim++) {
1185 geomCenter[dim] /=
static_cast<MFloat>(noElements);
1186 }
1187 }
1188
1189 m_log <<
"Surface geometry info: geomCenter =";
1190 for(
MInt dim = 0; dim < nDim; dim++) {
1191 m_log <<
" " << geomCenter[dim];
1192 }
1194
1196 for(
MInt i = 0; i < noElements; i++) {
1197 for(
MInt j = 0; j < nDim; j++) {
1198 for(
MInt k = 0; k < nDim; k++) {
1199 vertices[counter] =
m_geometry->elements[i].m_vertices[j][k];
1200 counter++;
1201 }
1202 }
1203
1205
1206 IF_CONSTEXPR(nDim == 3) {
1207
1214
1215
1216 const MFloat v_x = v12_y * v13_z - v12_z * v13_y;
1217 const MFloat v_y = v12_z * v13_x - v12_x * v13_z;
1218 const MFloat v_z = v12_x * v13_y - v12_y * v13_x;
1219
1220 geomMeasures[i] = 0.5 * sqrt(pow(v_x, 2) + pow(v_y, 2) + pow(v_z, 2));
1221 }
1222 else {
1227
1228 geomMeasures[i] = sqrt(pow(p1_x - p2_x, 2) + pow(p1_y - p2_y, 2));
1229 }
1230
1231 std::array<MFloat, nDim * nDim> vertex;
1232 m_geometry->elements[i].getVertices(&vertex[0]);
1233
1234
1235 m_geometry->elements[i].calcNormal(&vertex[0], &normalVecs[i * nDim]);
1236
1237
1238
1240 for(
MInt k = 0; k < nDim; k++) {
1241 const MFloat vecCenter = coordinates[i * nDim + k] - geomCenter[k];
1242 dotProduct += normalVecs[i * nDim + k] * vecCenter;
1243 }
1244
1245
1246
1247 if(!(dotProduct > 0)) {
1248 for(
MInt k = 0; k < nDim; k++) {
1249 normalVecs[i * nDim + k] = -normalVecs[i * nDim + k];
1250 }
1251 }
1252 }
1253
1254 const MFloat totalGeomMeasure = std::accumulate(geomMeasures.begin(), geomMeasures.end(), 0.0);
1255 const MString measure = (nDim == 3) ?
"area" :
"length";
1256 m_log <<
"Total segment " << measure <<
": " << totalGeomMeasure << std::endl;
1257
1258
1259 std::stringstream dumpFileName;
1260 dumpFileName <<
solver().outputDir() <<
"surface_geometryInfo_" << fileNo <<
".dump";
1261
1262 FILE* datei;
1263 datei = fopen(dumpFileName.str().c_str(), "w");
1264
1265 for(
MInt i = 0; i < noElements; i++) {
1266 fprintf(datei, "%d", i);
1267
1268 for(
MInt j = 0; j < nDim; j++) {
1269 fprintf(datei, " %.8f", coordinates[i * nDim + j]);
1270 }
1271
1272 for(
MInt j = 0; j < nDim; j++) {
1273 fprintf(datei, " %.8f", normalVecs[i * nDim + j]);
1274 }
1275 fprintf(datei, "\n");
1276 }
1277 fclose(datei);
1278
1279 const MInt sizeArray1 = noElements * nDim;
1280 const MInt sizeArray2 = noElements * nDim * nDim;
1281
1282
1283 file.defineArray(PIO_FLOAT, "vertices", sizeArray2);
1284 file.defineArray(PIO_FLOAT, "centroid", sizeArray1);
1285 file.defineArray(PIO_FLOAT, "normalVector", sizeArray1);
1286
1287 file.defineArray(PIO_FLOAT, "geomMeasure", noElements);
1288 IF_CONSTEXPR(nDim == 3) { file.setAttribute("area", "description", "geomMeasure"); }
1289 else {
1290 file.setAttribute("length", "description", "geomMeasure");
1291 }
1292
1293 file.setOffset(sizeArray2, 0);
1294 file.writeArray(&vertices[0], "vertices");
1295
1296 file.setOffset(sizeArray1, 0);
1297 file.writeArray(&coordinates[0], "centroid");
1298
1299 file.setOffset(sizeArray1, 0);
1300 file.writeArray(&normalVecs[0], "normalVector");
1301
1302 file.setOffset(noElements, 0);
1303 file.writeArray(&geomMeasures[0], "geomMeasure");
1304}
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
SolverType & solver()
Return reference to solver.
std::basic_string< char > MString
PARALLELIO_DEFAULT_BACKEND ParallelIo