From 7afe539227063c9bdc1e1e777fea7906421ef7c9 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Thu, 8 Oct 2009 09:22:02 +0000 Subject: [PATCH] actually implement the Neumann-Dirichlet coupling. This is completely untested yet [[Imported from SVN: r4974]] --- neudircoupling.cc | 98 +++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/neudircoupling.cc b/neudircoupling.cc index f62610dd..5c8f25bb 100644 --- a/neudircoupling.cc +++ b/neudircoupling.cc @@ -321,7 +321,7 @@ int main (int argc, char *argv[]) try // Init interface value RigidBodyMotion<3> referenceInterface = rodX[0]; - RigidBodyMotion<3> lambda = referenceInterface; + //RigidBodyMotion<3> lambda = referenceInterface; FieldVector<double,3> lambdaForce(0); FieldVector<double,3> lambdaTorque(0); @@ -331,7 +331,7 @@ int main (int argc, char *argv[]) try for (int i=0; i<maxDirichletNeumannSteps; i++) { std::cout << "----------------------------------------------------" << std::endl; - std::cout << " Dirichlet-Neumann Step Number: " << i << std::endl; + std::cout << " Dirichlet-Neumann Step Number: " << i << std::endl; std::cout << "----------------------------------------------------" << std::endl; // Backup of the current solution for the error computation later on @@ -339,11 +339,11 @@ int main (int argc, char *argv[]) try RodSolutionType oldSolutionRod = rodX; // ////////////////////////////////////////////////// - // Dirichlet step for the rod + // Neumann step for the rod // ////////////////////////////////////////////////// - rodX[0] = lambda; rodSolver.setInitialSolution(rodX); + rodAssembler.setNeumannData(lambdaForce, lambdaTorque, FieldVector<double,3>(0), FieldVector<double,3>(0)); rodSolver.solve(); rodX = rodSolver.getSol(); @@ -352,35 +352,46 @@ int main (int argc, char *argv[]) try // std::cout << rodX[j] << std::endl; // /////////////////////////////////////////////////////////// - // Extract Neumann values and transfer it to the 3d object + // Extract Dirichlet values and transfer it to the 3d object // /////////////////////////////////////////////////////////// - BitSetVector<1> couplingBitfield(rodX.size(),false); // Using that index 0 is always the left boundary for a uniformly refined OneDGrid - couplingBitfield[0] = true; - LevelBoundaryPatch<RodGridType> couplingBoundary(rodGrid, rodGrid.maxLevel(), couplingBitfield); + RigidBodyMotion<3> resultantConfiguration = rodX[0]; - FieldVector<double,dim> resultantForce, resultantTorque; - resultantForce = rodAssembler.getResultantForce(couplingBoundary, rodX, resultantTorque); + std::cout << "Resultant configuration: " << resultantConfiguration << std::endl; - std::cout << "resultant force: " << resultantForce << std::endl; - std::cout << "resultant torque: " << resultantTorque << std::endl; + // Compute difference to the reference interface + /** \todo This is a group operation --> put it into the RigidBodyMotion class */ + RigidBodyMotion<3> differenceToReferenceInterface = referenceInterface; + differenceToReferenceInterface.q.invert(); + differenceToReferenceInterface.r *= -1; + differenceToReferenceInterface.q.mult(resultantConfiguration.q); + differenceToReferenceInterface.r += resultantConfiguration.r; - VectorType neumannValues(rhs3d.size()); - // Using that index 0 is always the left boundary for a uniformly refined OneDGrid - computeAveragePressure<GridType>(resultantForce, resultantTorque, - interfaceBoundary[grid.maxLevel()], - rodX[0], - neumannValues); - rhs3d = 0; - assembleAndAddNeumannTerm<GridType::LevelGridView, VectorType>(interfaceBoundary[grid.maxLevel()], - neumannValues, - rhs3d); + GridType::Codim<dim>::LeafIterator vIt = grid.leafbegin<dim>(); + GridType::Codim<dim>::LeafIterator vEndIt = grid.leafend<dim>(); + + for (; vIt!=vEndIt; ++vIt) { + + unsigned int idx = grid.leafIndexSet().index(*vIt); + + // Consider only vertices on the interface boundary + if (interfaceBoundary.back().containsVertex(idx)) + continue; + + // apply the rigid body motion to the vertex position and subtract the old position + FieldMatrix<double,3,3> rotationMatrix; + differenceToReferenceInterface.q.matrix(rotationMatrix); + rotationMatrix.mv(vIt->geometry().corner(0), rhs3d[idx]); + rhs3d[idx] += differenceToReferenceInterface.r; + rhs3d[idx] -= vIt->geometry().corner(0); + + } // /////////////////////////////////////////////////////////// - // Solve the Neumann problem for the 3d body + // Solve the Dirichlet problem for the 3d body // /////////////////////////////////////////////////////////// multigridStep.setProblem(stiffnessMatrix3d, x3d, rhs3d, grid.maxLevel()+1); @@ -392,33 +403,38 @@ int main (int argc, char *argv[]) try x3d = multigridStep.getSol(); // /////////////////////////////////////////////////////////// - // Extract new interface position and orientation + // Extract new interface resultant force and torque // /////////////////////////////////////////////////////////// - RigidBodyMotion<3> averageInterface; - computeAverageInterface(interfaceBoundary[toplevel], x3d, averageInterface); + FieldVector<double,3> resultantForce(0); + FieldVector<double,3> resultantTorque(0); - //averageInterface.r[0] = averageInterface.r[1] = 0; - //averageInterface.q = Quaternion<double>::identity(); - std::cout << "average interface: " << averageInterface << std::endl; + VectorType residual = rhs3d; + stiffnessMatrix3d.mmv(x3d, residual); - std::cout << "director 0: " << averageInterface.q.director(0) << std::endl; - std::cout << "director 1: " << averageInterface.q.director(1) << std::endl; - std::cout << "director 2: " << averageInterface.q.director(2) << std::endl; - std::cout << std::endl; + for (vIt=grid.leafbegin<dim>(); vIt!=vEndIt; ++vIt) { + + unsigned int idx = grid.leafIndexSet().index(*vIt); + + if (interfaceBoundary.back().containsVertex(idx)) { + resultantForce += residual[idx]; + resultantTorque += crossProduct(residual[idx], vIt->geometry().corner(0)-resultantConfiguration.r); + } + } + + std::cout << "average force: " << resultantForce << std::endl; + std::cout << "average torque: " << resultantTorque << std::endl; // /////////////////////////////////////////////////////////// // Compute new damped interface value // /////////////////////////////////////////////////////////// - for (int j=0; j<dim; j++) - lambda.r[j] = (1-damping) * lambda.r[j] - + damping * (referenceInterface.r[j] + averageInterface.r[j]); - - lambda.q = Rotation<3,double>::interpolate(lambda.q, - referenceInterface.q.mult(averageInterface.q), - damping); + for (int j=0; j<dim; j++) { + lambdaForce[j] = (1-damping) * lambdaForce[j] + damping * resultantForce[j]; + lambdaTorque[j] = (1-damping) * lambdaTorque[j] + damping * resultantTorque[j]; + } - std::cout << "Lambda: " << lambda << std::endl; + std::cout << "Lambda force: " << lambdaForce << std::endl; + std::cout << "Lambda torque: " << lambdaTorque << std::endl; // //////////////////////////////////////////////////////////////////////// // Write the two iterates to disk for later convergence rate measurement -- GitLab