|
| 1 | +/** @file vertical-beam-IGA-IGA-fake-fluid.cpp |
| 2 | + * |
| 3 | + * @brief Provide the spline based coupling method through preCICE. |
| 4 | + * |
| 5 | + * This file is a part of G+Smo library. |
| 6 | + * |
| 7 | + * This Source Code Form is subject to the terms of the Mozilla Public |
| 8 | + * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 9 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 10 | + * |
| 11 | + * Author(s): J. Li |
| 12 | + * |
| 13 | + **/ |
| 14 | + |
| 15 | +#include <gismo.h> |
| 16 | +#include <gsPreCICE/gsPreCICE.h> |
| 17 | +#include <gsPreCICE/gsPreCICEUtils.h> |
| 18 | +#include <gsPreCICE/gsPreCICEFunction.h> |
| 19 | +// #include <gsPreCICE/gsPreCICEVectorFunction.h> |
| 20 | + |
| 21 | +#include <gsElasticity/gsMassAssembler.h> |
| 22 | +#include <gsElasticity/gsElasticityAssembler.h> |
| 23 | + |
| 24 | +#ifdef gsStructuralAnalysis_ENABLED |
| 25 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicExplicitEuler.h> |
| 26 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicImplicitEuler.h> |
| 27 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicNewmark.h> |
| 28 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicBathe.h> |
| 29 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicWilson.h> |
| 30 | +#include <gsStructuralAnalysis/src/gsDynamicSolvers/gsDynamicRK4.h> |
| 31 | +#include <gsStructuralAnalysis/src/gsStructuralAnalysisTools/gsStructuralAnalysisUtils.h> |
| 32 | +#endif |
| 33 | +using namespace gismo; |
| 34 | + |
| 35 | +int main(int argc, char *argv[]) |
| 36 | +{ |
| 37 | + |
| 38 | + //! [Parse command line] |
| 39 | + bool plot = false; |
| 40 | + bool write = false; |
| 41 | + bool get_readTime = false; // Command line option for spline read and write time |
| 42 | + bool get_writeTime = false; |
| 43 | + index_t plotmod = 1; |
| 44 | + index_t loadCase = 0; |
| 45 | + std::string precice_config("../precice_config.xml"); |
| 46 | + |
| 47 | + gsCmdLine cmd("Coupled heat equation using PreCICE."); |
| 48 | + cmd.addString( "c", "config", "PreCICE config file", precice_config ); |
| 49 | + cmd.addInt("l","loadCase", "Load case: 0=constant load, 1='spring' load", loadCase); |
| 50 | + cmd.addSwitch("write", "Create a file with point data", write); |
| 51 | + cmd.addSwitch("readTime", "Get the read time", get_readTime); |
| 52 | + cmd.addSwitch("writeTime", "Get the write time", get_writeTime); |
| 53 | + try { cmd.getValues(argc,argv); } catch (int rv) { return rv; } |
| 54 | + |
| 55 | + GISMO_ASSERT(gsFileManager::fileExists(precice_config),"No precice config file has been defined"); |
| 56 | + //! [Read input file] |
| 57 | + std::string participantName = "Fluid"; |
| 58 | + gsPreCICE<real_t> participant(participantName, precice_config); |
| 59 | + |
| 60 | + |
| 61 | + /* |
| 62 | + * Data initialization |
| 63 | + * |
| 64 | + * This participant receives mesh information (knot vector, control points) from the solid, |
| 65 | + * and it creates its own mesh based on the information. |
| 66 | + * And writes pressure, reads displacements from the solid participant. |
| 67 | + * The follow meshes and data are made available: |
| 68 | + * |
| 69 | + * - Meshes: |
| 70 | + * + GeometryControlPointMesh: This mesh contains the control points as mesh vertices. |
| 71 | + * + GeometryKnotMesh: This mesh contains the knots as mesh vertices. |
| 72 | + * + ForceKnotMesh: This mesh contains the knots as mesh vertices for force mesh. |
| 73 | + * + ForceControlPointMesh: This mesh contains the control points as mesh vertices for force mesh. |
| 74 | + * |
| 75 | + * |
| 76 | + * - Data: |
| 77 | + * + GeometryControlPointData: This data is defined on the ControlPointMesh and stores the displacement of the control points |
| 78 | + * + ForceControlPointData: This data is defined on the ForceControlPointMesh and stores the change of pressure/stress |
| 79 | + */ |
| 80 | + |
| 81 | + |
| 82 | + // Meshes |
| 83 | + std::string GeometryControlPointMesh = "GeometryControlPointMesh"; |
| 84 | + std::string GeometryKnotMesh = "GeometryKnotMesh"; |
| 85 | + |
| 86 | + |
| 87 | + std::string ForceKnotMesh = "ForceKnotMesh"; |
| 88 | + std::string ForceControlPointMesh = "ForceControlPointMesh"; |
| 89 | + |
| 90 | + |
| 91 | + // Data |
| 92 | + std::string GeometryControlPointData = "GeometryControlPointData"; |
| 93 | + std::string ForceControlPointData = "ForceControlPointData"; |
| 94 | + // std::string GeometryKnotData = "GeometryKnotData"; |
| 95 | + // std::string ForceKnotData = "ForceKnotMeshData"; |
| 96 | + |
| 97 | + gsMatrix<> bbox(3,2); |
| 98 | + bbox << -1e300, 1e300, // X dimension limits |
| 99 | + -1e300, 1e300, // Y dimension limits |
| 100 | + -1e300, 1e300; // Z dimension limits |
| 101 | + bbox.transposeInPlace(); |
| 102 | + bbox.resize(1,bbox.rows()*bbox.cols()); |
| 103 | + |
| 104 | + // Step 2: Add force mesh |
| 105 | + |
| 106 | + // Step 2.1: Define force knot mesh |
| 107 | + gsVector<index_t> forceKnotIDs; |
| 108 | + gsKnotVector<> kv(0,1,10,3,1); //begin, end, # interiors, mult, by default =1 |
| 109 | + gsTensorBSplineBasis<2, real_t> forceBasis(kv,kv); |
| 110 | + gsMatrix<> forceControlPoints(forceBasis.size(), 3); |
| 111 | + forceControlPoints.setZero(); |
| 112 | + forceControlPoints.col(2).setConstant(-5e3); |
| 113 | + forceControlPoints.transposeInPlace(); |
| 114 | + |
| 115 | + gsMatrix<> forceKnots = knotsToMatrix(forceBasis); |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + // Regenerate the geometry in another solver |
| 120 | + // forceMesh.addPatch(give(forceBasis.makeGeometry(forceControlPoints))); |
| 121 | + |
| 122 | + // Step 2.1: Define force control point mesh |
| 123 | + gsVector<index_t> forceControlPointIDs; |
| 124 | + participant.addMesh(ForceKnotMesh,forceKnots,forceKnotIDs); |
| 125 | + participant.addMesh(ForceControlPointMesh,forceControlPoints,forceControlPointIDs); |
| 126 | + participant.setMeshAccessRegion(GeometryControlPointMesh, bbox); |
| 127 | + |
| 128 | + real_t precice_dt = participant.initialize(); |
| 129 | + |
| 130 | + // Step 1: Collect geometry from PreCICE |
| 131 | + gsVector<index_t> geometryKnotIDs; |
| 132 | + gsMatrix<> geometryKnots; |
| 133 | + participant.getMeshVertexIDsAndCoordinates(GeometryKnotMesh, geometryKnotIDs, geometryKnots); |
| 134 | + |
| 135 | + |
| 136 | + gsBasis<> * geometryKnotBasis = knotMatrixToBasis<real_t>(geometryKnots).get(); |
| 137 | + |
| 138 | + gsVector<index_t> geometryControlPointIDs; |
| 139 | + gsMatrix<> geometryControlPoints; |
| 140 | + participant.getMeshVertexIDsAndCoordinates(GeometryControlPointMesh, geometryControlPointIDs, geometryControlPoints); |
| 141 | + |
| 142 | + gsMultiPatch<> mp, deformation; |
| 143 | + mp.addPatch(give(geometryKnotBasis->makeGeometry(geometryControlPoints.transpose()))); |
| 144 | + |
| 145 | + deformation = mp; |
| 146 | + |
| 147 | + |
| 148 | + real_t t=0; |
| 149 | + real_t dt = precice_dt; |
| 150 | + real_t t_read = 0; |
| 151 | + real_t t_write = 0; |
| 152 | + |
| 153 | + index_t timestep = 0; |
| 154 | + |
| 155 | + // Define the solution collection for Paraview |
| 156 | + gsParaviewCollection collection("./output/solution"); |
| 157 | + |
| 158 | + gsMatrix<> points(2,1); |
| 159 | + points.col(0)<<0.5,1; |
| 160 | + |
| 161 | + gsStructuralAnalysisOutput<real_t> writer("./output/pointData.csv",points); |
| 162 | + writer.init({"x","y","z"},{"time"}); |
| 163 | + |
| 164 | + // Time integration loop |
| 165 | + while(participant.isCouplingOngoing()) |
| 166 | + { |
| 167 | + |
| 168 | + // Read control point displacements |
| 169 | + participant.readData(GeometryControlPointMesh, GeometryControlPointData, geometryControlPointIDs, geometryControlPoints); |
| 170 | + deformation.patch(0).coefs() = geometryControlPoints.transpose(); |
| 171 | + if (get_readTime) |
| 172 | + t_read += participant.readTime(); |
| 173 | + |
| 174 | + /* |
| 175 | + * Two projection approaches: |
| 176 | + * - gsQuasiInterpolate<real_t>::localIntpl(forceBasis, deformation.patch(0), coefs); |
| 177 | + * - gsL2Projection<real_t>::projectFunction(forceBasis, deformation, mp, coefs) |
| 178 | + * |
| 179 | + * Check if forceBasis + coefs gives the same as deformation.patch(0) |
| 180 | + */ |
| 181 | + if (loadCase == 0) |
| 182 | + { |
| 183 | + gsInfo << "Load case 0: Constant load\n"; |
| 184 | + } |
| 185 | + else if (loadCase == 1) |
| 186 | + { |
| 187 | + gsInfo << "Load case 1: Spring load\n"; |
| 188 | + if(timestep > 0) |
| 189 | + { |
| 190 | + gsMatrix<> coefs; |
| 191 | + gsL2Projection<real_t>::projectFunction(forceBasis, deformation, mp, coefs); |
| 192 | + coefs.resize(forceControlPoints.rows(),forceControlPoints.cols()); |
| 193 | + forceControlPoints.row(2) = -coefs.row(2); |
| 194 | + } |
| 195 | + } |
| 196 | + else |
| 197 | + { |
| 198 | + GISMO_ERROR("Load case "<<loadCase<<" unknown."); |
| 199 | + } |
| 200 | + |
| 201 | + |
| 202 | + participant.writeData(ForceControlPointMesh,ForceControlPointData,forceControlPointIDs,forceControlPoints); |
| 203 | + |
| 204 | + if (get_writeTime) |
| 205 | + t_write +=participant.writeTime(); |
| 206 | + // bool requiresWritingCheckpoint and requiresReadingCheckpoint are **REQUIRED** in PreCICE. |
| 207 | + // And the requiresWritingCheckpoint() should be called before advance() |
| 208 | + gsMatrix<> pointDataMatrix; |
| 209 | + gsMatrix<> otherDataMatrix(1,1); |
| 210 | + if (participant.requiresWritingCheckpoint()) |
| 211 | + { |
| 212 | + gsInfo<<"Reading Checkpoint\n"; |
| 213 | + } |
| 214 | + |
| 215 | + // do the coupling |
| 216 | + precice_dt = participant.advance(dt); |
| 217 | + |
| 218 | + dt = std::min(precice_dt, dt); |
| 219 | + |
| 220 | + if (participant.requiresReadingCheckpoint()) |
| 221 | + { |
| 222 | + gsInfo<<"Writing Checkpoint \n"; |
| 223 | + } |
| 224 | + else |
| 225 | + { |
| 226 | + t += dt; |
| 227 | + timestep++; |
| 228 | + |
| 229 | + gsField<> solution(mp,deformation); |
| 230 | + if (timestep % plotmod==0 && plot) |
| 231 | + { |
| 232 | + // solution.patch(0).coefs() -= patches.patch(0).coefs();// assuming 1 patch here |
| 233 | + std::string fileName = "./output/solution" + util::to_string(timestep); |
| 234 | + gsWriteParaview<>(solution, fileName, 500); |
| 235 | + fileName = "solution" + util::to_string(timestep) + "0"; |
| 236 | + collection.addTimestep(fileName,t,".vts"); |
| 237 | + } |
| 238 | + if (write) |
| 239 | + { |
| 240 | + solution.patch(0).eval_into(points,pointDataMatrix); |
| 241 | + otherDataMatrix<<t; |
| 242 | + writer.add(pointDataMatrix,otherDataMatrix); |
| 243 | + } |
| 244 | + |
| 245 | + // solution.patch(0).eval_into(points,pointDataMatrix); |
| 246 | + // otherDataMatrix<<time; |
| 247 | + // writer.add(pointDataMatrix,otherDataMatrix); |
| 248 | + } |
| 249 | + } |
| 250 | + if (get_readTime) |
| 251 | + { |
| 252 | + gsInfo << "Fluid Read time: " << t_read << "\n"; |
| 253 | + } |
| 254 | + |
| 255 | + if (get_writeTime) |
| 256 | + { |
| 257 | + gsInfo << "Fluid Write time: " << t_write << "\n"; |
| 258 | + } |
| 259 | + |
| 260 | + if (plot) |
| 261 | + { |
| 262 | + // Refer to gsParaviewCollection |
| 263 | + collection.save(); |
| 264 | + } |
| 265 | + |
| 266 | + |
| 267 | + return EXIT_SUCCESS; |
| 268 | +} |
0 commit comments