19#include <unordered_map>
73 return nlohmann::json(type).get<std::string>();
98 using json = nlohmann::ordered_json;
100 auto numArray = []() -> json
104 s[
"items"] = json{{
"type",
"number"}};
107 auto intProp = [](
const char *desc) -> json
109 return json{{
"type",
"integer"}, {
"description", desc}, {
"default", 0}};
113 auto makeVariant = [&](std::vector<std::string> types,
114 const char *groupDesc,
116 std::vector<std::string> required) -> json
119 s[
"type"] =
"object";
120 s[
"description"] = groupDesc;
123 if (types.size() == 1)
124 typeSchema = json{{
"const", types[0]}};
126 typeSchema = json{{
"enum", types}};
127 typeSchema[
"description"] =
"Boundary condition type";
130 props[
"type"] = typeSchema;
131 props[
"name"] = json{{
"type",
"string"}, {
"description",
"Boundary zone name"}};
132 for (
auto &[k,
v] : extraProps.items())
135 s[
"properties"] = props;
136 s[
"required"] = required;
141 auto flowTypes = std::vector<std::string>{
"BCFar",
"BCOut",
"BCOutP",
"BCIn",
"BCInPsTs"};
143 flowProps[
"value"] = numArray();
144 flowProps[
"value"][
"description"] =
"BC state vector (size = nVars)";
145 flowProps[
"frameOption"] = intProp(
"Reference frame option");
146 flowProps[
"anchorOption"] = intProp(
"Anchor point option");
147 flowProps[
"integrationOption"] = intProp(
"Integration option");
148 flowProps[
"valueExtra"] = numArray();
149 flowProps[
"valueExtra"][
"description"] =
"Extra BC values (e.g. anchor coordinates)";
151 json oneOf = json::array();
152 for (
auto &t : flowTypes)
154 oneOf.push_back(makeVariant({t}, (
"Flow BC: " + t).c_str(),
156 {
"type",
"name",
"value"}));
161 wallProps[
"value"] = numArray();
162 wallProps[
"value"][
"description"] =
"BC state vector (optional except for BCWallIsothermal)";
163 wallProps[
"frameOption"] = intProp(
"Reference frame option");
164 wallProps[
"integrationOption"] = intProp(
"Integration option");
165 wallProps[
"specialOption"] = intProp(
"Special BC sub-type option");
166 wallProps[
"valueExtra"] = numArray();
167 wallProps[
"valueExtra"][
"description"] =
"Extra BC values";
168 auto wallTypes = std::vector<std::string>{
"BCWall",
"BCWallInvis",
"BCWallIsothermal",
"BCSpecial"};
169 for (
auto &t : wallTypes)
171 auto req = std::vector<std::string>{
"type",
"name"};
172 if (t ==
"BCWallIsothermal")
173 req.push_back(
"value");
174 oneOf.push_back(makeVariant({t}, (
"Wall BC: " + t).c_str(),
180 symProps[
"rectifyOption"] = intProp(
"Symmetry plane rectification option");
181 symProps[
"integrationOption"] = intProp(
"Integration option");
182 symProps[
"valueExtra"] = numArray();
183 symProps[
"valueExtra"][
"description"] =
"Extra BC values";
184 oneOf.push_back(makeVariant({
"BCSym"},
"Symmetry BC",
185 symProps, {
"type",
"name"}));
189 schema[
"type"] =
"array";
190 schema[
"description"] =
"Boundary condition settings (per-BC array)";
191 schema[
"items"] = json{{
"oneOf", oneOf}};
210 template <EulerModel model>
217 using TU_R = Eigen::Vector<real, nVarsFixed>;
219 using TFlags = std::map<std::string, uint32_t>;
222 std::vector<TU> BCValues;
223 std::vector<EulerBCType> BCTypes;
224 std::vector<TFlags> BCFlags;
225 std::vector<Eigen::Vector<real, Eigen::Dynamic>> BCValuesExtra;
226 std::unordered_map<std::string, Geom::t_index> name2ID;
227 std::unordered_map<Geom::t_index, std::string> ID2name;
241 BCValues.resize(Geom::BC_ID_DEFAULT_MAX);
242 for (
auto &
v : BCValues)
244 BCValuesExtra.resize(Geom::BC_ID_DEFAULT_MAX);
245 for (
auto &
v : BCValuesExtra)
247 BCFlags.resize(Geom::BC_ID_DEFAULT_MAX);
249 BCTypes.resize(Geom::BC_ID_DEFAULT_MAX,
BCUnknown);
250 BCTypes[Geom::BC_ID_DEFAULT_FAR] =
BCFar;
251 BCTypes[Geom::BC_ID_DEFAULT_SPECIAL_2DRiemann_FAR] =
BCSpecial;
252 BCTypes[Geom::BC_ID_DEFAULT_SPECIAL_DMR_FAR] =
BCSpecial;
253 BCTypes[Geom::BC_ID_DEFAULT_SPECIAL_IV_FAR] =
BCSpecial;
254 BCTypes[Geom::BC_ID_DEFAULT_SPECIAL_RT_FAR] =
BCSpecial;
255 BCTypes[Geom::BC_ID_DEFAULT_WALL] =
BCWall;
256 BCTypes[Geom::BC_ID_DEFAULT_WALL_INVIS] =
BCWallInvis;
267 std::vector<std::string> ret;
269 if (ID2name.count(i))
270 ret.push_back(ID2name.at(i));
277 return BCTypes.size();
284 for (
auto &p : name2ID)
285 ID2name[p.second] = p.first;
288 using json = nlohmann::ordered_json;
313 std::string bcName = item[
"name"];
314 bc.BCFlags.emplace_back();
323 uint32_t frameOption = 0;
324 uint32_t anchorOption = 0;
325 uint32_t integrationOption = 0;
326 Eigen::VectorXd bcValueExtra;
327 if (item.count(
"frameOption"))
328 frameOption = item[
"frameOption"];
329 if (item.count(
"anchorOption"))
330 anchorOption = item[
"anchorOption"];
331 if (item.count(
"integrationOption"))
332 integrationOption = item[
"integrationOption"];
333 if (item.count(
"valueExtra"))
334 bcValueExtra = item[
"valueExtra"];
335 Eigen::VectorXd bcValue = item[
"value"];
336 DNDS_assert_info(bcValue.size() == bc.nVars, fmt::format(
"[{}] bc value dim not right", bcName));
337 bc.BCValues.push_back(bcValue);
338 bc.BCFlags.back()[
"frameOpt"] = frameOption;
339 bc.BCFlags.back()[
"anchorOpt"] = anchorOption;
340 bc.BCFlags.back()[
"integrationOpt"] = integrationOption;
341 bc.BCValuesExtra.push_back(bcValueExtra);
350 uint32_t frameOption = 0;
351 uint32_t integrationOption = 0;
352 uint32_t specialOption = 0;
353 Eigen::VectorXd bcValueExtra;
354 Eigen::VectorXd bcValue;
355 if (item.count(
"frameOption"))
356 frameOption = item[
"frameOption"];
357 if (item.count(
"integrationOption"))
358 integrationOption = item[
"integrationOption"];
359 if (item.count(
"valueExtra"))
360 bcValueExtra = item[
"valueExtra"];
361 if (item.count(
"value"))
363 bcValue = item[
"value"];
365 DNDS_assert_info(bcValue.size() == bc.nVars, fmt::format(
"[{}] bc value dim not right", bcName));
369 bcValue.setZero(bc.nVars);
373 if (item.count(
"specialOption"))
374 specialOption = item[
"specialOption"];
376 bc.BCValues.push_back(bcValue);
377 bc.BCFlags.back()[
"frameOpt"] = frameOption;
378 bc.BCFlags.back()[
"integrationOpt"] = integrationOption;
379 bc.BCFlags.back()[
"specialOpt"] = specialOption;
380 bc.BCValuesExtra.push_back(bcValueExtra);
386 uint32_t rectifyOption = 0;
387 uint32_t integrationOption = 0;
388 Eigen::VectorXd bcValueExtra;
389 if (item.count(
"rectifyOption"))
390 rectifyOption = item[
"rectifyOption"];
391 if (item.count(
"integrationOption"))
392 integrationOption = item[
"integrationOption"];
393 if (item.count(
"valueExtra"))
394 bcValueExtra = item[
"valueExtra"];
395 bc.BCValues.push_back(TU::Zero(bc.nVars));
396 bc.BCFlags.back()[
"rectifyOpt"] = rectifyOption;
397 bc.BCFlags.back()[
"integrationOpt"] = integrationOption;
398 bc.BCValuesExtra.push_back(bcValueExtra);
407 bc.BCTypes.push_back(bcType);
408 DNDS_assert_info(bc.name2ID.count(bcName) == 0,
"the bc names are duplicate");
409 bc.name2ID[bcName] = bc.BCTypes.size() - 1;
412 bc.BCFlags.size() == bc.BCTypes.size() &&
413 bc.BCValues.size() == bc.BCTypes.size() &&
414 bc.BCValuesExtra.size() == bc.BCTypes.size());
431 for (
Geom::t_index i = Geom::BC_ID_DEFAULT_MAX; i < bc.BCTypes.size(); i++)
435 item[
"type"] = bcType;
436 item[
"name"] = bc.ID2name.at(i);
446 item[
"value"] =
static_cast<TU_R>(bc.BCValues.at(i));
447 item[
"frameOption"] = bc.BCFlags.at(i).at(
"frameOpt");
448 item[
"anchorOption"] = bc.BCFlags.at(i).at(
"anchorOpt");
449 item[
"valueExtra"] = bc.BCValuesExtra.at(i);
458 item[
"frameOption"] = bc.BCFlags.at(i).at(
"frameOpt");
459 item[
"integrationOption"] = bc.BCFlags.at(i).at(
"integrationOpt");
460 item[
"specialOption"] = bc.BCFlags.at(i).at(
"specialOpt");
461 item[
"valueExtra"] = bc.BCValuesExtra.at(i);
462 item[
"value"] =
static_cast<TU_R>(bc.BCValues.at(i));
468 item[
"rectifyOption"] = bc.BCFlags.at(i).at(
"rectifyOpt");
469 item[
"valueExtra"] = bc.BCValuesExtra.at(i);
491 if (name2ID.count(name))
492 return name2ID[name];
494 return Geom::BC_ID_NULL;
504 if (!ID2name.count(
id))
505 return std::string(
"UnNamedBC");
506 return ID2name.at(
id);
519 return BCTypes.at(
id);
530 return BCValues.at(0);
531 return BCValues.at(
id);
542 return BCValuesExtra.at(0);
543 return BCValuesExtra.at(
id);
559 return BCFlags.at(
id).at(key);
575 return BCFlags.at(
id).at(key);
589 Eigen::Vector<real, Eigen::Dynamic>
v;
629 Eigen::Vector<real, Eigen::Dynamic> v0 =
v;
645 template <
int nVarsFixed>
648 using TU = Eigen::Vector<real, nVarsFixed>;
692 Doubleint minDist, minDistall;
693 minDist.dint.d =
dist;
718 using tMap = std::map<std::string, tCellScalarFGet>;
742 for (
auto &name : names)
745 ret.push_back(std::make_tuple(
747 cellOutRegMap[name]));
766 template <
int nVarsFixed>
770 Eigen::Vector<real, Eigen::Dynamic>
nodes;
771 Eigen::Matrix<real, nVarsFixed, Eigen::Dynamic>
v;
772 Eigen::RowVector<real, Eigen::Dynamic>
div;
787 return nodes.size() - 1;
806 nodes.setLinSpaced(size + 1, minV, maxV);
807 v.resize(nvars, size);
824 v.resize(nvars, size);
851 iCL = std::min(
Size() - 1, std::max(
index(0), iCL));
853 iCR = std::min(
Size(), iCR);
855 for (
index i = iCL; i < iCR; i++)
859 real cinIntervalL = std::max(lV, cL);
860 real cinInvervalR = std::min(rV, cR);
861 real cinInvervalLenRel = std::max(cinInvervalR - cinIntervalL, 0.0) / (rV - lV);
862 div[i] += divV * cinInvervalLenRel;
863 v(EigenAll, i) += vmean * divV * cinInvervalLenRel;
871 Eigen::RowVector<real, Eigen::Dynamic> div0 =
div;
872 Eigen::Matrix<real, nVarsFixed, Eigen::Dynamic> v0 =
v;
903 iCL = std::min(
Size() - 1, std::max(
index(0), iCL));
907 vRel = std::min(vRel, 1.);
908 vRel = std::max(vRel, 0.);
909 Eigen::Vector<real, nVarsFixed> valL =
Get(std::max(iCL - 1,
index(0)));
910 Eigen::Vector<real, nVarsFixed> valR =
Get(std::min(iCL + 1,
Size() - 1));
911 valL = 0.5 * (valL +
Get(iCL));
912 valR = 0.5 * (valR +
Get(iCL));
913 return vRel * valR + (1 - vRel) * valL;
931 for (
index i = 0; i <
v.rows(); i++)
932 o <<
", U" << std::to_string(i);
935 o << std::scientific << std::setprecision(precision);
936 for (
index iN = 0; iN <
v.cols(); iN++)
940 for (
index i = 0; i < val.size(); i++)
Extended enum-to-JSON serialization macro that also exposes allowed string values for JSON Schema gen...
#define DNDS_DEFINE_ENUM_JSON(EnumType_,...)
Define JSON serialization for an enum AND expose its allowed string values.
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Core type definitions, enumerations, and distributed array wrappers for compressible Navier-Stokes / ...
JSON-to-Eigen conversion utilities and nlohmann_json helper macros.
Per-zone boundary condition handler for Euler/Navier-Stokes solvers.
nlohmann::ordered_json json
Geom::t_index GetIDFromName(const std::string &name)
Look up the internal BC index for a given zone name.
void RenewID2name()
Rebuild the reverse map (ID2name) from the current name2ID map.
auto GetNameFormID(Geom::t_index id)
Look up the zone name for a given internal BC index.
Eigen::Vector< real, Eigen::Dynamic > GetValueExtraFromID(Geom::t_index id)
Retrieve the extra BC value vector for a given zone index.
TU GetValueFromID(Geom::t_index id)
Retrieve the BC state vector for a given zone index.
std::vector< std::string > GetAllNames()
Return the names of all registered BC zones, ordered by internal ID.
EulerBCType GetTypeFromID(Geom::t_index id)
Retrieve the BC type for a given zone index.
Geom::t_index size()
Return the number of registered BC zones (including default slots).
Eigen::Vector< real, nVarsFixed > TU_R
Fixed-size (read-only) state vector type.
void PushBCWithJson(const json &gS)
Push a new BC zone from a JSON sub-object (not yet implemented).
static const int nVarsFixed
Compile-time variable count (or Eigen::Dynamic).
uint32_t GetFlagFromIDSoft(Geom::t_index id, const std::string &key)
Retrieve an option flag for a given zone index (lenient).
friend void to_json(json &j, const BoundaryHandler< model > &bc)
Serialize user-defined BC zones (those beyond the default slots) to JSON.
uint32_t GetFlagFromID(Geom::t_index id, const std::string &key)
Retrieve an option flag for a given zone index (strict).
BoundaryHandler(int _nVars)
Construct a BoundaryHandler and pre-populate default BC zones.
std::map< std::string, uint32_t > TFlags
Per-zone option flag map (key → integer flag).
friend void from_json(const json &j, BoundaryHandler< model > &bc)
Deserialize an array of BC entries from JSON into bc.
Registry that maps named cell-scalar output fields to getter lambdas.
tCellScalarList getSubsetList(const std::vector< std::string > &names)
Extract a subset of registered output fields by name.
void setMap(const tMap &v)
Register (or replace) the full set of available output fields.
std::map< std::string, tCellScalarFGet > tMap
Name-to-getter mapping type.
std::vector< std::tuple< std::string, const tCellScalarFGet > > tCellScalarList
List of (field_name, getter_function) pairs for cell-scalar output.
std::function< real(index)> tCellScalarFGet
Function type returning a scalar value for a given cell index [0, NumCell).
nlohmann::ordered_json bcSettingsSchema()
Build a JSON Schema (draft-07) for the bcSettings array.
EulerBCType
Boundary condition type identifiers for compressible flow solvers.
@ BCWallIsothermal
Isothermal wall; requires wall temperature in the BC value vector.
@ BCWall
No-slip viscous wall boundary.
@ BCWallInvis
Inviscid slip wall boundary.
@ BCSpecial
Test-case-specific boundary (Riemann, DMR, isentropic vortex, RT).
@ BCOut
Supersonic outflow (extrapolation) boundary.
@ BCUnknown
Uninitialized / invalid sentinel.
@ BCInPsTs
Subsonic inflow with prescribed total pressure and temperature.
@ BCSym
Symmetry plane boundary.
@ BCFar
Far-field (characteristic-based) boundary.
@ BCOutP
Back-pressure (subsonic) outflow boundary.
@ BCIn
Supersonic inflow (fully prescribed state) boundary.
DNDS_DEVICE_CALLABLE bool FaceIDIsExternalBC(t_index id)
void GetTanhDistributionBilateral(real x0, real x1, index NInterval, real d0, Eigen::Vector< real, Eigen::Dynamic > &d)
auto GetFaceName2IDDefault()
MPI_int Bcast(void *buf, MPI_int num, MPI_Datatype type, MPI_int source_rank, MPI_Comm comm)
dumb wrapper
void AllreduceOneReal(real &v, MPI_Op op, const MPIInfo &mpi)
Single-scalar Allreduce helper for reals (in-place, count = 1).
MPI_int Allreduce(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Allreduce.
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
DNDS_CONSTANT const real UnInitReal
Sentinel "not initialised" real value (NaN). Cheap to detect with std::isnan or IsUnInitReal; survive...
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
std::string to_string(const Eigen::DenseBase< dir > &v, int precision=5, bool scientific=false)
Render an Eigen::DenseBase to a string via operator<<.
DNDS_CONSTANT const real veryLargeReal
Catch-all upper bound ("practically infinity") for physical scalars.
int MPI_int
MPI counterpart type for MPI_int (= C int). Used for counts and ranks in MPI calls.
const MPI_Datatype DNDS_MPI_REAL
MPI datatype matching real (= MPI_REAL8).
Finds the cell closest to a specified anchor point across all MPI ranks.
void ObtainAnchorMPI()
Global MPI reduction to find the closest anchor across all ranks.
MPIInfo mpi
MPI communicator info.
TU val
State vector of the closest cell found so far.
Eigen::Vector< real, nVarsFixed > TU
State vector type.
AnchorPointRecorder(const MPIInfo &_mpi)
Construct with MPI communicator.
void AddAnchor(const TU &vin, real nDist)
Submit a candidate anchor cell on this rank.
void Reset()
Reset the recorded distance to veryLargeReal (invalidate current anchor).
real dist
Distance to the closest cell found so far.
Accumulator for MPI-reduced boundary-face integrals.
void Add(TU &&add, real dAdd)
Accumulate a contribution from a single boundary face.
void Reset()
Reset the integral vector and divisor to zero.
void Reduce()
MPI Allreduce (SUM) both the integral vector and the divisor.
real div
Accumulated divisor (area weight).
MPIInfo mpi
MPI communicator info.
Eigen::Vector< real, Eigen::Dynamic > v
Accumulated integral vector.
IntegrationRecorder(const MPIInfo &_nmpi, int siz)
Construct and zero-initialize the integration recorder.
One-dimensional profile for inlet/outlet boundary data.
Eigen::Vector< real, nVarsFixed > GetPlain(real v) const
Linearly interpolate the profile at coordinate v.
void GenerateTanh(index size, int nvars, real minV, real maxV, real d0)
Allocate a tanh-clustered (bilateral) profile.
real Len(index i)
Return the length of cell i (= nodes[i+1] - nodes[i]).
void SortNodes()
Sort node coordinates in ascending order.
Eigen::Vector< real, nVarsFixed > Get(index i) const
Retrieve the averaged value for cell i.
OneDimProfile(const MPIInfo &_mpi)
Construct with MPI communicator (no allocation yet).
Eigen::Vector< real, Eigen::Dynamic > nodes
Node coordinates (size = nCells + 1).
Eigen::RowVector< real, Eigen::Dynamic > div
Per-cell divisor (area weight).
MPIInfo mpi
MPI communicator info.
void GenerateUniform(index size, int nvars, real minV, real maxV)
Allocate a uniformly spaced profile.
void OutProfileCSV(std::ostream &o, bool title=true, int precision=16)
Write the profile to a CSV stream after a valid MPI reduction.
void Reduce()
MPI Allreduce (SUM) the value matrix and divisor across all ranks.
Eigen::Matrix< real, nVarsFixed, Eigen::Dynamic > v
Accumulated cell values (nVars × nCells).
void AddSimpleInterval(TU vmean, real divV, real lV, real rV)
Accumulate a cell-mean value over the interval [lV, rV].
void SetZero()
Zero both the value matrix and the divisor row vector.
index Size() const
Return the number of cells (= nodes.size() - 1).
Lightweight bundle of an MPI communicator and the calling rank's coordinates.
int rank
This rank's 0-based index within comm (-1 until initialised).
MPI_Comm comm
The underlying MPI communicator handle.
Eigen::Matrix wrapper that hides begin/end from fmt.
Eigen::Matrix< real, 5, 1 > v