using namespace boost::numeric;
static char help[] =
"Navier-Stokes Example\n";
commonData = boost::make_shared<NavierStokesElement::CommonData>(m_field);
}
}
private:
PetscBool isPartitioned = PETSC_FALSE;
int orderVelocity = 2;
int orderPressure = 1;
PetscBool isDiscontPressure = PETSC_FALSE;
PetscBool isHoGeometry = PETSC_TRUE;
double pressureScale = 1.0;
double lengthScale = 1.0;
double velocityScale = 1.0;
double reNumber = 1.0;
double density;
double viscosity;
PetscBool isStokesFlow = PETSC_FALSE;
int numSteps = 1;
double lambdaStep = 1.0;
int step;
DM dM;
SNES snes;
boost::shared_ptr<NavierStokesElement::CommonData> commonData;
boost::shared_ptr<VolumeElementForcesAndSourcesCore> feLhsPtr;
boost::shared_ptr<VolumeElementForcesAndSourcesCore> feRhsPtr;
boost::shared_ptr<FaceElementForcesAndSourcesCore> feDragPtr;
boost::shared_ptr<VolumeElementForcesAndSourcesCoreOnSide> feDragSidePtr;
boost::shared_ptr<DirichletDisplacementBc> dirichletBcPtr;
boost::ptr_map<std::string, NeumannForcesSurface> neumannForces;
boost::shared_ptr<PostProcVol> fePostProcPtr;
boost::shared_ptr<PostProcFace> fePostProcDragPtr;
};
CHKERR defineFiniteElements();
CHKERR setupDiscreteManager();
CHKERR setupAlgebraicStructures();
CHKERR setupElementInstances();
}
PetscBool flg_mesh_file;
CHKERR PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"NAVIER_STOKES problem",
"none");
CHKERR PetscOptionsString(
"-my_file",
"mesh file name",
"",
"mesh.h5m",
CHKERR PetscOptionsBool(
"-my_is_partitioned",
"is partitioned?",
"",
isPartitioned, &isPartitioned, PETSC_NULL);
CHKERR PetscOptionsInt(
"-my_order_u",
"approximation orderVelocity",
"",
orderVelocity, &orderVelocity, PETSC_NULL);
CHKERR PetscOptionsInt(
"-my_order_p",
"approximation orderPressure",
"",
orderPressure, &orderPressure, PETSC_NULL);
CHKERR PetscOptionsInt(
"-my_num_ho_levels",
"number of higher order boundary levels", "",
CHKERR PetscOptionsBool(
"-my_discont_pressure",
"discontinuous pressure",
"",
isDiscontPressure, &isDiscontPressure, PETSC_NULL);
CHKERR PetscOptionsBool(
"-my_ho_geometry",
"use second order geometry",
"",
isHoGeometry, &isHoGeometry, PETSC_NULL);
CHKERR PetscOptionsScalar(
"-my_length_scale",
"length scale",
"", lengthScale,
&lengthScale, PETSC_NULL);
CHKERR PetscOptionsScalar(
"-my_velocity_scale",
"velocity scale",
"",
velocityScale, &velocityScale, PETSC_NULL);
CHKERR PetscOptionsBool(
"-my_stokes_flow",
"stokes flow",
"", isStokesFlow,
&isStokesFlow, PETSC_NULL);
CHKERR PetscOptionsInt(
"-my_step_num",
"number of steps",
"", numSteps,
&numSteps, PETSC_NULL);
ierr = PetscOptionsEnd();
if (flg_mesh_file != PETSC_TRUE) {
SETERRQ(PETSC_COMM_SELF, 1, "*** ERROR -my_file (MESH FILE NEEDED)");
}
if (isPartitioned == PETSC_TRUE) {
const char *option;
option = "PARALLEL=READ_PART;"
"PARALLEL_RESOLVE_SHARED_ENTS;"
"PARTITION=PARALLEL_PARTITION;";
} else {
const char *option;
option = "";
}
CHKERR mField.rebuild_database();
bitLevel.set(0);
bitLevel);
}
if (
bit->getName().compare(0, 9,
"MAT_FLUID") == 0) {
const int id =
bit->getMeshsetId();
CHKERR mField.get_moab().get_entities_by_dimension(
bit->getMeshset(), 3, commonData->setOfBlocksData[
id].eNts,
true);
std::vector<double> attributes;
bit->getAttributes(attributes);
if (attributes.size() < 2) {
"should be at least 2 attributes but is %d",
attributes.size());
}
commonData->setOfBlocksData[id].iD = id;
commonData->setOfBlocksData[id].fluidViscosity = attributes[0];
commonData->setOfBlocksData[id].fluidDensity = attributes[1];
viscosity = commonData->setOfBlocksData[id].fluidViscosity;
density = commonData->setOfBlocksData[id].fluidDensity;
}
}
if (
bit->getName().compare(0, 9,
"INT_SOLID") == 0) {
const int id =
bit->getMeshsetId();
CHKERR mField.get_moab().get_entities_by_type(
bit->getMeshset(), MBTRI, commonData->setOfFacesData[
id].eNts,
true);
solidFaces.merge(commonData->setOfFacesData[id].eNts);
CHKERR mField.get_moab().get_adjacencies(
commonData->setOfFacesData[id].eNts, 3, true, tets,
moab::Interface::UNION);
tet =
Range(tets.front(), tets.front());
for (
auto &
bit : commonData->setOfBlocksData) {
if (
bit.second.eNts.contains(tet)) {
commonData->setOfFacesData[id].fluidViscosity =
bit.second.fluidViscosity;
commonData->setOfFacesData[id].fluidDensity =
bit.second.fluidDensity;
commonData->setOfFacesData[id].iD = id;
break;
}
}
if (commonData->setOfFacesData[id].fluidViscosity < 0) {
"Cannot find a fluid block adjacent to a given solid face");
}
}
}
}
if (isDiscontPressure) {
} else {
}
3);
CHKERR mField.add_ents_to_field_by_dim(0, 3,
"VELOCITY");
CHKERR mField.add_ents_to_field_by_dim(0, 3,
"PRESSURE");
CHKERR mField.add_ents_to_field_by_dim(0, 3,
"MESH_NODE_POSITIONS");
CHKERR mField.set_field_order(0, MBVERTEX,
"VELOCITY", 1);
CHKERR mField.set_field_order(0, MBEDGE,
"VELOCITY", orderVelocity);
CHKERR mField.set_field_order(0, MBTRI,
"VELOCITY", orderVelocity);
CHKERR mField.set_field_order(0, MBTET,
"VELOCITY", orderVelocity);
if (!isDiscontPressure) {
CHKERR mField.set_field_order(0, MBVERTEX,
"PRESSURE", 1);
CHKERR mField.set_field_order(0, MBEDGE,
"PRESSURE", orderPressure);
CHKERR mField.set_field_order(0, MBTRI,
"PRESSURE", orderPressure);
}
CHKERR mField.set_field_order(0, MBTET,
"PRESSURE", orderPressure);
ents.merge(solidFaces);
CHKERR mField.get_moab().get_connectivity(ents, verts,
true);
for (
auto d : {1, 2, 3}) {
CHKERR mField.get_moab().get_adjacencies(verts,
d,
false, ents,
moab::Interface::UNION);
}
levels[ll] = subtract(ents, ents.subset_by_type(MBVERTEX));
}
levels[ll] = subtract(levels[ll], levels[ll - 1]);
}
int add_order = 1;
if (isPartitioned)
levels[ll]);
CHKERR mField.set_field_order(levels[ll],
"VELOCITY",
orderVelocity + add_order);
if (!isDiscontPressure)
CHKERR mField.set_field_order(levels[ll],
"PRESSURE",
orderPressure + add_order);
else
CHKERR mField.set_field_order(levels[ll].subset_by_type(MBTET),
"PRESSURE", orderPressure + add_order);
++add_order;
}
}
CHKERR mField.set_field_order(0, MBVERTEX,
"MESH_NODE_POSITIONS", 1);
if (isHoGeometry) {
CHKERR mField.get_moab().get_entities_by_dimension(0, 3, ents);
CHKERR mField.get_moab().get_adjacencies(ents, 1,
false, edges,
moab::Interface::UNION);
if (isPartitioned)
CHKERR mField.set_field_order(edges,
"MESH_NODE_POSITIONS", 2);
}
if (isPartitioned) {
"VELOCITY");
"PRESSURE");
"MESH_NODE_POSITIONS");
}
"MESH_NODE_POSITIONS");
CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_material);
}
"PRESSURE", "MESH_NODE_POSITIONS");
"MESH_NODE_POSITIONS", 2, &solidFaces);
CHKERR mField.build_finite_elements();
CHKERR mField.build_adjacencies(bitLevel);
}
DMType dm_name = "DM_NAVIER_STOKES";
CHKERR DMCreate(PETSC_COMM_WORLD, &dM);
CHKERR DMSetType(dM, dm_name);
if (mField.check_finite_element("PRESSURE_FE"))
}
CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
}
feLhsPtr = boost::shared_ptr<VolumeElementForcesAndSourcesCore>(
feRhsPtr = boost::shared_ptr<VolumeElementForcesAndSourcesCore>(
true);
true);
feDragPtr = boost::shared_ptr<FaceElementForcesAndSourcesCore>(
feDragSidePtr = boost::shared_ptr<VolumeElementForcesAndSourcesCoreOnSide>(
true);
if (isStokesFlow) {
feRhsPtr, feLhsPtr, "VELOCITY", "PRESSURE", commonData);
} else {
feRhsPtr, feLhsPtr, "VELOCITY", "PRESSURE", commonData);
}
"NAVIER_STOKES", "VELOCITY",
"PRESSURE", commonData);
dirichletBcPtr = boost::shared_ptr<DirichletDisplacementBc>(
dirichletBcPtr->snes_x =
D;
NULL, "VELOCITY");
fePostProcPtr = boost::make_shared<PostProcVol>(mField);
true);
auto v_ptr = boost::make_shared<MatrixDouble>();
auto grad_ptr = boost::make_shared<MatrixDouble>();
auto pos_ptr = boost::make_shared<MatrixDouble>();
auto p_ptr = boost::make_shared<VectorDouble>();
fePostProcPtr->getOpPtrVector().push_back(
fePostProcPtr->getOpPtrVector().push_back(
fePostProcPtr->getOpPtrVector().push_back(
fePostProcPtr->getOpPtrVector().push_back(
fePostProcPtr->getOpPtrVector().push_back(
fePostProcPtr->getPostProcMesh(), fePostProcPtr->getMapGaussPts(),
{{"PRESSURE", p_ptr}},
{{"VELOCITY", v_ptr}, {"MESH_NODE_POSITIONS", pos_ptr}},
{{"VELOCITY_GRAD", grad_ptr}},
{}
)
);
fePostProcDragPtr = boost::make_shared<PostProcFace>(mField);
fePostProcDragPtr->getOpPtrVector().push_back(
fePostProcDragPtr->getOpPtrVector().push_back(
fePostProcDragPtr->getPostProcMesh(),
fePostProcDragPtr->getMapGaussPts(),
{},
{{"MESH_NODE_POSITIONS", pos_ptr}},
{},
{}
)
);
fePostProcDragPtr, feDragSidePtr, "NAVIER_STOKES", "VELOCITY", "PRESSURE",
commonData);
}
boost::ptr_map<std::string, NeumannForcesSurface>::iterator mit =
neumannForces.begin();
for (; mit != neumannForces.end(); mit++) {
&mit->second->getLoopFe(), NULL, NULL);
}
boost::shared_ptr<FEMethod> null_fe;
null_fe);
dirichletBcPtr);
null_fe);
null_fe);
dirichletBcPtr);
CHKERR SNESCreate(PETSC_COMM_WORLD, &snes);
CHKERR SNESSetFromOptions(snes);
}
auto scale_problem = [&](
double U,
double L,
double P) {
"MESH_NODE_POSITIONS");
mField, "MESH_NODE_POSITIONS", true, true);
CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_on_10nodeTet);
ent_method_on_10nodeTet.setNodes = false;
CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_on_10nodeTet);
};
pressureScale = viscosity * velocityScale / lengthScale;
CHKERR scale_problem(1.0 / velocityScale, 1.0 / lengthScale,
1.0 / pressureScale);
step = 0;
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Viscosity: %6.4e\n", viscosity);
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Density: %6.4e\n", density);
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Length scale: %6.4e\n", lengthScale);
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Velocity scale: %6.4e\n",
velocityScale);
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Pressure scale: %6.4e\n",
pressureScale);
if (isStokesFlow) {
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Re number: 0 (Stokes flow)\n");
} else {
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Re number: %6.4e\n",
density / viscosity * velocityScale * lengthScale);
}
lambdaStep = 1.0 / numSteps;
while (
lambda < 1.0 - 1e-12) {
if (isStokesFlow) {
reNumber = 0.0;
for (
auto &
bit : commonData->setOfBlocksData) {
bit.second.inertiaCoef = 0.0;
bit.second.viscousCoef = 1.0;
}
} else {
reNumber = density / viscosity * velocityScale * lengthScale *
lambda;
for (
auto &
bit : commonData->setOfBlocksData) {
bit.second.inertiaCoef = reNumber;
bit.second.viscousCoef = 1.0;
}
}
PETSC_COMM_WORLD,
"Step: %d | Lambda: %6.4e | Inc: %6.4e | Re number: %6.4e \n", step,
lambda, lambdaStep, reNumber);
CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR SNESSolve(snes, PETSC_NULL,
D);
CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR scale_problem(velocityScale, lengthScale, pressureScale);
CHKERR scale_problem(1.0 / velocityScale, 1.0 / lengthScale,
1.0 / pressureScale);
step++;
}
}
{
std::ostringstream stm;
stm << "out_" << step << ".h5m";
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Write file %s\n",
}
CHKERR VecZeroEntries(commonData->pressureDragForceVec);
CHKERR VecZeroEntries(commonData->shearDragForceVec);
CHKERR VecZeroEntries(commonData->totalDragForceVec);
auto get_vec_data = [&](auto vec, std::array<double, 3> &data) {
const double *array;
CHKERR VecGetArrayRead(vec, &array);
if (mField.get_comm_rank() == 0) {
}
CHKERR VecRestoreArrayRead(vec, &array);
};
std::array<double, 3> pressure_drag;
std::array<double, 3> shear_drag;
std::array<double, 3> total_drag;
CHKERR get_vec_data(commonData->pressureDragForceVec, pressure_drag);
CHKERR get_vec_data(commonData->shearDragForceVec, shear_drag);
CHKERR get_vec_data(commonData->totalDragForceVec, total_drag);
if (mField.get_comm_rank() == 0) {
"Pressure drag force: [ %6.4e, %6.4e, %6.4e ]",
pressure_drag[0], pressure_drag[1], pressure_drag[2]);
"Shear drag force: [ %6.4e, %6.4e, %6.4e ]", shear_drag[0],
shear_drag[1], shear_drag[2]);
"Total drag force: [ %6.4e, %6.4e, %6.4e ]", total_drag[0],
total_drag[1], total_drag[2]);
}
{
std::ostringstream stm;
stm << "out_drag_" << step << ".h5m";
CHKERR PetscPrintf(PETSC_COMM_WORLD,
"out file %s\n",
}
}
int main(
int argc,
char *argv[]) {
const char param_file[] = "param_file.petsc";
try {
}
return 0;
}