2023-02-05 08:02:01 +01:00
|
|
|
/*
|
2024-01-31 17:40:36 +01:00
|
|
|
* Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
|
2023-02-05 08:02:01 +01:00
|
|
|
* All rights reserved. This file is part of nusif-solver.
|
|
|
|
* Use of this source code is governed by a MIT style
|
|
|
|
* license that can be found in the LICENSE file.
|
|
|
|
*/
|
2023-02-06 20:09:11 +01:00
|
|
|
#include <mpi.h>
|
2023-02-05 08:02:01 +01:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
2023-02-05 11:22:05 +01:00
|
|
|
#include <stdlib.h>
|
2023-02-05 08:02:01 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
#include "allocate.h"
|
|
|
|
#include "comm.h"
|
2023-02-05 08:02:01 +01:00
|
|
|
#include "vtkWriter.h"
|
|
|
|
|
2024-01-31 17:40:36 +01:00
|
|
|
// reset fileview for output of string headers
|
2023-02-07 09:48:24 +01:00
|
|
|
static void resetFileview(VtkOptions* o)
|
|
|
|
{
|
|
|
|
MPI_Offset disp;
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_sync(o->fh);
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Barrier(o->comm.comm);
|
|
|
|
MPI_File_get_size(o->fh, &disp);
|
|
|
|
MPI_File_set_view(o->fh, disp, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
|
|
|
|
}
|
|
|
|
|
2024-01-31 17:40:36 +01:00
|
|
|
static void writeVersion(VtkOptions* o)
|
2023-02-05 08:02:01 +01:00
|
|
|
{
|
2024-01-31 17:40:36 +01:00
|
|
|
char header[50] = "# vtk DataFile Version 3.0\n";
|
|
|
|
// always overwrite exiting files
|
|
|
|
MPI_File_set_view(o->fh, 0, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
|
2023-02-05 11:22:05 +01:00
|
|
|
|
2024-01-31 17:40:36 +01:00
|
|
|
if (commIsMaster(&o->comm)) {
|
|
|
|
MPI_File_write(o->fh, header, (int)strlen(header), MPI_CHAR, MPI_STATUS_IGNORE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void writeHeader(VtkOptions* o)
|
|
|
|
{
|
|
|
|
char header[400];
|
2023-02-05 11:22:05 +01:00
|
|
|
char* cursor = header;
|
|
|
|
|
|
|
|
cursor += sprintf(cursor, "PAMPI cfd solver output\n");
|
|
|
|
cursor += sprintf(cursor, "BINARY\n");
|
|
|
|
|
|
|
|
cursor += sprintf(cursor, "DATASET STRUCTURED_POINTS\n");
|
|
|
|
cursor += sprintf(cursor,
|
|
|
|
"DIMENSIONS %d %d %d\n",
|
|
|
|
o->grid.imax,
|
|
|
|
o->grid.jmax,
|
|
|
|
o->grid.kmax);
|
|
|
|
cursor += sprintf(cursor,
|
2023-02-05 08:02:01 +01:00
|
|
|
"ORIGIN %f %f %f\n",
|
|
|
|
o->grid.dx * 0.5,
|
|
|
|
o->grid.dy * 0.5,
|
|
|
|
o->grid.dz * 0.5);
|
2023-02-05 11:22:05 +01:00
|
|
|
cursor += sprintf(cursor, "SPACING %f %f %f\n", o->grid.dx, o->grid.dy, o->grid.dz);
|
|
|
|
cursor += sprintf(cursor,
|
|
|
|
"POINT_DATA %d\n",
|
|
|
|
o->grid.imax * o->grid.jmax * o->grid.kmax);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
if (commIsMaster(&o->comm)) {
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_write(o->fh, header, (int)strlen(header), MPI_CHAR, MPI_STATUS_IGNORE);
|
2023-02-06 20:09:11 +01:00
|
|
|
}
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void vtkOpen(VtkOptions* o, char* problem)
|
|
|
|
{
|
|
|
|
char filename[50];
|
|
|
|
|
2023-02-05 11:22:05 +01:00
|
|
|
snprintf(filename, 50, "%s-p%d.vtk", problem, o->comm.size);
|
|
|
|
MPI_File_open(o->comm.comm,
|
|
|
|
filename,
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_MODE_WRONLY | MPI_MODE_CREATE,
|
2023-02-05 11:22:05 +01:00
|
|
|
MPI_INFO_NULL,
|
|
|
|
&o->fh);
|
2023-02-05 08:02:01 +01:00
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
if (commIsMaster(&o->comm)) {
|
|
|
|
printf("Writing VTK output for %s\n", problem);
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
|
2024-01-31 17:40:36 +01:00
|
|
|
writeVersion(o);
|
2023-02-07 09:48:24 +01:00
|
|
|
writeHeader(o);
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void vtkScalar(VtkOptions* o, char* name, double* s)
|
|
|
|
{
|
2023-02-06 20:09:11 +01:00
|
|
|
resetFileview(o);
|
2023-02-05 08:02:01 +01:00
|
|
|
if (commIsMaster(&o->comm)) printf("Register scalar %s\n", name);
|
|
|
|
|
2024-01-31 17:40:36 +01:00
|
|
|
char header[100];
|
2023-02-06 20:09:11 +01:00
|
|
|
char* cursor = header;
|
|
|
|
|
2024-01-15 06:26:40 +01:00
|
|
|
cursor += sprintf(cursor, "SCALARS %s double\n", name);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
if (commIsMaster(&o->comm)) {
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_write(o->fh, header, (int)strlen(header), MPI_CHAR, MPI_STATUS_IGNORE);
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
int offsets[NDIMS];
|
2024-01-31 17:40:36 +01:00
|
|
|
commGetOffsets(&o->comm, offsets, o->grid.kmax, o->grid.jmax, o->grid.imax);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
// set global view in file
|
|
|
|
MPI_Offset disp;
|
|
|
|
MPI_Datatype fileViewType;
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_sync(o->fh);
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Barrier(o->comm.comm);
|
2023-02-06 20:09:11 +01:00
|
|
|
MPI_File_get_size(o->fh, &disp);
|
|
|
|
|
|
|
|
MPI_Type_create_subarray(NDIMS,
|
|
|
|
(int[NDIMS]) { o->grid.kmax, o->grid.jmax, o->grid.imax },
|
|
|
|
(int[NDIMS]) { o->comm.kmaxLocal, o->comm.jmaxLocal, o->comm.imaxLocal },
|
|
|
|
offsets,
|
|
|
|
MPI_ORDER_C,
|
|
|
|
MPI_DOUBLE,
|
|
|
|
&fileViewType);
|
|
|
|
MPI_Type_commit(&fileViewType);
|
|
|
|
MPI_File_set_view(o->fh, disp, MPI_DOUBLE, fileViewType, "external32", MPI_INFO_NULL);
|
|
|
|
|
2023-02-07 09:48:24 +01:00
|
|
|
#ifdef VERBOSE
|
|
|
|
printf("Rank: %d, Disp: %lld, Size(k,j,i): %d %d %d, Offset(k,j,i): %d %d %d\n",
|
|
|
|
o->comm.rank,
|
|
|
|
disp,
|
|
|
|
o->comm.kmaxLocal,
|
|
|
|
o->comm.jmaxLocal,
|
|
|
|
o->comm.imaxLocal,
|
|
|
|
offsets[KDIM],
|
|
|
|
offsets[JDIM],
|
|
|
|
offsets[IDIM]);
|
|
|
|
#endif
|
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
// create local bulk type
|
|
|
|
MPI_Datatype bulkType;
|
|
|
|
|
|
|
|
MPI_Type_create_subarray(NDIMS,
|
|
|
|
(int[NDIMS]) { o->comm.kmaxLocal + 2,
|
|
|
|
o->comm.jmaxLocal + 2,
|
|
|
|
o->comm.imaxLocal + 2 }, // oldsizes
|
|
|
|
(int[NDIMS]) { o->comm.kmaxLocal,
|
|
|
|
o->comm.jmaxLocal,
|
|
|
|
o->comm.imaxLocal }, // newsizes
|
|
|
|
(int[NDIMS]) { 1, 1, 1 }, // offsets
|
|
|
|
MPI_ORDER_C,
|
|
|
|
MPI_DOUBLE,
|
|
|
|
&bulkType);
|
|
|
|
MPI_Type_commit(&bulkType);
|
|
|
|
|
|
|
|
MPI_File_write(o->fh, s, 1, bulkType, MPI_STATUS_IGNORE);
|
|
|
|
MPI_Type_free(&bulkType);
|
|
|
|
MPI_Type_free(&fileViewType);
|
|
|
|
|
|
|
|
// Binary segment must be terminated with newline character
|
|
|
|
resetFileview(o);
|
|
|
|
if (commIsMaster(&o->comm)) {
|
|
|
|
MPI_File_write(o->fh, "\n", 1, MPI_CHAR, MPI_STATUS_IGNORE);
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
#define G(v, i, j, k) \
|
|
|
|
v[(k) * (imaxLocal + 2) * (jmaxLocal + 2) + (j) * (imaxLocal + 2) + (i)]
|
|
|
|
|
2023-02-05 08:02:01 +01:00
|
|
|
void vtkVector(VtkOptions* o, char* name, VtkVector vec)
|
|
|
|
{
|
2023-02-06 20:09:11 +01:00
|
|
|
int imaxLocal = o->comm.imaxLocal;
|
|
|
|
int jmaxLocal = o->comm.jmaxLocal;
|
|
|
|
int kmaxLocal = o->comm.kmaxLocal;
|
|
|
|
|
2023-02-05 08:02:01 +01:00
|
|
|
if (commIsMaster(&o->comm)) printf("Register vector %s\n", name);
|
2023-02-06 20:09:11 +01:00
|
|
|
const size_t MAX_HEADER = 100;
|
2023-02-05 08:02:01 +01:00
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
char* header = (char*)malloc(MAX_HEADER);
|
2023-02-07 09:48:24 +01:00
|
|
|
sprintf(header, "VECTORS %s double\n", name);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
resetFileview(o);
|
|
|
|
if (commIsMaster(&o->comm)) {
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_write(o->fh, header, (int)strlen(header), MPI_CHAR, MPI_STATUS_IGNORE);
|
2023-02-06 20:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int offsets[NDIMS];
|
2024-01-31 17:40:36 +01:00
|
|
|
commGetOffsets(&o->comm, offsets, o->grid.kmax, o->grid.jmax, o->grid.imax);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
// set global view in file
|
|
|
|
MPI_Offset disp;
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Datatype fileViewType, vectorType;
|
2024-01-31 17:40:36 +01:00
|
|
|
MPI_File_sync(o->fh);
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Barrier(o->comm.comm);
|
2023-02-06 20:09:11 +01:00
|
|
|
MPI_File_get_size(o->fh, &disp);
|
|
|
|
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Type_contiguous(NDIMS, MPI_DOUBLE, &vectorType);
|
|
|
|
MPI_Type_commit(&vectorType);
|
|
|
|
|
|
|
|
MPI_Type_create_subarray(NDIMS,
|
|
|
|
(int[NDIMS]) { o->grid.kmax, o->grid.jmax, o->grid.imax },
|
|
|
|
(int[NDIMS]) { kmaxLocal, jmaxLocal, imaxLocal },
|
2023-02-06 20:09:11 +01:00
|
|
|
offsets,
|
|
|
|
MPI_ORDER_C,
|
2023-02-07 09:48:24 +01:00
|
|
|
vectorType,
|
2023-02-06 20:09:11 +01:00
|
|
|
&fileViewType);
|
|
|
|
MPI_Type_commit(&fileViewType);
|
|
|
|
MPI_File_set_view(o->fh, disp, MPI_DOUBLE, fileViewType, "external32", MPI_INFO_NULL);
|
|
|
|
|
2023-02-07 09:48:24 +01:00
|
|
|
size_t cnt = imaxLocal * jmaxLocal * kmaxLocal;
|
|
|
|
double* tmp = allocate(64, cnt * NDIMS * sizeof(double));
|
2023-02-06 20:09:11 +01:00
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
for (int k = 1; k < kmaxLocal + 1; k++) {
|
|
|
|
for (int j = 1; j < jmaxLocal + 1; j++) {
|
|
|
|
for (int i = 1; i < imaxLocal + 1; i++) {
|
|
|
|
tmp[idx++] = (G(vec.u, i, j, k) + G(vec.u, i - 1, j, k)) / 2.0;
|
|
|
|
tmp[idx++] = (G(vec.v, i, j, k) + G(vec.v, i, j - 1, k)) / 2.0;
|
|
|
|
tmp[idx++] = (G(vec.w, i, j, k) + G(vec.w, i, j, k - 1)) / 2.0;
|
|
|
|
}
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
2023-02-06 20:09:11 +01:00
|
|
|
}
|
|
|
|
|
2023-02-07 09:48:24 +01:00
|
|
|
if (commIsMaster(&o->comm)) printf("Write %d vectors\n", (int)cnt);
|
|
|
|
MPI_File_write(o->fh, tmp, cnt, vectorType, MPI_STATUS_IGNORE);
|
2023-02-06 20:09:11 +01:00
|
|
|
MPI_Type_free(&fileViewType);
|
2023-02-07 09:48:24 +01:00
|
|
|
MPI_Type_free(&vectorType);
|
2023-02-06 20:09:11 +01:00
|
|
|
|
|
|
|
// Binary segment must be terminated with newline character
|
|
|
|
resetFileview(o);
|
|
|
|
if (commIsMaster(&o->comm)) {
|
|
|
|
MPI_File_write(o->fh, "\n", 1, MPI_CHAR, MPI_STATUS_IGNORE);
|
2023-02-05 08:02:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-06 20:09:11 +01:00
|
|
|
void vtkClose(VtkOptions* o) { MPI_File_close(&o->fh); }
|