| 321 | } |
| 322 | |
| 323 | ZSparseMatrix Assembler3D::getBdLaplacianMatrix() { |
| 324 | typedef Eigen::Triplet<double> T; |
| 325 | std::vector<T> triplets; |
| 326 | |
| 327 | size_t num_bdv = m_mesh->getNbrBoundaryNodes(); |
| 328 | size_t num_bdf = m_mesh->getNbrBoundaryFaces(); |
| 329 | |
| 330 | // Compute lumped mass |
| 331 | VectorF lumped_mass(num_bdv); |
| 332 | for (size_t i=0; i<num_bdv; i++) { |
| 333 | VectorI neighbor_faces = m_mesh->getBoundaryNodeAdjacentBoundaryFaces(i); |
| 334 | assert(neighbor_faces.size() == 3); |
| 335 | |
| 336 | double total_weight = |
| 337 | m_mesh->getBoundaryFaceArea(neighbor_faces[0]) + |
| 338 | m_mesh->getBoundaryFaceArea(neighbor_faces[1]) + |
| 339 | m_mesh->getBoundaryFaceArea(neighbor_faces[2]); |
| 340 | lumped_mass[i] = total_weight / 3.0; |
| 341 | } |
| 342 | |
| 343 | // Compute laplacian matrix. |
| 344 | for (size_t i=0; i<num_bdf; i++) { |
| 345 | VectorI face = m_mesh->getBoundaryFace(i); |
| 346 | assert(face.size() == 3); |
| 347 | |
| 348 | size_t v[3] = { |
| 349 | m_mesh->getBoundaryIndex(face[0]), |
| 350 | m_mesh->getBoundaryIndex(face[1]), |
| 351 | m_mesh->getBoundaryIndex(face[2]) |
| 352 | }; |
| 353 | Eigen::Vector3d p[3] = { |
| 354 | Eigen::Vector3d(m_mesh->getNode(face[0])), |
| 355 | Eigen::Vector3d(m_mesh->getNode(face[1])), |
| 356 | Eigen::Vector3d(m_mesh->getNode(face[2])) |
| 357 | }; |
| 358 | |
| 359 | for (size_t j=0; j<3; j++) { |
| 360 | size_t i0 = j; |
| 361 | size_t i1 = (j+1)%3; |
| 362 | size_t i2 = (j+2)%3; |
| 363 | |
| 364 | double cos_angle = (p[i1] - p[i0]).dot(p[i2] - p[i0]); |
| 365 | double sin_angle = ((p[i1] - p[i0]).cross(p[i2] - p[i0])).norm(); |
| 366 | double weight = 0.5 * cos_angle / sin_angle; |
| 367 | |
| 368 | triplets.push_back(T(v[i1], v[i1], -weight / lumped_mass[v[i1]])); |
| 369 | triplets.push_back(T(v[i1], v[i2], weight / lumped_mass[v[i1]])); |
| 370 | triplets.push_back(T(v[i2], v[i1], weight / lumped_mass[v[i2]])); |
| 371 | triplets.push_back(T(v[i2], v[i2], -weight / lumped_mass[v[i2]])); |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | Eigen::SparseMatrix<double> Lb = Eigen::SparseMatrix<double>(num_bdv, num_bdv); |
| 376 | Lb.setFromTriplets(triplets.begin(), triplets.end()); |
| 377 | return ZSparseMatrix(Lb); |
| 378 | } |
| 379 |
nothing calls this directly
no test coverage detected