void Foam::patchDist::correct() { // Calculate distance starting from patch faces patchWave wave(mesh(), patchIDs_, correctWalls_); // Transfer cell values from wave into *this gpuList<scalar> dist(wave.distance()); this->getField().transfer(dist); // Transfer values on patches into boundaryField of *this forAll(boundaryField(), patchI) { if (!isA<emptyFvPatchScalarField>(boundaryField()[patchI])) { boundaryField()[patchI].operator=(wave.patchDistance()[patchI]); // scalargpuField waveFld(wave.patchDistance()[patchI]); // boundaryField()[patchI].transfer(waveFld); } } // Transfer number of unset values nUnset_ = wave.nUnset(); }
void Foam::phaseModel::correctInflowOutflow(surfaceScalarField& alphaPhi) const { surfaceScalarField::Boundary& alphaPhiBf = alphaPhi.boundaryFieldRef(); const volScalarField::Boundary& alphaBf = boundaryField(); const surfaceScalarField::Boundary& phiBf = phi()().boundaryField(); forAll(alphaPhiBf, patchi) { fvsPatchScalarField& alphaPhip = alphaPhiBf[patchi]; if (!alphaPhip.coupled()) { alphaPhip = phiBf[patchi]*alphaBf[patchi]; } }
// Correct for mesh geom/topo changes. Might be more intelligent in the // future (if only small topology change) void Foam::wallDist::correct() { // AJ: make sure to pick up all patches that are specified as a wall const polyBoundaryMesh& bMesh = cellDistFuncs::mesh().boundaryMesh(); labelHashSet wallPatchIDs(bMesh.size()); forAll(bMesh, patchI) { if (bMesh[patchI].isWall()) { wallPatchIDs.insert(patchI); } } // Get patchids of walls // labelHashSet wallPatchIDs(getPatchIDs<wallPolyPatch>()); // Calculate distance starting from wallPatch faces. patchWave wave(cellDistFuncs::mesh(), wallPatchIDs, correctWalls_); // Transfer cell values from wave into *this transfer(wave.distance()); // Transfer values on patches into boundaryField of *this forAll(boundaryField(), patchI) { if (!isA<emptyFvPatchScalarField>(boundaryField()[patchI])) { scalarField& waveFld = wave.patchDistance()[patchI]; boundaryField()[patchI].transfer(waveFld); } } // Transfer number of unset values nUnset_ = wave.nUnset(); }
/** Analysis of a CSG-modelled geometry (elasticity) */ int cutCell::csgElastic( int argc, char* argv[] ) { // spatial dimension const unsigned dim = 3; typedef base::Vector<dim,double>::Type VecDim; //-------------------------------------------------------------------------- // surfaces // sphere const double rs = 0.65; const VecDim cs = base::constantVector<dim>( 0.5 ); base::cut::Sphere<dim> sphere( rs, cs, true ); // cylinder const double rc = 0.3; const VecDim cc = cs; const VecDim zero = base::constantVector<dim>(0.); VecDim e1 = zero; e1[0] = 1.; VecDim e2 = zero; e2[1] = 1.; VecDim e3 = zero; e3[2] = 1.; base::cut::Cylinder<dim> cyl1( rc, cc, e1, false ); base::cut::Cylinder<dim> cyl2( rc, cc, e2, false ); base::cut::Cylinder<dim> cyl3( rc, cc, e3, false ); if ( argc != 3 ) { std::cerr << "Usage: " << argv[0] << " N input.dat\n" << "(Compiled for dim=" << dim << ")\n\n"; return -1; } // read name of input file const unsigned numElements = boost::lexical_cast<unsigned>( argv[1] ); const std::string inputFile = boost::lexical_cast<std::string>( argv[2] ); // read from input file double E, nu, xmax, cutThreshold, sX, sY, sZ; std::string meshFile; unsigned stabilise; // 0 - not, 1 - Höllig bool compute; unsigned maxIter, loadSteps; double tolerance, forceVal; { //Feed properties parser with the variables to be read base::io::PropertiesParser prop; prop.registerPropertiesVar( "E", E ); prop.registerPropertiesVar( "nu", nu ); prop.registerPropertiesVar( "xmax", xmax ); prop.registerPropertiesVar( "sX", sX ); prop.registerPropertiesVar( "sY", sY ); prop.registerPropertiesVar( "sZ", sZ ); prop.registerPropertiesVar( "stabilise", stabilise ); prop.registerPropertiesVar( "meshFile", meshFile ); prop.registerPropertiesVar( "compute", compute ); prop.registerPropertiesVar( "cutThreshold", cutThreshold ); prop.registerPropertiesVar( "maxIter", maxIter ); prop.registerPropertiesVar( "tolerance", tolerance ); prop.registerPropertiesVar( "loadSteps", loadSteps ); prop.registerPropertiesVar( "forceVal", forceVal ); // Read variables from the input file std::ifstream inp( inputFile.c_str() ); VERIFY_MSG( inp.is_open(), "Cannot open input file" ); VERIFY_MSG( prop.readValuesAndCheck( inp ), "Input error" ); inp.close( ); } // in case of no computation, do not stabilise if ( not compute ) stabilise = 0; // basic attributes of the computation const unsigned geomDeg = 1; const unsigned fieldDeg = 1; const base::Shape shape = //base::SimplexShape<dim>::value; base::HyperCubeShape<dim>::value; const base::Shape surfShape = base::SimplexShape<dim-1>::value; const unsigned kernelDegEstimate = 5; // Bulk mesh typedef base::Unstructured<shape,geomDeg> Mesh; typedef Mesh::Node::VecDim VecDim; Mesh mesh; std::string baseName; VecDim a, b; for ( unsigned d = 0; d < dim; d++ ) { a[d] = 0.; b[d] = xmax; } base::auxi::BoundingBox<dim> bbox( a, b ); if ( numElements > 0 ) { base::Vector<dim,unsigned>::Type N; for ( unsigned d = 0; d < dim; d++ ) { N[d] = numElements; } generateMesh<dim>( mesh, N, a, b ); baseName = argv[0] + std::string(".") + base::io::leadingZeros( numElements ); } else{ std::ifstream smf( meshFile.c_str() ); base::io::smf::readMesh( smf, mesh ); baseName = base::io::baseName( meshFile, ".smf" ); } // Boundary mesh typedef base::mesh::BoundaryMeshBinder<Mesh,true>::Type BoundaryMesh; BoundaryMesh boundaryMesh; base::mesh::MeshBoundary meshBoundary; meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() ); base::mesh::generateBoundaryMesh( meshBoundary.begin(), meshBoundary.end(), mesh, boundaryMesh ); // Cell structures typedef base::cut::Cell<shape> Cell; std::vector<Cell> cells; typedef base::cut::Cell<surfShape> SurfCell; std::vector<SurfCell> surfCells; // intersection of all level sets typedef base::cut::LevelSet<dim> LevelSet; std::vector<LevelSet> levelSetIntersection; //-------------------------------------------------------------------------- // go through immersed surfaces //ImplicitGeometry<Mesh> geometry( mesh, boundaryMesh, sphere ); cutCell::ImplicitGeometry<Mesh> geometry( mesh, boundaryMesh ); geometry.intersectAnalytical( sphere, cutThreshold ); geometry.intersectAnalytical( cyl1, cutThreshold ); geometry.intersectAnalytical( cyl2, cutThreshold ); geometry.intersectAnalytical( cyl3, cutThreshold ); levelSetIntersection = geometry.getLevelSet(); #ifdef EMBEDFIRST cells = geometry.getCells(); surfCells = geometry.getSurfCells(); #else base::cut::generateCutCells( mesh, levelSetIntersection, cells, base::cut::CREATE ); base::cut::generateCutCells( boundaryMesh, levelSetIntersection, surfCells, base::cut::CREATE ); #endif // Generate a mesh from the immersed surface typedef base::cut::SurfaceMeshBinder<Mesh>::SurfaceMesh SurfaceMesh; SurfaceMesh surfaceMesh; base::cut::generateSurfaceMesh<Mesh,Cell>( mesh, cells, surfaceMesh ); //-------------------------------------------------------------------------- // FE #ifdef LINEAR typedef mat::hypel::StVenant Material; #else typedef mat::hypel::NeoHookeanCompressible Material; #endif typedef cutCell::HyperElastic<Mesh,Material,fieldDeg> HyperElastic; HyperElastic hyperElastic( mesh, E, nu ); typedef cutCell::SurfaceField<SurfaceMesh,HyperElastic::Field> SurfaceField; SurfaceField surfaceField( surfaceMesh, hyperElastic.getField() ); SurfaceField boundaryField( boundaryMesh, hyperElastic.getField() ); //-------------------------------------------------------------------------- // Quadratures typedef base::cut::Quadrature<kernelDegEstimate,shape> CutQuadrature; CutQuadrature cutQuadrature( cells, true ); typedef base::Quadrature<kernelDegEstimate,surfShape> SurfaceQuadrature; SurfaceQuadrature surfaceQuadrature; typedef base::cut::Quadrature<kernelDegEstimate,surfShape> SurfaceCutQuadrature; SurfaceCutQuadrature surfaceCutQuadrature( surfCells, true ); // compute supports const std::size_t numDoFs = std::distance( hyperElastic.getField().doFsBegin(), hyperElastic.getField().doFsEnd() ); std::vector<double> supports; supports.resize( numDoFs ); base::cut::supportComputation( mesh, hyperElastic.getField(), cutQuadrature, supports ); std::vector<std::pair<std::size_t,VecDim> > doFLocation; base::dof::associateLocation( hyperElastic.getField(), doFLocation ); // Fundamental solution #ifdef LINEAR HyperElastic::VecDim sourcePoint = base::constantVector<dim>( 0. ); HyperElastic::VecDim pointForce = base::constantVector<dim>( 0. ); sourcePoint[0] = sX; pointForce[0] = 1.; if ( dim > 1 ) { sourcePoint[1] = sY; pointForce[1] = 2.; } if ( dim > 2 ) { sourcePoint[2] = sZ; pointForce[2] = 3.; } typedef base::auxi::FundSolElastoStatic<dim> FSol; FSol fSol( mat::Lame::lambda( E, nu ), mat::Lame::mu( E, nu ) ); typedef boost::function< HyperElastic::VecDoF( const VecDim& ) > FFun; FFun fFun = boost::bind( &FSol::fun, &fSol, _1, sourcePoint, pointForce ); // apply dirichlet constraints base::dof::constrainBoundary<HyperElastic::FEBasis>( meshBoundary.begin(), meshBoundary.end(), mesh, hyperElastic.getField(), boost::bind( &dirichletBCFromFSol<FFun,HyperElastic::DoF>, _1, _2, fFun ) ); typedef boost::function< HyperElastic::VecDoF( const VecDim&, const VecDim&) > FFun2; FFun2 fFun2 = boost::bind( &FSol::coNormal, &fSol, _1, sourcePoint, pointForce, _2 ); #else base::dof::constrainBoundary<HyperElastic::FEBasis>( meshBoundary.begin(), meshBoundary.end(), mesh, hyperElastic.getField(), boost::bind( &fixBottom<dim,HyperElastic::DoF>, _1, _2, bbox ) ); #endif base::cut::stabiliseBasis( mesh, hyperElastic.getField(), supports, doFLocation ); // number DoFs const std::size_t activeDoFsU = base::dof::numberDoFsConsecutively( hyperElastic.getField().doFsBegin(), hyperElastic.getField().doFsEnd() ); //-------------------------------------------------------------------------- // Load step loop #ifdef LINEAR const unsigned numSteps = 1; const unsigned numIter = 1; #else const unsigned numSteps = loadSteps; const unsigned numIter = maxIter; // write zero state hyperElastic.writeVTKFile( baseName, 0, levelSetIntersection, cells, true ); hyperElastic.writeVTKFileCut( baseName, 0, levelSetIntersection, cells, true ); #endif for ( unsigned s = 0; s < numSteps and compute; s++ ) { //---------------------------------------------------------------------- // Nonlinear iterations unsigned iter = 0; while( iter < numIter ) { // Create a solver object typedef base::solver::Eigen3 Solver; Solver solver( activeDoFsU ); #ifdef LINEAR // Neumann boundary condition -- box boundary boundaryField.applyNeumannBoundaryConditions( surfaceCutQuadrature, solver, fFun2 ); // Neumann boundary condition -- immersed surface surfaceField.applyNeumannBoundaryConditions( surfaceQuadrature, solver, fFun2 ); #else const double factor = static_cast<double>( s+1 ) / static_cast<double>( numSteps ); boundaryField.applyNeumannBoundaryConditions( surfaceCutQuadrature, solver, boost::bind( &twistTop<dim>, _1, _2, bbox, forceVal * factor ) ); #endif hyperElastic.assembleBulk( cutQuadrature, solver, iter ); // Finalise assembly solver.finishAssembly(); // norm of residual const double conv1 = solver.norm(); #ifndef LINEAR std::cout << s << " " << iter << " " << conv1 << " "; #endif // convergence via residual norm if ( conv1 < tolerance * E ) { // note the tolerance multiplier #ifndef LINEAR std::cout << std::endl; #endif break; } // Solve //solver.choleskySolve(); //solver.cgSolve(); solver.superLUSolve(); // distribute results back to dofs base::dof::addToDoFsFromSolver( solver, hyperElastic.getField() ); // norm of displacement increment const double conv2 = solver.norm(); #ifndef LINEAR std::cout << conv2 << std::endl; #endif iter++; // convergence via increment if ( conv2 < tolerance ) break; } // end iterations // warning if ( iter == maxIter ) { std::cout << "# (WW) Step " << s << " has not converged within " << maxIter << " iterations \n"; } //---------------------------------------------------------------------- // write a vtk file hyperElastic.writeVTKFile( baseName, s+1, levelSetIntersection, cells ); hyperElastic.writeVTKFileCut( baseName, s+1, levelSetIntersection, cells ); } // end load steps //------------------------------------------------------------------------------ // Compute error and mesh volume for convergence (linear only) #ifdef LINEAR double hmin; { std::vector<double> h; Mesh::ElementPtrConstIter eIter = mesh.elementsBegin(); Mesh::ElementPtrConstIter eEnd = mesh.elementsEnd(); for ( ; eIter != eEnd; ++eIter ) { h.push_back( base::mesh::elementSize( *eIter ) ); } hmin = *std::min_element( h.begin(), h.end() ); } std::cout << hmin << " "; //-------------------------------------------------------------------------- // Error std::cout << hyperElastic.computeL2Error( cutQuadrature, fFun ) << " "; //-------------------------------------------------------------------------- // Compute mesh volume const double volume = hyperElastic.computeVolume( cutQuadrature ); std::cout << std::abs(volume-exactV) << " "; //-------------------------------------------------------------------------- // Compute surface area double area = surfaceField.computeArea( surfaceQuadrature ); area += boundaryField.computeArea( surfaceCutQuadrature ); std::cout << std::abs(area-exactA) << " " << std::endl; #endif return 0; }