diff --git a/Adapter.C b/Adapter.C index 7146b1c9..1afa6c4c 100644 --- a/Adapter.C +++ b/Adapter.C @@ -654,13 +654,11 @@ void preciceAdapter::Adapter::adjustSolverTimeStepAndReadData() double tolerance = 1e-14; if (precice_->getMaxTimeStepSize() - timestepSolverDetermined > tolerance) { - // Add a bool 'subCycling = true' which is checked in the storeMeshPoints() function. adapterInfo( "The solver's timestep is smaller than the " "coupling timestep. Subcycling...", "info"); timestepSolver_ = timestepSolverDetermined; - // TODO subcycling is enabled. For FSI the oldVolumes must be written, which is normally not done. if (FSIenabled_) { adapterInfo( @@ -754,23 +752,15 @@ void preciceAdapter::Adapter::reloadCheckpointTime() void preciceAdapter::Adapter::storeMeshPoints() { - DEBUG(adapterInfo("Storing mesh points...")); - // TODO: In foam-extend, we would need "allPoints()". Check if this gives the same data. - meshPoints_ = mesh_.points(); - oldMeshPoints_ = mesh_.oldPoints(); - - /* - // TODO This is only required for subcycling. It should not be called when not subcycling!! - // Add a bool 'subcycling' which can be evaluated every timestep. - if ( !oldVolsStored && mesh_.foundObject("V00") ) // For Ddt schemes which use one previous timestep + if (!meshPoints_) { - setupMeshVolCheckpointing(); - oldVolsStored = true; + DEBUG(adapterInfo("Storing mesh points...")); + // Add points and oldPoints + meshPoints_ = new Foam::pointField(mesh_.points()); + // First timestep oldPoints doesn't exist yet + meshOldPoints_ = new Foam::pointField(mesh_.oldPoints()); } - // Update any volume fields from the buffer to the checkpointed values (if already exists.) - */ - DEBUG(adapterInfo("Stored mesh points.")); if (mesh_.moving()) { if (!meshCheckPointed) @@ -780,7 +770,14 @@ void preciceAdapter::Adapter::storeMeshPoints() meshCheckPointed = true; } writeMeshCheckpoint(); - writeVolCheckpoint(); // Does not write anything unless subcycling. + + // For Ddt schemes which use up to two previous timesteps V0, V00 + if (volumeCheckpointCounter < 3) + { + setupMeshVolCheckpointing(); + } + + writeMeshVolCheckpoint(); } } @@ -792,100 +789,53 @@ void preciceAdapter::Adapter::reloadMeshPoints() return; } - // In Foam::polyMesh::movePoints. - // TODO: The function movePoints overwrites the pointer to the old mesh. - // Therefore, if you revert the mesh, the oldpointer will be set to the points, which are the new values. - DEBUG(adapterInfo("Moving mesh points to their previous locations...")); + // Reload mesh points + const_cast(mesh_).movePoints(*meshPoints_); - // TODO - // Switch oldpoints on for pure physics. (is this required?). Switch off for better mesh deformation capabilities? - // const_cast(mesh_.points()) = oldMeshPoints_; - const_cast(mesh_).movePoints(meshPoints_); + // polyMesh.movePoints will only update oldPoints + // if (curMotionTimeIndex_ != time().timeIndex()) + const_cast(mesh_.oldPoints()) = *meshOldPoints_; - DEBUG(adapterInfo("Moved mesh points to their previous locations.")); + readMeshCheckpoint(); - // TODO The if statement can be removed in this case, but it is still included for clarity - if (meshCheckPointed) - { - readMeshCheckpoint(); - } + DEBUG(adapterInfo("Moved mesh points to their previous locations.")); - /* // TODO This part should only be used when sybcycling. See the description in 'storeMeshPoints()' - // The if statement can be removed in this case, but it is still included for clarity - if ( oldVolsStored ) - { - readVolCheckpoint(); - } - */ + readMeshVolCheckpoint(); } void preciceAdapter::Adapter::setupMeshCheckpointing() { - // The other mesh Fields: - // C - // Cf - // Sf - // magSf - // delta - // are updated by the function fvMesh::movePoints. Only the meshPhi needs checkpointing. DEBUG(adapterInfo("Creating a list of the mesh checkpointed fields...")); + // Add meshPhi (Face motion flux) + addMeshCheckpointField(const_cast(mesh_.phi())); - // Add meshPhi to the checkpointed fields - addMeshCheckpointField( - const_cast( - mesh_.phi())); -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Added " + mesh_.phi().name() + " in the list of checkpointed fields."); -#endif + DEBUG(adapterInfo("Added " + mesh_.phi().name() + " to the list of checkpointed fields.")); } void preciceAdapter::Adapter::setupMeshVolCheckpointing() { - DEBUG(adapterInfo("Creating a list of the mesh volume checkpointed fields...")); - // Add the V0 and the V00 to the list of checkpointed fields. - // For V0 - addVolCheckpointField( - const_cast( - mesh_.V0())); -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Added " + mesh_.V0().name() + " in the list of checkpointed fields."); -#endif - // For V00 - addVolCheckpointField( - const_cast( - mesh_.V00())); -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Added " + mesh_.V00().name() + " in the list of checkpointed fields."); -#endif - - // Also add the buffer fields. - // TODO For V0 - /* addVolCheckpointFieldBuffer - ( - const_cast - ( - mesh_.V0() - ) - ); */ -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Added " + mesh_.V0().name() + " in the list of buffer checkpointed fields."); -#endif - // TODO For V00 - /* addVolCheckpointFieldBuffer - ( - const_cast - ( - mesh_.V00() - ) - );*/ -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Added " + mesh_.V00().name() + " in the list of buffer checkpointed fields."); -#endif + // Add the mesh volumes for the current and up to two previous time steps (V, V0, V00), if available + if (volumeCheckpointCounter == 0) + { + // When V is available, also V0 is available (see fvMesh::movePoints, storeOldVol(V())) + // volumeCheckpointCounter will be 2 after this call + + addMeshVolCheckpointField(const_cast(mesh_.V())); + DEBUG(adapterInfo("Checkpoint mesh V")); + + volumeCheckpointCounter += 1; + + addMeshVolCheckpointField(const_cast(mesh_.V0())); + DEBUG(adapterInfo("Checkpoint mesh V0")); + } + + if (volumeCheckpointCounter == 2) + { + addMeshVolCheckpointField(const_cast(mesh_.V00())); + DEBUG(adapterInfo("Checkpoint mesh V00")); + } + + volumeCheckpointCounter += 1; } @@ -988,35 +938,13 @@ void preciceAdapter::Adapter::pruneCheckpointedFields() void preciceAdapter::Adapter::addMeshCheckpointField(surfaceScalarField& field) { - { - meshSurfaceScalarFields_.push_back(&field); - meshSurfaceScalarFieldCopies_.push_back(new surfaceScalarField(field)); - } -} - -void preciceAdapter::Adapter::addMeshCheckpointField(surfaceVectorField& field) -{ - { - meshSurfaceVectorFields_.push_back(&field); - meshSurfaceVectorFieldCopies_.push_back(new surfaceVectorField(field)); - } -} - -void preciceAdapter::Adapter::addMeshCheckpointField(volVectorField& field) -{ - { - meshVolVectorFields_.push_back(&field); - meshVolVectorFieldCopies_.push_back(new volVectorField(field)); - } + meshSurfaceScalarFields_.push_back(&field); + meshSurfaceScalarFieldCopies_.push_back(new surfaceScalarField(field)); } -// TODO Internal field for the V0 (volume old) and V00 (volume old-old) fields -void preciceAdapter::Adapter::addVolCheckpointField(volScalarField::Internal& field) +void preciceAdapter::Adapter::addMeshVolCheckpointField(volScalarField::Internal& field) { - { - volScalarInternalFields_.push_back(&field); - volScalarInternalFieldCopies_.push_back(new volScalarField::Internal(field)); - } + meshVolFieldCopies_.push_back(new volScalarField::Internal(field)); } @@ -1305,10 +1233,7 @@ void preciceAdapter::Adapter::readCheckpoint() // NOTE: Add here other field types to read, if needed. -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Checkpoint was read. Time = " + std::to_string(runTime_.value())); -#endif + DEBUG(adapterInfo("Checkpoint was read. Time = " + std::to_string(runTime_.value()))); ACCUMULATE_TIMER(timeInCheckpointingRead_); @@ -1392,10 +1317,7 @@ void preciceAdapter::Adapter::writeCheckpoint() } // NOTE: Add here other types to write, if needed. -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored."); -#endif + DEBUG(adapterInfo("Checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored.")); ACCUMULATE_TIMER(timeInCheckpointingWrite_); @@ -1406,11 +1328,9 @@ void preciceAdapter::Adapter::readMeshCheckpoint() { DEBUG(adapterInfo("Reading a mesh checkpoint...")); - // TODO only the meshPhi field is here, which is a surfaceScalarField. The other fields can be removed. - // Reload all the fields of type mesh surfaceScalarField + // Only the meshPhi field is here, which is a surfaceScalarField. for (uint i = 0; i < meshSurfaceScalarFields_.size(); i++) { - // Load the volume field *(meshSurfaceScalarFields_.at(i)) == *(meshSurfaceScalarFieldCopies_.at(i)); int nOldTimes(meshSurfaceScalarFields_.at(i)->nOldTimes()); @@ -1424,118 +1344,74 @@ void preciceAdapter::Adapter::readMeshCheckpoint() } } - // Reload all the fields of type mesh surfaceVectorField - for (uint i = 0; i < meshSurfaceVectorFields_.size(); i++) - { - // Load the volume field - *(meshSurfaceVectorFields_.at(i)) == *(meshSurfaceVectorFieldCopies_.at(i)); - - int nOldTimes(meshSurfaceVectorFields_.at(i)->nOldTimes()); - if (nOldTimes >= 1) - { - meshSurfaceVectorFields_.at(i)->oldTime() == meshSurfaceVectorFieldCopies_.at(i)->oldTime(); - } - if (nOldTimes == 2) - { - meshSurfaceVectorFields_.at(i)->oldTime().oldTime() == meshSurfaceVectorFieldCopies_.at(i)->oldTime().oldTime(); - } - } - - // Reload all the fields of type mesh volVectorField - for (uint i = 0; i < meshVolVectorFields_.size(); i++) - { - // Load the volume field - *(meshVolVectorFields_.at(i)) == *(meshVolVectorFieldCopies_.at(i)); - - int nOldTimes(meshVolVectorFields_.at(i)->nOldTimes()); - if (nOldTimes >= 1) - { - meshVolVectorFields_.at(i)->oldTime() == meshVolVectorFieldCopies_.at(i)->oldTime(); - } - if (nOldTimes == 2) - { - meshVolVectorFields_.at(i)->oldTime().oldTime() == meshVolVectorFieldCopies_.at(i)->oldTime().oldTime(); - } - } - -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Mesh checkpoint was read. Time = " + std::to_string(runTime_.value())); -#endif - - return; + DEBUG(adapterInfo("Mesh checkpoint was read. Time = " + std::to_string(runTime_.value()))); } void preciceAdapter::Adapter::writeMeshCheckpoint() { DEBUG(adapterInfo("Writing a mesh checkpoint...")); - // Store all the fields of type mesh surfaceScalar + // Store all the fields of type mesh surfaceScalar (phi) for (uint i = 0; i < meshSurfaceScalarFields_.size(); i++) { *(meshSurfaceScalarFieldCopies_.at(i)) == *(meshSurfaceScalarFields_.at(i)); } - // Store all the fields of type mesh surfaceVector - for (uint i = 0; i < meshSurfaceVectorFields_.size(); i++) - { - *(meshSurfaceVectorFieldCopies_.at(i)) == *(meshSurfaceVectorFields_.at(i)); - } + DEBUG(adapterInfo("Storing mesh points...")); - // Store all the fields of type mesh volVector - for (uint i = 0; i < meshVolVectorFields_.size(); i++) - { - *(meshVolVectorFieldCopies_.at(i)) == *(meshVolVectorFields_.at(i)); - } + // Store mesh points + *(meshOldPoints_) = *(meshPoints_); + *(meshPoints_) = mesh_.points(); -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Mesh checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored."); -#endif + DEBUG(adapterInfo("Mesh checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored.")); return; } -// TODO for the volumes of the mesh, check this part for subcycling. -void preciceAdapter::Adapter::readVolCheckpoint() +void preciceAdapter::Adapter::readMeshVolCheckpoint() { - DEBUG(adapterInfo("Reading the mesh volumes checkpoint...")); + // Reload V, V0, V00 + if (volumeCheckpointCounter == 2 || volumeCheckpointCounter == 3) + { + const_cast(mesh_.V()) = *(meshVolFieldCopies_.at(0)); + DEBUG(adapterInfo("Read mesh volume " + meshVolFieldCopies_.at(0)->name())); + + const_cast(mesh_.V0()) = *(meshVolFieldCopies_.at(1)); + DEBUG(adapterInfo("Read mesh volume " + meshVolFieldCopies_.at(1)->name())); - // Reload all the fields of type mesh volVectorField::Internal - for (uint i = 0; i < volScalarInternalFields_.size(); i++) + DEBUG(adapterInfo("Mesh volumes checkpoint for time t = " + std::to_string(runTime_.value()) + " were read.")); + } + if (volumeCheckpointCounter == 3) { - // Load the volume field - *(volScalarInternalFields_.at(i)) = *(volScalarInternalFieldCopies_.at(i)); - // There are no old times for the internal fields. + const_cast(mesh_.V00()) = *(meshVolFieldCopies_.at(2)); + DEBUG(adapterInfo("Read mesh volume " + meshVolFieldCopies_.at(2)->name())); } -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Mesh volumes were read. Time = " + std::to_string(runTime_.value())); -#endif - return; } -void preciceAdapter::Adapter::writeVolCheckpoint() +void preciceAdapter::Adapter::writeMeshVolCheckpoint() { - DEBUG(adapterInfo("Writing a mesh volumes checkpoint...")); + // Store V, V0, V00 + if (volumeCheckpointCounter == 2 || volumeCheckpointCounter == 3) + { + *(meshVolFieldCopies_.at(0)) = const_cast(mesh_.V()); + DEBUG(adapterInfo("Write mesh volume " + meshVolFieldCopies_.at(0)->name())); + + *(meshVolFieldCopies_.at(1)) = const_cast(mesh_.V0()); + DEBUG(adapterInfo("Write mesh volume " + meshVolFieldCopies_.at(1)->name())); - // Store all the fields of type mesh volScalarField::Internal - for (uint i = 0; i < volScalarInternalFields_.size(); i++) + DEBUG(adapterInfo("Mesh volumes checkpoint for time t = " + std::to_string(runTime_.value()) + " were stored.")); + } + if (volumeCheckpointCounter == 3) { - *(volScalarInternalFieldCopies_.at(i)) = *(volScalarInternalFields_.at(i)); + *(meshVolFieldCopies_.at(2)) = const_cast(mesh_.V00()); + DEBUG(adapterInfo("Write mesh volume " + meshVolFieldCopies_.at(2)->name())); } -#ifdef ADAPTER_DEBUG_MODE - adapterInfo( - "Mesh volumes checkpoint for time t = " + std::to_string(runTime_.value()) + " was stored."); -#endif - return; } - void preciceAdapter::Adapter::end() { // Throw a warning if the simulation exited before the coupling was complete @@ -1620,27 +1496,14 @@ void preciceAdapter::Adapter::teardown() } meshSurfaceScalarFieldCopies_.clear(); - // meshSurfaceVector - for (uint i = 0; i < meshSurfaceVectorFieldCopies_.size(); i++) + for (uint i = 0; i < meshVolFieldCopies_.size(); i++) { - delete meshSurfaceVectorFieldCopies_.at(i); + delete meshVolFieldCopies_.at(i); } - meshSurfaceVectorFieldCopies_.clear(); + meshVolFieldCopies_.clear(); - // meshVolVector - for (uint i = 0; i < meshVolVectorFieldCopies_.size(); i++) - { - delete meshVolVectorFieldCopies_.at(i); - } - meshVolVectorFieldCopies_.clear(); - - // TODO for the internal volume - // volScalarInternal - for (uint i = 0; i < volScalarInternalFieldCopies_.size(); i++) - { - delete volScalarInternalFieldCopies_.at(i); - } - volScalarInternalFieldCopies_.clear(); + delete meshPoints_; + delete meshOldPoints_; // volTensorField for (uint i = 0; i < volTensorFieldCopies_.size(); i++) diff --git a/Adapter.H b/Adapter.H index b82efa20..8da70237 100644 --- a/Adapter.H +++ b/Adapter.H @@ -138,45 +138,27 @@ private: //- Checkpointed time (index) Foam::label couplingIterationTimeIndex_; - //- Checkpointed mesh points - Foam::pointField meshPoints_; - Foam::pointField oldMeshPoints_; bool meshCheckPointed = false; + bool oldVolsStored = false; - // TODO: Currently unused, see storeMeshPoints(). - //- Checkpointed mesh volume - // bool oldVolsStored = false; - // Foam::volScalarField::Internal * oldVols_; - // Foam::volScalarField::Internal * oldOldVols_; - // int curTimeIndex_ = 0; + //- Volume checkpointing counter (max value 3) + u_int8_t volumeCheckpointCounter = 0; // Vectors of pointers to the checkpointed mesh fields and their copies - //- Checkpointed surfaceScalarField mesh fields + //- Checkpointed mesh points, oldPoints + Foam::pointField* meshPoints_; + Foam::pointField* meshOldPoints_; + + //- Checkpointed volScalarField mesh fields (V, V0, V00) + std::vector meshVolFieldCopies_; + + //- Checkpointed surfaceScalarField mesh fields (phi) std::vector meshSurfaceScalarFields_; //- Checkpointed surfaceScalarField mesh fields (copies) std::vector meshSurfaceScalarFieldCopies_; - //- Checkpointed surfaceVectorField mesh fields - std::vector meshSurfaceVectorFields_; - - //- Checkpointed surfaceVectorField mesh fields (copies) - std::vector meshSurfaceVectorFieldCopies_; - - //- Checkpointed volVectorField mesh fields - std::vector meshVolVectorFields_; - - //- Checkpointed volVectorField mesh fields (copies) - std::vector meshVolVectorFieldCopies_; - - // TODO checkpoint for the V0 (Old volume) and V00 (Old-Old volume) fields. - //- Checkpointed volScalarField mesh fields - std::vector volScalarInternalFields_; - - //- Checkpointed volScalarField mesh fields (copies) - std::vector volScalarInternalFieldCopies_; - // Vectors of pointers to the checkpointed fields and their copies //- Checkpointed volScalarField fields @@ -311,21 +293,12 @@ private: void reloadMeshPoints(); // Add mesh checkpoint fields, depending on the type - //- Add a surfaceScalarField mesh field - void addMeshCheckpointField(surfaceScalarField& field); - - //- Add a surfaceVectorField mesh field - void addMeshCheckpointField(surfaceVectorField& field); - - //- Add a volVectorField mesh field - void addMeshCheckpointField(volVectorField& field); - // TODO V0 and V00 checkpointed field. - //- Add the V0 and V00 checkpoint fields - void addVolCheckpointField(volScalarField::Internal& field); - // void addVolCheckpointFieldBuffer(volScalarField::Internal & field); + //- Add a volScalarField::Internal mesh field (V, V0, V00) + void addMeshVolCheckpointField(volScalarField::Internal& field); - // Add checkpoint fields, depending on the type + //- Add a surfaceScalarField mesh field (phi) + void addMeshCheckpointField(Foam::surfaceScalarField& field); //- Add a volScalarField to checkpoint void addCheckpointField(volScalarField* field); @@ -374,10 +347,10 @@ private: // TODO Probably these can be included to the mesh checkpoints. //- Read the volume checkpoint - restore the mesh volume fields - void readVolCheckpoint(); + void readMeshVolCheckpoint(); //- Write the volume checkpoint to a buffer - restore the mesh volume fields - void writeVolCheckpoint(); + void writeMeshVolCheckpoint(); //- Destroy the preCICE interface and delete the allocated // memory in a proper way. Called by the destructor.