diff --git a/Cheng-model.stl b/Cheng-model.stl new file mode 100644 index 000000000..916ae89d6 Binary files /dev/null and b/Cheng-model.stl differ diff --git a/models/flow/d3q27_cumulant/Dynamics.R b/models/flow/d3q27_cumulant/Dynamics.R index fcb1f0b53..fde24e12c 100644 --- a/models/flow/d3q27_cumulant/Dynamics.R +++ b/models/flow/d3q27_cumulant/Dynamics.R @@ -46,7 +46,10 @@ AddNodeType(name="SPressure", group="BOUNDARY") AddNodeType(name="NSymmetry", group="ADDITIONALS") AddNodeType(name="SSymmetry", group="ADDITIONALS") AddNodeType(name="Body", group="BODY") - +AddNodeType(name="FVelocity", group="BOUNDARY") +AddNodeType(name="BVelocity", group="BOUNDARY") +AddNodeType(name="FPressure", group="BOUNDARY") +AddNodeType(name="BPressure", group="BOUNDARY") for (f in fname) AddField(f,dx=0,dy=0,dz=0) # Make f accessible also in present node (not only streamed) diff --git a/models/flow/d3q27_cumulant/Dynamics.c.Rt b/models/flow/d3q27_cumulant/Dynamics.c.Rt index e75b957b2..ba3451445 100644 --- a/models/flow/d3q27_cumulant/Dynamics.c.Rt +++ b/models/flow/d3q27_cumulant/Dynamics.c.Rt @@ -136,6 +136,16 @@ CudaDeviceFunction void WVelocity() } +CudaDeviceFunction void FVelocity() +{ + +} + +CudaDeviceFunction void BVelocity() +{ + +} + CudaDeviceFunction void SVelocity() { @@ -156,6 +166,16 @@ CudaDeviceFunction void SPressure() } +CudaDeviceFunction void FPressure() +{ + +} + +CudaDeviceFunction void BPressure() +{ + +} + CudaDeviceFunction void NPressure() { @@ -242,26 +262,38 @@ CudaDeviceFunction void RunBoundaries() { WVelocityTurbulent(); break; case NODE_EPressure: - EPressure(); - break; + EPressure(); + break; case NODE_WPressure: WPressure(); break; + case NODE_FPressure: + FPressure(); + break; + case NODE_BPressure: + BPressure(); + break; case NODE_SPressure: - SPressure(); - break; + SPressure(); + break; case NODE_NPressure: - NPressure(); - break; + NPressure(); + break; case NODE_WVelocity: WVelocity(); break; - case NODE_NVelocity: - NVelocity(); - break; - case NODE_SVelocity: - SVelocity(); - break; + case NODE_FVelocity: + NVelocity(); + break; + case NODE_BVelocity: + SVelocity(); + break; + case NODE_NVelocity: + NVelocity(); + break; + case NODE_SVelocity: + SVelocity(); + break; case NODE_EVelocity: EVelocity(); break; diff --git a/src/ArbConnectivity.hpp b/src/ArbConnectivity.hpp index f6380d5f5..448f081c6 100644 --- a/src/ArbConnectivity.hpp +++ b/src/ArbConnectivity.hpp @@ -5,6 +5,8 @@ #include #include +#include "types.h" + struct ArbLatticeConnectivity { using Index = long; using ZoneIndex = unsigned short; @@ -14,8 +16,10 @@ struct ArbLatticeConnectivity { std::unique_ptr og_index; std::unique_ptr nbrs; std::unique_ptr zones_per_node; + std::vector cart_index; std::vector zones; double grid_size{}; + int nx, ny, nz; // total region ArbLatticeConnectivity() = default; ArbLatticeConnectivity(size_t chunk_begin_, size_t chunk_end_, size_t num_nodes_global_, size_t Q_) @@ -26,7 +30,8 @@ struct ArbLatticeConnectivity { coords(std::make_unique(3 * (chunk_end_ - chunk_begin_))), og_index(std::make_unique(chunk_end_ - chunk_begin_)), nbrs(std::make_unique((chunk_end_ - chunk_begin_) * Q)), - zones_per_node(std::make_unique(chunk_end_ - chunk_begin_)) { + zones_per_node(std::make_unique(chunk_end_ - chunk_begin_)), + cart_index(chunk_end_ - chunk_begin_) { zones.reserve(getLocalSize()); } @@ -46,12 +51,16 @@ struct ArbLatticeConnectivity { } size_t getLocalSize() const { return chunk_end - chunk_begin; } + bool isGhost(Index nbr) const { return nbr != -1 && (nbr < static_cast(chunk_begin) || nbr >= static_cast(chunk_end)); } double& coord(size_t dim, size_t local_node_ind) { return coords[local_node_ind + dim * getLocalSize()]; } double coord(size_t dim, size_t local_node_ind) const { return coords[local_node_ind + dim * getLocalSize()]; } + Index& cartesian_ind(size_t local_node_ind) { return cart_index[local_node_ind]; } + Index cartesian_ind(size_t local_node_ind) const { return cart_index[local_node_ind]; } Index& neighbor(size_t q, size_t local_node_ind) { return nbrs[local_node_ind + q * getLocalSize()]; } Index neighbor(size_t q, size_t local_node_ind) const { return nbrs[local_node_ind + q * getLocalSize()]; } + }; inline auto computeInitialNodeDist(size_t num_nodes_global, size_t comm_size) -> std::vector { diff --git a/src/ArbLattice.cpp b/src/ArbLattice.cpp index 23129f962..0750e70ed 100644 --- a/src/ArbLattice.cpp +++ b/src/ArbLattice.cpp @@ -24,6 +24,7 @@ ArbLattice::ArbLattice(size_t num_snaps_, const UnitEnv& units_, const std::map< void ArbLattice::initialize(size_t num_snaps_, const std::map& setting_zones, pugi::xml_node arb_node) { const int rank = mpitools::MPI_Rank(comm); sizes.snaps = num_snaps_; + sample = std::make_unique(model.get(), units, rank); #ifdef ADJOINT sizes.snaps += 2; // Adjoint snaps are appended to the total snap allocation #endif @@ -71,6 +72,20 @@ int ArbLattice::reinitialize(size_t num_snaps_, const std::map return EXIT_SUCCESS; } +int ArbLattice::getId(const double &dx, const double &dy, const double &dz) +{ + int id = 0; + double epsilon = std::fabs(connect.coord(0, 0) - dx) + std::fabs(connect.coord(1, 0) - dy) + std::fabs(connect.coord(2, 0) - dz); + for (int i = 1; i < getLocalSize(); i++) { + double tmp = std::fabs(connect.coord(0, i) - dx) + std::fabs(connect.coord(1, i) - dy) + std::fabs(connect.coord(2, i) - dz); + if (tmp < epsilon) { + epsilon = tmp; + id = i; + } + } + return id; +} + void ArbLattice::readFromCxn(const std::string& cxn_path) { using namespace std::string_literals; using namespace std::string_view_literals; @@ -152,6 +167,14 @@ void ArbLattice::readFromCxn(const std::string& cxn_path) { file >> grid_size; check_file_ok("Failed to read section: GRID_SIZE"); + // Total region + file >> word; + check_file_ok("Failed to read section header: TOTAL_REGION"); + check_expected_word("TOTAL_REGION", word); + int nx, ny, nz; + file >> nx >> ny >> nz; + check_file_ok("Failed to read section: TOTAL_REGION"); + // Labels present in the .cxn file const auto labels = process_section("NODE_LABELS", [&file](size_t n_labels) { std::vector retval(n_labels); @@ -162,17 +185,20 @@ void ArbLattice::readFromCxn(const std::string& cxn_path) { // Nodes header process_section("NODES", [&](size_t num_nodes_global) { - // Compute the current rank's offset and number of nodes to read + // Compute the current ranks offset and number of nodes to read const auto chunk_offsets = computeInitialNodeDist(num_nodes_global, static_cast(comm_size)); const auto chunk_begin = static_cast(chunk_offsets[comm_rank]), chunk_end = static_cast(chunk_offsets[comm_rank + 1]); const auto num_nodes_local = chunk_end - chunk_begin; connect = ArbLatticeConnectivity(chunk_begin, chunk_end, num_nodes_global, Q); connect.grid_size = grid_size; + connect.nx = nx; + connect.ny = ny; + connect.nz = nz; // Skip chunk_begin + 1 (header) newlines for (size_t i = 0; i != chunk_begin + 1; ++i) file.ignore(std::numeric_limits::max(), '\n'); - check_file_ok("Failed to skip ahead to this rank's chunk"); + check_file_ok("Failed to skip ahead to this ranks chunk"); // Parse node data std::vector nbrs_in_file(q_provided.size()); @@ -180,6 +206,9 @@ void ArbLattice::readFromCxn(const std::string& cxn_path) { // Read coords file >> connect.coord(0, local_node_ind) >> connect.coord(1, local_node_ind) >> connect.coord(2, local_node_ind); + // Read cartesian index + file >> connect.cartesian_ind(local_node_ind); + // Read neighbors, map to local (required) ones for (auto& nbr : nbrs_in_file) file >> nbr; size_t j = 0; @@ -539,6 +568,15 @@ std::vector ArbLattice::getQuantity(const Model::Quantity& q, real_t sca return ret; } +void ArbLattice::getSample(int quant, lbRegion r, real_t scale, real_t *buf) { + setSnapIn(Snap); +#ifdef ADJOINT + setAdjSnapIn(aSnap); +#endif + int lid = getId(r.x, r.y, r.z); + launcher.SampleQuantity(quant, lid, buf, scale, data); +} + std::vector ArbLattice::getCoord(const Model::Coord& d, real_t scale) { size_t size = getLocalSize(); std::vector ret(size); @@ -549,8 +587,6 @@ std::vector ArbLattice::getCoord(const Model::Coord& d, real_t scale) { return ret; } -#include - void ArbLattice::initCommManager() { if (mpitools::MPI_Size(comm) == 1) return; int rank = mpitools::MPI_Rank(comm); @@ -843,4 +879,20 @@ void ArbLattice::resetAverage(){ CudaMemset(&getSnapPtr(Snap)[f.id*sizes.snaps_pitch], 0, sizes.snaps_pitch*sizeof(real_t)); } } -} \ No newline at end of file +} + +void ArbLattice::updateAllSamples(){ + const int rank = mpitools::MPI_Rank(comm); + if (sample->size != 0) { + for (size_t j = 0; j < sample->spoints.size(); j++) { + if (rank == sample->spoints[j].rank) { + for(const Model::Quantity& q : model->quantities) { + if (sample->quant->in(q.name.c_str())){ + double v = sample->units->alt(q.unit.c_str()); + getSample(q.id, sample->spoints[j].location, 1/v, &sample->gpu_buffer[sample->location[q.name.c_str()]+(data.iter - sample->startIter)*sample->size + sample->totalIter*j*sample->size]); + } + } + } + } + } +} diff --git a/src/ArbLattice.hpp b/src/ArbLattice.hpp index 4883ff4b6..8170a7660 100644 --- a/src/ArbLattice.hpp +++ b/src/ArbLattice.hpp @@ -7,6 +7,7 @@ #include "ArbConnectivity.hpp" #include "ArbLatticeLauncher.h" +#include "Sampler.h" #include "CudaUtils.hpp" #include "LatticeBase.hpp" #include "Lists.h" @@ -71,6 +72,7 @@ class ArbLattice : public LatticeBase { public: static constexpr size_t Q = Model_m::Q; /// Stencil size static constexpr size_t NF = Model_m::NF; /// Number of fields + std::unique_ptr sample; /// initializing sample with zero size ArbLattice(size_t num_snaps_, const UnitEnv& units_, const std::map& setting_zones, pugi::xml_node arb_node, MPI_Comm comm_); ArbLattice(const ArbLattice&) = delete; @@ -86,10 +88,12 @@ class ArbLattice : public LatticeBase { virtual std::vector shape() const { return {static_cast(getLocalSize())}; }; virtual std::vector getQuantity(const Model::Quantity& q, real_t scale = 1) ; + virtual void getSample(int quant, lbRegion r, real_t scale, real_t *buf); virtual std::vector getFlags() const; virtual std::vector getField(const Model::Field& f); virtual std::vector getFieldAdj(const Model::Field& f); virtual std::vector getCoord(const Model::Coord& q, real_t scale = 1); + virtual int getId(const double &dx, const double &dy, const double &dz); virtual void setFlags(const std::vector& x); virtual void setField(const Model::Field& f, const std::vector& x); @@ -99,8 +103,10 @@ class ArbLattice : public LatticeBase { Span getNodeTypes() const { return {node_types_host.data(), node_types_host.size()}; } /// Get host view of node types (permuted) const ArbLatticeConnectivity& getConnectivity() const { return connect; } const std::vector& getLocalPermutation() const { return local_permutation; } + lbRegion getLocalBoundingBox() const; /// Compute local bounding box, assuming the arbitrary lattice is a subset of a Cartesian lattice void resetAverage(); + void updateAllSamples(); protected: ArbLatticeLauncher launcher; /// Launcher responsible for running CUDA kernels on the lattice @@ -134,7 +140,7 @@ class ArbLattice : public LatticeBase { #endif void clearAdjoint() final; /// TODO - void initialize(size_t num_snaps_, const std::map& setting_zones, pugi::xml_node arb_node); /// Init based on args + void initialize(size_t num_snaps_, const std::map& setting_zones, pugi::xml_node arb_node); /// Init based on args /// Calculation of the offset from x, y and z void readFromCxn(const std::string& cxn_path); /// Read the lattice info from a .cxn file void partition(); /// Repartition the lattice, if ParMETIS is not present this is a noop std::function makePermCompare(pugi::xml_node arb_node, const std::map& setting_zones); /// Make type-erased comparison operator for computing the local permutation, according to the strategy specified in the xml file @@ -149,7 +155,6 @@ class ArbLattice : public LatticeBase { void initCommManager(); /// Compute which fields need to be sent to/received from which neighbors void initContainer(); /// Initialize the data residing in launcher.container int fullLatticePos(double pos) const; /// Compute the position (in terms of lattice offsets) of a node, assuming the arbitrary lattice is a subset of a Cartesian lattice - lbRegion getLocalBoundingBox() const; /// Compute local bounding box, assuming the arbitrary lattice is a subset of a Cartesian lattice ArbVTUGeom makeVTUGeom() const; /// Compute VTU geometry void communicateBorder(); /// Send and receive border values in snap (overlapped with interior computation) unsigned lookupLocalGhostIndex(ArbLatticeConnectivity::Index gid) const; /// For a given ghost gid, look up its local id diff --git a/src/ArbLatticeLauncher.h.Rt b/src/ArbLatticeLauncher.h.Rt index 31c604a97..47662df6a 100644 --- a/src/ArbLatticeLauncher.h.Rt +++ b/src/ArbLatticeLauncher.h.Rt @@ -21,6 +21,7 @@ struct ArbLatticeLauncher { void unpack(CudaStream_t stream) const; void getQuantity(int quant, real_t* host_tab, real_t scale, const LatticeData& data) const; + void SampleQuantity(int quant, int lid, real_t *host_tab, real_t scale, const LatticeData& data); private: void getQuantity(* tab, real_t scale, const LatticeData& data) const; + void getSample(int lid, * tab, real_t scale, const LatticeData& data) const; }; diff --git a/src/ArbLatticeLauncher.hpp.Rt b/src/ArbLatticeLauncher.hpp.Rt index ecddb46d8..0ff3a438e 100644 --- a/src/ArbLatticeLauncher.hpp.Rt +++ b/src/ArbLatticeLauncher.hpp.Rt @@ -87,6 +87,22 @@ ifdef(); } } +void ArbLatticeLauncher::SampleQuantity(int quant, int lid, real_t* host_tab, real_t scale, const LatticeData &data) { + switch(quant) { + case : { + const auto gpu_tab = cudaMakeUnique<>(1); + getSample(lid, gpu_tab.get(), scale, data); + CudaMemcpy(host_tab, gpu_tab.get(), sizeof(), CudaMemcpyDeviceToHost); + break; + } + } +} + : public LinearExecutor { + ArbLatticeContainer container; + LatticeData data; + + int lid; + * buf; + real_t scale; + + CudaDeviceFunction void Execute() const { + using LA = ArbLatticeAccess; + using N = Node< LA, Adjoint, NoGlobals, Get >; + using N = Node< LA, Primal, NoGlobals, Get >; + + LA acc(lid, container); + N now(acc, data); + acc.pop(now); + acc.pop_adj(now); + auto val = now.get(); + val. *= scale; + val *= scale; + buf[0] = val; + } +}; + void ArbLatticeLauncher::getQuantity(* tab, real_t scale, const LatticeData& data) const { const GetQuantityArbExecutor executor{{container.num_border_nodes + container.num_interior_nodes}, container, data, tab, scale}; LaunchExecutor(executor); } + +void ArbLatticeLauncher::getSample(int lid, * tab, real_t scale, const LatticeData& data) const { + const GetSampleArbExecutor executor{{1}, container, data, lid, tab, scale}; + LaunchExecutor(executor); +} + diff --git a/src/CartLatticeLauncher.hpp.Rt b/src/CartLatticeLauncher.hpp.Rt index e4e6f47a7..63bf04610 100644 --- a/src/CartLatticeLauncher.hpp.Rt +++ b/src/CartLatticeLauncher.hpp.Rt @@ -255,9 +255,9 @@ public: CudaDeviceFunction void Execute() const { using LA = CartLatticeAccessAll; - int x = CudaBlock.x + small.dx; - int y = CudaBlock.y + small.dy; - int z = CudaBlock.z + small.dz; + int x = (CudaBlock.x + small.dx) %container.nx; + int y = (CudaBlock.y + small.dy) %container.ny; + int z = (CudaBlock.z + small.dz) %container.nz; LA acc(x, y, z, container); Node< LA, Adjoint, NoGlobals, Get > now(acc, data); #include "Solver.h" +#include #define ITERATION_STOP 1 diff --git a/src/Handlers/cbSample.cpp b/src/Handlers/cbSample.cpp index 295488d85..e961971d6 100644 --- a/src/Handlers/cbSample.cpp +++ b/src/Handlers/cbSample.cpp @@ -3,20 +3,20 @@ std::string cbSample::xmlname = "Sample"; #include "../HandlerFactory.h" int cbSample::Init () { - std::string nm="Sampler"; - Callback::Init(); - if (everyIter == 0) { - error("Iteration value in sampler should not be zero"); - return -1; - } - pugi::xml_attribute attr=node.attribute("what"); - if (attr) { - s.add_from_string(attr.value(),','); - } - else { - s.add_from_string("all",','); - } - const auto lattice = solver->getCartLattice(); + std::string nm="Sampler"; + Callback::Init(); + if (everyIter == 0) { + error("Iteration value in sampler should not be zero"); + return -1; + } + pugi::xml_attribute attr=node.attribute("what"); + if (attr) { + s.add_from_string(attr.value(),','); + } + else { + s.add_from_string("all",','); + } + const auto init_cartesian = [&](const Lattice* lattice){ for (pugi::xml_node par = node.first_child(); par; par = par.next_sibling()) { if (strcmp(par.name(),"Point") == 0) { lbRegion loc; @@ -44,24 +44,75 @@ int cbSample::Init () { lattice->sample->mpi_rank = solver->mpi_rank; lattice->sample->Allocate(&s,startIter,everyIter); lattice->sample->initCSV(filename.c_str()); - return 0; - } + return EXIT_SUCCESS; + }; + + const auto init_arbitrary = [&](const Lattice* lattice) { + for (pugi::xml_node par = node.first_child(); par; par = par.next_sibling()) { + if (strcmp(par.name(),"Point") == 0) { + lbRegion loc; + attr = par.attribute("dx"); + if (attr) { + loc.x = solver->units.si(attr.value()); + loc.dx = solver->units.alt(attr.value()); + } + attr = par.attribute("dy"); + if (attr) { + loc.y = solver->units.si(attr.value()); + loc.dy = solver->units.alt(attr.value()); + } + attr = par.attribute("dz"); + if (attr) { + loc.z = solver->units.si(attr.value()); + loc.dz = solver->units.alt(attr.value()); + } + if (loc.nx == 1) lattice->sample->addPoint(loc, solver->mpi_rank); + } else { + error("Uknown element in Sampler\n"); + return -1; + } + } + filename = solver->outIterFile(nm, ".csv"); + lattice->sample->units = &solver->units; + lattice->sample->mpi_rank = solver->mpi_rank; + lattice->sample->Allocate(&s,startIter,everyIter); + lattice->sample->initCSV(filename.c_str()); + return EXIT_SUCCESS; + }; + return std::visit(OverloadSet{init_cartesian, init_arbitrary}, solver->getLatticeVariant()); +} int cbSample::DoIt () { - Callback::DoIt(); - const auto lattice = solver->getCartLattice(); - lattice->sample->writeHistory(solver->iter); - lattice->sample->startIter = solver->iter; - return 0; - } + Callback::DoIt(); + const auto do_cartesian = [&](Lattice* lattice) { + lattice->sample->writeHistory(solver->iter); + lattice->sample->startIter = solver->iter; + return EXIT_SUCCESS; + }; + const auto do_arbitrary = [&](Lattice* lattice) { + lattice->sample->writeHistory(solver->iter); + lattice->sample->startIter = solver->iter; + return EXIT_SUCCESS; + }; + return std::visit(OverloadSet{do_cartesian, do_arbitrary}, solver->getLatticeVariant()); +} int cbSample::Finish () { - solver->getCartLattice()->sample->Finish(); - return Callback::Finish(); - } + const auto end_cartesian = [&](const Lattice* lattice) { + lattice->sample->Finish(); + return Callback::Finish(); + }; + const auto end_arbitrary = [&](const Lattice* lattice) { + lattice->sample->Finish(); + return Callback::Finish(); + }; + return std::visit(OverloadSet{end_cartesian, end_arbitrary}, solver->getLatticeVariant()); +} // Register the handler (basing on xmlname) in the Handler Factory template class HandlerFactory::Register< GenericAsk< cbSample > >; + + diff --git a/src/Lattice.hpp.Rt b/src/Lattice.hpp.Rt index de3ac6bf8..70cc47324 100644 --- a/src/Lattice.hpp.Rt +++ b/src/Lattice.hpp.Rt @@ -109,8 +109,7 @@ struct Lattice : public LatticeType { CudaDeviceSynchronize(); LatticeType::Snap = tab_out; LatticeType::MarkIteration(); - if constexpr(std::is_same_v) /// TODO - LatticeType::updateAllSamples(); + LatticeType::updateAllSamples(); DEBUG_PROF_POP(); } diff --git a/src/Region.h b/src/Region.h index 9d2f197ca..83484b800 100644 --- a/src/Region.h +++ b/src/Region.h @@ -8,6 +8,7 @@ struct lbRegion { int dx = 0, dy = 0, dz = 0; int nx = 1, ny = 1, nz = 1; + float x = 0.0f, y = 0.0f, z = 0.0f; lbRegion() = default; lbRegion(int w, int h) : nx(w), ny(h) {} lbRegion(int x, int y, int w, int h) : dx(x), dy(y), nx(w), ny(h) {} diff --git a/src/toArb.cpp b/src/toArb.cpp index 7244fd721..05318ab2a 100644 --- a/src/toArb.cpp +++ b/src/toArb.cpp @@ -57,10 +57,11 @@ static auto makeArbLatticeIndexMap(const lbRegion& region, const std::vector& zone_map) { +static int writeArbLatticeHeader(std::fstream& file, const lbRegion& region, size_t n_nodes, double grid_size, const Model& model, const std::map& zone_map) { file << "OFFSET_DIRECTIONS " << Model_m::offset_directions.size() << '\n'; for (const auto [x, y, z] : Model_m::offset_directions) file << x << ' ' << y << ' ' << z << '\n'; file << "GRID_SIZE " << grid_size << '\n'; + file << "TOTAL_REGION " << region.nx << ' ' << region.ny << ' ' << region.nz << '\n'; file << "NODE_LABELS " << model.nodetypeflags.size() + zone_map.size() << '\n'; for (const auto& ntf : model.nodetypeflags) file << ntf.name << '\n'; for (const auto& [name, zf] : zone_map) file << "_Z_" << name << '\n'; @@ -93,6 +94,9 @@ static int writeArbLatticeNodes(const Geometry& geo, const double z_coord = (static_cast(z) + .5) * spacing; file << x_coord << ' ' << y_coord << ' ' << z_coord << ' '; + // Cartesian index + file << current_lin_pos << ' '; + // Neighbors for (const auto [dx, dy, dz] : Model_m::offset_directions) { const auto lin_pos_offset = linPosBoundschecked(x + dx, y + dy, z + dz, nx, ny, nz); @@ -140,7 +144,7 @@ static int writeArbLattice(const Geometry& geo, ERROR("Failed to open .cxn file for writing"); return EXIT_FAILURE; } - if (writeArbLatticeHeader(file, lin_to_arb_index_map.size(), spacing, model, zone_map)) return EXIT_FAILURE; + if (writeArbLatticeHeader(file, geo.totalregion, lin_to_arb_index_map.size(), spacing, model, zone_map)) return EXIT_FAILURE; return writeArbLatticeNodes(geo, model, zone_map, lin_to_arb_index_map, bulk_bmp, file, spacing); } diff --git a/src/vtkLattice.cpp b/src/vtkLattice.cpp index befdccf5c..721020a74 100644 --- a/src/vtkLattice.cpp +++ b/src/vtkLattice.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "Global.h" #include "cross.h" diff --git a/src/vtuOutput.h b/src/vtuOutput.h index 8ad2f5fc4..2733dfbcc 100644 --- a/src/vtuOutput.h +++ b/src/vtuOutput.h @@ -2,6 +2,7 @@ #define VTUOUTPUT_H #include +#include #include "cross.h" #include "types.h"