14 using namespace boost::numeric;
17 static char help[] =
"Navier-Stokes Example\n";
25 commonData = boost::make_shared<NavierStokesElement::CommonData>(m_field);
37 PetscBool isPartitioned = PETSC_FALSE;
39 int orderVelocity = 2;
40 int orderPressure = 1;
42 PetscBool isDiscontPressure = PETSC_FALSE;
43 PetscBool isHoGeometry = PETSC_TRUE;
45 double pressureScale = 1.0;
46 double lengthScale = 1.0;
47 double velocityScale = 1.0;
48 double reNumber = 1.0;
51 PetscBool isStokesFlow = PETSC_FALSE;
54 double lambdaStep = 1.0;
64 boost::shared_ptr<NavierStokesElement::CommonData>
commonData;
70 boost::shared_ptr<VolumeElementForcesAndSourcesCore>
feLhsPtr;
71 boost::shared_ptr<VolumeElementForcesAndSourcesCore>
feRhsPtr;
73 boost::shared_ptr<FaceElementForcesAndSourcesCore>
feDragPtr;
74 boost::shared_ptr<VolumeElementForcesAndSourcesCoreOnSide>
feDragSidePtr;
101 CHKERR defineFiniteElements();
102 CHKERR setupDiscreteManager();
103 CHKERR setupAlgebraicStructures();
104 CHKERR setupElementInstances();
115 PetscBool flg_mesh_file;
117 CHKERR PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"NAVIER_STOKES problem",
120 CHKERR PetscOptionsString(
"-my_file",
"mesh file name",
"",
"mesh.h5m",
122 CHKERR PetscOptionsBool(
"-my_is_partitioned",
"is partitioned?",
"",
123 isPartitioned, &isPartitioned, PETSC_NULL);
125 CHKERR PetscOptionsInt(
"-my_order_u",
"approximation orderVelocity",
"",
126 orderVelocity, &orderVelocity, PETSC_NULL);
127 CHKERR PetscOptionsInt(
"-my_order_p",
"approximation orderPressure",
"",
128 orderPressure, &orderPressure, PETSC_NULL);
129 CHKERR PetscOptionsInt(
"-my_num_ho_levels",
130 "number of higher order boundary levels",
"",
132 CHKERR PetscOptionsBool(
"-my_discont_pressure",
"discontinuous pressure",
"",
133 isDiscontPressure, &isDiscontPressure, PETSC_NULL);
134 CHKERR PetscOptionsBool(
"-my_ho_geometry",
"use second order geometry",
"",
135 isHoGeometry, &isHoGeometry, PETSC_NULL);
137 CHKERR PetscOptionsScalar(
"-my_length_scale",
"length scale",
"", lengthScale,
138 &lengthScale, PETSC_NULL);
139 CHKERR PetscOptionsScalar(
"-my_velocity_scale",
"velocity scale",
"",
140 velocityScale, &velocityScale, PETSC_NULL);
141 CHKERR PetscOptionsBool(
"-my_stokes_flow",
"stokes flow",
"", isStokesFlow,
142 &isStokesFlow, PETSC_NULL);
144 CHKERR PetscOptionsInt(
"-my_step_num",
"number of steps",
"", numSteps,
145 &numSteps, PETSC_NULL);
147 ierr = PetscOptionsEnd();
149 if (flg_mesh_file != PETSC_TRUE) {
150 SETERRQ(PETSC_COMM_SELF, 1,
"*** ERROR -my_file (MESH FILE NEEDED)");
154 if (isPartitioned == PETSC_TRUE) {
158 option =
"PARALLEL=READ_PART;"
159 "PARALLEL_RESOLVE_SHARED_ENTS;"
160 "PARTITION=PARALLEL_PARTITION;";
171 CHKERR mField.rebuild_database();
186 if (
bit->getName().compare(0, 9,
"MAT_FLUID") == 0) {
187 const int id =
bit->getMeshsetId();
188 CHKERR mField.get_moab().get_entities_by_dimension(
189 bit->getMeshset(), 3, commonData->setOfBlocksData[
id].eNts,
true);
191 std::vector<double> attributes;
192 bit->getAttributes(attributes);
193 if (attributes.size() < 2) {
195 "should be at least 2 attributes but is %d",
198 commonData->setOfBlocksData[id].iD = id;
199 commonData->setOfBlocksData[id].fluidViscosity = attributes[0];
200 commonData->setOfBlocksData[id].fluidDensity = attributes[1];
202 viscosity = commonData->setOfBlocksData[id].fluidViscosity;
203 density = commonData->setOfBlocksData[id].fluidDensity;
208 if (
bit->getName().compare(0, 9,
"INT_SOLID") == 0) {
210 const int id =
bit->getMeshsetId();
211 CHKERR mField.get_moab().get_entities_by_type(
212 bit->getMeshset(), MBTRI, commonData->setOfFacesData[
id].eNts,
true);
213 solidFaces.merge(commonData->setOfFacesData[
id].eNts);
214 CHKERR mField.get_moab().get_adjacencies(
215 commonData->setOfFacesData[
id].eNts, 3,
true, tets,
216 moab::Interface::UNION);
217 tet =
Range(tets.front(), tets.front());
218 for (
auto &
bit : commonData->setOfBlocksData) {
219 if (
bit.second.eNts.contains(tet)) {
220 commonData->setOfFacesData[id].fluidViscosity =
221 bit.second.fluidViscosity;
222 commonData->setOfFacesData[id].fluidDensity =
bit.second.fluidDensity;
223 commonData->setOfFacesData[id].iD = id;
227 if (commonData->setOfFacesData[
id].fluidViscosity < 0) {
229 "Cannot find a fluid block adjacent to a given solid face");
243 if (isDiscontPressure) {
251 CHKERR mField.add_ents_to_field_by_dim(0, 3,
"VELOCITY");
252 CHKERR mField.add_ents_to_field_by_dim(0, 3,
"PRESSURE");
253 CHKERR mField.add_ents_to_field_by_dim(0, 3,
"MESH_NODE_POSITIONS");
255 CHKERR mField.set_field_order(0, MBVERTEX,
"VELOCITY", 1);
256 CHKERR mField.set_field_order(0, MBEDGE,
"VELOCITY", orderVelocity);
257 CHKERR mField.set_field_order(0, MBTRI,
"VELOCITY", orderVelocity);
258 CHKERR mField.set_field_order(0, MBTET,
"VELOCITY", orderVelocity);
260 if (!isDiscontPressure) {
261 CHKERR mField.set_field_order(0, MBVERTEX,
"PRESSURE", 1);
262 CHKERR mField.set_field_order(0, MBEDGE,
"PRESSURE", orderPressure);
263 CHKERR mField.set_field_order(0, MBTRI,
"PRESSURE", orderPressure);
265 CHKERR mField.set_field_order(0, MBTET,
"PRESSURE", orderPressure);
270 ents.merge(solidFaces);
273 CHKERR mField.get_moab().get_connectivity(ents, verts,
true);
274 for (
auto d : {1, 2, 3}) {
275 CHKERR mField.get_moab().get_adjacencies(verts,
d,
false, ents,
276 moab::Interface::UNION);
278 levels[ll] = subtract(ents, ents.subset_by_type(MBVERTEX));
281 levels[ll] = subtract(levels[ll], levels[ll - 1]);
290 CHKERR mField.set_field_order(levels[ll],
"VELOCITY",
291 orderVelocity + add_order);
292 if (!isDiscontPressure)
293 CHKERR mField.set_field_order(levels[ll],
"PRESSURE",
294 orderPressure + add_order);
296 CHKERR mField.set_field_order(levels[ll].subset_by_type(MBTET),
297 "PRESSURE", orderPressure + add_order);
302 CHKERR mField.set_field_order(0, MBVERTEX,
"MESH_NODE_POSITIONS", 1);
306 CHKERR mField.get_moab().get_entities_by_dimension(0, 3, ents);
307 CHKERR mField.get_moab().get_adjacencies(ents, 1,
false, edges,
308 moab::Interface::UNION);
311 CHKERR mField.set_field_order(edges,
"MESH_NODE_POSITIONS", 2);
320 "MESH_NODE_POSITIONS");
323 CHKERR mField.build_fields();
326 "MESH_NODE_POSITIONS");
327 CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_material);
339 "PRESSURE",
"MESH_NODE_POSITIONS");
342 "MESH_NODE_POSITIONS", 2, &solidFaces);
348 CHKERR mField.build_finite_elements();
350 CHKERR mField.build_adjacencies(bitLevel);
359 DMType dm_name =
"DM_NAVIER_STOKES";
362 CHKERR DMCreate(PETSC_COMM_WORLD, &dM);
363 CHKERR DMSetType(dM, dm_name);
367 CHKERR DMSetFromOptions(dM);
371 if (mField.check_finite_element(
"PRESSURE_FE"))
389 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
390 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
393 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
394 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
396 CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
397 CHKERR MatZeroEntries(Aij);
407 feLhsPtr = boost::shared_ptr<VolumeElementForcesAndSourcesCore>(
409 feRhsPtr = boost::shared_ptr<VolumeElementForcesAndSourcesCore>(
419 feDragPtr = boost::shared_ptr<FaceElementForcesAndSourcesCore>(
421 feDragSidePtr = boost::shared_ptr<VolumeElementForcesAndSourcesCoreOnSide>(
430 feRhsPtr, feLhsPtr,
"VELOCITY",
"PRESSURE", commonData);
433 feRhsPtr, feLhsPtr,
"VELOCITY",
"PRESSURE", commonData);
437 "NAVIER_STOKES",
"VELOCITY",
438 "PRESSURE", commonData);
440 dirichletBcPtr = boost::shared_ptr<DirichletDisplacementBc>(
444 dirichletBcPtr->snes_x =
D;
451 fePostProcPtr = boost::make_shared<PostProcVol>(mField);
455 auto v_ptr = boost::make_shared<MatrixDouble>();
456 auto grad_ptr = boost::make_shared<MatrixDouble>();
457 auto pos_ptr = boost::make_shared<MatrixDouble>();
458 auto p_ptr = boost::make_shared<VectorDouble>();
460 fePostProcPtr->getOpPtrVector().push_back(
462 fePostProcPtr->getOpPtrVector().push_back(
464 fePostProcPtr->getOpPtrVector().push_back(
466 fePostProcPtr->getOpPtrVector().push_back(
471 fePostProcPtr->getOpPtrVector().push_back(
475 fePostProcPtr->getPostProcMesh(), fePostProcPtr->getMapGaussPts(),
477 {{
"PRESSURE", p_ptr}},
479 {{
"VELOCITY", v_ptr}, {
"MESH_NODE_POSITIONS", pos_ptr}},
481 {{
"VELOCITY_GRAD", grad_ptr}},
489 fePostProcDragPtr = boost::make_shared<PostProcFace>(mField);
490 fePostProcDragPtr->getOpPtrVector().push_back(
492 fePostProcDragPtr->getOpPtrVector().push_back(
496 fePostProcDragPtr->getPostProcMesh(),
497 fePostProcDragPtr->getMapGaussPts(),
501 {{
"MESH_NODE_POSITIONS", pos_ptr}},
512 fePostProcDragPtr, feDragSidePtr,
"NAVIER_STOKES",
"VELOCITY",
"PRESSURE",
523 boost::ptr_map<std::string, NeumannForcesSurface>::iterator mit =
524 neumannForces.begin();
525 for (; mit != neumannForces.end(); mit++) {
527 &mit->second->getLoopFe(), NULL, NULL);
530 boost::shared_ptr<FEMethod> null_fe;
545 CHKERR SNESCreate(PETSC_COMM_WORLD, &snes);
549 CHKERR SNESSetFromOptions(snes);
559 auto scale_problem = [&](
double U,
double L,
double P) {
562 "MESH_NODE_POSITIONS");
565 mField,
"MESH_NODE_POSITIONS",
true,
true);
566 CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_on_10nodeTet);
567 ent_method_on_10nodeTet.
setNodes =
false;
568 CHKERR mField.loop_dofs(
"MESH_NODE_POSITIONS", ent_method_on_10nodeTet);
575 pressureScale = viscosity * velocityScale / lengthScale;
577 CHKERR scale_problem(1.0 / velocityScale, 1.0 / lengthScale,
578 1.0 / pressureScale);
582 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Viscosity: %6.4e\n", viscosity);
583 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Density: %6.4e\n", density);
584 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Length scale: %6.4e\n", lengthScale);
585 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Velocity scale: %6.4e\n",
587 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Pressure scale: %6.4e\n",
590 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Re number: 0 (Stokes flow)\n");
592 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Re number: %6.4e\n",
593 density / viscosity * velocityScale * lengthScale);
596 lambdaStep = 1.0 / numSteps;
598 while (
lambda < 1.0 - 1e-12) {
604 for (
auto &
bit : commonData->setOfBlocksData) {
605 bit.second.inertiaCoef = 0.0;
606 bit.second.viscousCoef = 1.0;
609 reNumber = density / viscosity * velocityScale * lengthScale *
lambda;
610 for (
auto &
bit : commonData->setOfBlocksData) {
611 bit.second.inertiaCoef = reNumber;
612 bit.second.viscousCoef = 1.0;
618 "Step: %d | Lambda: %6.4e | Inc: %6.4e | Re number: %6.4e \n", step,
619 lambda, lambdaStep, reNumber);
625 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
626 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
628 CHKERR SNESSolve(snes, PETSC_NULL,
D);
630 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
631 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
634 CHKERR scale_problem(velocityScale, lengthScale, pressureScale);
638 CHKERR scale_problem(1.0 / velocityScale, 1.0 / lengthScale,
639 1.0 / pressureScale);
656 std::ostringstream stm;
657 stm <<
"out_" << step <<
".h5m";
659 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"Write file %s\n",
664 CHKERR VecZeroEntries(commonData->pressureDragForceVec);
665 CHKERR VecZeroEntries(commonData->shearDragForceVec);
666 CHKERR VecZeroEntries(commonData->totalDragForceVec);
669 auto get_vec_data = [&](
auto vec, std::array<double, 3> &data) {
671 CHKERR VecAssemblyBegin(vec);
672 CHKERR VecAssemblyEnd(vec);
674 CHKERR VecGetArrayRead(vec, &array);
675 if (mField.get_comm_rank() == 0) {
676 for (
int i : {0, 1, 2})
679 CHKERR VecRestoreArrayRead(vec, &array);
683 std::array<double, 3> pressure_drag;
684 std::array<double, 3> shear_drag;
685 std::array<double, 3> total_drag;
687 CHKERR get_vec_data(commonData->pressureDragForceVec, pressure_drag);
688 CHKERR get_vec_data(commonData->shearDragForceVec, shear_drag);
689 CHKERR get_vec_data(commonData->totalDragForceVec, total_drag);
691 if (mField.get_comm_rank() == 0) {
693 "Pressure drag force: [ %6.4e, %6.4e, %6.4e ]",
694 pressure_drag[0], pressure_drag[1], pressure_drag[2]);
696 "Shear drag force: [ %6.4e, %6.4e, %6.4e ]", shear_drag[0],
697 shear_drag[1], shear_drag[2]);
699 "Total drag force: [ %6.4e, %6.4e, %6.4e ]", total_drag[0],
700 total_drag[1], total_drag[2]);
705 std::ostringstream stm;
706 stm <<
"out_drag_" << step <<
".h5m";
708 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"out file %s\n",
717 int main(
int argc,
char *argv[]) {
719 const char param_file[] =
"param_file.petsc";